import { readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { afterEach, describe, expect, it, vi } from "vitest"; import { desktopOAuthCode, oauthStateOf, onDesktopOAuthCallback, type RakazoDesktop, type RakazoDesktopOAuthCallback, windowChromeKind, } from "./desktop.js"; function desktop(platform: string): RakazoDesktop { const updateState = { phase: "unsupported" as const, currentVersion: "0.1.0", availableVersion: null, percent: null, message: "Automatic updates only run in an installed build.", checkedAt: null, }; return { platform, window: { close: async () => undefined, minimize: async () => undefined, toggleMaximize: async () => undefined, state: async () => ({ minimized: false, maximized: false, fullScreen: false }), }, update: { state: async () => updateState, check: async () => updateState, download: async () => updateState, install: async () => updateState, }, oauth: { onCallback: () => () => undefined }, }; } describe("window chrome", () => { it("does not paint fake traffic lights in the browser", () => { expect(windowChromeKind(undefined)).toBe("spacer"); }); it("leaves macOS traffic lights to Electron", () => { expect(windowChromeKind(desktop("darwin"))).toBe("darwin"); }); it("uses real window-control buttons on Windows and Linux", () => { expect(windowChromeKind(desktop("win32"))).toBe("controls"); expect(windowChromeKind(desktop("linux"))).toBe("controls"); }); it("does not paint fake traffic lights into the browser shell or welcome page", () => { const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "../pages"); const shell = readFileSync(path.join(root, "Shell.tsx"), "utf8"); const welcome = readFileSync(path.join(root, "Welcome.tsx"), "utf8"); expect(shell).not.toContain("FF5F57"); expect(welcome).not.toContain("FF5F57"); }); it("keeps conversation header controls clickable", () => { const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "../pages"); const shell = readFileSync(path.join(root, "Shell.tsx"), "utf8"); const toggles = readFileSync(path.join(root, "shell/sidebar-toggle-buttons.tsx"), "utf8"); expect(shell).toContain( 'className="app-drag flex items-center justify-between border-b border-sidebar-border', ); expect(shell).toContain('className="app-no-drag grid size-control-lg'); expect(shell).toContain('className="app-no-drag flex min-w-0 items-center gap-3"'); // Ensure header sidebar toggle controls stay clickable (not part of drag region) expect( toggles.match(/app-no-drag .* size-control-lg .* place-items-center/g)?.length ?? 0, ).toBeGreaterThanOrEqual(2); }); it("moves window chrome into the conversation header when the bots sidebar is collapsed", () => { const root = path.join(path.dirname(fileURLToPath(import.meta.url)), "../pages"); const shell = readFileSync(path.join(root, "Shell.tsx"), "utf8"); const toggles = readFileSync(path.join(root, "shell/sidebar-toggle-buttons.tsx"), "utf8"); expect(shell).toContain("collapsed={botsSidebarCollapsed}"); expect(toggles).toContain("{collapsed && desktopBridge() ? : null}"); }); }); describe("captured OAuth callbacks", () => { it("sends the code and state as the compact form the paste flow accepts", () => { expect(desktopOAuthCode({ code: "ac_123", state: "verifier_456" })).toBe("ac_123#verifier_456"); }); it("sends a bare code when the provider redirects without state", () => { expect(desktopOAuthCode({ code: "ac_123" })).toBe("ac_123"); }); }); describe("attempt correlation", () => { afterEach(() => vi.unstubAllGlobals()); function bridgeEmitting() { let emit: (callback: RakazoDesktopOAuthCallback) => void = () => undefined; const unsubscribe = vi.fn(); vi.stubGlobal("window", { rakazoDesktop: { ...desktop("linux"), oauth: { onCallback: (listener: (callback: RakazoDesktopOAuthCallback) => void) => { emit = listener; return unsubscribe; }, }, }, }); return { emit: (c: RakazoDesktopOAuthCallback) => emit(c), unsubscribe }; } it("reads the attempt state out of the authorize URL", () => { expect(oauthStateOf("https://claude.ai/oauth/authorize?code=true&state=verifier_456")).toBe( "verifier_456", ); expect(oauthStateOf("https://claude.ai/oauth/authorize?code=true")).toBeUndefined(); expect(oauthStateOf("not a url")).toBeUndefined(); }); it("ignores a code captured for a different attempt", () => { const { emit } = bridgeEmitting(); const received: string[] = []; onDesktopOAuthCallback((code) => received.push(code), "verifier_456"); emit({ code: "stale", state: "verifier_000" }); expect(received).toEqual([]); emit({ code: "ac_123", state: "verifier_456" }); expect(received).toEqual(["ac_123#verifier_456"]); }); it("accepts any code when the provider carries no state to correlate on", () => { const { emit } = bridgeEmitting(); const received: string[] = []; onDesktopOAuthCallback((code) => received.push(code)); emit({ code: "ac_123" }); expect(received).toEqual(["ac_123"]); }); it("no-ops in a browser without the desktop bridge", () => { vi.stubGlobal("window", {}); const received: string[] = []; expect(() => onDesktopOAuthCallback((code) => received.push(code))()).not.toThrow(); expect(received).toEqual([]); }); });