





















11// Nodes CLI plugin registration tests cover node command plugin registration.
2+// Built-in node command registration runs for real so the guard is exercised against the actual
3+// registered subcommand names; only the plugin-loader boundary is stubbed.
24import { Command } from "commander";
35import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
46import { loggingState } from "../logging/state.js";
5768const registerPluginCliCommandsFromValidatedConfig = vi.fn(async () => ({}));
7-const registerNodesCameraCommands = vi.fn();
8-const registerNodesInvokeCommands = vi.fn();
9-const registerNodesLocationCommands = vi.fn();
10-const registerNodesNotifyCommand = vi.fn();
11-const registerNodesPairingCommands = vi.fn();
12-const registerNodesPushCommand = vi.fn();
13-const registerNodesScreenCommands = vi.fn();
14-const registerNodesStatusCommands = vi.fn();
1591610vi.mock("../plugins/cli.js", () => ({
1711 registerPluginCliCommandsFromValidatedConfig,
1812}));
191320-vi.mock("./nodes-cli/register.camera.js", () => ({ registerNodesCameraCommands }));
21-vi.mock("./nodes-cli/register.invoke.js", () => ({ registerNodesInvokeCommands }));
22-vi.mock("./nodes-cli/register.location.js", () => ({ registerNodesLocationCommands }));
23-vi.mock("./nodes-cli/register.notify.js", () => ({ registerNodesNotifyCommand }));
24-vi.mock("./nodes-cli/register.pairing.js", () => ({ registerNodesPairingCommands }));
25-vi.mock("./nodes-cli/register.push.js", () => ({ registerNodesPushCommand }));
26-vi.mock("./nodes-cli/register.screen.js", () => ({ registerNodesScreenCommands }));
27-vi.mock("./nodes-cli/register.status.js", () => ({ registerNodesStatusCommands }));
28-2914const { registerNodesCli } = await import("./nodes-cli/register.js");
30153116describe("registerNodesCli plugin registration", () => {
@@ -50,14 +35,29 @@ describe("registerNodesCli plugin registration", () => {
5035return program;
5136}
523753-it("routes plugin registration logs to stderr for nodes --json commands", async () => {
38+it("skips plugin CLI/runtime registration for built-in nodes subcommands", async () => {
39+for (const subcommand of ["status", "list", "describe", "invoke", "pending", "camera"]) {
40+registerPluginCliCommandsFromValidatedConfig.mockClear();
41+await registerWithArgv(["node", "openclaw", "nodes", subcommand, "--json"]);
42+expect(registerPluginCliCommandsFromValidatedConfig).not.toHaveBeenCalled();
43+}
44+});
45+46+it("registers plugin-provided node subcommands lazily and routes their logs to stderr", async () => {
5447let forceStderrDuringRegistration = false;
5548registerPluginCliCommandsFromValidatedConfig.mockImplementationOnce(async () => {
5649forceStderrDuringRegistration = loggingState.forceConsoleToStderr;
5750return {};
5851});
595260-const program = await registerWithArgv(["node", "openclaw", "nodes", "list", "--json"]);
53+const program = await registerWithArgv([
54+"node",
55+"openclaw",
56+"nodes",
57+"canvas",
58+"snapshot",
59+"--json",
60+]);
61616262expect(registerPluginCliCommandsFromValidatedConfig).toHaveBeenCalledWith(
6363program,
@@ -69,14 +69,24 @@ describe("registerNodesCli plugin registration", () => {
6969expect(loggingState.forceConsoleToStderr).toBe(false);
7070});
717172+it("surfaces plugin subcommands for bare `nodes` listing", async () => {
73+const program = await registerWithArgv(["node", "openclaw", "nodes"]);
74+expect(registerPluginCliCommandsFromValidatedConfig).toHaveBeenCalledWith(
75+program,
76+undefined,
77+undefined,
78+{ mode: "lazy", primary: "nodes" },
79+);
80+});
81+7282it("does not route pass-through --json after the terminator", async () => {
7383let forceStderrDuringRegistration = true;
7484registerPluginCliCommandsFromValidatedConfig.mockImplementationOnce(async () => {
7585forceStderrDuringRegistration = loggingState.forceConsoleToStderr;
7686return {};
7787});
788879-await registerWithArgv(["node", "openclaw", "nodes", "invoke", "--", "--json"]);
89+await registerWithArgv(["node", "openclaw", "nodes", "canvas", "--", "--json"]);
80908191expect(forceStderrDuringRegistration).toBe(false);
8292expect(loggingState.forceConsoleToStderr).toBe(false);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。