From 4605dfd2ae9847676c3a9aac01d8d66a40d2f590 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 18 Feb 2026 16:31:27 +0000 Subject: [PATCH] test(channels): add slack group-mention and onboarding helper coverage --- src/channels/plugins/group-mentions.test.ts | 55 +++++++++++++++ .../plugins/onboarding/helpers.test.ts | 69 +++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/channels/plugins/group-mentions.test.ts create mode 100644 src/channels/plugins/onboarding/helpers.test.ts diff --git a/src/channels/plugins/group-mentions.test.ts b/src/channels/plugins/group-mentions.test.ts new file mode 100644 index 000000000..cc0c3668a --- /dev/null +++ b/src/channels/plugins/group-mentions.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from "vitest"; +import { resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy } from "./group-mentions.js"; + +const cfg = { + channels: { + slack: { + botToken: "xoxb-test", + appToken: "xapp-test", + channels: { + alerts: { + requireMention: false, + tools: { allow: ["message.send"] }, + toolsBySender: { + "user:alice": { allow: ["sessions.list"] }, + }, + }, + "*": { + requireMention: true, + tools: { deny: ["exec"] }, + }, + }, + }, + }, + // oxlint-disable-next-line typescript/no-explicit-any +} as any; + +describe("group mentions (slack)", () => { + it("uses matched channel requireMention and wildcard fallback", () => { + expect(resolveSlackGroupRequireMention({ cfg, groupChannel: "#alerts" })).toBe(false); + expect(resolveSlackGroupRequireMention({ cfg, groupChannel: "#missing" })).toBe(true); + }); + + it("resolves sender override, then channel tools, then wildcard tools", () => { + const senderOverride = resolveSlackGroupToolPolicy({ + cfg, + groupChannel: "#alerts", + senderId: "user:alice", + }); + expect(senderOverride).toEqual({ allow: ["sessions.list"] }); + + const channelTools = resolveSlackGroupToolPolicy({ + cfg, + groupChannel: "#alerts", + senderId: "user:bob", + }); + expect(channelTools).toEqual({ allow: ["message.send"] }); + + const wildcardTools = resolveSlackGroupToolPolicy({ + cfg, + groupChannel: "#missing", + senderId: "user:bob", + }); + expect(wildcardTools).toEqual({ deny: ["exec"] }); + }); +}); diff --git a/src/channels/plugins/onboarding/helpers.test.ts b/src/channels/plugins/onboarding/helpers.test.ts new file mode 100644 index 000000000..14f593f3c --- /dev/null +++ b/src/channels/plugins/onboarding/helpers.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, it, vi } from "vitest"; +import { promptResolvedAllowFrom } from "./helpers.js"; + +function createPrompter(inputs: string[]) { + return { + text: vi.fn(async () => inputs.shift() ?? ""), + note: vi.fn(async () => undefined), + }; +} + +describe("promptResolvedAllowFrom", () => { + it("re-prompts without token until all ids are parseable", async () => { + const prompter = createPrompter(["@alice", "123"]); + const resolveEntries = vi.fn(); + + const result = await promptResolvedAllowFrom({ + // oxlint-disable-next-line typescript/no-explicit-any + prompter: prompter as any, + existing: ["111"], + token: "", + message: "msg", + placeholder: "placeholder", + label: "allowlist", + parseInputs: (value) => + value + .split(",") + .map((part) => part.trim()) + .filter(Boolean), + parseId: (value) => (/^\d+$/.test(value.trim()) ? value.trim() : null), + invalidWithoutTokenNote: "ids only", + // oxlint-disable-next-line typescript/no-explicit-any + resolveEntries: resolveEntries as any, + }); + + expect(result).toEqual(["111", "123"]); + expect(prompter.note).toHaveBeenCalledWith("ids only", "allowlist"); + expect(resolveEntries).not.toHaveBeenCalled(); + }); + + it("re-prompts when token resolution returns unresolved entries", async () => { + const prompter = createPrompter(["alice", "bob"]); + const resolveEntries = vi + .fn() + .mockResolvedValueOnce([{ input: "alice", resolved: false }]) + .mockResolvedValueOnce([{ input: "bob", resolved: true, id: "U123" }]); + + const result = await promptResolvedAllowFrom({ + // oxlint-disable-next-line typescript/no-explicit-any + prompter: prompter as any, + existing: [], + token: "xoxb-test", + message: "msg", + placeholder: "placeholder", + label: "allowlist", + parseInputs: (value) => + value + .split(",") + .map((part) => part.trim()) + .filter(Boolean), + parseId: () => null, + invalidWithoutTokenNote: "ids only", + resolveEntries, + }); + + expect(result).toEqual(["U123"]); + expect(prompter.note).toHaveBeenCalledWith("Could not resolve: alice", "allowlist"); + expect(resolveEntries).toHaveBeenCalledTimes(2); + }); +});