import { afterAll, afterEach, beforeEach, vi } from "vitest"; // Ensure Vitest environment is properly set process.env.VITEST = "true"; import type { ChannelId, ChannelOutboundAdapter, ChannelPlugin, } from "../src/channels/plugins/types.js"; import type { ClawdbotConfig } from "../src/config/config.js"; import type { OutboundSendDeps } from "../src/infra/outbound/deliver.js"; import { installProcessWarningFilter } from "../src/infra/warnings.js"; import { setActivePluginRegistry } from "../src/plugins/runtime.js"; import { createTestRegistry } from "../src/test-utils/channel-plugins.js"; import { withIsolatedTestHome } from "./test-env"; installProcessWarningFilter(); const testEnv = withIsolatedTestHome(); afterAll(() => testEnv.cleanup()); const pickSendFn = (id: ChannelId, deps?: OutboundSendDeps) => { switch (id) { case "discord": return deps?.sendDiscord; case "slack": return deps?.sendSlack; case "telegram": return deps?.sendTelegram; case "whatsapp": return deps?.sendWhatsApp; case "signal": return deps?.sendSignal; case "imessage": return deps?.sendIMessage; default: return undefined; } }; const createStubOutbound = ( id: ChannelId, deliveryMode: ChannelOutboundAdapter["deliveryMode"] = "direct", ): ChannelOutboundAdapter => ({ deliveryMode, sendText: async ({ deps, to, text }) => { const send = pickSendFn(id, deps); if (send) { const result = await send(to, text, {}); return { channel: id, ...result }; } return { channel: id, messageId: "test" }; }, sendMedia: async ({ deps, to, text, mediaUrl }) => { const send = pickSendFn(id, deps); if (send) { const result = await send(to, text, { mediaUrl }); return { channel: id, ...result }; } return { channel: id, messageId: "test" }; }, }); const createStubPlugin = (params: { id: ChannelId; label?: string; aliases?: string[]; deliveryMode?: ChannelOutboundAdapter["deliveryMode"]; preferSessionLookupForAnnounceTarget?: boolean; }): ChannelPlugin => ({ id: params.id, meta: { id: params.id, label: params.label ?? String(params.id), selectionLabel: params.label ?? String(params.id), docsPath: `/channels/${params.id}`, blurb: "test stub.", aliases: params.aliases, preferSessionLookupForAnnounceTarget: params.preferSessionLookupForAnnounceTarget, }, capabilities: { chatTypes: ["direct", "group"] }, config: { listAccountIds: (cfg: ClawdbotConfig) => { const channels = cfg.channels as Record | undefined; const entry = channels?.[params.id]; if (!entry || typeof entry !== "object") return []; const accounts = (entry as { accounts?: Record }).accounts; const ids = accounts ? Object.keys(accounts).filter(Boolean) : []; return ids.length > 0 ? ids : ["default"]; }, resolveAccount: (cfg: ClawdbotConfig, accountId: string) => { const channels = cfg.channels as Record | undefined; const entry = channels?.[params.id]; if (!entry || typeof entry !== "object") return {}; const accounts = (entry as { accounts?: Record }).accounts; const match = accounts?.[accountId]; return (match && typeof match === "object") || typeof match === "string" ? match : entry; }, isConfigured: async (_account, cfg: ClawdbotConfig) => { const channels = cfg.channels as Record | undefined; return Boolean(channels?.[params.id]); }, }, outbound: createStubOutbound(params.id, params.deliveryMode), }); const createDefaultRegistry = () => createTestRegistry([ { pluginId: "discord", plugin: createStubPlugin({ id: "discord", label: "Discord" }), source: "test", }, { pluginId: "slack", plugin: createStubPlugin({ id: "slack", label: "Slack" }), source: "test", }, { pluginId: "telegram", plugin: { ...createStubPlugin({ id: "telegram", label: "Telegram" }), status: { buildChannelSummary: async () => ({ configured: false, tokenSource: process.env.TELEGRAM_BOT_TOKEN ? "env" : "none", }), }, }, source: "test", }, { pluginId: "whatsapp", plugin: createStubPlugin({ id: "whatsapp", label: "WhatsApp", deliveryMode: "gateway", preferSessionLookupForAnnounceTarget: true, }), source: "test", }, { pluginId: "signal", plugin: createStubPlugin({ id: "signal", label: "Signal" }), source: "test", }, { pluginId: "imessage", plugin: createStubPlugin({ id: "imessage", label: "iMessage", aliases: ["imsg"] }), source: "test", }, ]); beforeEach(() => { setActivePluginRegistry(createDefaultRegistry()); }); afterEach(() => { setActivePluginRegistry(createDefaultRegistry()); // Guard against leaked fake timers across test files/workers. vi.useRealTimers(); });