import { Command } from "commander"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { loggingState } from "../logging/state.js"; const registerPluginCliCommandsFromValidatedConfig = vi.fn(async () => ({})); const registerNodesCameraCommands = vi.fn(); const registerNodesInvokeCommands = vi.fn(); const registerNodesLocationCommands = vi.fn(); const registerNodesNotifyCommand = vi.fn(); const registerNodesPairingCommands = vi.fn(); const registerNodesPushCommand = vi.fn(); const registerNodesScreenCommands = vi.fn(); const registerNodesStatusCommands = vi.fn(); vi.mock("../plugins/cli.js", () => ({ registerPluginCliCommandsFromValidatedConfig, })); vi.mock("./nodes-cli/register.camera.js", () => ({ registerNodesCameraCommands })); vi.mock("./nodes-cli/register.invoke.js", () => ({ registerNodesInvokeCommands })); vi.mock("./nodes-cli/register.location.js", () => ({ registerNodesLocationCommands })); vi.mock("./nodes-cli/register.notify.js", () => ({ registerNodesNotifyCommand })); vi.mock("./nodes-cli/register.pairing.js", () => ({ registerNodesPairingCommands })); vi.mock("./nodes-cli/register.push.js", () => ({ registerNodesPushCommand })); vi.mock("./nodes-cli/register.screen.js", () => ({ registerNodesScreenCommands })); vi.mock("./nodes-cli/register.status.js", () => ({ registerNodesStatusCommands })); const { registerNodesCli } = await import("./nodes-cli/register.js"); describe("registerNodesCli plugin registration", () => { const originalArgv = process.argv; let originalForceConsoleToStderr = false; beforeEach(() => { originalForceConsoleToStderr = loggingState.forceConsoleToStderr; loggingState.forceConsoleToStderr = false; registerPluginCliCommandsFromValidatedConfig.mockClear(); }); afterEach(() => { process.argv = originalArgv; loggingState.forceConsoleToStderr = originalForceConsoleToStderr; }); async function registerWithArgv(argv: string[]) { process.argv = argv; const program = new Command(); await registerNodesCli(program); return program; } it("routes plugin registration logs to stderr for nodes --json commands", async () => { let forceStderrDuringRegistration = false; registerPluginCliCommandsFromValidatedConfig.mockImplementationOnce(async () => { forceStderrDuringRegistration = loggingState.forceConsoleToStderr; return {}; }); const program = await registerWithArgv(["node", "openclaw", "nodes", "list", "--json"]); expect(registerPluginCliCommandsFromValidatedConfig).toHaveBeenCalledWith( program, undefined, undefined, { mode: "lazy", primary: "nodes" }, ); expect(forceStderrDuringRegistration).toBe(true); expect(loggingState.forceConsoleToStderr).toBe(false); }); it("does not route pass-through --json after the terminator", async () => { let forceStderrDuringRegistration = true; registerPluginCliCommandsFromValidatedConfig.mockImplementationOnce(async () => { forceStderrDuringRegistration = loggingState.forceConsoleToStderr; return {}; }); await registerWithArgv(["node", "openclaw", "nodes", "invoke", "--", "--json"]); expect(forceStderrDuringRegistration).toBe(false); expect(loggingState.forceConsoleToStderr).toBe(false); }); });