File size: 2,682 Bytes
eb3f11e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import { Command } from "commander";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { CliGatewayStateDirOutcome } from "../state-dir-gateway-check.js";
const mocks = vi.hoisted(() => ({
action: vi.fn(),
check: vi.fn<() => Promise<CliGatewayStateDirOutcome>>(async () => ({ kind: "allow" })),
debug: vi.fn(),
log: vi.fn(),
ensureBootstrap: vi.fn(async () => {}),
}));
vi.mock("../state-dir-gateway-check.js", () => ({ checkCliGatewayStateDir: mocks.check }));
vi.mock("../../logger.js", () => ({ logDebug: mocks.debug }));
vi.mock("../../runtime.js", () => ({
defaultRuntime: {
log: mocks.log,
error: vi.fn(),
writeStdout: vi.fn(),
writeJson: vi.fn(),
exit: vi.fn(),
},
}));
vi.mock("../command-execution-startup.js", () => ({
applyCliExecutionStartupPresentation: vi.fn(async () => {}),
ensureCliExecutionBootstrap: mocks.ensureBootstrap,
}));
let program: Command;
let originalArgv: string[];
beforeAll(async () => {
const { registerPreActionHooks } = await import("./preaction.js");
program = new Command().name("openclaw");
program.command("configure").action(mocks.action);
registerPreActionHooks(program, "test");
});
beforeEach(() => {
originalArgv = [...process.argv];
vi.clearAllMocks();
process.argv = ["node", "openclaw", "configure"];
});
afterEach(() => {
process.argv = originalArgv;
});
describe("state-store preAction guard", () => {
it("refuses before bootstrap and action", async () => {
mocks.check.mockResolvedValueOnce({ kind: "refuse", message: "state stores differ" });
await expect(program.parseAsync(process.argv)).rejects.toThrow("state stores differ");
expect(mocks.check).toHaveBeenCalledWith({ command: "openclaw configure" });
expect(mocks.ensureBootstrap).not.toHaveBeenCalled();
expect(mocks.action).not.toHaveBeenCalled();
});
it("allows the action when inspection fails", async () => {
mocks.check.mockRejectedValueOnce(new Error("inspection failed"));
await expect(program.parseAsync(process.argv)).resolves.toBe(program);
expect(mocks.debug).toHaveBeenCalledWith("state-store guard unavailable: inspection failed");
expect(mocks.action).toHaveBeenCalledOnce();
});
it("shows an unknown-path warning while allowing the action", async () => {
mocks.check.mockResolvedValueOnce({
kind: "warn",
message: "Service paths could not be verified.",
});
await expect(program.parseAsync(process.argv)).resolves.toBe(program);
expect(mocks.log).toHaveBeenCalledWith("Service paths could not be verified.");
expect(mocks.action).toHaveBeenCalledOnce();
});
});
|