import { beforeEach, describe, expect, it, vi } from "vitest"; import { importFreshModule } from "../../test/helpers/import-fresh.ts"; import type { ChannelPlugin } from "../channels/plugins/types.js"; const runtimeFactories = vi.hoisted(() => ({ whatsapp: vi.fn(), telegram: vi.fn(), discord: vi.fn(), slack: vi.fn(), signal: vi.fn(), imessage: vi.fn(), })); const sendFns = vi.hoisted(() => ({ whatsapp: vi.fn(async () => ({ messageId: "w1", toJid: "whatsapp:1" })), telegram: vi.fn(async () => ({ messageId: "t1", chatId: "telegram:1" })), discord: vi.fn(async () => ({ messageId: "d1", channelId: "discord:1" })), slack: vi.fn(async () => ({ messageId: "s1", channelId: "slack:1" })), signal: vi.fn(async () => ({ messageId: "sg1", conversationId: "signal:1" })), imessage: vi.fn(async () => ({ messageId: "i1", chatId: "imessage:1" })), })); vi.mock("../channels/plugins/index.js", () => ({ listChannelPlugins: () => ["whatsapp", "telegram", "discord", "slack", "signal", "imessage"].map( (id) => ({ id, meta: { label: id, selectionLabel: id, docsPath: `/channels/${id}`, blurb: "" }, }) as ChannelPlugin, ), })); vi.mock("./send-runtime/channel-outbound-send.js", () => ({ createChannelOutboundRuntimeSend: ({ channelId, }: { channelId: keyof typeof runtimeFactories; }) => { runtimeFactories[channelId](); return { sendMessage: sendFns[channelId] }; }, })); describe("createDefaultDeps", () => { async function loadCreateDefaultDeps(scope: string) { return ( await importFreshModule( import.meta.url, `./deps.js?scope=${scope}`, ) ).createDefaultDeps; } function expectUnusedRuntimeFactoriesNotLoaded(exclude: keyof typeof runtimeFactories): void { const keys = Object.keys(runtimeFactories) as Array; for (const key of keys) { if (key === exclude) { continue; } expect(runtimeFactories[key]).not.toHaveBeenCalled(); } } beforeEach(() => { vi.clearAllMocks(); }); it("does not build runtime send surfaces until a dependency is used", async () => { const createDefaultDeps = await loadCreateDefaultDeps("lazy-load"); const deps = createDefaultDeps(); expect(runtimeFactories.whatsapp).not.toHaveBeenCalled(); expect(runtimeFactories.telegram).not.toHaveBeenCalled(); expect(runtimeFactories.discord).not.toHaveBeenCalled(); expect(runtimeFactories.slack).not.toHaveBeenCalled(); expect(runtimeFactories.signal).not.toHaveBeenCalled(); expect(runtimeFactories.imessage).not.toHaveBeenCalled(); const sendTelegram = deps.telegram as (...args: unknown[]) => Promise; await sendTelegram("chat", "hello", { verbose: false }); expect(runtimeFactories.telegram).toHaveBeenCalledTimes(1); expect(sendFns.telegram).toHaveBeenCalledTimes(1); expectUnusedRuntimeFactoriesNotLoaded("telegram"); }); it("reuses cached runtime send surfaces after first lazy load", async () => { const createDefaultDeps = await loadCreateDefaultDeps("module-cache"); const deps = createDefaultDeps(); const sendDiscord = deps.discord as (...args: unknown[]) => Promise; await sendDiscord("channel", "first", { verbose: false }); await sendDiscord("channel", "second", { verbose: false }); expect(runtimeFactories.discord).toHaveBeenCalledTimes(1); expect(sendFns.discord).toHaveBeenCalledTimes(2); }); });