test: cover channels capabilities probes
This commit is contained in:
138
src/commands/channels/capabilities.test.ts
Normal file
138
src/commands/channels/capabilities.test.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
process.env.NO_COLOR = "1";
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { ChannelPlugin } from "../../channels/plugins/types.js";
|
||||
import { channelsCapabilitiesCommand } from "./capabilities.js";
|
||||
import { fetchSlackScopes } from "../../slack/scopes.js";
|
||||
import {
|
||||
getChannelPlugin,
|
||||
listChannelPlugins,
|
||||
} from "../../channels/plugins/index.js";
|
||||
|
||||
const logs: string[] = [];
|
||||
const errors: string[] = [];
|
||||
|
||||
vi.mock("./shared.js", () => ({
|
||||
requireValidConfig: vi.fn(async () => ({ channels: {} })),
|
||||
formatChannelAccountLabel: vi.fn(({ channel, accountId }: { channel: string; accountId: string }) =>
|
||||
`${channel}:${accountId}`,
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("../../channels/plugins/index.js", () => ({
|
||||
listChannelPlugins: vi.fn(),
|
||||
getChannelPlugin: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../slack/scopes.js", () => ({
|
||||
fetchSlackScopes: vi.fn(),
|
||||
}));
|
||||
|
||||
const runtime = {
|
||||
log: (value: string) => logs.push(value),
|
||||
error: (value: string) => errors.push(value),
|
||||
exit: (code: number) => {
|
||||
throw new Error(`exit:${code}`);
|
||||
},
|
||||
};
|
||||
|
||||
function resetOutput() {
|
||||
logs.length = 0;
|
||||
errors.length = 0;
|
||||
}
|
||||
|
||||
function buildPlugin(params: {
|
||||
id: string;
|
||||
capabilities?: ChannelPlugin["capabilities"];
|
||||
account?: Record<string, unknown>;
|
||||
probe?: unknown;
|
||||
}): ChannelPlugin {
|
||||
const capabilities =
|
||||
params.capabilities ?? ({ chatTypes: ["direct"] } as ChannelPlugin["capabilities"]);
|
||||
return {
|
||||
id: params.id,
|
||||
meta: {
|
||||
id: params.id,
|
||||
label: params.id,
|
||||
selectionLabel: params.id,
|
||||
docsPath: "/channels/test",
|
||||
blurb: "test",
|
||||
},
|
||||
capabilities,
|
||||
config: {
|
||||
listAccountIds: () => ["default"],
|
||||
resolveAccount: () => params.account ?? { accountId: "default" },
|
||||
defaultAccountId: () => "default",
|
||||
isConfigured: () => true,
|
||||
isEnabled: () => true,
|
||||
},
|
||||
status: params.probe
|
||||
? {
|
||||
probeAccount: async () => params.probe,
|
||||
}
|
||||
: undefined,
|
||||
actions: {
|
||||
listActions: () => ["poll"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("channelsCapabilitiesCommand", () => {
|
||||
beforeEach(() => {
|
||||
resetOutput();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("prints Slack bot + user scopes when user token is configured", async () => {
|
||||
const plugin = buildPlugin({
|
||||
id: "slack",
|
||||
account: {
|
||||
accountId: "default",
|
||||
botToken: "xoxb-bot",
|
||||
config: { userToken: "xoxp-user" },
|
||||
},
|
||||
probe: { ok: true, bot: { name: "clawdbot" }, team: { name: "team" } },
|
||||
});
|
||||
vi.mocked(listChannelPlugins).mockReturnValue([plugin]);
|
||||
vi.mocked(getChannelPlugin).mockReturnValue(plugin);
|
||||
vi.mocked(fetchSlackScopes).mockImplementation(async (token: string) => {
|
||||
if (token === "xoxp-user") {
|
||||
return { ok: true, scopes: ["users:read"], source: "auth.scopes" };
|
||||
}
|
||||
return { ok: true, scopes: ["chat:write"], source: "auth.scopes" };
|
||||
});
|
||||
|
||||
await channelsCapabilitiesCommand({ channel: "slack" }, runtime);
|
||||
|
||||
const output = logs.join("\n");
|
||||
expect(output).toContain("Bot scopes");
|
||||
expect(output).toContain("User scopes");
|
||||
expect(output).toContain("chat:write");
|
||||
expect(output).toContain("users:read");
|
||||
expect(fetchSlackScopes).toHaveBeenCalledWith("xoxb-bot", expect.any(Number));
|
||||
expect(fetchSlackScopes).toHaveBeenCalledWith("xoxp-user", expect.any(Number));
|
||||
});
|
||||
|
||||
it("prints Teams Graph permission hints when present", async () => {
|
||||
const plugin = buildPlugin({
|
||||
id: "msteams",
|
||||
probe: {
|
||||
ok: true,
|
||||
appId: "app-id",
|
||||
graph: {
|
||||
ok: true,
|
||||
roles: ["ChannelMessage.Read.All", "Files.Read.All"],
|
||||
},
|
||||
},
|
||||
});
|
||||
vi.mocked(listChannelPlugins).mockReturnValue([plugin]);
|
||||
vi.mocked(getChannelPlugin).mockReturnValue(plugin);
|
||||
|
||||
await channelsCapabilitiesCommand({ channel: "msteams" }, runtime);
|
||||
|
||||
const output = logs.join("\n");
|
||||
expect(output).toContain("ChannelMessage.Read.All (channel history)");
|
||||
expect(output).toContain("Files.Read.All (files (OneDrive))");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user