mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-07 07:11:06 +00:00
100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
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<typeof import("./deps.js")>(
|
|
import.meta.url,
|
|
`./deps.js?scope=${scope}`,
|
|
)
|
|
).createDefaultDeps;
|
|
}
|
|
|
|
function expectUnusedRuntimeFactoriesNotLoaded(exclude: keyof typeof runtimeFactories): void {
|
|
const keys = Object.keys(runtimeFactories) as Array<keyof typeof runtimeFactories>;
|
|
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<unknown>;
|
|
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<unknown>;
|
|
|
|
await sendDiscord("channel", "first", { verbose: false });
|
|
await sendDiscord("channel", "second", { verbose: false });
|
|
|
|
expect(runtimeFactories.discord).toHaveBeenCalledTimes(1);
|
|
expect(sendFns.discord).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|