test: dedupe and optimize test suites
This commit is contained in:
@@ -39,6 +39,18 @@ const testProgramContext: ProgramContext = {
|
||||
};
|
||||
|
||||
describe("command-registry", () => {
|
||||
const createProgram = () => new Command();
|
||||
|
||||
const withProcessArgv = async (argv: string[], run: () => Promise<void>) => {
|
||||
const prevArgv = process.argv;
|
||||
process.argv = argv;
|
||||
try {
|
||||
await run();
|
||||
} finally {
|
||||
process.argv = prevArgv;
|
||||
}
|
||||
};
|
||||
|
||||
it("includes both agent and agents in core CLI command names", () => {
|
||||
const names = getCoreCliCommandNames();
|
||||
expect(names).toContain("agent");
|
||||
@@ -46,7 +58,7 @@ describe("command-registry", () => {
|
||||
});
|
||||
|
||||
it("registerCoreCliByName resolves agents to the agent entry", async () => {
|
||||
const program = new Command();
|
||||
const program = createProgram();
|
||||
const found = await registerCoreCliByName(program, testProgramContext, "agents");
|
||||
expect(found).toBe(true);
|
||||
const agentsCmd = program.commands.find((c) => c.name() === "agents");
|
||||
@@ -57,20 +69,20 @@ describe("command-registry", () => {
|
||||
});
|
||||
|
||||
it("registerCoreCliByName returns false for unknown commands", async () => {
|
||||
const program = new Command();
|
||||
const program = createProgram();
|
||||
const found = await registerCoreCliByName(program, testProgramContext, "nonexistent");
|
||||
expect(found).toBe(false);
|
||||
});
|
||||
|
||||
it("registers doctor placeholder for doctor primary command", () => {
|
||||
const program = new Command();
|
||||
const program = createProgram();
|
||||
registerCoreCliCommands(program, testProgramContext, ["node", "openclaw", "doctor"]);
|
||||
|
||||
expect(program.commands.map((command) => command.name())).toEqual(["doctor"]);
|
||||
});
|
||||
|
||||
it("treats maintenance commands as top-level builtins", async () => {
|
||||
const program = new Command();
|
||||
const program = createProgram();
|
||||
|
||||
expect(await registerCoreCliByName(program, testProgramContext, "doctor")).toBe(true);
|
||||
|
||||
@@ -83,17 +95,12 @@ describe("command-registry", () => {
|
||||
});
|
||||
|
||||
it("registers grouped core entry placeholders without duplicate command errors", async () => {
|
||||
const program = new Command();
|
||||
const program = createProgram();
|
||||
registerCoreCliCommands(program, testProgramContext, ["node", "openclaw", "vitest"]);
|
||||
|
||||
const prevArgv = process.argv;
|
||||
process.argv = ["node", "openclaw", "status"];
|
||||
try {
|
||||
program.exitOverride();
|
||||
program.exitOverride();
|
||||
await withProcessArgv(["node", "openclaw", "status"], async () => {
|
||||
await program.parseAsync(["node", "openclaw", "status"]);
|
||||
} finally {
|
||||
process.argv = prevArgv;
|
||||
}
|
||||
});
|
||||
|
||||
const names = program.commands.map((command) => command.name());
|
||||
expect(names).toContain("status");
|
||||
|
||||
@@ -29,22 +29,30 @@ function makeRuntime() {
|
||||
}
|
||||
|
||||
describe("ensureConfigReady", () => {
|
||||
async function runEnsureConfigReady(commandPath: string[]) {
|
||||
vi.resetModules();
|
||||
const { ensureConfigReady } = await import("./config-guard.js");
|
||||
await ensureConfigReady({ runtime: makeRuntime() as never, commandPath });
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
readConfigFileSnapshotMock.mockResolvedValue(makeSnapshot());
|
||||
});
|
||||
|
||||
it("skips doctor flow for read-only fast path commands", async () => {
|
||||
vi.resetModules();
|
||||
const { ensureConfigReady } = await import("./config-guard.js");
|
||||
await ensureConfigReady({ runtime: makeRuntime() as never, commandPath: ["status"] });
|
||||
expect(loadAndMaybeMigrateDoctorConfigMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs doctor flow for commands that may mutate state", async () => {
|
||||
vi.resetModules();
|
||||
const { ensureConfigReady } = await import("./config-guard.js");
|
||||
await ensureConfigReady({ runtime: makeRuntime() as never, commandPath: ["message"] });
|
||||
expect(loadAndMaybeMigrateDoctorConfigMock).toHaveBeenCalledTimes(1);
|
||||
it.each([
|
||||
{
|
||||
name: "skips doctor flow for read-only fast path commands",
|
||||
commandPath: ["status"],
|
||||
expectedDoctorCalls: 0,
|
||||
},
|
||||
{
|
||||
name: "runs doctor flow for commands that may mutate state",
|
||||
commandPath: ["message"],
|
||||
expectedDoctorCalls: 1,
|
||||
},
|
||||
])("$name", async ({ commandPath, expectedDoctorCalls }) => {
|
||||
await runEnsureConfigReady(commandPath);
|
||||
expect(loadAndMaybeMigrateDoctorConfigMock).toHaveBeenCalledTimes(expectedDoctorCalls);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Command } from "commander";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const doctorCommand = vi.fn();
|
||||
const dashboardCommand = vi.fn();
|
||||
@@ -32,7 +32,19 @@ vi.mock("../../runtime.js", () => ({
|
||||
defaultRuntime: runtime,
|
||||
}));
|
||||
|
||||
let registerMaintenanceCommands: typeof import("./register.maintenance.js").registerMaintenanceCommands;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ registerMaintenanceCommands } = await import("./register.maintenance.js"));
|
||||
});
|
||||
|
||||
describe("registerMaintenanceCommands doctor action", () => {
|
||||
async function runMaintenanceCli(args: string[]) {
|
||||
const program = new Command();
|
||||
registerMaintenanceCommands(program);
|
||||
await program.parseAsync(args, { from: "user" });
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
@@ -40,11 +52,7 @@ describe("registerMaintenanceCommands doctor action", () => {
|
||||
it("exits with code 0 after successful doctor run", async () => {
|
||||
doctorCommand.mockResolvedValue(undefined);
|
||||
|
||||
const { registerMaintenanceCommands } = await import("./register.maintenance.js");
|
||||
const program = new Command();
|
||||
registerMaintenanceCommands(program);
|
||||
|
||||
await program.parseAsync(["doctor", "--non-interactive", "--yes"], { from: "user" });
|
||||
await runMaintenanceCli(["doctor", "--non-interactive", "--yes"]);
|
||||
|
||||
expect(doctorCommand).toHaveBeenCalledWith(
|
||||
runtime,
|
||||
@@ -59,11 +67,7 @@ describe("registerMaintenanceCommands doctor action", () => {
|
||||
it("exits with code 1 when doctor fails", async () => {
|
||||
doctorCommand.mockRejectedValue(new Error("doctor failed"));
|
||||
|
||||
const { registerMaintenanceCommands } = await import("./register.maintenance.js");
|
||||
const program = new Command();
|
||||
registerMaintenanceCommands(program);
|
||||
|
||||
await program.parseAsync(["doctor"], { from: "user" });
|
||||
await runMaintenanceCli(["doctor"]);
|
||||
|
||||
expect(runtime.error).toHaveBeenCalledWith("Error: doctor failed");
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1);
|
||||
|
||||
@@ -27,6 +27,16 @@ describe("registerSubCliCommands", () => {
|
||||
const originalArgv = process.argv;
|
||||
const originalEnv = { ...process.env };
|
||||
|
||||
const createRegisteredProgram = (argv: string[], name?: string) => {
|
||||
process.argv = argv;
|
||||
const program = new Command();
|
||||
if (name) {
|
||||
program.name(name);
|
||||
}
|
||||
registerSubCliCommands(program, process.argv);
|
||||
return program;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
process.env = { ...originalEnv };
|
||||
delete process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS;
|
||||
@@ -42,9 +52,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("registers only the primary placeholder and dispatches", async () => {
|
||||
process.argv = ["node", "openclaw", "acp"];
|
||||
const program = new Command();
|
||||
registerSubCliCommands(program, process.argv);
|
||||
const program = createRegisteredProgram(["node", "openclaw", "acp"]);
|
||||
|
||||
expect(program.commands.map((cmd) => cmd.name())).toEqual(["acp"]);
|
||||
|
||||
@@ -55,9 +63,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("registers placeholders for all subcommands when no primary", () => {
|
||||
process.argv = ["node", "openclaw"];
|
||||
const program = new Command();
|
||||
registerSubCliCommands(program, process.argv);
|
||||
const program = createRegisteredProgram(["node", "openclaw"]);
|
||||
|
||||
const names = program.commands.map((cmd) => cmd.name());
|
||||
expect(names).toContain("acp");
|
||||
@@ -67,10 +73,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("re-parses argv for lazy subcommands", async () => {
|
||||
process.argv = ["node", "openclaw", "nodes", "list"];
|
||||
const program = new Command();
|
||||
program.name("openclaw");
|
||||
registerSubCliCommands(program, process.argv);
|
||||
const program = createRegisteredProgram(["node", "openclaw", "nodes", "list"], "openclaw");
|
||||
|
||||
expect(program.commands.map((cmd) => cmd.name())).toEqual(["nodes"]);
|
||||
|
||||
@@ -81,10 +84,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("replaces placeholder when registering a subcommand by name", async () => {
|
||||
process.argv = ["node", "openclaw", "acp", "--help"];
|
||||
const program = new Command();
|
||||
program.name("openclaw");
|
||||
registerSubCliCommands(program, process.argv);
|
||||
const program = createRegisteredProgram(["node", "openclaw", "acp", "--help"], "openclaw");
|
||||
|
||||
await registerSubCliByName(program, "acp");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user