test: speed up command runtime suites

This commit is contained in:
Peter Steinberger
2026-03-24 17:14:43 +00:00
parent 6e20c26397
commit cc9d1103d9
6 changed files with 35 additions and 97 deletions

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { ReplyPayload } from "../auto-reply/types.js";
import type { CliDeps } from "../cli/deps.js";
import type { OpenClawConfig } from "../config/config.js";
@@ -32,28 +32,12 @@ vi.mock("../infra/outbound/targets.js", async () => {
let deliverAgentCommandResult: typeof import("./agent/delivery.js").deliverAgentCommandResult;
async function loadFreshAgentDeliveryModuleForTest() {
vi.resetModules();
vi.doMock("../channels/plugins/index.js", () => ({
getChannelPlugin: mocks.getChannelPlugin,
normalizeChannelId: (value: string) => value,
}));
vi.doMock("../infra/outbound/deliver.js", () => ({
deliverOutboundPayloads: mocks.deliverOutboundPayloads,
}));
vi.doMock("../infra/outbound/targets.js", async () => {
const actual = await vi.importActual<typeof import("../infra/outbound/targets.js")>(
"../infra/outbound/targets.js",
);
return {
...actual,
resolveOutboundTarget: mocks.resolveOutboundTarget,
};
});
return await import("./agent/delivery.js");
}
describe("deliverAgentCommandResult", () => {
beforeAll(async () => {
vi.resetModules();
({ deliverAgentCommandResult } = await import("./agent/delivery.js"));
});
function createRuntime(): RuntimeEnv {
return {
log: vi.fn(),
@@ -100,11 +84,9 @@ describe("deliverAgentCommandResult", () => {
return { runtime };
}
beforeEach(async () => {
beforeEach(() => {
mocks.deliverOutboundPayloads.mockClear();
mocks.resolveOutboundTarget.mockClear();
({ deliverAgentCommandResult } = await loadFreshAgentDeliveryModuleForTest());
});
it("prefers explicit accountId for outbound delivery", async () => {

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
const mocks = vi.hoisted(() => ({
@@ -24,11 +24,6 @@ vi.mock("../../agents/agent-scope.js", () => ({
let resolveSessionKeyForRequest: typeof import("./session.js").resolveSessionKeyForRequest;
async function loadFreshSessionModuleForTest() {
vi.resetModules();
({ resolveSessionKeyForRequest } = await import("./session.js"));
}
describe("resolveSessionKeyForRequest", () => {
const MAIN_STORE_PATH = "/tmp/main-store.json";
const MYBOT_STORE_PATH = "/tmp/mybot-store.json";
@@ -51,8 +46,12 @@ describe("resolveSessionKeyForRequest", () => {
mocks.loadSessionStore.mockImplementation((storePath: string) => stores[storePath] ?? {});
};
beforeEach(async () => {
await loadFreshSessionModuleForTest();
beforeAll(async () => {
vi.resetModules();
({ resolveSessionKeyForRequest } = await import("./session.js"));
});
beforeEach(() => {
vi.clearAllMocks();
mocks.listAgentIds.mockReturnValue(["main"]);
});

View File

@@ -2,6 +2,7 @@ import { matrixPlugin, setMatrixRuntime } from "../../extensions/matrix/index.js
import { msteamsPlugin } from "../../extensions/msteams/index.js";
import { nostrPlugin } from "../../extensions/nostr/index.js";
import { tlonPlugin } from "../../extensions/tlon/index.js";
import { whatsappPlugin } from "../../extensions/whatsapp/index.js";
import { bundledChannelPlugins } from "../channels/plugins/bundled.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { createTestRegistry } from "../test-utils/channel-plugins.js";
@@ -40,6 +41,7 @@ export function setDefaultChannelPluginRegistryForTests(): void {
msteamsPlugin,
nostrPlugin,
tlonPlugin,
whatsappPlugin,
].map((plugin) => ({
pluginId: plugin.id,
plugin,

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn());
const resolveGatewayPortMock = vi.hoisted(() => vi.fn());
@@ -31,27 +31,6 @@ vi.mock("../secrets/resolve.js", () => ({
let dashboardCommand: typeof import("./dashboard.js").dashboardCommand;
async function loadFreshDashboardModuleForTest() {
vi.resetModules();
vi.doMock("../config/config.js", () => ({
readConfigFileSnapshot: readConfigFileSnapshotMock,
resolveGatewayPort: resolveGatewayPortMock,
}));
vi.doMock("./onboard-helpers.js", () => ({
resolveControlUiLinks: resolveControlUiLinksMock,
detectBrowserOpenSupport: detectBrowserOpenSupportMock,
openUrl: openUrlMock,
formatControlUiSshHint: formatControlUiSshHintMock,
}));
vi.doMock("../infra/clipboard.js", () => ({
copyToClipboard: copyToClipboardMock,
}));
vi.doMock("../secrets/resolve.js", () => ({
resolveSecretRefValues: resolveSecretRefValuesMock,
}));
return await import("./dashboard.js");
}
const runtime = {
log: vi.fn(),
error: vi.fn(),
@@ -84,7 +63,12 @@ function mockSnapshot(token: unknown = "abc") {
}
describe("dashboardCommand", () => {
beforeEach(async () => {
beforeAll(async () => {
vi.resetModules();
({ dashboardCommand } = await import("./dashboard.js"));
});
beforeEach(() => {
resetRuntime();
readConfigFileSnapshotMock.mockClear();
resolveGatewayPortMock.mockClear();
@@ -95,7 +79,6 @@ describe("dashboardCommand", () => {
copyToClipboardMock.mockClear();
delete process.env.OPENCLAW_GATEWAY_TOKEN;
delete process.env.CUSTOM_GATEWAY_TOKEN;
({ dashboardCommand } = await loadFreshDashboardModuleForTest());
});
it("opens and copies the dashboard link by default", async () => {

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { ChannelPlugin as TelegramChannelPlugin } from "../../extensions/telegram/runtime-api.js";
import type { HealthSummary } from "./health.js";
@@ -168,7 +168,7 @@ function createTelegramHealthPlugin(): Pick<
}
describe("getHealthSnapshot", () => {
beforeEach(async () => {
beforeAll(async () => {
({
buildTokenChannelStatusSummary,
probeTelegram,
@@ -180,6 +180,9 @@ describe("getHealthSnapshot", () => {
createTestRegistry,
getHealthSnapshot,
} = await loadFreshHealthModulesForTest());
});
beforeEach(() => {
setActivePluginRegistry(
createTestRegistry([
{ pluginId: "telegram", plugin: createTelegramHealthPlugin(), source: "test" },

View File

@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type {
ChannelMessageActionAdapter,
ChannelOutboundAdapter,
@@ -72,45 +72,15 @@ vi.mock("../../extensions/whatsapp/runtime-api.js", () => ({
let messageCommand: typeof import("./message.js").messageCommand;
async function loadFreshMessageCommandModuleForTest() {
vi.resetModules();
vi.doMock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../config/config.js")>();
return {
...actual,
loadConfig: () => testConfig,
};
});
vi.doMock("../cli/command-secret-gateway.js", () => ({
resolveCommandSecretRefsViaGateway,
}));
vi.doMock("../gateway/call.js", () => ({
callGateway: callGatewayMock,
callGatewayLeastPrivilege: callGatewayMock,
randomIdempotencyKey: () => "idem-1",
}));
vi.doMock("../../extensions/whatsapp/src/session.js", () => ({
webAuthExists,
}));
vi.doMock("../../extensions/discord/src/actions/runtime.js", () => ({
handleDiscordAction,
}));
vi.doMock("../../extensions/slack/runtime-api.js", () => ({
handleSlackAction,
}));
vi.doMock("../../extensions/telegram/src/action-runtime.js", () => ({
handleTelegramAction,
}));
vi.doMock("../../extensions/whatsapp/runtime-api.js", () => ({
handleWhatsAppAction,
}));
({ messageCommand } = await import("./message.js"));
}
let envSnapshot: ReturnType<typeof captureEnv>;
const EMPTY_TEST_REGISTRY = createTestRegistry([]);
beforeEach(async () => {
beforeAll(async () => {
vi.resetModules();
({ messageCommand } = await import("./message.js"));
});
beforeEach(() => {
envSnapshot = captureEnv(["TELEGRAM_BOT_TOKEN", "DISCORD_BOT_TOKEN"]);
process.env.TELEGRAM_BOT_TOKEN = "";
process.env.DISCORD_BOT_TOKEN = "";
@@ -123,7 +93,6 @@ beforeEach(async () => {
handleTelegramAction.mockClear();
handleWhatsAppAction.mockClear();
resolveCommandSecretRefsViaGateway.mockClear();
await loadFreshMessageCommandModuleForTest();
});
afterEach(() => {