Files
openclaw/src/cli/nodes-cli.plugin-registration.test.ts
clawsweeper[bot] b3ec4f08d1 Route JSON-mode plugin registration logs to stderr (#84741)
Summary:
- The PR extracts JSON-mode console-to-stderr routing into a shared CLI helper, wraps root and `nodes` lazy plugin registration, adds nodes registration coverage, and adds a changelog entry.
- Reproducibility: yes. for source-level reproduction: the linked report shows `openclaw nodes list --json 2>  ... ssing the existing JSON stderr guard. I did not run the live Helm/container repro in this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: Route JSON-mode plugin registration logs to stderr

Validation:
- ClawSweeper review passed for head c9d0867db0.
- Required merge gates passed before the squash merge.

Prepared head SHA: c9d0867db0
Review: https://github.com/openclaw/openclaw/pull/84741#issuecomment-4503741078

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-21 00:35:40 +00:00

84 lines
3.2 KiB
TypeScript

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);
});
});