test: align extension seam mocks
Regeneration-Prompt: | Clean up extension tests that still mocked old src/** internals after the plugin-sdk/runtime seam refactors. Inspect the production imports first, then update only the tests whose mocked dependency no longer matches the live seam. Keep the change test-only, prefer mocking openclaw/plugin-sdk/* entry points over core internals, and remove redundant dead mocks where the seam mock already covers the behavior. Validate with targeted vitest runs for the touched Telegram, Slack, Discord, WhatsApp, and Feishu tests.
This commit is contained in:
parent
5408a3d1a4
commit
c6433f8de4
@ -4,16 +4,16 @@ import { sendWebhookMessageDiscord } from "./send.js";
|
||||
const recordChannelActivityMock = vi.hoisted(() => vi.fn());
|
||||
const loadConfigMock = vi.hoisted(() => vi.fn(() => ({ channels: { discord: {} } })));
|
||||
|
||||
vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/config.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => loadConfigMock(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/channel-activity.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/infra/channel-activity.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/infra-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/infra-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
recordChannelActivity: (...args: unknown[]) => recordChannelActivityMock(...args),
|
||||
|
||||
@ -64,13 +64,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
resolveByConversation: resolveBoundConversationMock,
|
||||
touch: touchBindingMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
function createLifecycleConfig(): ClawdbotConfig {
|
||||
return {
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
|
||||
@ -75,13 +75,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
resolveByConversation: resolveBoundConversationMock,
|
||||
touch: touchBindingMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
function createLifecycleConfig(): ClawdbotConfig {
|
||||
return {
|
||||
channels: {
|
||||
|
||||
@ -71,13 +71,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
resolveByConversation: resolveBoundConversationMock,
|
||||
touch: touchBindingMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
function createLifecycleConfig(): ClawdbotConfig {
|
||||
return {
|
||||
broadcast: {
|
||||
|
||||
@ -77,13 +77,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
resolveByConversation: resolveBoundConversationMock,
|
||||
touch: touchBindingMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
function createLifecycleConfig(): ClawdbotConfig {
|
||||
return {
|
||||
channels: {
|
||||
|
||||
@ -71,13 +71,6 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
resolveByConversation: resolveBoundConversationMock,
|
||||
touch: touchBindingMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
function createLifecycleConfig(): ClawdbotConfig {
|
||||
return {
|
||||
messages: {
|
||||
|
||||
@ -10,20 +10,20 @@ const dispatchPluginInteractiveHandlerMock = vi.fn(async () => ({
|
||||
const resolvePluginConversationBindingApprovalMock = vi.fn();
|
||||
const buildPluginBindingResolvedTextMock = vi.fn(() => "Binding updated.");
|
||||
|
||||
vi.mock("../../../../../src/infra/system-events.js", () => ({
|
||||
vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
|
||||
enqueueSystemEvent: (...args: unknown[]) =>
|
||||
(enqueueSystemEventMock as (...innerArgs: unknown[]) => unknown)(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../../src/plugins/interactive.js", () => ({
|
||||
vi.mock("openclaw/plugin-sdk/plugin-runtime", () => ({
|
||||
dispatchPluginInteractiveHandler: (...args: unknown[]) =>
|
||||
(dispatchPluginInteractiveHandlerMock as (...innerArgs: unknown[]) => unknown)(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../../src/plugins/conversation-binding.js", async () => {
|
||||
const actual = await vi.importActual<
|
||||
typeof import("../../../../../src/plugins/conversation-binding.js")
|
||||
>("../../../../../src/plugins/conversation-binding.js");
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/conversation-runtime")>(
|
||||
"openclaw/plugin-sdk/conversation-runtime",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
resolvePluginConversationBindingApproval: (...args: unknown[]) =>
|
||||
|
||||
@ -9,9 +9,8 @@ const hoisted = vi.hoisted(() => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import("../../../src/infra/outbound/session-binding-service.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/conversation-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
getSessionBindingService: () => ({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { loadConfig } from "../../../src/config/config.js";
|
||||
|
||||
const { defaultRouteConfig } = vi.hoisted(() => ({
|
||||
defaultRouteConfig: {
|
||||
@ -11,8 +11,8 @@ const { defaultRouteConfig } = vi.hoisted(() => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/config.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: vi.fn(() => defaultRouteConfig),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { ResolvedAgentRoute } from "../../../src/routing/resolve-route.js";
|
||||
import type { TelegramBotDeps } from "./bot-deps.js";
|
||||
import {
|
||||
@ -56,6 +56,11 @@ const replyMocks = vi.hoisted(() => ({
|
||||
const deliveryMocks = vi.hoisted(() => ({
|
||||
deliverReplies: vi.fn<DeliverRepliesFn>(async () => ({ delivered: true })),
|
||||
}));
|
||||
const pluginRuntimeMocks = vi.hoisted(() => ({
|
||||
getPluginCommandSpecs: vi.fn(() => []),
|
||||
matchPluginCommand: vi.fn(() => null),
|
||||
executePluginCommand: vi.fn(async () => ({ text: "ok" })),
|
||||
}));
|
||||
const sessionBindingMocks = vi.hoisted(() => ({
|
||||
resolveByConversation: vi.fn<
|
||||
(ref: unknown) => { bindingId: string; targetSessionKey: string } | null
|
||||
@ -123,28 +128,19 @@ vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
|
||||
listSkillCommandsForAgents: vi.fn(() => []),
|
||||
};
|
||||
});
|
||||
vi.mock("openclaw/plugin-sdk/plugin-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/plugin-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
getPluginCommandSpecs: pluginRuntimeMocks.getPluginCommandSpecs,
|
||||
matchPluginCommand: pluginRuntimeMocks.matchPluginCommand,
|
||||
executePluginCommand: pluginRuntimeMocks.executePluginCommand,
|
||||
};
|
||||
});
|
||||
vi.mock("../../../src/config/sessions.js", () => ({
|
||||
recordSessionMetaFromInbound: sessionMocks.recordSessionMetaFromInbound,
|
||||
resolveStorePath: sessionMocks.resolveStorePath,
|
||||
}));
|
||||
vi.mock("../../../src/pairing/pairing-store.js", () => ({
|
||||
readChannelAllowFromStore: vi.fn(async () => []),
|
||||
}));
|
||||
vi.mock("../../../src/infra/outbound/session-binding-service.js", () => ({
|
||||
getSessionBindingService: () => ({
|
||||
bind: vi.fn(),
|
||||
getCapabilities: vi.fn(),
|
||||
listBySession: vi.fn(),
|
||||
resolveByConversation: (ref: unknown) => sessionBindingMocks.resolveByConversation(ref),
|
||||
touch: (bindingId: string, at?: number) => sessionBindingMocks.touch(bindingId, at),
|
||||
unbind: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
vi.mock("../../../src/plugins/commands.js", () => ({
|
||||
getPluginCommandSpecs: vi.fn(() => []),
|
||||
matchPluginCommand: vi.fn(() => null),
|
||||
executePluginCommand: vi.fn(async () => ({ text: "ok" })),
|
||||
}));
|
||||
vi.mock("./bot/delivery.js", () => ({
|
||||
deliverReplies: deliveryMocks.deliverReplies,
|
||||
}));
|
||||
|
||||
@ -21,8 +21,8 @@ const { resolveTelegramFetch } = vi.hoisted(() => ({
|
||||
resolveTelegramFetch: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/config.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { getReplyFromConfig } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { HEARTBEAT_TOKEN } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { redactIdentifier } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { getReplyFromConfig } from "../../../../src/auto-reply/reply.js";
|
||||
import { HEARTBEAT_TOKEN } from "../../../../src/auto-reply/tokens.js";
|
||||
import { redactIdentifier } from "../../../../src/logging/redact-identifier.js";
|
||||
import type { sendMessageWhatsApp } from "../send.js";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
@ -22,78 +22,66 @@ const state = vi.hoisted(() => ({
|
||||
heartbeatWarnLogs: [] as string[],
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/agents/current-time.js", () => ({
|
||||
appendCronStyleCurrentTimeLine: (body: string) =>
|
||||
`${body}\nCurrent time: 2026-02-15T00:00:00Z (mock)`,
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/agent-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/agent-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
appendCronStyleCurrentTimeLine: (body: string) =>
|
||||
`${body}\nCurrent time: 2026-02-15T00:00:00Z (mock)`,
|
||||
};
|
||||
});
|
||||
|
||||
// Perf: this module otherwise pulls a large dependency graph that we don't need
|
||||
// for these unit tests.
|
||||
vi.mock("../../../../src/auto-reply/reply.js", () => ({
|
||||
getReplyFromConfig: vi.fn(async () => undefined),
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/reply-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
getReplyFromConfig: vi.fn(async () => undefined),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../../src/channels/plugins/whatsapp-heartbeat.js", () => ({
|
||||
resolveWhatsAppHeartbeatRecipients: () => [],
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/channel-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/channel-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveWhatsAppHeartbeatRecipients: () => [],
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../../src/config/config.js", () => ({
|
||||
loadConfig: () => ({ agents: { defaults: {} }, session: {} }),
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => ({ agents: { defaults: {} }, session: {} }),
|
||||
loadSessionStore: () => state.store,
|
||||
resolveSessionKey: () => "k",
|
||||
resolveStorePath: () => "/tmp/store.json",
|
||||
updateSessionStore: async (_path: string, updater: (store: typeof state.store) => void) => {
|
||||
updater(state.store);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../../src/routing/session-key.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../../src/routing/session-key.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/routing", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/routing")>();
|
||||
return {
|
||||
...actual,
|
||||
normalizeMainKey: () => null,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../../src/infra/heartbeat-visibility.js", () => ({
|
||||
resolveHeartbeatVisibility: () => state.visibility,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/config/sessions.js", () => ({
|
||||
loadSessionStore: () => state.store,
|
||||
resolveSessionKey: () => "k",
|
||||
resolveStorePath: () => "/tmp/store.json",
|
||||
updateSessionStore: async (_path: string, updater: (store: typeof state.store) => void) => {
|
||||
updater(state.store);
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./session-snapshot.js", () => ({
|
||||
getSessionSnapshot: () => state.snapshot,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/infra/heartbeat-events.js", () => ({
|
||||
emitHeartbeatEvent: (event: unknown) => state.events.push(event),
|
||||
resolveIndicatorType: (status: string) => `indicator:${status}`,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/logging.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../../src/logging.js")>();
|
||||
const createStubLogger = () => ({
|
||||
info: () => undefined,
|
||||
warn: () => undefined,
|
||||
error: () => undefined,
|
||||
child: createStubLogger,
|
||||
});
|
||||
vi.mock("openclaw/plugin-sdk/infra-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/infra-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
getChildLogger: () => ({
|
||||
info: (...args: unknown[]) => state.loggerInfoCalls.push(args),
|
||||
warn: (...args: unknown[]) => state.loggerWarnCalls.push(args),
|
||||
}),
|
||||
createSubsystemLogger: () => createStubLogger(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/state-paths", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/state-paths")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveOAuthDir: () => "/tmp/openclaw-oauth",
|
||||
resolveHeartbeatVisibility: () => state.visibility,
|
||||
emitHeartbeatEvent: (event: unknown) => state.events.push(event),
|
||||
resolveIndicatorType: (status: string) => `indicator:${status}`,
|
||||
};
|
||||
});
|
||||
|
||||
@ -108,10 +96,22 @@ vi.mock("openclaw/plugin-sdk/runtime-env", async (importOriginal) => {
|
||||
};
|
||||
return {
|
||||
...actual,
|
||||
getChildLogger: () => ({
|
||||
info: (...args: unknown[]) => state.loggerInfoCalls.push(args),
|
||||
warn: (...args: unknown[]) => state.loggerWarnCalls.push(args),
|
||||
}),
|
||||
createSubsystemLogger: () => logger,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/state-paths", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/state-paths")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveOAuthDir: () => "/tmp/openclaw-oauth",
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../auth-store.js", () => ({
|
||||
WA_WEB_AUTH_DIR: "/tmp/openclaw-oauth/whatsapp/default",
|
||||
resolveDefaultWebAuthDir: () => "/tmp/openclaw-oauth/whatsapp/default",
|
||||
|
||||
@ -4,12 +4,10 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const readAllowFromStoreMock = vi.fn().mockResolvedValue([]);
|
||||
const upsertPairingRequestMock = vi.fn().mockResolvedValue({ code: "PAIRCODE", created: true });
|
||||
const saveMediaBufferSpy = vi.fn();
|
||||
|
||||
vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/config.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: vi.fn().mockReturnValue({
|
||||
@ -26,17 +24,6 @@ vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/pairing/pairing-store.js", () => {
|
||||
return {
|
||||
readChannelAllowFromStore(...args: unknown[]) {
|
||||
return readAllowFromStoreMock(...args);
|
||||
},
|
||||
upsertChannelPairingRequest(...args: unknown[]) {
|
||||
return upsertPairingRequestMock(...args);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../src/media/store.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/media/store.js")>();
|
||||
return {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const recordChannelActivity = vi.fn();
|
||||
vi.mock("../../../../src/infra/channel-activity.js", () => ({
|
||||
vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
|
||||
recordChannelActivity: (...args: unknown[]) => recordChannelActivity(...args),
|
||||
}));
|
||||
|
||||
|
||||
@ -19,18 +19,22 @@ function resolveTestAuthDir() {
|
||||
|
||||
const authDir = resolveTestAuthDir();
|
||||
|
||||
vi.mock("../../../src/config/config.js", () => ({
|
||||
loadConfig: () =>
|
||||
({
|
||||
channels: {
|
||||
whatsapp: {
|
||||
accounts: {
|
||||
default: { enabled: true, authDir: resolveTestAuthDir() },
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () =>
|
||||
({
|
||||
channels: {
|
||||
whatsapp: {
|
||||
accounts: {
|
||||
default: { enabled: true, authDir: resolveTestAuthDir() },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as never,
|
||||
}));
|
||||
}) as never,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./session.js", () => {
|
||||
const authDir = resolveTestAuthDir();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user