test: simplify mattermost token summary fixtures

This commit is contained in:
Peter Steinberger
2026-03-13 23:01:09 +00:00
parent a474a9c45d
commit a56e620777

View File

@@ -37,139 +37,94 @@ function makeMattermostPlugin(): ChannelPlugin {
};
}
function makeSlackPlugin(params?: { botToken?: string; appToken?: string }): ChannelPlugin {
return {
id: "slack",
meta: {
id: "slack",
label: "Slack",
selectionLabel: "Slack",
docsPath: "/channels/slack",
blurb: "test",
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: () => ({
name: "Primary",
enabled: true,
botToken: params?.botToken ?? "bot-token",
appToken: params?.appToken ?? "app-token",
}),
resolveAccount: () => ({
name: "Primary",
enabled: true,
botToken: params?.botToken ?? "bot-token",
appToken: params?.appToken ?? "app-token",
}),
isConfigured: () => true,
isEnabled: () => true,
},
actions: {
listActions: () => ["send"],
},
};
}
type TestTable = Awaited<ReturnType<typeof buildChannelsTable>>;
function makeUnavailableSlackPlugin(): ChannelPlugin {
return {
id: "slack",
meta: {
id: "slack",
label: "Slack",
selectionLabel: "Slack",
docsPath: "/channels/slack",
blurb: "test",
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: () => ({
name: "Primary",
enabled: true,
configured: true,
botToken: "",
appToken: "",
botTokenSource: "config",
appTokenSource: "config",
botTokenStatus: "configured_unavailable",
appTokenStatus: "configured_unavailable",
}),
resolveAccount: () => ({
name: "Primary",
enabled: true,
configured: true,
botToken: "",
appToken: "",
botTokenSource: "config",
appTokenSource: "config",
botTokenStatus: "configured_unavailable",
appTokenStatus: "configured_unavailable",
}),
isConfigured: () => true,
isEnabled: () => true,
},
actions: {
listActions: () => ["send"],
},
};
}
function makeSourceAwareUnavailablePlugin(): ChannelPlugin {
function makeSlackDirectPlugin(config: ChannelPlugin["config"]): ChannelPlugin {
return makeDirectPlugin({
id: "slack",
label: "Slack",
docsPath: "/channels/slack",
config: {
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: (cfg) =>
(cfg as { marker?: string }).marker === "source"
? {
name: "Primary",
enabled: true,
configured: true,
botToken: "",
appToken: "",
botTokenSource: "config",
appTokenSource: "config",
botTokenStatus: "configured_unavailable",
appTokenStatus: "configured_unavailable",
}
: {
name: "Primary",
enabled: true,
configured: false,
botToken: "",
appToken: "",
botTokenSource: "none",
appTokenSource: "none",
},
resolveAccount: () => ({
name: "Primary",
enabled: true,
botToken: "",
appToken: "",
}),
isConfigured: (account) => Boolean((account as { configured?: boolean }).configured),
isEnabled: () => true,
},
config,
});
}
function createSlackTokenAccount(params?: { botToken?: string; appToken?: string }) {
return {
name: "Primary",
enabled: true,
botToken: params?.botToken ?? "bot-token",
appToken: params?.appToken ?? "app-token",
};
}
function createUnavailableSlackTokenAccount() {
return {
name: "Primary",
enabled: true,
configured: true,
botToken: "",
appToken: "",
botTokenSource: "config",
appTokenSource: "config",
botTokenStatus: "configured_unavailable",
appTokenStatus: "configured_unavailable",
};
}
function makeSlackPlugin(params?: { botToken?: string; appToken?: string }): ChannelPlugin {
return makeSlackDirectPlugin({
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: () => createSlackTokenAccount(params),
resolveAccount: () => createSlackTokenAccount(params),
isConfigured: () => true,
isEnabled: () => true,
});
}
function makeUnavailableSlackPlugin(): ChannelPlugin {
return makeSlackDirectPlugin({
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: () => createUnavailableSlackTokenAccount(),
resolveAccount: () => createUnavailableSlackTokenAccount(),
isConfigured: () => true,
isEnabled: () => true,
});
}
function makeSourceAwareUnavailablePlugin(): ChannelPlugin {
return makeSlackDirectPlugin({
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
inspectAccount: (cfg) =>
(cfg as { marker?: string }).marker === "source"
? createUnavailableSlackTokenAccount()
: {
name: "Primary",
enabled: true,
configured: false,
botToken: "",
appToken: "",
botTokenSource: "none",
appTokenSource: "none",
},
resolveAccount: () => ({
name: "Primary",
enabled: true,
botToken: "",
appToken: "",
}),
isConfigured: (account) => Boolean((account as { configured?: boolean }).configured),
isEnabled: () => true,
});
}
function makeSourceUnavailableResolvedAvailablePlugin(): ChannelPlugin {
return {
return makeDirectPlugin({
id: "discord",
meta: {
id: "discord",
label: "Discord",
selectionLabel: "Discord",
docsPath: "/channels/discord",
blurb: "test",
},
capabilities: { chatTypes: ["direct"] },
label: "Discord",
docsPath: "/channels/discord",
config: {
listAccountIds: () => ["primary"],
defaultAccountId: () => "primary",
@@ -199,10 +154,7 @@ function makeSourceUnavailableResolvedAvailablePlugin(): ChannelPlugin {
isConfigured: (account) => Boolean((account as { configured?: boolean }).configured),
isEnabled: () => true,
},
actions: {
listActions: () => ["send"],
},
};
});
}
function makeHttpSlackUnavailablePlugin(): ChannelPlugin {
@@ -263,64 +215,76 @@ function makeTokenPlugin(): ChannelPlugin {
});
}
async function buildTestTable(
plugins: ChannelPlugin[],
params?: { cfg?: Record<string, unknown>; sourceConfig?: Record<string, unknown> },
) {
vi.mocked(listChannelPlugins).mockReturnValue(plugins);
return await buildChannelsTable((params?.cfg ?? { channels: {} }) as never, {
showSecrets: false,
sourceConfig: params?.sourceConfig as never,
});
}
function expectTableRow(
table: TestTable,
params: { id: string; state: string; detailContains?: string; detailEquals?: string },
) {
const row = table.rows.find((entry) => entry.id === params.id);
expect(row).toBeDefined();
expect(row?.state).toBe(params.state);
if (params.detailContains) {
expect(row?.detail).toContain(params.detailContains);
}
if (params.detailEquals) {
expect(row?.detail).toBe(params.detailEquals);
}
return row;
}
function expectTableDetailRows(
table: TestTable,
title: string,
rows: Array<Record<string, string>>,
) {
const detail = table.details.find((entry) => entry.title === title);
expect(detail).toBeDefined();
expect(detail?.rows).toEqual(rows);
}
describe("buildChannelsTable - mattermost token summary", () => {
it("does not require appToken for mattermost accounts", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeMattermostPlugin()]);
const table = await buildChannelsTable({ channels: {} } as never, {
showSecrets: false,
});
const mattermostRow = table.rows.find((row) => row.id === "mattermost");
expect(mattermostRow).toBeDefined();
expect(mattermostRow?.state).toBe("ok");
const table = await buildTestTable([makeMattermostPlugin()]);
const mattermostRow = expectTableRow(table, { id: "mattermost", state: "ok" });
expect(mattermostRow?.detail).not.toContain("need bot+app");
});
it("keeps bot+app requirement when both fields exist", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([
makeSlackPlugin({ botToken: "bot-token", appToken: "" }),
]);
const table = await buildChannelsTable({ channels: {} } as never, {
showSecrets: false,
});
const slackRow = table.rows.find((row) => row.id === "slack");
expect(slackRow).toBeDefined();
expect(slackRow?.state).toBe("warn");
expect(slackRow?.detail).toContain("need bot+app");
const table = await buildTestTable([makeSlackPlugin({ botToken: "bot-token", appToken: "" })]);
expectTableRow(table, { id: "slack", state: "warn", detailContains: "need bot+app" });
});
it("reports configured-but-unavailable Slack credentials as warn", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeUnavailableSlackPlugin()]);
const table = await buildChannelsTable({ channels: {} } as never, {
showSecrets: false,
const table = await buildTestTable([makeUnavailableSlackPlugin()]);
expectTableRow(table, {
id: "slack",
state: "warn",
detailContains: "unavailable in this command path",
});
const slackRow = table.rows.find((row) => row.id === "slack");
expect(slackRow).toBeDefined();
expect(slackRow?.state).toBe("warn");
expect(slackRow?.detail).toContain("unavailable in this command path");
});
it("preserves unavailable credential state from the source config snapshot", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeSourceAwareUnavailablePlugin()]);
const table = await buildChannelsTable({ marker: "resolved", channels: {} } as never, {
showSecrets: false,
sourceConfig: { marker: "source", channels: {} } as never,
const table = await buildTestTable([makeSourceAwareUnavailablePlugin()], {
cfg: { marker: "resolved", channels: {} },
sourceConfig: { marker: "source", channels: {} },
});
const slackRow = table.rows.find((row) => row.id === "slack");
expect(slackRow).toBeDefined();
expect(slackRow?.state).toBe("warn");
expect(slackRow?.detail).toContain("unavailable in this command path");
const slackDetails = table.details.find((detail) => detail.title === "Slack accounts");
expect(slackDetails).toBeDefined();
expect(slackDetails?.rows).toEqual([
expectTableRow(table, {
id: "slack",
state: "warn",
detailContains: "unavailable in this command path",
});
expectTableDetailRows(table, "Slack accounts", [
{
Account: "primary (Primary)",
Notes: "bot:config · app:config · secret unavailable in this command path",
@@ -330,21 +294,13 @@ describe("buildChannelsTable - mattermost token summary", () => {
});
it("treats status-only available credentials as resolved", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeSourceUnavailableResolvedAvailablePlugin()]);
const table = await buildChannelsTable({ marker: "resolved", channels: {} } as never, {
showSecrets: false,
sourceConfig: { marker: "source", channels: {} } as never,
const table = await buildTestTable([makeSourceUnavailableResolvedAvailablePlugin()], {
cfg: { marker: "resolved", channels: {} },
sourceConfig: { marker: "source", channels: {} },
});
const discordRow = table.rows.find((row) => row.id === "discord");
expect(discordRow).toBeDefined();
expect(discordRow?.state).toBe("ok");
expect(discordRow?.detail).toBe("configured");
const discordDetails = table.details.find((detail) => detail.title === "Discord accounts");
expect(discordDetails).toBeDefined();
expect(discordDetails?.rows).toEqual([
expectTableRow(table, { id: "discord", state: "ok", detailEquals: "configured" });
expectTableDetailRows(table, "Discord accounts", [
{
Account: "primary (Primary)",
Notes: "token:config",
@@ -354,20 +310,13 @@ describe("buildChannelsTable - mattermost token summary", () => {
});
it("treats Slack HTTP signing-secret availability as required config", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeHttpSlackUnavailablePlugin()]);
const table = await buildChannelsTable({ channels: {} } as never, {
showSecrets: false,
const table = await buildTestTable([makeHttpSlackUnavailablePlugin()]);
expectTableRow(table, {
id: "slack",
state: "warn",
detailContains: "configured http credentials unavailable",
});
const slackRow = table.rows.find((row) => row.id === "slack");
expect(slackRow).toBeDefined();
expect(slackRow?.state).toBe("warn");
expect(slackRow?.detail).toContain("configured http credentials unavailable");
const slackDetails = table.details.find((detail) => detail.title === "Slack accounts");
expect(slackDetails).toBeDefined();
expect(slackDetails?.rows).toEqual([
expectTableDetailRows(table, "Slack accounts", [
{
Account: "primary (Primary)",
Notes: "bot:config · signing:config · secret unavailable in this command path",
@@ -377,15 +326,7 @@ describe("buildChannelsTable - mattermost token summary", () => {
});
it("still reports single-token channels as ok", async () => {
vi.mocked(listChannelPlugins).mockReturnValue([makeTokenPlugin()]);
const table = await buildChannelsTable({ channels: {} } as never, {
showSecrets: false,
});
const tokenRow = table.rows.find((row) => row.id === "token-only");
expect(tokenRow).toBeDefined();
expect(tokenRow?.state).toBe("ok");
expect(tokenRow?.detail).toContain("token");
const table = await buildTestTable([makeTokenPlugin()]);
expectTableRow(table, { id: "token-only", state: "ok", detailContains: "token" });
});
});