Spaces:
Sleeping
Sleeping
| 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 { OpenClawConfig } 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: OpenClawConfig) => { | |
| const channels = cfg.channels as Record<string, unknown> | undefined; | |
| const entry = channels?.[params.id]; | |
| if (!entry || typeof entry !== "object") { | |
| return []; | |
| } | |
| const accounts = (entry as { accounts?: Record<string, unknown> }).accounts; | |
| const ids = accounts ? Object.keys(accounts).filter(Boolean) : []; | |
| return ids.length > 0 ? ids : ["default"]; | |
| }, | |
| resolveAccount: (cfg: OpenClawConfig, accountId: string) => { | |
| const channels = cfg.channels as Record<string, unknown> | undefined; | |
| const entry = channels?.[params.id]; | |
| if (!entry || typeof entry !== "object") { | |
| return {}; | |
| } | |
| const accounts = (entry as { accounts?: Record<string, unknown> }).accounts; | |
| const match = accounts?.[accountId]; | |
| return (match && typeof match === "object") || typeof match === "string" ? match : entry; | |
| }, | |
| isConfigured: async (_account, cfg: OpenClawConfig) => { | |
| const channels = cfg.channels as Record<string, unknown> | 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(); | |
| }); | |