import { Command } from "commander"; import { beforeEach, describe, expect, it, vi } from "vitest"; const startGatewayServer = vi.fn(async () => ({ close: vi.fn(async () => {}), })); const setGatewayWsLogStyle = vi.fn(); const setVerbose = vi.fn(); const forceFreePortAndWait = vi.fn(async () => ({ killed: [], waitedMs: 0, escalatedToSigkill: false, })); const ensureDevGatewayConfig = vi.fn(async () => {}); const runGatewayLoop = vi.fn(async ({ start }: { start: () => Promise }) => { await start(); }); const runtimeLogs: string[] = []; const runtimeErrors: string[] = []; const defaultRuntime = { log: (msg: string) => runtimeLogs.push(msg), error: (msg: string) => runtimeErrors.push(msg), exit: (code: number) => { throw new Error(`__exit__:${code}`); }, }; vi.mock("../../config/config.js", () => ({ getConfigPath: () => "/tmp/openclaw-test-missing-config.json", loadConfig: () => ({}), readConfigFileSnapshot: async () => ({ exists: false }), resolveStateDir: () => "/tmp", resolveGatewayPort: () => 18789, })); vi.mock("../../gateway/auth.js", () => ({ resolveGatewayAuth: (params: { authConfig?: { token?: string }; env?: NodeJS.ProcessEnv }) => ({ mode: "token", token: params.authConfig?.token ?? params.env?.OPENCLAW_GATEWAY_TOKEN, password: undefined, allowTailscale: false, }), })); vi.mock("../../gateway/server.js", () => ({ startGatewayServer: (port: number, opts?: unknown) => startGatewayServer(port, opts), })); vi.mock("../../gateway/ws-logging.js", () => ({ setGatewayWsLogStyle: (style: string) => setGatewayWsLogStyle(style), })); vi.mock("../../globals.js", () => ({ setVerbose: (enabled: boolean) => setVerbose(enabled), })); vi.mock("../../infra/gateway-lock.js", () => ({ GatewayLockError: class GatewayLockError extends Error {}, })); vi.mock("../../infra/ports.js", () => ({ formatPortDiagnostics: () => [], inspectPortUsage: async () => ({ status: "free" }), })); vi.mock("../../logging/console.js", () => ({ setConsoleSubsystemFilter: () => undefined, setConsoleTimestampPrefix: () => undefined, })); vi.mock("../../logging/subsystem.js", () => ({ createSubsystemLogger: () => ({ info: () => undefined, warn: () => undefined, error: () => undefined, }), })); vi.mock("../../runtime.js", () => ({ defaultRuntime, })); vi.mock("../command-format.js", () => ({ formatCliCommand: (cmd: string) => cmd, })); vi.mock("../ports.js", () => ({ forceFreePortAndWait: (port: number, opts: unknown) => forceFreePortAndWait(port, opts), })); vi.mock("./dev.js", () => ({ ensureDevGatewayConfig: (opts?: unknown) => ensureDevGatewayConfig(opts), })); vi.mock("./run-loop.js", () => ({ runGatewayLoop: (params: { start: () => Promise }) => runGatewayLoop(params), })); describe("gateway run option collisions", () => { beforeEach(() => { runtimeLogs.length = 0; runtimeErrors.length = 0; startGatewayServer.mockClear(); setGatewayWsLogStyle.mockClear(); setVerbose.mockClear(); forceFreePortAndWait.mockClear(); ensureDevGatewayConfig.mockClear(); runGatewayLoop.mockClear(); }); it("forwards parent-captured options to `gateway run` subcommand", async () => { const { addGatewayRunCommand } = await import("./run.js"); const program = new Command(); const gateway = addGatewayRunCommand(program.command("gateway")); addGatewayRunCommand(gateway.command("run")); await program.parseAsync( [ "gateway", "run", "--token", "tok_run", "--allow-unconfigured", "--ws-log", "full", "--force", ], { from: "user" }, ); expect(forceFreePortAndWait).toHaveBeenCalledWith(18789, expect.anything()); expect(setGatewayWsLogStyle).toHaveBeenCalledWith("full"); expect(startGatewayServer).toHaveBeenCalledWith( 18789, expect.objectContaining({ auth: expect.objectContaining({ token: "tok_run", }), }), ); }); });