diff --git a/extensions/telegram/src/bot.media.e2e-harness.ts b/extensions/telegram/src/bot.media.e2e-harness.ts index 54ae862ce87..5edebbbb648 100644 --- a/extensions/telegram/src/bot.media.e2e-harness.ts +++ b/extensions/telegram/src/bot.media.e2e-harness.ts @@ -56,12 +56,7 @@ const apiStub: ApiStub = { setMyCommands: vi.fn(async () => undefined), }; -beforeEach(() => { - resetInboundDedupe(); - resetSaveMediaBufferMock(); -}); - -vi.mock("grammy", () => ({ +export const telegramBotRuntimeForTest = { Bot: class { api = apiStub; use = middlewareUseSpy; @@ -71,20 +66,25 @@ vi.mock("grammy", () => ({ catch = vi.fn(); constructor(public token: string) {} }, - InputFile: class {}, - webhookCallback: vi.fn(), -})); - -vi.mock("@grammyjs/runner", () => ({ sequentialize: () => vi.fn(), -})); + apiThrottler: () => throttlerSpy(), + loadConfig: () => ({ + channels: { telegram: { dmPolicy: "open", allowFrom: ["*"] } }, + }), +}; + +beforeEach(() => { + resetInboundDedupe(); + resetSaveMediaBufferMock(); +}); const throttlerSpy = vi.fn(() => "throttler"); -vi.mock("@grammyjs/transformer-throttler", () => ({ - apiThrottler: () => throttlerSpy(), + +vi.doMock("./bot.runtime.js", () => ({ + ...telegramBotRuntimeForTest, })); -vi.mock("undici", async (importOriginal) => { +vi.doMock("undici", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, @@ -92,7 +92,7 @@ vi.mock("undici", async (importOriginal) => { }; }); -vi.mock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => { +vi.doMock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => { const actual = await importOriginal(); const mockModule = Object.create(null) as Record; Object.defineProperties(mockModule, Object.getOwnPropertyDescriptors(actual)); @@ -105,7 +105,7 @@ vi.mock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => { return mockModule; }); -vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { +vi.doMock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, @@ -115,7 +115,7 @@ vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { }; }); -vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { +vi.doMock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, @@ -123,7 +123,7 @@ vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { }; }); -vi.mock("openclaw/plugin-sdk/conversation-runtime", () => ({ +vi.doMock("openclaw/plugin-sdk/conversation-runtime", () => ({ readChannelAllowFromStore: vi.fn(async () => [] as string[]), upsertChannelPairingRequest: vi.fn(async () => ({ code: "PAIRCODE", @@ -131,7 +131,7 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", () => ({ })), })); -vi.mock("openclaw/plugin-sdk/reply-runtime", () => { +vi.doMock("openclaw/plugin-sdk/reply-runtime", () => { const replySpy = vi.fn(async (_ctx, opts) => { await opts?.onReplyStart?.(); return undefined; diff --git a/extensions/telegram/src/bot.media.test-utils.ts b/extensions/telegram/src/bot.media.test-utils.ts index 3fee9271e3e..1324980a941 100644 --- a/extensions/telegram/src/bot.media.test-utils.ts +++ b/extensions/telegram/src/bot.media.test-utils.ts @@ -1,6 +1,5 @@ import * as ssrf from "openclaw/plugin-sdk/infra-runtime"; import { afterEach, beforeAll, beforeEach, expect, vi, type Mock } from "vitest"; -import { onSpy, sendChatActionSpy } from "./bot.media.e2e-harness.js"; type StickerSpy = Mock<(...args: unknown[]) => unknown>; @@ -21,6 +20,8 @@ const TELEGRAM_BOT_IMPORT_TIMEOUT_MS = process.platform === "win32" ? 180_000 : let createTelegramBotRef: typeof import("./bot.js").createTelegramBot; let replySpyRef: ReturnType; +let onSpyRef: Mock; +let sendChatActionSpyRef: Mock; export async function createBotHandler(): Promise<{ handler: (ctx: Record) => Promise; @@ -39,9 +40,9 @@ export async function createBotHandlerWithOptions(options: { replySpy: ReturnType; runtimeError: ReturnType; }> { - onSpy.mockClear(); + onSpyRef.mockClear(); replySpyRef.mockClear(); - sendChatActionSpy.mockClear(); + sendChatActionSpyRef.mockClear(); const runtimeError = options.runtimeError ?? vi.fn(); const runtimeLog = options.runtimeLog ?? vi.fn(); @@ -57,7 +58,7 @@ export async function createBotHandlerWithOptions(options: { }, }, }); - const handler = onSpy.mock.calls.find((call) => call[0] === "message")?.[1] as ( + const handler = onSpyRef.mock.calls.find((call) => call[0] === "message")?.[1] as ( ctx: Record, ) => Promise; expect(handler).toBeDefined(); @@ -102,7 +103,12 @@ afterEach(() => { }); beforeAll(async () => { - ({ createTelegramBot: createTelegramBotRef } = await import("./bot.js")); + const harness = await import("./bot.media.e2e-harness.js"); + onSpyRef = harness.onSpy; + sendChatActionSpyRef = harness.sendChatActionSpy; + const botModule = await import("./bot.js"); + botModule.setTelegramBotRuntimeForTest(harness.telegramBotRuntimeForTest); + ({ createTelegramBot: createTelegramBotRef } = botModule); const replyModule = await import("openclaw/plugin-sdk/reply-runtime"); replySpyRef = (replyModule as unknown as { __replySpy: ReturnType }).__replySpy; }, TELEGRAM_BOT_IMPORT_TIMEOUT_MS);