diff --git a/src/auto-reply/reply/route-reply.test.ts b/src/auto-reply/reply/route-reply.test.ts index e2eecad16a6..997e2bc4fa7 100644 --- a/src/auto-reply/reply/route-reply.test.ts +++ b/src/auto-reply/reply/route-reply.test.ts @@ -9,11 +9,8 @@ import { slackOutbound } from "../../channels/plugins/outbound/slack.js"; import { telegramOutbound } from "../../channels/plugins/outbound/telegram.js"; import { whatsappOutbound } from "../../channels/plugins/outbound/whatsapp.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; -import { - createIMessageTestPlugin, - createOutboundTestPlugin, - createTestRegistry, -} from "../../test-utils/channel-plugins.js"; +import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../../test-utils/imessage-test-plugin.js"; import { SILENT_REPLY_TOKEN } from "../tokens.js"; const mocks = vi.hoisted(() => ({ diff --git a/src/commands/channels.surfaces-signal-runtime-errors-channels-status-output.e2e.test.ts b/src/commands/channels.surfaces-signal-runtime-errors-channels-status-output.e2e.test.ts index 0b4af8bd3d4..64976f667fe 100644 --- a/src/commands/channels.surfaces-signal-runtime-errors-channels-status-output.e2e.test.ts +++ b/src/commands/channels.surfaces-signal-runtime-errors-channels-status-output.e2e.test.ts @@ -2,7 +2,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { RuntimeEnv } from "../runtime.js"; import { signalPlugin } from "../../extensions/signal/src/channel.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; -import { createIMessageTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js"; +import { createTestRegistry } from "../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../test-utils/imessage-test-plugin.js"; const configMocks = vi.hoisted(() => ({ readConfigFileSnapshot: vi.fn(), diff --git a/src/gateway/hooks.test.ts b/src/gateway/hooks.test.ts index b37bc621ac8..74141f78c4f 100644 --- a/src/gateway/hooks.test.ts +++ b/src/gateway/hooks.test.ts @@ -3,7 +3,8 @@ import { afterEach, beforeEach, describe, expect, test } from "vitest"; import type { ChannelPlugin } from "../channels/plugins/types.js"; import type { OpenClawConfig } from "../config/config.js"; import { setActivePluginRegistry } from "../plugins/runtime.js"; -import { createIMessageTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js"; +import { createTestRegistry } from "../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../test-utils/imessage-test-plugin.js"; import { extractHookToken, isHookAgentAllowed, diff --git a/src/infra/outbound/deliver.test.ts b/src/infra/outbound/deliver.test.ts index 3247149bec4..afe94f5bf49 100644 --- a/src/infra/outbound/deliver.test.ts +++ b/src/infra/outbound/deliver.test.ts @@ -5,11 +5,8 @@ import { telegramOutbound } from "../../channels/plugins/outbound/telegram.js"; import { whatsappOutbound } from "../../channels/plugins/outbound/whatsapp.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; import { markdownToSignalTextChunks } from "../../signal/format.js"; -import { - createIMessageTestPlugin, - createOutboundTestPlugin, - createTestRegistry, -} from "../../test-utils/channel-plugins.js"; +import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../../test-utils/imessage-test-plugin.js"; const mocks = vi.hoisted(() => ({ appendAssistantMessageToSessionTranscript: vi.fn(async () => ({ ok: true, sessionFile: "x" })), diff --git a/src/infra/outbound/message-action-runner.test.ts b/src/infra/outbound/message-action-runner.test.ts index 6b8bfd4ef79..28013c5764d 100644 --- a/src/infra/outbound/message-action-runner.test.ts +++ b/src/infra/outbound/message-action-runner.test.ts @@ -9,11 +9,8 @@ import { telegramPlugin } from "../../../extensions/telegram/src/channel.js"; import { whatsappPlugin } from "../../../extensions/whatsapp/src/channel.js"; import { jsonResult } from "../../agents/tools/common.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; -import { - createIMessageTestPlugin, - createOutboundTestPlugin, - createTestRegistry, -} from "../../test-utils/channel-plugins.js"; +import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../../test-utils/imessage-test-plugin.js"; import { loadWebMedia } from "../../web/media.js"; import { runMessageAction } from "./message-action-runner.js"; diff --git a/src/infra/outbound/message.e2e.test.ts b/src/infra/outbound/message.e2e.test.ts index c263a66a775..fa2dfea6ef5 100644 --- a/src/infra/outbound/message.e2e.test.ts +++ b/src/infra/outbound/message.e2e.test.ts @@ -1,7 +1,8 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { ChannelOutboundAdapter, ChannelPlugin } from "../../channels/plugins/types.js"; import { setActivePluginRegistry } from "../../plugins/runtime.js"; -import { createIMessageTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; +import { createTestRegistry } from "../../test-utils/channel-plugins.js"; +import { createIMessageTestPlugin } from "../../test-utils/imessage-test-plugin.js"; import { sendMessage, sendPoll } from "./message.js"; const setRegistry = (registry: ReturnType) => { diff --git a/src/memory/qmd-manager.test.ts b/src/memory/qmd-manager.test.ts index 11b622f7dae..b6354391d60 100644 --- a/src/memory/qmd-manager.test.ts +++ b/src/memory/qmd-manager.test.ts @@ -68,7 +68,13 @@ vi.mock("../logging/subsystem.js", () => ({ }, })); -vi.mock("node:child_process", () => ({ spawn: vi.fn() })); +vi.mock(import("node:child_process"), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + spawn: vi.fn(), + }; +}); import { spawn as mockedSpawn } from "node:child_process"; import type { OpenClawConfig } from "../config/config.js"; diff --git a/src/telegram/sticker-cache.test.ts b/src/telegram/sticker-cache.test.ts index 7d82c7651fe..0c9ac280406 100644 --- a/src/telegram/sticker-cache.test.ts +++ b/src/telegram/sticker-cache.test.ts @@ -10,9 +10,13 @@ import { } from "./sticker-cache.js"; // Mock the state directory to use a temp location -vi.mock("../config/paths.js", () => ({ - STATE_DIR: "/tmp/openclaw-test-sticker-cache", -})); +vi.mock("../config/paths.js", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + STATE_DIR: "/tmp/openclaw-test-sticker-cache", + }; +}); const TEST_CACHE_DIR = "/tmp/openclaw-test-sticker-cache/telegram"; const TEST_CACHE_FILE = path.join(TEST_CACHE_DIR, "sticker-cache.json"); diff --git a/src/test-utils/channel-plugins.ts b/src/test-utils/channel-plugins.ts index 783582b20de..f0ba062c94e 100644 --- a/src/test-utils/channel-plugins.ts +++ b/src/test-utils/channel-plugins.ts @@ -5,8 +5,6 @@ import type { ChannelPlugin, } from "../channels/plugins/types.js"; import type { PluginRegistry } from "../plugins/registry.js"; -import { imessageOutbound } from "../channels/plugins/outbound/imessage.js"; -import { normalizeIMessageHandle } from "../imessage/targets.js"; export const createTestRegistry = (channels: PluginRegistry["channels"] = []): PluginRegistry => ({ plugins: [], @@ -24,62 +22,6 @@ export const createTestRegistry = (channels: PluginRegistry["channels"] = []): P diagnostics: [], }); -export const createIMessageTestPlugin = (params?: { - outbound?: ChannelOutboundAdapter; -}): ChannelPlugin => ({ - id: "imessage", - meta: { - id: "imessage", - label: "iMessage", - selectionLabel: "iMessage (imsg)", - docsPath: "/channels/imessage", - blurb: "iMessage test stub.", - aliases: ["imsg"], - }, - capabilities: { chatTypes: ["direct", "group"], media: true }, - config: { - listAccountIds: () => [], - resolveAccount: () => ({}), - }, - status: { - collectStatusIssues: (accounts) => - accounts.flatMap((account) => { - const lastError = typeof account.lastError === "string" ? account.lastError.trim() : ""; - if (!lastError) { - return []; - } - return [ - { - channel: "imessage", - accountId: account.accountId, - kind: "runtime", - message: `Channel error: ${lastError}`, - }, - ]; - }), - }, - outbound: params?.outbound ?? imessageOutbound, - messaging: { - targetResolver: { - looksLikeId: (raw) => { - const trimmed = raw.trim(); - if (!trimmed) { - return false; - } - if (/^(imessage:|sms:|auto:|chat_id:|chat_guid:|chat_identifier:)/i.test(trimmed)) { - return true; - } - if (trimmed.includes("@")) { - return true; - } - return /^\+?\d{3,}$/.test(trimmed); - }, - hint: "", - }, - normalizeTarget: (raw) => normalizeIMessageHandle(raw), - }, -}); - export const createOutboundTestPlugin = (params: { id: ChannelId; outbound: ChannelOutboundAdapter; diff --git a/src/test-utils/imessage-test-plugin.ts b/src/test-utils/imessage-test-plugin.ts new file mode 100644 index 00000000000..0c02987edec --- /dev/null +++ b/src/test-utils/imessage-test-plugin.ts @@ -0,0 +1,59 @@ +import type { ChannelOutboundAdapter, ChannelPlugin } from "../channels/plugins/types.js"; +import { imessageOutbound } from "../channels/plugins/outbound/imessage.js"; +import { normalizeIMessageHandle } from "../imessage/targets.js"; + +export const createIMessageTestPlugin = (params?: { + outbound?: ChannelOutboundAdapter; +}): ChannelPlugin => ({ + id: "imessage", + meta: { + id: "imessage", + label: "iMessage", + selectionLabel: "iMessage (imsg)", + docsPath: "/channels/imessage", + blurb: "iMessage test stub.", + aliases: ["imsg"], + }, + capabilities: { chatTypes: ["direct", "group"], media: true }, + config: { + listAccountIds: () => [], + resolveAccount: () => ({}), + }, + status: { + collectStatusIssues: (accounts) => + accounts.flatMap((account) => { + const lastError = typeof account.lastError === "string" ? account.lastError.trim() : ""; + if (!lastError) { + return []; + } + return [ + { + channel: "imessage", + accountId: account.accountId, + kind: "runtime", + message: `Channel error: ${lastError}`, + }, + ]; + }), + }, + outbound: params?.outbound ?? imessageOutbound, + messaging: { + targetResolver: { + looksLikeId: (raw) => { + const trimmed = raw.trim(); + if (!trimmed) { + return false; + } + if (/^(imessage:|sms:|auto:|chat_id:|chat_guid:|chat_identifier:)/i.test(trimmed)) { + return true; + } + if (trimmed.includes("@")) { + return true; + } + return /^\+?\d{3,}$/.test(trimmed); + }, + hint: "", + }, + normalizeTarget: (raw) => normalizeIMessageHandle(raw), + }, +}); diff --git a/src/tts/tts.test.ts b/src/tts/tts.test.ts index 43389724b8a..a7fc0daec54 100644 --- a/src/tts/tts.test.ts +++ b/src/tts/tts.test.ts @@ -6,6 +6,9 @@ import * as tts from "./tts.js"; vi.mock("@mariozechner/pi-ai", () => ({ completeSimple: vi.fn(), + // Some auth helpers import oauth provider metadata at module load time. + getOAuthProviders: () => [], + getOAuthApiKey: vi.fn(async () => null), })); vi.mock("../agents/pi-embedded-runner/model.js", () => ({ diff --git a/vitest.unit.config.ts b/vitest.unit.config.ts index 541dd864e46..20f6abe6885 100644 --- a/vitest.unit.config.ts +++ b/vitest.unit.config.ts @@ -2,11 +2,9 @@ import { defineConfig } from "vitest/config"; import baseConfig from "./vitest.config.ts"; const baseTest = (baseConfig as { test?: { include?: string[]; exclude?: string[] } }).test ?? {}; -const include = baseTest.include ?? [ - "src/**/*.test.ts", - "extensions/**/*.test.ts", - "test/format-error.test.ts", -]; +const include = ( + baseTest.include ?? ["src/**/*.test.ts", "extensions/**/*.test.ts", "test/format-error.test.ts"] +).filter((pattern) => !pattern.includes("extensions/")); const exclude = baseTest.exclude ?? []; export default defineConfig({