diff --git a/src/cli/qr-dashboard.integration.test.ts b/src/cli/qr-dashboard.integration.test.ts index 8a063dfca72..bd0d7cfcc8a 100644 --- a/src/cli/qr-dashboard.integration.test.ts +++ b/src/cli/qr-dashboard.integration.test.ts @@ -104,6 +104,22 @@ async function loadCliModules() { for (const id of unmockedDependencyIds) { vi.doUnmock(id); } + vi.doMock("../config/config.js", async () => { + const actual = + await vi.importActual("../config/config.js"); + return { + ...actual, + loadConfig: loadConfigMock, + readConfigFileSnapshot: readConfigFileSnapshotMock, + resolveGatewayPort: resolveGatewayPortMock, + }; + }); + vi.doMock("../infra/clipboard.js", () => ({ + copyToClipboard: copyToClipboardMock, + })); + vi.doMock("../runtime.js", () => ({ + defaultRuntime: runtime, + })); ({ dashboardCommand } = await import("../commands/dashboard.js")); ({ registerQrCli } = await import("./qr-cli.js")); } @@ -119,10 +135,6 @@ describe("cli integration: qr + dashboard token SecretRef", () => { ]); }); - beforeAll(async () => { - await loadCliModules(); - }); - afterAll(() => { envSnapshot.restore(); vi.restoreAllMocks(); @@ -135,13 +147,14 @@ describe("cli integration: qr + dashboard token SecretRef", () => { vi.resetModules(); }); - beforeEach(() => { + beforeEach(async () => { runtimeLogs.length = 0; runtimeErrors.length = 0; vi.clearAllMocks(); delete process.env.OPENCLAW_GATEWAY_TOKEN; delete process.env.OPENCLAW_GATEWAY_PASSWORD; delete process.env.SHARED_GATEWAY_TOKEN; + await loadCliModules(); }); it("uses the same resolved token SecretRef for qr auth validation and dashboard commands", async () => { diff --git a/src/process/exec.test.ts b/src/process/exec.test.ts index febe67370fe..4c811203d50 100644 --- a/src/process/exec.test.ts +++ b/src/process/exec.test.ts @@ -3,25 +3,34 @@ import { EventEmitter } from "node:events"; import process from "node:process"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { OPENCLAW_CLI_ENV_VALUE } from "../infra/openclaw-exec-env.js"; -import { attachChildProcessBridge } from "./child-process-bridge.js"; -import { - resolveCommandEnv, - resolveProcessExitCode, - runCommandWithTimeout, - shouldSpawnWithShell, -} from "./exec.js"; + +let attachChildProcessBridge: typeof import("./child-process-bridge.js").attachChildProcessBridge; +let resolveCommandEnv: typeof import("./exec.js").resolveCommandEnv; +let resolveProcessExitCode: typeof import("./exec.js").resolveProcessExitCode; +let runCommandWithTimeout: typeof import("./exec.js").runCommandWithTimeout; +let shouldSpawnWithShell: typeof import("./exec.js").shouldSpawnWithShell; + +async function loadExecModules() { + vi.resetModules(); + vi.doUnmock("node:child_process"); + ({ attachChildProcessBridge } = await import("./child-process-bridge.js")); + ({ resolveCommandEnv, resolveProcessExitCode, runCommandWithTimeout, shouldSpawnWithShell } = + await import("./exec.js")); +} describe("runCommandWithTimeout", () => { function createSilentIdleArgv(): string[] { return [process.execPath, "-e", "setInterval(() => {}, 1_000)"]; } - beforeEach(() => { + beforeEach(async () => { vi.useRealTimers(); + await loadExecModules(); }); afterEach(() => { vi.useRealTimers(); + vi.doUnmock("node:child_process"); }); it("never enables shell execution (Windows cmd.exe injection hardening)", () => {