| import { afterAll, afterEach, beforeEach, vi } from "vitest"; |
|
|
| |
| 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()); |
| |
| vi.useRealTimers(); |
| }); |
|
|