From aa87d6cee82199426d1898a7e27b4f8bd12fa146 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 7 Jan 2026 03:12:30 +0000 Subject: [PATCH] refactor(relay): add --smoke entrypoint --- scripts/package-mac-app.sh | 2 +- src/macos/relay-smoke.test.ts | 37 +++++++++++++++++++++++++++++++++ src/macos/relay-smoke.ts | 39 +++++++++++++++++++++++++++++++++++ src/macos/relay.ts | 13 ++++++------ 4 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 src/macos/relay-smoke.test.ts create mode 100644 src/macos/relay-smoke.ts diff --git a/scripts/package-mac-app.sh b/scripts/package-mac-app.sh index b60a6cb75..aed72a4f1 100755 --- a/scripts/package-mac-app.sh +++ b/scripts/package-mac-app.sh @@ -255,7 +255,7 @@ if [[ "${SKIP_GATEWAY_PACKAGE:-0}" != "1" ]]; then rm -rf "$RELAY_BUILD_DIR" echo "🧪 Smoke testing bundled relay QR modules" - CLAWDBOT_SMOKE_QR=1 "$RELAY_OUT" >/dev/null + "$RELAY_OUT" --smoke qr >/dev/null echo "🎨 Copying gateway A2UI host assets" rm -rf "$RELAY_DIR/a2ui" diff --git a/src/macos/relay-smoke.test.ts b/src/macos/relay-smoke.test.ts new file mode 100644 index 000000000..cdc02dd54 --- /dev/null +++ b/src/macos/relay-smoke.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it, vi } from "vitest"; +import { parseRelaySmokeTest, runRelaySmokeTest } from "./relay-smoke.js"; + +vi.mock("../web/qr-image.js", () => ({ + renderQrPngBase64: vi.fn(async () => "base64"), +})); + +describe("parseRelaySmokeTest", () => { + it("parses --smoke qr", () => { + expect(parseRelaySmokeTest(["--smoke", "qr"], {})).toBe("qr"); + }); + + it("parses --smoke-qr", () => { + expect(parseRelaySmokeTest(["--smoke-qr"], {})).toBe("qr"); + }); + + it("parses env var smoke mode only when no args", () => { + expect(parseRelaySmokeTest([], { CLAWDBOT_SMOKE_QR: "1" })).toBe("qr"); + expect(parseRelaySmokeTest(["send"], { CLAWDBOT_SMOKE_QR: "1" })).toBe( + null, + ); + }); + + it("rejects unknown smoke values", () => { + expect(() => parseRelaySmokeTest(["--smoke", "nope"], {})).toThrow( + "Unknown smoke test", + ); + }); +}); + +describe("runRelaySmokeTest", () => { + it("runs qr smoke test", async () => { + await runRelaySmokeTest("qr"); + const mod = await import("../web/qr-image.js"); + expect(mod.renderQrPngBase64).toHaveBeenCalledWith("smoke-test"); + }); +}); diff --git a/src/macos/relay-smoke.ts b/src/macos/relay-smoke.ts new file mode 100644 index 000000000..f544ccb50 --- /dev/null +++ b/src/macos/relay-smoke.ts @@ -0,0 +1,39 @@ +export type RelaySmokeTest = "qr"; + +export function parseRelaySmokeTest( + args: string[], + env: NodeJS.ProcessEnv, +): RelaySmokeTest | null { + const smokeIdx = args.indexOf("--smoke"); + if (smokeIdx !== -1) { + const value = args[smokeIdx + 1]; + if (!value || value.startsWith("-")) { + throw new Error("Missing value for --smoke (expected: qr)"); + } + if (value === "qr") return "qr"; + throw new Error(`Unknown smoke test: ${value}`); + } + + if (args.includes("--smoke-qr")) return "qr"; + + // Back-compat: only run env-based smoke mode when no CLI args are present, + // to avoid surprising early-exit when users set env vars globally. + if ( + args.length === 0 && + (env.CLAWDBOT_SMOKE_QR === "1" || env.CLAWDBOT_SMOKE === "qr") + ) { + return "qr"; + } + + return null; +} + +export async function runRelaySmokeTest(test: RelaySmokeTest): Promise { + switch (test) { + case "qr": { + const { renderQrPngBase64 } = await import("../web/qr-image.js"); + await renderQrPngBase64("smoke-test"); + return; + } + } +} diff --git a/src/macos/relay.ts b/src/macos/relay.ts index 0db04a4c8..d9dcc8f0f 100644 --- a/src/macos/relay.ts +++ b/src/macos/relay.ts @@ -32,15 +32,16 @@ async function main() { process.exit(0); } - // Smoke test for QR modules in bun-compiled binaries. - // Verifies that QR code generation works in the bundled relay. - if (process.env.CLAWDBOT_SMOKE_QR === "1" && args.length === 0) { + const { parseRelaySmokeTest, runRelaySmokeTest } = await import( + "./relay-smoke.js" + ); + const smokeTest = parseRelaySmokeTest(args, process.env); + if (smokeTest) { try { - const { renderQrPngBase64 } = await import("../web/qr-image.js"); - await renderQrPngBase64("smoke-test"); + await runRelaySmokeTest(smokeTest); process.exit(0); } catch (err) { - console.error("QR smoke test failed:", err); + console.error(`Relay smoke test failed (${smokeTest}):`, err); process.exit(1); } }