diff --git a/src/commands/onboard-non-interactive.gateway.test.ts b/src/commands/onboard-non-interactive.gateway.test.ts index 3387a90729f..beb92f09f4b 100644 --- a/src/commands/onboard-non-interactive.gateway.test.ts +++ b/src/commands/onboard-non-interactive.gateway.test.ts @@ -190,6 +190,58 @@ async function expectLocalJsonSetupFailure(stateDir: string, runtimeWithCapture: ).rejects.toThrow("exit should not be reached after runtime.error"); } +function createLocalDaemonSetupOptions(stateDir: string) { + return { + nonInteractive: true, + mode: "local" as const, + workspace: path.join(stateDir, "openclaw"), + authChoice: "skip" as const, + skipSkills: true, + skipHealth: false, + installDaemon: true, + gatewayBind: "loopback" as const, + }; +} + +async function runLocalDaemonSetup(stateDir: string, runtimeEnv: RuntimeEnv = runtime) { + await runNonInteractiveSetup(createLocalDaemonSetupOptions(stateDir), runtimeEnv); +} + +async function withMockedPlatform(platform: NodeJS.Platform, run: () => Promise): Promise { + const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue(platform); + try { + return await run(); + } finally { + platformSpy.mockRestore(); + } +} + +function mockGatewayReachableWithCapturedTimeouts() { + let capturedDeadlineMs: number | undefined; + let capturedProbeTimeoutMs: number | undefined; + waitForGatewayReachableMock = vi.fn( + async (params: { + url: string; + token?: string; + password?: string; + deadlineMs?: number; + probeTimeoutMs?: number; + }) => { + capturedDeadlineMs = params.deadlineMs; + capturedProbeTimeoutMs = params.probeTimeoutMs; + return { ok: true }; + }, + ); + return { + get deadlineMs() { + return capturedDeadlineMs; + }, + get probeTimeoutMs() { + return capturedProbeTimeoutMs; + }, + }; +} + describe("onboard (non-interactive): gateway and remote auth", () => { let envSnapshot: ReturnType; let tempHome: string | undefined; @@ -507,82 +559,27 @@ describe("onboard (non-interactive): gateway and remote auth", () => { it("uses a longer health deadline when daemon install was requested", async () => { await withStateDir("state-local-daemon-health-", async (stateDir) => { - let capturedDeadlineMs: number | undefined; - let capturedProbeTimeoutMs: number | undefined; - waitForGatewayReachableMock = vi.fn( - async (params: { - url: string; - token?: string; - password?: string; - deadlineMs?: number; - probeTimeoutMs?: number; - }) => { - capturedDeadlineMs = params.deadlineMs; - capturedProbeTimeoutMs = params.probeTimeoutMs; - return { ok: true }; - }, - ); + const captured = mockGatewayReachableWithCapturedTimeouts(); - await runNonInteractiveSetup( - { - nonInteractive: true, - mode: "local", - workspace: path.join(stateDir, "openclaw"), - authChoice: "skip", - skipSkills: true, - skipHealth: false, - installDaemon: true, - gatewayBind: "loopback", - }, - runtime, - ); + await runLocalDaemonSetup(stateDir); expect(installGatewayDaemonNonInteractiveMock).toHaveBeenCalledTimes(1); - expect(capturedDeadlineMs).toBe(45_000); - expect(capturedProbeTimeoutMs).toBe(10_000); + expect(captured.deadlineMs).toBe(45_000); + expect(captured.probeTimeoutMs).toBe(10_000); }); }, 60_000); it("uses a longer Windows health deadline when daemon install was requested", async () => { await withStateDir("state-local-daemon-health-win-", async (stateDir) => { - let capturedDeadlineMs: number | undefined; - let capturedProbeTimeoutMs: number | undefined; - waitForGatewayReachableMock = vi.fn( - async (params: { - url: string; - token?: string; - password?: string; - deadlineMs?: number; - probeTimeoutMs?: number; - }) => { - capturedDeadlineMs = params.deadlineMs; - capturedProbeTimeoutMs = params.probeTimeoutMs; - return { ok: true }; - }, - ); + const captured = mockGatewayReachableWithCapturedTimeouts(); - const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); - try { - await runNonInteractiveSetup( - { - nonInteractive: true, - mode: "local", - workspace: path.join(stateDir, "openclaw"), - authChoice: "skip", - skipSkills: true, - skipHealth: false, - installDaemon: true, - gatewayBind: "loopback", - }, - runtime, - ); - } finally { - platformSpy.mockRestore(); - } + await withMockedPlatform("win32", async () => { + await runLocalDaemonSetup(stateDir); + }); expect(installGatewayDaemonNonInteractiveMock).toHaveBeenCalledTimes(1); - expect(capturedDeadlineMs).toBe(90_000); - expect(capturedProbeTimeoutMs).toBe(15_000); + expect(captured.deadlineMs).toBe(90_000); + expect(captured.probeTimeoutMs).toBe(15_000); }); }, 60_000); @@ -590,24 +587,9 @@ describe("onboard (non-interactive): gateway and remote auth", () => { await withStateDir("state-local-daemon-health-command-win-", async (stateDir) => { waitForGatewayReachableMock = vi.fn(async () => ({ ok: true })); - const platformSpy = vi.spyOn(process, "platform", "get").mockReturnValue("win32"); - try { - await runNonInteractiveSetup( - { - nonInteractive: true, - mode: "local", - workspace: path.join(stateDir, "openclaw"), - authChoice: "skip", - skipSkills: true, - skipHealth: false, - installDaemon: true, - gatewayBind: "loopback", - }, - runtime, - ); - } finally { - platformSpy.mockRestore(); - } + await withMockedPlatform("win32", async () => { + await runLocalDaemonSetup(stateDir); + }); expect(healthCommandMock).toHaveBeenCalledTimes(1); expect(healthCommandMock).toHaveBeenCalledWith(