import { afterEach, describe, expect, test } from "bun:test"; import { exchangeHandoffAndSignIn } from "../src/app/lib/den-handoff"; import { hasActiveDesktopSignInIntent, markDesktopSignInInitiated, markOrgSelectionPending, readOrgSelectionPending, } from "../src/app/lib/den-sign-in-intent"; const originalWindow = globalThis.window; const originalFetch = globalThis.fetch; function memoryStorage(): Storage { const map = new Map(); return { get length() { return map.size; }, clear() { map.clear(); }, getItem(key: string) { return map.get(key) ?? null; }, key(index: number) { return Array.from(map.keys())[index] ?? null; }, removeItem(key: string) { map.delete(key); }, setItem(key: string, value: string) { map.set(key, value); }, }; } function stubWindow() { Object.defineProperty(globalThis, "window", { configurable: true, value: { localStorage: memoryStorage(), sessionStorage: memoryStorage(), dispatchEvent: () => true, }, }); } function stubExchangeResponse(payload: Record) { Object.defineProperty(globalThis, "fetch", { configurable: true, value: (async () => new Response(JSON.stringify(payload), { status: 200, headers: { "Content-Type": "application/json" }, })) satisfies typeof fetch, }); } const exchangeUser = { id: "user_invited", email: "invited@example.com", name: "Invited Member" }; afterEach(() => { Object.defineProperty(globalThis, "window", { configurable: true, value: originalWindow, }); Object.defineProperty(globalThis, "fetch", { configurable: true, value: originalFetch, }); }); describe("exchangeHandoffAndSignIn", () => { test("persists the organization resolved by the handoff exchange", async () => { stubWindow(); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_invited", slug: "invited-org", name: "Invited Org" }, connectEnabled: false, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test" }); expect(result.ok).toBe(true); if (!result.ok) throw new Error(result.error); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBe("org_invited"); expect(window.localStorage.getItem("openwork.den.activeOrgSlug")).toBe("invited-org"); expect(window.localStorage.getItem("openwork.den.activeOrgName")).toBe("Invited Org"); expect(result.exchange.connectEnabled).toBe(false); expect(window.localStorage.getItem("openwork.den.desktopConfig:https://den.test::org_invited")) .toBe(JSON.stringify({ connectEnabled: false })); }); test("prefers the caller-provided organization over the exchange payload", async () => { stubWindow(); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_exchange", slug: "exchange-org", name: "Exchange Org" }, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test", activeOrg: { id: "org_bootstrap", slug: "bootstrap-org", name: "Bootstrap Org" }, }); expect(result.ok).toBe(true); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBe("org_bootstrap"); expect(window.localStorage.getItem("openwork.den.desktopConfig:https://den.test::org_bootstrap")).toBeNull(); }); test("preserves the stored organization when the exchange has none", async () => { stubWindow(); window.localStorage.setItem("openwork.den.activeOrgId", "org_stored"); window.localStorage.setItem("openwork.den.activeOrgSlug", "stored-org"); window.localStorage.setItem("openwork.den.activeOrgName", "Stored Org"); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test" }); expect(result.ok).toBe(true); if (!result.ok) throw new Error(result.error); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBe("org_stored"); expect(window.localStorage.getItem("openwork.den.activeOrgSlug")).toBe("stored-org"); expect(window.localStorage.getItem("openwork.den.activeOrgName")).toBe("Stored Org"); expect(result.exchange.connectEnabled).toBeNull(); expect(window.localStorage.getItem("openwork.den.desktopConfig:https://den.test::org_stored")) .toBeNull(); }); test("a desktop-initiated sign-in defers the org choice to the chooser", async () => { stubWindow(); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_default", slug: "default-org", name: "Default Org" }, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test", desktopInitiated: true, }); expect(result.ok).toBe(true); // Token persists, but no organization is committed… expect(window.localStorage.getItem("openwork.den.authToken")).toBe("tok_handoff"); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBeNull(); // …and the chooser sees the pending state with the exchange org suggested. expect(readOrgSelectionPending()).toEqual({ pending: true, suggestion: { id: "org_default", slug: "default-org", name: "Default Org" }, }); }); test("the desktop sign-in intent marker classifies an unlabeled handoff", async () => { stubWindow(); markDesktopSignInInitiated(); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_default", slug: "default-org", name: "Default Org" }, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test" }); expect(result.ok).toBe(true); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBeNull(); expect(readOrgSelectionPending().pending).toBe(true); // The marker is consumed: a later remote handoff is not reclassified. expect(hasActiveDesktopSignInIntent()).toBe(false); }); test("an explicitly scoped org connects straight through even when desktop-initiated", async () => { stubWindow(); markDesktopSignInInitiated(); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_exchange", slug: "exchange-org", name: "Exchange Org" }, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test", activeOrg: { id: "org_invite", slug: "invite-org", name: "Invite Org" }, desktopInitiated: true, }); expect(result.ok).toBe(true); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBe("org_invite"); expect(readOrgSelectionPending().pending).toBe(false); }); test("a remote handoff clears stale pending state and commits its organization", async () => { stubWindow(); markOrgSelectionPending({ id: "org_stale", slug: null, name: null }); stubExchangeResponse({ token: "tok_handoff", user: exchangeUser, organization: { id: "org_remote", slug: "remote-org", name: "Remote Org" }, }); const result = await exchangeHandoffAndSignIn("grant_test", { baseUrl: "https://den.test", desktopInitiated: false, }); expect(result.ok).toBe(true); expect(window.localStorage.getItem("openwork.den.activeOrgId")).toBe("org_remote"); expect(readOrgSelectionPending()).toEqual({ pending: false, suggestion: null }); }); });