import { describe, expect, it } from "@effect/vitest"; import { openOAuthPopup, reserveOAuthPopup } from "./oauth-popup"; type OAuthPopupTestWindow = { readonly screenX: number; readonly screenY: number; readonly outerWidth: number; readonly outerHeight: number; readonly location: { readonly origin: string }; readonly addEventListener: () => void; readonly removeEventListener: () => void; readonly open: ( url: string, name: string, features: string, ) => { closed: boolean; close: () => void; opener?: unknown; location: { href: string } }; }; type FakePopup = { closed: boolean; close: () => void; opener?: unknown; location: { href: string }; }; describe("openOAuthPopup", () => { it("does not open unsupported OAuth endpoint URLs", async () => { let openFailed = false; const teardown = openOAuthPopup({ url: "javascript:alert(1)", popupName: "oauth", channelName: "oauth-channel", onResult: () => {}, onOpenFailed: () => { openFailed = true; }, }); teardown(); await new Promise((resolve) => queueMicrotask(() => resolve())); expect(openFailed).toBe(true); }); it("opens supported OAuth URLs through a reserved popup with opener available", () => { let features = ""; let opened = ""; const popup: FakePopup = { closed: false, close: () => {}, location: { href: "" } }; const previousWindow = globalThis.window; const fakeWindow: OAuthPopupTestWindow = { screenX: 0, screenY: 0, outerWidth: 1200, outerHeight: 900, location: { origin: "https://app.example" }, addEventListener: () => {}, removeEventListener: () => {}, open: (url: string, _name: string, requestedFeatures: string) => { opened = url; features = requestedFeatures; return popup; }, }; Object.defineProperty(globalThis, "window", { configurable: true, value: fakeWindow, writable: true, }); const teardown = openOAuthPopup({ url: "https://auth.example/authorize", popupName: "oauth", channelName: "oauth-channel", onResult: () => {}, }); teardown(); Object.defineProperty(globalThis, "window", { configurable: true, value: previousWindow, writable: true, }); expect(opened).toBe("about:blank"); expect(popup.opener).toBeUndefined(); expect(popup.location.href).toBe("https://auth.example/authorize"); expect(features).toContain("popup=1"); expect(features).not.toContain("noopener"); expect(features).not.toContain("noreferrer"); }); it("can reserve the popup before an async authorization start", () => { let opened = ""; const popup: FakePopup = { closed: false, close: () => {}, location: { href: "" } }; const previousWindow = globalThis.window; const fakeWindow: OAuthPopupTestWindow = { screenX: 0, screenY: 0, outerWidth: 1200, outerHeight: 900, location: { origin: "https://app.example" }, addEventListener: () => {}, removeEventListener: () => {}, open: (url: string) => { opened = url; return popup; }, }; Object.defineProperty(globalThis, "window", { configurable: true, value: fakeWindow, writable: true, }); const reservedPopup = reserveOAuthPopup({ popupName: "oauth" }); const teardown = openOAuthPopup({ url: "https://auth.example/authorize", popupName: "oauth", channelName: "oauth-channel", reservedPopup: reservedPopup ?? undefined, onResult: () => {}, }); teardown(); Object.defineProperty(globalThis, "window", { configurable: true, value: previousWindow, writable: true, }); expect(opened).toBe("about:blank"); expect(reservedPopup).not.toBeNull(); expect(popup.opener).toBeUndefined(); expect(popup.location.href).toBe("https://auth.example/authorize"); }); it("opens HTTP authorization URLs returned by local flows", () => { let opened = ""; const popup: FakePopup = { closed: false, close: () => {}, location: { href: "" } }; const previousWindow = globalThis.window; const fakeWindow: OAuthPopupTestWindow = { screenX: 0, screenY: 0, outerWidth: 1200, outerHeight: 900, location: { origin: "http://127.0.0.1:4000" }, addEventListener: () => {}, removeEventListener: () => {}, open: (url: string) => { opened = url; return popup; }, }; Object.defineProperty(globalThis, "window", { configurable: true, value: fakeWindow, writable: true, }); const teardown = openOAuthPopup({ url: "http://example.com/authorize", popupName: "oauth", channelName: "oauth-channel", onResult: () => {}, }); teardown(); Object.defineProperty(globalThis, "window", { configurable: true, value: previousWindow, writable: true, }); expect(opened).toBe("about:blank"); expect(popup.location.href).toBe("http://example.com/authorize"); }); it("can disable popup.closed polling for providers with strict opener policies", () => { let closedCalled = false; let intervalStarted = false; const popup: FakePopup = { closed: true, close: () => {}, location: { href: "" } }; const previousWindow = globalThis.window; const previousSetInterval = globalThis.setInterval; const fakeWindow: OAuthPopupTestWindow = { screenX: 0, screenY: 0, outerWidth: 1200, outerHeight: 900, location: { origin: "https://app.example" }, addEventListener: () => {}, removeEventListener: () => {}, open: () => popup, }; Object.defineProperty(globalThis, "window", { configurable: true, value: fakeWindow, writable: true, }); Object.defineProperty(globalThis, "setInterval", { configurable: true, value: () => { intervalStarted = true; return 1; }, writable: true, }); const teardown = openOAuthPopup({ url: "https://auth.example/authorize", popupName: "oauth", channelName: "oauth-channel", closedPollMs: null, onResult: () => {}, onClosed: () => { closedCalled = true; }, }); teardown(); Object.defineProperty(globalThis, "window", { configurable: true, value: previousWindow, writable: true, }); Object.defineProperty(globalThis, "setInterval", { configurable: true, value: previousSetInterval, writable: true, }); expect(intervalStarted).toBe(false); expect(closedCalled).toBe(false); }); });