121 lines
4.2 KiB
TypeScript
121 lines
4.2 KiB
TypeScript
import type { App } from "@slack/bolt";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import type { ClawdbotConfig } from "../../config/config.js";
|
|
import type { RuntimeEnv } from "../../runtime.js";
|
|
import { createSlackMonitorContext, normalizeSlackChannelType } from "./context.js";
|
|
|
|
const baseParams = () => ({
|
|
cfg: {} as ClawdbotConfig,
|
|
accountId: "default",
|
|
botToken: "token",
|
|
app: { client: {} } as App,
|
|
runtime: {} as RuntimeEnv,
|
|
botUserId: "B1",
|
|
teamId: "T1",
|
|
apiAppId: "A1",
|
|
historyLimit: 0,
|
|
sessionScope: "per-sender" as const,
|
|
mainKey: "main",
|
|
dmEnabled: true,
|
|
dmPolicy: "open" as const,
|
|
allowFrom: [],
|
|
groupDmEnabled: true,
|
|
groupDmChannels: [],
|
|
defaultRequireMention: true,
|
|
groupPolicy: "open" as const,
|
|
useAccessGroups: false,
|
|
reactionMode: "off" as const,
|
|
reactionAllowlist: [],
|
|
replyToMode: "off" as const,
|
|
slashCommand: {
|
|
enabled: false,
|
|
name: "clawd",
|
|
sessionPrefix: "slack:slash",
|
|
ephemeral: true,
|
|
},
|
|
textLimit: 4000,
|
|
ackReactionScope: "group-mentions",
|
|
mediaMaxBytes: 1,
|
|
removeAckAfterReply: false,
|
|
});
|
|
|
|
describe("normalizeSlackChannelType", () => {
|
|
it("infers channel types from ids when missing", () => {
|
|
expect(normalizeSlackChannelType(undefined, "C123")).toBe("channel");
|
|
expect(normalizeSlackChannelType(undefined, "D123")).toBe("im");
|
|
expect(normalizeSlackChannelType(undefined, "G123")).toBe("group");
|
|
});
|
|
|
|
it("prefers explicit channel_type values", () => {
|
|
expect(normalizeSlackChannelType("mpim", "C123")).toBe("mpim");
|
|
});
|
|
});
|
|
|
|
describe("resolveSlackSystemEventSessionKey", () => {
|
|
it("defaults missing channel_type to channel sessions", () => {
|
|
const ctx = createSlackMonitorContext(baseParams());
|
|
expect(ctx.resolveSlackSystemEventSessionKey({ channelId: "C123" })).toBe(
|
|
"agent:main:slack:channel:c123",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("isChannelAllowed with groupPolicy and channelsConfig", () => {
|
|
it("allows unlisted channels when groupPolicy is open even with channelsConfig entries", () => {
|
|
// Bug fix: when groupPolicy="open" and channels has some entries,
|
|
// unlisted channels should still be allowed (not blocked)
|
|
const ctx = createSlackMonitorContext({
|
|
...baseParams(),
|
|
groupPolicy: "open",
|
|
channelsConfig: {
|
|
C_LISTED: { requireMention: true },
|
|
},
|
|
});
|
|
// Listed channel should be allowed
|
|
expect(ctx.isChannelAllowed({ channelId: "C_LISTED", channelType: "channel" })).toBe(true);
|
|
// Unlisted channel should ALSO be allowed when policy is "open"
|
|
expect(ctx.isChannelAllowed({ channelId: "C_UNLISTED", channelType: "channel" })).toBe(true);
|
|
});
|
|
|
|
it("blocks unlisted channels when groupPolicy is allowlist", () => {
|
|
const ctx = createSlackMonitorContext({
|
|
...baseParams(),
|
|
groupPolicy: "allowlist",
|
|
channelsConfig: {
|
|
C_LISTED: { requireMention: true },
|
|
},
|
|
});
|
|
// Listed channel should be allowed
|
|
expect(ctx.isChannelAllowed({ channelId: "C_LISTED", channelType: "channel" })).toBe(true);
|
|
// Unlisted channel should be blocked when policy is "allowlist"
|
|
expect(ctx.isChannelAllowed({ channelId: "C_UNLISTED", channelType: "channel" })).toBe(false);
|
|
});
|
|
|
|
it("blocks explicitly denied channels even when groupPolicy is open", () => {
|
|
const ctx = createSlackMonitorContext({
|
|
...baseParams(),
|
|
groupPolicy: "open",
|
|
channelsConfig: {
|
|
C_ALLOWED: { allow: true },
|
|
C_DENIED: { allow: false },
|
|
},
|
|
});
|
|
// Explicitly allowed channel
|
|
expect(ctx.isChannelAllowed({ channelId: "C_ALLOWED", channelType: "channel" })).toBe(true);
|
|
// Explicitly denied channel should be blocked even with open policy
|
|
expect(ctx.isChannelAllowed({ channelId: "C_DENIED", channelType: "channel" })).toBe(false);
|
|
// Unlisted channel should be allowed with open policy
|
|
expect(ctx.isChannelAllowed({ channelId: "C_UNLISTED", channelType: "channel" })).toBe(true);
|
|
});
|
|
|
|
it("allows all channels when groupPolicy is open and channelsConfig is empty", () => {
|
|
const ctx = createSlackMonitorContext({
|
|
...baseParams(),
|
|
groupPolicy: "open",
|
|
channelsConfig: undefined,
|
|
});
|
|
expect(ctx.isChannelAllowed({ channelId: "C_ANY", channelType: "channel" })).toBe(true);
|
|
});
|
|
});
|