mirror of https://github.com/openclaw/openclaw.git
refactor: reuse shared cli runtime test mocks
This commit is contained in:
parent
2e6f2b0f07
commit
54213b587f
|
|
@ -1,5 +1,8 @@
|
|||
import { Command } from "commander";
|
||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const { defaultRuntime: runtime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
const gatewayMocks = vi.hoisted(() => ({
|
||||
callGatewayFromCli: vi.fn(async () => ({
|
||||
|
|
@ -47,17 +50,6 @@ vi.mock("./browser-cli-shared.js", () => ({
|
|||
callBrowserRequest: sharedMocks.callBrowserRequest,
|
||||
}));
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
runtime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime: runtime,
|
||||
}));
|
||||
|
|
@ -91,6 +83,7 @@ describe("browser cli snapshot defaults", () => {
|
|||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,22 @@
|
|||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerBrowserManageCommands } from "./browser-cli-manage.js";
|
||||
import { createBrowserProgram } from "./browser-cli-test-helpers.js";
|
||||
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
|
||||
|
||||
function getRuntimeCapture(): CliRuntimeCapture {
|
||||
if (!runtimeState.capture) {
|
||||
throw new Error("runtime capture not initialized");
|
||||
}
|
||||
return runtimeState.capture;
|
||||
}
|
||||
|
||||
function getRuntime() {
|
||||
return getRuntimeCapture().defaultRuntime;
|
||||
}
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const runtimeLog = vi.fn();
|
||||
const runtimeError = vi.fn();
|
||||
const runtimeExit = vi.fn();
|
||||
return {
|
||||
callBrowserRequest: vi.fn<
|
||||
(
|
||||
|
|
@ -14,20 +25,6 @@ const mocks = vi.hoisted(() => {
|
|||
runtimeOpts?: { timeoutMs?: number },
|
||||
) => Promise<Record<string, unknown>>
|
||||
>(async () => ({})),
|
||||
runtimeLog,
|
||||
runtimeError,
|
||||
runtimeExit,
|
||||
runtime: {
|
||||
log: runtimeLog,
|
||||
error: runtimeError,
|
||||
writeStdout: vi.fn((value: string) =>
|
||||
runtimeLog(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
),
|
||||
writeJson: vi.fn((value: unknown, space = 2) =>
|
||||
runtimeLog(JSON.stringify(value, null, space)),
|
||||
),
|
||||
exit: runtimeExit,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -43,9 +40,11 @@ vi.mock("./cli-utils.js", () => ({
|
|||
) => await action().catch(onError),
|
||||
}));
|
||||
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime: mocks.runtime,
|
||||
}));
|
||||
vi.mock("../runtime.js", async () => {
|
||||
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
|
||||
runtimeState.capture ??= createCliRuntimeCapture();
|
||||
return { defaultRuntime: runtimeState.capture.defaultRuntime };
|
||||
});
|
||||
|
||||
function createProgram() {
|
||||
const { program, browser, parentOpts } = createBrowserProgram();
|
||||
|
|
@ -56,9 +55,7 @@ function createProgram() {
|
|||
describe("browser manage output", () => {
|
||||
beforeEach(() => {
|
||||
mocks.callBrowserRequest.mockClear();
|
||||
mocks.runtimeLog.mockClear();
|
||||
mocks.runtimeError.mockClear();
|
||||
mocks.runtimeExit.mockClear();
|
||||
getRuntimeCapture().resetRuntimeCapture();
|
||||
});
|
||||
|
||||
it("shows chrome-mcp transport for existing-session status without fake CDP fields", async () => {
|
||||
|
|
@ -91,7 +88,7 @@ describe("browser manage output", () => {
|
|||
from: "user",
|
||||
});
|
||||
|
||||
const output = mocks.runtimeLog.mock.calls.at(-1)?.[0] as string;
|
||||
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
|
||||
expect(output).toContain("transport: chrome-mcp");
|
||||
expect(output).not.toContain("cdpPort:");
|
||||
expect(output).not.toContain("cdpUrl:");
|
||||
|
|
@ -127,7 +124,7 @@ describe("browser manage output", () => {
|
|||
from: "user",
|
||||
});
|
||||
|
||||
const output = mocks.runtimeLog.mock.calls.at(-1)?.[0] as string;
|
||||
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
|
||||
expect(output).toContain(
|
||||
"userDataDir: /Users/test/Library/Application Support/BraveSoftware/Brave-Browser",
|
||||
);
|
||||
|
|
@ -158,7 +155,7 @@ describe("browser manage output", () => {
|
|||
const program = createProgram();
|
||||
await program.parseAsync(["browser", "profiles"], { from: "user" });
|
||||
|
||||
const output = mocks.runtimeLog.mock.calls.at(-1)?.[0] as string;
|
||||
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
|
||||
expect(output).toContain("chrome-live: running (2 tabs) [existing-session]");
|
||||
expect(output).toContain("transport: chrome-mcp");
|
||||
expect(output).not.toContain("port: 0");
|
||||
|
|
@ -186,7 +183,7 @@ describe("browser manage output", () => {
|
|||
{ from: "user" },
|
||||
);
|
||||
|
||||
const output = mocks.runtimeLog.mock.calls.at(-1)?.[0] as string;
|
||||
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
|
||||
expect(output).toContain('Created profile "chrome-live"');
|
||||
expect(output).toContain("transport: chrome-mcp");
|
||||
expect(output).not.toContain("port: 0");
|
||||
|
|
@ -223,7 +220,7 @@ describe("browser manage output", () => {
|
|||
from: "user",
|
||||
});
|
||||
|
||||
const output = mocks.runtimeLog.mock.calls.at(-1)?.[0] as string;
|
||||
const output = getRuntime().log.mock.calls.at(-1)?.[0] as string;
|
||||
expect(output).toContain("cdpUrl: https://example.com/chrome?token=supers…7890");
|
||||
expect(output).not.toContain("alice");
|
||||
expect(output).not.toContain("supersecretpasswordvalue1234");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerBrowserManageCommands } from "./browser-cli-manage.js";
|
||||
import { createBrowserProgram } from "./browser-cli-test-helpers.js";
|
||||
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
|
||||
|
||||
function getRuntimeCapture(): CliRuntimeCapture {
|
||||
if (!runtimeState.capture) {
|
||||
throw new Error("runtime capture not initialized");
|
||||
}
|
||||
return runtimeState.capture;
|
||||
}
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const runtimeLog = vi.fn();
|
||||
const runtimeError = vi.fn();
|
||||
const runtimeExit = vi.fn();
|
||||
return {
|
||||
callBrowserRequest: vi.fn(async (_opts: unknown, req: { path?: string }) =>
|
||||
req.path === "/"
|
||||
|
|
@ -22,20 +29,6 @@ const mocks = vi.hoisted(() => {
|
|||
}
|
||||
: {},
|
||||
),
|
||||
runtimeLog,
|
||||
runtimeError,
|
||||
runtimeExit,
|
||||
runtime: {
|
||||
log: runtimeLog,
|
||||
error: runtimeError,
|
||||
writeStdout: vi.fn((value: string) =>
|
||||
runtimeLog(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
),
|
||||
writeJson: vi.fn((value: unknown, space = 2) =>
|
||||
runtimeLog(JSON.stringify(value, null, space)),
|
||||
),
|
||||
exit: runtimeExit,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -51,9 +44,11 @@ vi.mock("./cli-utils.js", () => ({
|
|||
) => await action().catch(onError),
|
||||
}));
|
||||
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime: mocks.runtime,
|
||||
}));
|
||||
vi.mock("../runtime.js", async () => {
|
||||
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
|
||||
runtimeState.capture ??= createCliRuntimeCapture();
|
||||
return { defaultRuntime: runtimeState.capture.defaultRuntime };
|
||||
});
|
||||
|
||||
describe("browser manage start timeout option", () => {
|
||||
function createProgram() {
|
||||
|
|
@ -65,9 +60,7 @@ describe("browser manage start timeout option", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
mocks.callBrowserRequest.mockClear();
|
||||
mocks.runtimeLog.mockClear();
|
||||
mocks.runtimeError.mockClear();
|
||||
mocks.runtimeExit.mockClear();
|
||||
getRuntimeCapture().resetRuntimeCapture();
|
||||
});
|
||||
|
||||
it("uses parent --timeout for browser start instead of hardcoded 15s", async () => {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerBrowserStateCommands } from "./browser-cli-state.js";
|
||||
import { createBrowserProgram as createBrowserProgramShared } from "./browser-cli-test-helpers.js";
|
||||
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
|
||||
|
||||
function getRuntimeCapture(): CliRuntimeCapture {
|
||||
if (!runtimeState.capture) {
|
||||
throw new Error("runtime capture not initialized");
|
||||
}
|
||||
return runtimeState.capture;
|
||||
}
|
||||
|
||||
function getRuntime() {
|
||||
return getRuntimeCapture().defaultRuntime;
|
||||
}
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
callBrowserRequest: vi.fn(async (..._args: unknown[]) => ({ ok: true })),
|
||||
runBrowserResizeWithOutput: vi.fn(async (_params: unknown) => {}),
|
||||
runtime: {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
mocks.runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
mocks.runtime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./browser-cli-shared.js", () => ({
|
||||
|
|
@ -26,9 +29,11 @@ vi.mock("./browser-cli-resize.js", () => ({
|
|||
runBrowserResizeWithOutput: mocks.runBrowserResizeWithOutput,
|
||||
}));
|
||||
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime: mocks.runtime,
|
||||
}));
|
||||
vi.mock("../runtime.js", async () => {
|
||||
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
|
||||
runtimeState.capture ??= createCliRuntimeCapture();
|
||||
return { defaultRuntime: runtimeState.capture.defaultRuntime };
|
||||
});
|
||||
|
||||
describe("browser state option collisions", () => {
|
||||
const createStateProgram = ({ withGatewayUrl = false } = {}) => {
|
||||
|
|
@ -59,11 +64,8 @@ describe("browser state option collisions", () => {
|
|||
beforeEach(() => {
|
||||
mocks.callBrowserRequest.mockClear();
|
||||
mocks.runBrowserResizeWithOutput.mockClear();
|
||||
mocks.runtime.log.mockClear();
|
||||
mocks.runtime.error.mockClear();
|
||||
mocks.runtime.writeStdout.mockClear();
|
||||
mocks.runtime.writeJson.mockClear();
|
||||
mocks.runtime.exit.mockClear();
|
||||
getRuntimeCapture().resetRuntimeCapture();
|
||||
getRuntime().exit.mockImplementation(() => {});
|
||||
});
|
||||
|
||||
it("forwards parent-captured --target-id on `browser cookies set`", async () => {
|
||||
|
|
@ -143,37 +145,37 @@ describe("browser state option collisions", () => {
|
|||
await runBrowserCommand(["set", "offline", "maybe"]);
|
||||
|
||||
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
|
||||
expect(mocks.runtime.error).toHaveBeenCalledWith(expect.stringContaining("Expected on|off"));
|
||||
expect(mocks.runtime.exit).toHaveBeenCalledWith(1);
|
||||
expect(getRuntime().error).toHaveBeenCalledWith(expect.stringContaining("Expected on|off"));
|
||||
expect(getRuntime().exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("errors when set media receives an invalid value", async () => {
|
||||
await runBrowserCommand(["set", "media", "sepia"]);
|
||||
|
||||
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
|
||||
expect(mocks.runtime.error).toHaveBeenCalledWith(
|
||||
expect(getRuntime().error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Expected dark|light|none"),
|
||||
);
|
||||
expect(mocks.runtime.exit).toHaveBeenCalledWith(1);
|
||||
expect(getRuntime().exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("errors when headers JSON is missing", async () => {
|
||||
await runBrowserCommand(["set", "headers"]);
|
||||
|
||||
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
|
||||
expect(mocks.runtime.error).toHaveBeenCalledWith(
|
||||
expect(getRuntime().error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Missing headers JSON"),
|
||||
);
|
||||
expect(mocks.runtime.exit).toHaveBeenCalledWith(1);
|
||||
expect(getRuntime().exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it("errors when headers JSON is not an object", async () => {
|
||||
await runBrowserCommand(["set", "headers", "--json", "[]"]);
|
||||
|
||||
expect(mocks.callBrowserRequest).not.toHaveBeenCalled();
|
||||
expect(mocks.runtime.error).toHaveBeenCalledWith(
|
||||
expect(getRuntime().error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Headers JSON must be a JSON object"),
|
||||
);
|
||||
expect(mocks.runtime.exit).toHaveBeenCalledWith(1);
|
||||
expect(getRuntime().exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import { Command } from "commander";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const CRON_CLI_TEST_TIMEOUT_MS = 15_000;
|
||||
const { defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
const defaultGatewayMock = async (
|
||||
method: string,
|
||||
|
|
@ -25,24 +27,9 @@ vi.mock("./gateway-rpc.js", async () => {
|
|||
};
|
||||
});
|
||||
|
||||
vi.mock("../runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../runtime.js")>();
|
||||
const log = vi.fn();
|
||||
return {
|
||||
...actual,
|
||||
defaultRuntime: {
|
||||
...actual.defaultRuntime,
|
||||
log,
|
||||
error: vi.fn(),
|
||||
writeStdout: (value: string) => log(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
writeJson: (value: unknown, space = 2) =>
|
||||
log(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
||||
exit: (code: number) => {
|
||||
throw new Error(`__exit__:${code}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime,
|
||||
}));
|
||||
|
||||
const { registerCronCli } = await import("./cron-cli.js");
|
||||
|
||||
|
|
@ -85,6 +72,7 @@ function buildProgram() {
|
|||
function resetGatewayMock() {
|
||||
callGatewayFromCli.mockClear();
|
||||
callGatewayFromCli.mockImplementation(defaultGatewayMock);
|
||||
resetRuntimeCapture();
|
||||
}
|
||||
|
||||
async function runCronCommand(args: string[]): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import path from "node:path";
|
|||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { makeTempWorkspace } from "../../test-helpers/workspace.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
||||
|
||||
const runtimeLogs: string[] = [];
|
||||
const runtimeErrors: string[] = [];
|
||||
const { runtimeLogs, defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
const serviceMock = vi.hoisted(() => ({
|
||||
label: "Gateway",
|
||||
|
|
@ -24,24 +24,9 @@ vi.mock("../../daemon/service.js", () => ({
|
|||
resolveGatewayService: () => serviceMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../runtime.js")>();
|
||||
return {
|
||||
...actual,
|
||||
defaultRuntime: {
|
||||
...actual.defaultRuntime,
|
||||
log: (message: string) => runtimeLogs.push(message),
|
||||
error: (message: string) => runtimeErrors.push(message),
|
||||
writeStdout: (value: string) =>
|
||||
runtimeLogs.push(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
writeJson: (value: unknown, space = 2) =>
|
||||
runtimeLogs.push(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
||||
exit: (code: number) => {
|
||||
throw new Error(`__exit__:${code}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock("../../runtime.js", () => ({
|
||||
defaultRuntime,
|
||||
}));
|
||||
|
||||
const { runDaemonInstall } = await import("./install.js");
|
||||
const { clearConfigCache } = await import("../../config/config.js");
|
||||
|
|
@ -78,9 +63,8 @@ describe("runDaemonInstall integration", () => {
|
|||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
runtimeLogs.length = 0;
|
||||
runtimeErrors.length = 0;
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
// Keep these defined-but-empty so dotenv won't repopulate from local .env.
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = "";
|
||||
process.env.CLAWDBOT_GATEWAY_TOKEN = "";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { captureFullEnv } from "../../test-utils/env.js";
|
||||
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
||||
import type { DaemonActionResponse } from "./response.js";
|
||||
|
||||
const resolveNodeStartupTlsEnvironmentMock = vi.hoisted(() => vi.fn());
|
||||
|
|
@ -125,19 +126,9 @@ vi.mock("./response.js", () => ({
|
|||
installDaemonServiceAndEmit: installDaemonServiceAndEmitMock,
|
||||
}));
|
||||
|
||||
const runtimeLogs: string[] = [];
|
||||
const { defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
vi.mock("../../runtime.js", () => ({
|
||||
defaultRuntime: {
|
||||
log: (message: string) => runtimeLogs.push(message),
|
||||
writeStdout: (value: string) => {
|
||||
runtimeLogs.push(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
},
|
||||
writeJson: (value: unknown, space = 2) => {
|
||||
runtimeLogs.push(JSON.stringify(value, null, space));
|
||||
},
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
},
|
||||
defaultRuntime,
|
||||
}));
|
||||
|
||||
function expectFirstInstallPlanCallOmitsToken() {
|
||||
|
|
@ -176,7 +167,7 @@ describe("runDaemonInstall", () => {
|
|||
isGatewayDaemonRuntimeMock.mockReset();
|
||||
installDaemonServiceAndEmitMock.mockReset();
|
||||
service.isLoaded.mockReset();
|
||||
runtimeLogs.length = 0;
|
||||
resetRuntimeCapture();
|
||||
actionState.warnings.length = 0;
|
||||
actionState.emitted.length = 0;
|
||||
actionState.failed.length = 0;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { Command } from "commander";
|
||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const { defaultRuntime: runtime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
runtime.exit.mockImplementation(() => {});
|
||||
const callGateway = vi.fn();
|
||||
const buildGatewayConnectionDetails = vi.fn(() => ({
|
||||
url: "ws://127.0.0.1:18789",
|
||||
|
|
@ -11,18 +14,6 @@ const listDevicePairing = vi.fn();
|
|||
const approveDevicePairing = vi.fn();
|
||||
const summarizeDeviceTokens = vi.fn();
|
||||
const withProgress = vi.fn(async (_opts: unknown, fn: () => Promise<unknown>) => await fn());
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
runtime.log(JSON.stringify(value, null, space > 0 ? space : undefined));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
|
||||
vi.mock("../gateway/call.js", () => ({
|
||||
callGateway,
|
||||
buildGatewayConnectionDetails,
|
||||
|
|
@ -59,6 +50,11 @@ async function runDevicesCommand(argv: string[]) {
|
|||
await program.parseAsync(["devices", ...argv], { from: "user" });
|
||||
}
|
||||
|
||||
function readRuntimeCallText(call: unknown[] | undefined): string {
|
||||
const value = call?.[0];
|
||||
return typeof value === "string" ? value : "";
|
||||
}
|
||||
|
||||
describe("devices cli approve", () => {
|
||||
it("approves an explicit request id without listing", async () => {
|
||||
callGateway.mockResolvedValueOnce({ device: { deviceId: "device-1" } });
|
||||
|
|
@ -312,13 +308,14 @@ describe("devices cli list", () => {
|
|||
|
||||
await runDevicesCommand(["list"]);
|
||||
|
||||
const output = runtime.log.mock.calls.map((entry) => String(entry[0] ?? "")).join("\n");
|
||||
const output = runtime.log.mock.calls.map((entry) => readRuntimeCallText(entry)).join("\n");
|
||||
expect(output).toContain("Scopes");
|
||||
expect(output).toContain("operator.admin, operator.read");
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
resetRuntimeCapture();
|
||||
callGateway.mockClear();
|
||||
buildGatewayConnectionDetails.mockClear();
|
||||
buildGatewayConnectionDetails.mockReturnValue({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
import { Command } from "commander";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { registerDirectoryCli } from "./directory-cli.js";
|
||||
import type { CliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const runtimeState = vi.hoisted(() => ({ capture: null as CliRuntimeCapture | null }));
|
||||
|
||||
function getRuntimeCapture(): CliRuntimeCapture {
|
||||
if (!runtimeState.capture) {
|
||||
throw new Error("runtime capture not initialized");
|
||||
}
|
||||
return runtimeState.capture;
|
||||
}
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
loadConfig: vi.fn(),
|
||||
|
|
@ -9,9 +19,6 @@ const mocks = vi.hoisted(() => ({
|
|||
resolveMessageChannelSelection: vi.fn(),
|
||||
getChannelPlugin: vi.fn(),
|
||||
resolveChannelDefaultAccountId: vi.fn(),
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
|
|
@ -35,25 +42,16 @@ vi.mock("../channels/plugins/helpers.js", () => ({
|
|||
resolveChannelDefaultAccountId: mocks.resolveChannelDefaultAccountId,
|
||||
}));
|
||||
|
||||
vi.mock("../runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../runtime.js")>();
|
||||
return {
|
||||
...actual,
|
||||
defaultRuntime: {
|
||||
...actual.defaultRuntime,
|
||||
log: (...args: unknown[]) => mocks.log(...args),
|
||||
error: (...args: unknown[]) => mocks.error(...args),
|
||||
writeStdout: (value: string) => mocks.log(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
writeJson: (value: unknown, space = 2) =>
|
||||
mocks.log(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
||||
exit: (...args: unknown[]) => mocks.exit(...args),
|
||||
},
|
||||
};
|
||||
vi.mock("../runtime.js", async () => {
|
||||
const { createCliRuntimeCapture } = await import("./test-runtime-capture.js");
|
||||
runtimeState.capture ??= createCliRuntimeCapture();
|
||||
return { defaultRuntime: runtimeState.capture.defaultRuntime };
|
||||
});
|
||||
|
||||
describe("registerDirectoryCli", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
getRuntimeCapture().resetRuntimeCapture();
|
||||
mocks.loadConfig.mockReturnValue({ channels: {} });
|
||||
mocks.writeConfigFile.mockResolvedValue(undefined);
|
||||
mocks.resolveChannelDefaultAccountId.mockReturnValue("default");
|
||||
|
|
@ -62,8 +60,8 @@ describe("registerDirectoryCli", () => {
|
|||
configured: ["slack"],
|
||||
source: "explicit",
|
||||
});
|
||||
mocks.exit.mockImplementation((code?: number) => {
|
||||
throw new Error(`exit:${code ?? 0}`);
|
||||
getRuntimeCapture().defaultRuntime.exit.mockImplementation((code: number) => {
|
||||
throw new Error(`exit:${code}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -105,9 +103,9 @@ describe("registerDirectoryCli", () => {
|
|||
accountId: "default",
|
||||
}),
|
||||
);
|
||||
expect(mocks.log).toHaveBeenCalledWith(
|
||||
expect(getRuntimeCapture().defaultRuntime.log).toHaveBeenCalledWith(
|
||||
JSON.stringify({ id: "self-1", name: "Family Phone" }, null, 2),
|
||||
);
|
||||
expect(mocks.error).not.toHaveBeenCalled();
|
||||
expect(getRuntimeCapture().defaultRuntime.error).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,28 +4,15 @@ import path from "node:path";
|
|||
import { Command } from "commander";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { withTempHome } from "../config/home-env.test-harness.js";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const mockLog = vi.fn();
|
||||
const mockError = vi.fn();
|
||||
const mockExit = vi.fn((code: number) => {
|
||||
throw new Error(`__exit__:${code}`);
|
||||
});
|
||||
const { defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
const mockLog = defaultRuntime.log;
|
||||
const mockError = defaultRuntime.error;
|
||||
|
||||
vi.mock("../runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../runtime.js")>();
|
||||
return {
|
||||
...actual,
|
||||
defaultRuntime: {
|
||||
...actual.defaultRuntime,
|
||||
log: (...args: unknown[]) => mockLog(...args),
|
||||
error: (...args: unknown[]) => mockError(...args),
|
||||
writeStdout: (value: string) => mockLog(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
writeJson: (value: unknown, space = 2) =>
|
||||
mockLog(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
||||
exit: (code: number) => mockExit(code),
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime,
|
||||
}));
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
|
|
@ -52,6 +39,7 @@ describe("mcp cli", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Command } from "commander";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
||||
|
||||
const agentCliCommandMock = vi.fn();
|
||||
const agentsAddCommandMock = vi.fn();
|
||||
|
|
@ -12,17 +13,7 @@ const agentsUnbindCommandMock = vi.fn();
|
|||
const setVerboseMock = vi.fn();
|
||||
const createDefaultDepsMock = vi.fn(() => ({ deps: true }));
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
runtime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const { defaultRuntime: runtime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
vi.mock("../../commands/agent-via-gateway.js", () => ({
|
||||
agentCliCommand: agentCliCommandMock,
|
||||
|
|
@ -80,6 +71,8 @@ describe("registerAgentCommands", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
runtime.exit.mockImplementation(() => {});
|
||||
agentCliCommandMock.mockResolvedValue(undefined);
|
||||
agentsAddCommandMock.mockResolvedValue(undefined);
|
||||
agentsBindingsCommandMock.mockResolvedValue(undefined);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,11 @@
|
|||
import { Command } from "commander";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
||||
|
||||
const backupCreateCommand = vi.fn();
|
||||
const backupVerifyCommand = vi.fn();
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
runtime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const { defaultRuntime: runtime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
vi.mock("../../commands/backup.js", () => ({
|
||||
backupCreateCommand,
|
||||
|
|
@ -56,6 +47,7 @@ describe("registerBackupCommand", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
backupCreateCommand.mockResolvedValue(undefined);
|
||||
backupVerifyCommand.mockResolvedValue(undefined);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Command } from "commander";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createCliRuntimeCapture } from "../test-runtime-capture.js";
|
||||
|
||||
const statusCommand = vi.fn();
|
||||
const healthCommand = vi.fn();
|
||||
|
|
@ -7,17 +8,7 @@ const sessionsCommand = vi.fn();
|
|||
const sessionsCleanupCommand = vi.fn();
|
||||
const setVerbose = vi.fn();
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
runtime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const { defaultRuntime: runtime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
vi.mock("../../commands/status.js", () => ({
|
||||
statusCommand,
|
||||
|
|
@ -58,6 +49,8 @@ describe("registerStatusHealthSessionsCommands", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
runtime.exit.mockImplementation(() => {});
|
||||
statusCommand.mockResolvedValue(undefined);
|
||||
healthCommand.mockResolvedValue(undefined);
|
||||
sessionsCommand.mockResolvedValue(undefined);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,12 @@
|
|||
import { Command } from "commander";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { encodePairingSetupCode } from "../pairing/setup-code.js";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const runtimeCapture = createCliRuntimeCapture();
|
||||
const runtime = runtimeCapture.defaultRuntime;
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
runtime: {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
mocks.runtime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
mocks.runtime.log(JSON.stringify(value, null, space > 0 ? space : undefined));
|
||||
}),
|
||||
exit: vi.fn(() => {
|
||||
throw new Error("exit");
|
||||
}),
|
||||
},
|
||||
loadConfig: vi.fn(),
|
||||
runCommandWithTimeout: vi.fn(),
|
||||
resolveCommandSecretRefsViaGateway: vi.fn(async ({ config }: { config: unknown }) => ({
|
||||
|
|
@ -27,10 +18,7 @@ const mocks = vi.hoisted(() => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../runtime.js", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../runtime.js")>()),
|
||||
defaultRuntime: mocks.runtime,
|
||||
}));
|
||||
vi.mock("../runtime.js", () => ({ defaultRuntime: runtime }));
|
||||
vi.mock("../config/config.js", () => ({ loadConfig: mocks.loadConfig }));
|
||||
vi.mock("../process/exec.js", () => ({ runCommandWithTimeout: mocks.runCommandWithTimeout }));
|
||||
vi.mock("./command-secret-gateway.js", () => ({
|
||||
|
|
@ -48,7 +36,6 @@ vi.mock("qrcode-terminal", () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const runtime = mocks.runtime;
|
||||
const loadConfig = mocks.loadConfig;
|
||||
const runCommandWithTimeout = mocks.runCommandWithTimeout;
|
||||
const resolveCommandSecretRefsViaGateway = mocks.resolveCommandSecretRefsViaGateway;
|
||||
|
|
@ -135,8 +122,17 @@ describe("registerQrCli", () => {
|
|||
await expect(runQr(args)).rejects.toThrow("exit");
|
||||
}
|
||||
|
||||
function readRuntimeCallText(call: unknown[] | undefined): string {
|
||||
const value = call?.[0];
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
return value === undefined ? "" : JSON.stringify(value);
|
||||
}
|
||||
|
||||
function parseLastLoggedQrJson() {
|
||||
return JSON.parse(String(runtime.log.mock.calls.at(-1)?.[0] ?? "{}")) as {
|
||||
const raw = runtime.log.mock.calls.at(-1)?.[0];
|
||||
return JSON.parse(typeof raw === "string" ? raw : "{}") as {
|
||||
setupCode?: string;
|
||||
gatewayUrl?: string;
|
||||
auth?: string;
|
||||
|
|
@ -166,10 +162,14 @@ describe("registerQrCli", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
runtimeCapture.resetRuntimeCapture();
|
||||
vi.stubEnv("OPENCLAW_GATEWAY_TOKEN", "");
|
||||
vi.stubEnv("CLAWDBOT_GATEWAY_TOKEN", "");
|
||||
vi.stubEnv("OPENCLAW_GATEWAY_PASSWORD", "");
|
||||
vi.stubEnv("CLAWDBOT_GATEWAY_PASSWORD", "");
|
||||
runtime.exit.mockImplementation(() => {
|
||||
throw new Error("exit");
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -208,7 +208,7 @@ describe("registerQrCli", () => {
|
|||
await runQr([]);
|
||||
|
||||
expect(qrGenerate).toHaveBeenCalledTimes(1);
|
||||
const output = runtime.log.mock.calls.map((call) => String(call[0] ?? "")).join("\n");
|
||||
const output = runtime.log.mock.calls.map((call) => readRuntimeCallText(call)).join("\n");
|
||||
expect(output).toContain("Pairing QR");
|
||||
expect(output).toContain("ASCII-QR");
|
||||
expect(output).toContain("Gateway:");
|
||||
|
|
@ -316,7 +316,7 @@ describe("registerQrCli", () => {
|
|||
});
|
||||
|
||||
await expectQrExit(["--setup-code-only"]);
|
||||
const output = runtime.error.mock.calls.map((call) => String(call[0] ?? "")).join("\n");
|
||||
const output = runtime.error.mock.calls.map((call) => readRuntimeCallText(call)).join("\n");
|
||||
expect(output).toContain("gateway.auth.mode is unset");
|
||||
expect(resolveCommandSecretRefsViaGateway).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -331,7 +331,7 @@ describe("registerQrCli", () => {
|
|||
|
||||
await expectQrExit([]);
|
||||
|
||||
const output = runtime.error.mock.calls.map((call) => String(call[0] ?? "")).join("\n");
|
||||
const output = runtime.error.mock.calls.map((call) => readRuntimeCallText(call)).join("\n");
|
||||
expect(output).toContain("only bound to loopback");
|
||||
});
|
||||
|
||||
|
|
@ -363,7 +363,7 @@ describe("registerQrCli", () => {
|
|||
|
||||
expect(
|
||||
runtime.log.mock.calls.some((call) =>
|
||||
String(call[0] ?? "").includes("gateway.remote.token inactive"),
|
||||
readRuntimeCallText(call).includes("gateway.remote.token inactive"),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
|
@ -379,7 +379,7 @@ describe("registerQrCli", () => {
|
|||
|
||||
expect(
|
||||
runtime.error.mock.calls.some((call) =>
|
||||
String(call[0] ?? "").includes("gateway.remote.token inactive"),
|
||||
readRuntimeCallText(call).includes("gateway.remote.token inactive"),
|
||||
),
|
||||
).toBe(true);
|
||||
const expected = encodePairingSetupCode({
|
||||
|
|
@ -419,7 +419,7 @@ describe("registerQrCli", () => {
|
|||
expect(payload.gatewayUrl).toBe("wss://remote.example.com:444");
|
||||
expect(
|
||||
runtime.error.mock.calls.some((call) =>
|
||||
String(call[0] ?? "").includes("gateway.remote.password inactive"),
|
||||
readRuntimeCallText(call).includes("gateway.remote.password inactive"),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
|
@ -434,7 +434,7 @@ describe("registerQrCli", () => {
|
|||
});
|
||||
|
||||
await expectQrExit(["--remote"]);
|
||||
const output = runtime.error.mock.calls.map((call) => String(call[0] ?? "")).join("\n");
|
||||
const output = runtime.error.mock.calls.map((call) => readRuntimeCallText(call)).join("\n");
|
||||
expect(output).toContain("qr --remote requires");
|
||||
expect(resolveCommandSecretRefsViaGateway).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -461,7 +461,8 @@ describe("registerQrCli", () => {
|
|||
|
||||
await runQr(["--json", "--remote"]);
|
||||
|
||||
const payload = JSON.parse(String(runtime.log.mock.calls.at(-1)?.[0] ?? "{}")) as {
|
||||
const raw = runtime.log.mock.calls.at(-1)?.[0];
|
||||
const payload = JSON.parse(typeof raw === "string" ? raw : "{}") as {
|
||||
gatewayUrl?: string;
|
||||
auth?: string;
|
||||
urlSource?: string;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,13 @@
|
|||
import { Command } from "commander";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { runRegisteredCli } from "../test-utils/command-runner.js";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const updateCommand = vi.fn(async (_opts: unknown) => {});
|
||||
const updateStatusCommand = vi.fn(async (_opts: unknown) => {});
|
||||
const updateWizardCommand = vi.fn(async (_opts: unknown) => {});
|
||||
|
||||
const defaultRuntime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
writeStdout: vi.fn((value: string) => {
|
||||
defaultRuntime.log(value.endsWith("\n") ? value.slice(0, -1) : value);
|
||||
}),
|
||||
writeJson: vi.fn((value: unknown, space = 2) => {
|
||||
defaultRuntime.log(JSON.stringify(value, null, space));
|
||||
}),
|
||||
exit: vi.fn(),
|
||||
};
|
||||
const { defaultRuntime, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
vi.mock("./update-cli/update-command.js", () => ({
|
||||
updateCommand: (opts: unknown) => updateCommand(opts),
|
||||
|
|
@ -45,6 +36,7 @@ describe("update cli option collisions", () => {
|
|||
updateCommand.mockClear();
|
||||
updateStatusCommand.mockClear();
|
||||
updateWizardCommand.mockClear();
|
||||
resetRuntimeCapture();
|
||||
defaultRuntime.log.mockClear();
|
||||
defaultRuntime.error.mockClear();
|
||||
defaultRuntime.writeStdout.mockClear();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|||
import type { OpenClawConfig, ConfigFileSnapshot } from "../config/types.openclaw.js";
|
||||
import type { UpdateRunResult } from "../infra/update-runner.js";
|
||||
import { withEnvAsync } from "../test-utils/env.js";
|
||||
import { createCliRuntimeCapture } from "./test-runtime-capture.js";
|
||||
|
||||
const confirm = vi.fn();
|
||||
const select = vi.fn();
|
||||
|
|
@ -25,6 +26,7 @@ const formatPortDiagnostics = vi.fn();
|
|||
const pathExists = vi.fn();
|
||||
const syncPluginsForUpdateChannel = vi.fn();
|
||||
const updateNpmInstalledPlugins = vi.fn();
|
||||
const { defaultRuntime: runtimeCapture, resetRuntimeCapture } = createCliRuntimeCapture();
|
||||
|
||||
vi.mock("@clack/prompts", () => ({
|
||||
confirm,
|
||||
|
|
@ -129,22 +131,9 @@ vi.mock("./daemon-cli.js", () => ({
|
|||
}));
|
||||
|
||||
// Mock the runtime
|
||||
vi.mock("../runtime.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../runtime.js")>();
|
||||
const log = vi.fn();
|
||||
return {
|
||||
...actual,
|
||||
defaultRuntime: {
|
||||
...actual.defaultRuntime,
|
||||
log,
|
||||
error: vi.fn(),
|
||||
writeStdout: (value: string) => log(value.endsWith("\n") ? value.slice(0, -1) : value),
|
||||
writeJson: (value: unknown, space = 2) =>
|
||||
log(JSON.stringify(value, null, space > 0 ? space : undefined)),
|
||||
exit: vi.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock("../runtime.js", () => ({
|
||||
defaultRuntime: runtimeCapture,
|
||||
}));
|
||||
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { resolveOpenClawPackageRoot } = await import("../infra/openclaw-root.js");
|
||||
|
|
@ -298,6 +287,8 @@ describe("update-cli", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
resetRuntimeCapture();
|
||||
vi.mocked(defaultRuntime.exit).mockImplementation(() => {});
|
||||
vi.mocked(resolveOpenClawPackageRoot).mockResolvedValue(process.cwd());
|
||||
vi.mocked(readConfigFileSnapshot).mockResolvedValue(baseSnapshot);
|
||||
vi.mocked(fetchNpmTagVersion).mockResolvedValue({
|
||||
|
|
|
|||
Loading…
Reference in New Issue