File size: 4,834 Bytes
fc93158 | 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import { Command } from "commander";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
const { acpAction, registerAcpCli } = vi.hoisted(() => {
const action = vi.fn();
const register = vi.fn((program: Command) => {
program.command("acp").action(action);
});
return { acpAction: action, registerAcpCli: register };
});
const { nodesAction, registerNodesCli } = vi.hoisted(() => {
const action = vi.fn();
const register = vi.fn((program: Command) => {
const nodes = program.command("nodes");
nodes.command("list").action(action);
});
return { nodesAction: action, registerNodesCli: register };
});
const configModule = vi.hoisted(() => ({
loadConfig: vi.fn(),
readConfigFileSnapshot: vi.fn(),
}));
vi.mock("../acp-cli.js", () => ({ registerAcpCli }));
vi.mock("../nodes-cli.js", () => ({ registerNodesCli }));
vi.mock("../../config/config.js", () => configModule);
const { loadValidatedConfigForPluginRegistration, registerSubCliByName, registerSubCliCommands } =
await import("./register.subclis.js");
describe("registerSubCliCommands", () => {
const originalArgv = process.argv;
const originalDisableLazySubcommands = process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS;
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(() => {
if (originalDisableLazySubcommands === undefined) {
delete process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS;
} else {
process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS = originalDisableLazySubcommands;
}
registerAcpCli.mockClear();
acpAction.mockClear();
registerNodesCli.mockClear();
nodesAction.mockClear();
configModule.loadConfig.mockReset();
configModule.readConfigFileSnapshot.mockReset();
});
afterEach(() => {
process.argv = originalArgv;
if (originalDisableLazySubcommands === undefined) {
delete process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS;
} else {
process.env.OPENCLAW_DISABLE_LAZY_SUBCOMMANDS = originalDisableLazySubcommands;
}
});
it("registers only the primary placeholder and dispatches", async () => {
const program = createRegisteredProgram(["node", "openclaw", "acp"]);
expect(program.commands.map((cmd) => cmd.name())).toEqual(["acp"]);
await program.parseAsync(["acp"], { from: "user" });
expect(registerAcpCli).toHaveBeenCalledTimes(1);
expect(acpAction).toHaveBeenCalledTimes(1);
});
it("registers placeholders for all subcommands when no primary", () => {
const program = createRegisteredProgram(["node", "openclaw"]);
const names = program.commands.map((cmd) => cmd.name());
expect(names).toContain("acp");
expect(names).toContain("gateway");
expect(names).toContain("clawbot");
expect(registerAcpCli).not.toHaveBeenCalled();
});
it("returns null for plugin registration when the config snapshot is invalid", async () => {
configModule.readConfigFileSnapshot.mockResolvedValueOnce({
valid: false,
config: { plugins: { load: { paths: ["/tmp/evil"] } } },
});
await expect(loadValidatedConfigForPluginRegistration()).resolves.toBeNull();
expect(configModule.loadConfig).not.toHaveBeenCalled();
});
it("loads validated config for plugin registration when the snapshot is valid", async () => {
const loadedConfig = { plugins: { enabled: true } };
configModule.readConfigFileSnapshot.mockResolvedValueOnce({
valid: true,
config: loadedConfig,
});
configModule.loadConfig.mockReturnValueOnce(loadedConfig);
await expect(loadValidatedConfigForPluginRegistration()).resolves.toBe(loadedConfig);
expect(configModule.loadConfig).toHaveBeenCalledTimes(1);
});
it("re-parses argv for lazy subcommands", async () => {
const program = createRegisteredProgram(["node", "openclaw", "nodes", "list"], "openclaw");
expect(program.commands.map((cmd) => cmd.name())).toEqual(["nodes"]);
await program.parseAsync(["nodes", "list"], { from: "user" });
expect(registerNodesCli).toHaveBeenCalledTimes(1);
expect(nodesAction).toHaveBeenCalledTimes(1);
});
it("replaces placeholder when registering a subcommand by name", async () => {
const program = createRegisteredProgram(["node", "openclaw", "acp", "--help"], "openclaw");
await registerSubCliByName(program, "acp");
const names = program.commands.map((cmd) => cmd.name());
expect(names.filter((name) => name === "acp")).toHaveLength(1);
await program.parseAsync(["acp"], { from: "user" });
expect(registerAcpCli).toHaveBeenCalledTimes(1);
expect(acpAction).toHaveBeenCalledTimes(1);
});
});
|