import type { MockFn } from "openclaw/plugin-sdk/testing"; import { beforeEach, vi } from "vitest"; const { botApi, botCtorSpy } = vi.hoisted(() => ({ botApi: { deleteMessage: vi.fn(), editForumTopic: vi.fn(), editMessageText: vi.fn(), editMessageReplyMarkup: vi.fn(), pinChatMessage: vi.fn(), sendChatAction: vi.fn(), sendMessage: vi.fn(), sendPoll: vi.fn(), sendPhoto: vi.fn(), sendVoice: vi.fn(), sendAudio: vi.fn(), sendVideo: vi.fn(), sendVideoNote: vi.fn(), sendAnimation: vi.fn(), setMessageReaction: vi.fn(), sendSticker: vi.fn(), unpinChatMessage: vi.fn(), }, botCtorSpy: vi.fn(), })); const { loadWebMedia } = vi.hoisted(() => ({ loadWebMedia: vi.fn(), })); const { imageMetadata } = vi.hoisted(() => ({ imageMetadata: { width: 1200 as number | undefined, height: 800 as number | undefined, }, })); const { loadConfig } = vi.hoisted(() => ({ loadConfig: vi.fn(() => ({})), })); const { maybePersistResolvedTelegramTarget } = vi.hoisted(() => ({ maybePersistResolvedTelegramTarget: vi.fn(async () => {}), })); const { undiciFetch, undiciSetGlobalDispatcher, undiciAgentCtor, undiciEnvHttpProxyAgentCtor, undiciProxyAgentCtor, } = vi.hoisted(() => ({ undiciFetch: vi.fn(), undiciSetGlobalDispatcher: vi.fn(), undiciAgentCtor: vi.fn(function MockAgent( this: { options?: Record }, options?: Record, ) { this.options = options; }), undiciEnvHttpProxyAgentCtor: vi.fn(function MockEnvHttpProxyAgent( this: { options?: Record }, options?: Record, ) { this.options = options; }), undiciProxyAgentCtor: vi.fn(function MockProxyAgent( this: { options?: Record | string }, options?: Record | string, ) { this.options = options; }), })); type TelegramSendTestMocks = { botApi: Record; botCtorSpy: MockFn; loadConfig: MockFn; loadWebMedia: MockFn; maybePersistResolvedTelegramTarget: MockFn; imageMetadata: { width: number | undefined; height: number | undefined }; }; vi.mock("openclaw/plugin-sdk/web-media", () => ({ loadWebMedia, })); vi.mock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, getImageMetadata: vi.fn(async () => ({ ...imageMetadata })), }; }); vi.mock("grammy", () => ({ API_CONSTANTS: { DEFAULT_UPDATE_TYPES: ["message"], ALL_UPDATE_TYPES: ["message"], }, Bot: class { api = botApi; catch = vi.fn(); constructor( public token: string, public options?: { client?: { fetch?: typeof fetch; timeoutSeconds?: number }; }, ) { botCtorSpy(token, options); } }, HttpError: class HttpError extends Error { constructor( message = "HttpError", public error?: unknown, ) { super(message); } }, GrammyError: class GrammyError extends Error { description = ""; }, InputFile: class {}, })); vi.mock("undici", () => ({ Agent: undiciAgentCtor, EnvHttpProxyAgent: undiciEnvHttpProxyAgentCtor, ProxyAgent: undiciProxyAgentCtor, fetch: undiciFetch, setGlobalDispatcher: undiciSetGlobalDispatcher, })); vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, loadConfig, }; }); vi.mock("./target-writeback.js", () => ({ maybePersistResolvedTelegramTarget, })); export function getTelegramSendTestMocks(): TelegramSendTestMocks { return { botApi, botCtorSpy, loadConfig, loadWebMedia, maybePersistResolvedTelegramTarget, imageMetadata, }; } export function installTelegramSendTestHooks() { beforeEach(() => { loadConfig.mockReturnValue({}); loadWebMedia.mockReset(); imageMetadata.width = 1200; imageMetadata.height = 800; maybePersistResolvedTelegramTarget.mockReset(); maybePersistResolvedTelegramTarget.mockResolvedValue(undefined); undiciFetch.mockReset(); undiciSetGlobalDispatcher.mockReset(); undiciAgentCtor.mockClear(); undiciEnvHttpProxyAgentCtor.mockClear(); undiciProxyAgentCtor.mockClear(); botCtorSpy.mockReset(); for (const fn of Object.values(botApi)) { fn.mockReset(); } }); } export async function importTelegramSendModule() { vi.resetModules(); return await import("./send.js"); }