From ae385f3c6bbd5124a1c2e5a1625a8e8b30336e8a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 14 Aug 2026 13:44:20 -0700 Subject: [PATCH] test: remove obsolete QR dashboard integration suite (#123819) --- src/cli/qr-dashboard.integration.test.ts | 218 ----------------------- 1 file changed, 218 deletions(-) delete mode 100644 src/cli/qr-dashboard.integration.test.ts diff --git a/src/cli/qr-dashboard.integration.test.ts b/src/cli/qr-dashboard.integration.test.ts deleted file mode 100644 index 27abf4f131e6..000000000000 --- a/src/cli/qr-dashboard.integration.test.ts +++ /dev/null @@ -1,218 +0,0 @@ -// QR dashboard integration tests cover QR dashboard command wiring and rendered output. -import { Command } from "commander"; -import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { captureEnv } from "../test-utils/env.js"; -import { createCliRuntimeCapture } from "./test-runtime-capture.js"; - -const loadConfigMock = vi.hoisted(() => vi.fn()); -const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn()); -const resolveGatewayPortMock = vi.hoisted(() => vi.fn(() => 18789)); -const copyToClipboardMock = vi.hoisted(() => vi.fn(async () => false)); -const ensureGatewayReadyForOperationMock = vi.hoisted(() => vi.fn()); -const { - runtimeLogs, - runtimeErrors, - defaultRuntime: runtime, - resetRuntimeCapture, -} = createCliRuntimeCapture(); -const runtimeExit = runtime.exit; - -vi.mock("../config/config.js", async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - getRuntimeConfig: loadConfigMock, - loadConfig: loadConfigMock, - readConfigFileSnapshot: readConfigFileSnapshotMock, - resolveGatewayPort: resolveGatewayPortMock, - }; -}); - -vi.mock("../infra/clipboard.js", () => ({ - copyToClipboard: copyToClipboardMock, -})); - -vi.mock("../commands/gateway-readiness.js", () => ({ - ensureGatewayReadyForOperation: ensureGatewayReadyForOperationMock, -})); - -vi.mock("../commands/control-ui-handoff.js", async (importOriginal) => ({ - ...(await importOriginal()), - waitForControlUiDocument: vi.fn(async () => ({ ready: true })), -})); - -vi.mock("../infra/device-bootstrap.js", () => ({ - issueDeviceBootstrapToken: vi.fn(async () => ({ - token: "bootstrap-123", - expiresAtMs: 123, - })), - issueDevicePairSetupBootstrapToken: vi.fn(async () => ({ - token: "bootstrap-123", - expiresAtMs: 123, - setupId: "setup-123", - })), -})); - -vi.mock("../runtime.js", () => ({ - defaultRuntime: runtime, -})); - -const { dashboardCommand } = await import("../commands/dashboard.js"); -const { registerQrCli } = await import("./qr-cli.js"); - -function createGatewayTokenRefFixture() { - return { - secrets: { - providers: { - default: { - source: "env", - }, - }, - defaults: { - env: "default", - }, - }, - gateway: { - bind: "custom", - customBindHost: "127.0.0.1", - port: 18789, - auth: { - mode: "token", - token: { - source: "env", - provider: "default", - id: "SHARED_GATEWAY_TOKEN", - }, - }, - }, - }; -} - -function decodeSetupCode(setupCode: string): { - url?: string; - bootstrapToken?: string; -} { - const padded = setupCode.replace(/-/g, "+").replace(/_/g, "/"); - const padLength = (4 - (padded.length % 4)) % 4; - const normalized = padded + "=".repeat(padLength); - const json = Buffer.from(normalized, "base64").toString("utf8"); - return JSON.parse(json) as { - url?: string; - bootstrapToken?: string; - }; -} - -function findSetupCodeLogLine(lines: string[]): string | undefined { - for (const line of lines) { - try { - const payload = decodeSetupCode(line); - if (payload.url || payload.bootstrapToken) { - return line; - } - } catch { - // Ignore non-setup-code log lines. - } - } - return undefined; -} - -async function runCli(args: string[]): Promise { - const program = new Command(); - registerQrCli(program); - await program.parseAsync(args, { from: "user" }); -} - -describe("cli integration: qr + dashboard token SecretRef", () => { - let envSnapshot: ReturnType; - - beforeAll(() => { - envSnapshot = captureEnv([ - "SHARED_GATEWAY_TOKEN", - "OPENCLAW_GATEWAY_TOKEN", - "OPENCLAW_GATEWAY_PASSWORD", - ]); - }); - - beforeEach(() => { - resetRuntimeCapture(); - vi.clearAllMocks(); - ensureGatewayReadyForOperationMock.mockResolvedValue({ - ready: true, - status: {}, - recovered: false, - }); - runtimeExit.mockImplementation(() => {}); - delete process.env.OPENCLAW_GATEWAY_TOKEN; - delete process.env.OPENCLAW_GATEWAY_PASSWORD; - delete process.env.SHARED_GATEWAY_TOKEN; - }); - - it("uses the same resolved token SecretRef for qr auth validation and dashboard commands", async () => { - const fixture = createGatewayTokenRefFixture(); - process.env.SHARED_GATEWAY_TOKEN = "shared-token-123"; - loadConfigMock.mockReturnValue(fixture); - readConfigFileSnapshotMock.mockResolvedValue({ - path: "/tmp/openclaw.json", - exists: true, - valid: true, - issues: [], - config: fixture, - }); - - await runCli(["qr", "--setup-code-only"]); - const setupCode = findSetupCodeLogLine(runtimeLogs); - if (!setupCode) { - throw new Error("expected QR setup code log line"); - } - const payload = decodeSetupCode(setupCode); - expect(payload.url).toBe("ws://127.0.0.1:18789"); - expect(payload.bootstrapToken).toBe("bootstrap-123"); - expect(runtimeErrors).toStrictEqual([]); - - runtimeLogs.length = 0; - runtimeErrors.length = 0; - await dashboardCommand(runtime, { noOpen: true }); - const joined = runtimeLogs.join("\n"); - expect(joined).toContain("Dashboard URL: http://127.0.0.1:18789/"); - expect(joined).not.toContain("#token="); - expect(joined).toContain("One-time pairing URL not delivered"); - expect(joined).toContain("openclaw dashboard --json"); - expect(joined).toContain("browserUrl"); - expect(joined).not.toContain("Token auto-auth is disabled"); - expect(joined).not.toContain("Token auto-auth unavailable"); - expect(runtimeErrors).toStrictEqual([]); - }); - - it("fails qr but keeps dashboard actionable when the shared token SecretRef is unresolved", async () => { - const fixture = createGatewayTokenRefFixture(); - loadConfigMock.mockReturnValue(fixture); - readConfigFileSnapshotMock.mockResolvedValue({ - path: "/tmp/openclaw.json", - exists: true, - valid: true, - issues: [], - config: fixture, - }); - - await runCli(["qr", "--setup-code-only"]); - expect(runtime.exit).toHaveBeenCalledWith(1); - expect(runtimeErrors.join("\n")).toMatch(/SHARED_GATEWAY_TOKEN/); - - runtimeLogs.length = 0; - runtimeErrors.length = 0; - await dashboardCommand(runtime, { noOpen: true }); - const joined = runtimeLogs.join("\n"); - expect(joined).toContain("Dashboard URL: http://127.0.0.1:18789/"); - expect(joined).not.toContain("#token="); - expect(joined).toContain("One-time pairing URL not delivered"); - expect(joined).toContain("openclaw dashboard --json"); - expect(joined).toContain("browserUrl"); - expect(joined).not.toContain("Token auto-auth unavailable"); - expect(joined).not.toContain("Set OPENCLAW_GATEWAY_TOKEN"); - expect(runtimeErrors).toStrictEqual([]); - }); - - afterAll(() => { - envSnapshot.restore(); - }); -});