import { JSDOM } from "jsdom"; import { beforeEach, describe, expect, test, vi } from "vitest"; import { bootPopup } from "../src/popup/index"; describe("popup-entry", () => { let dom: JSDOM; beforeEach(() => { dom = new JSDOM(""); }); test("renders a sign-in button when unauthenticated", async () => { dom.window.document.body.innerHTML = "
"; await bootPopup({ document: dom.window.document, sendMessage: vi.fn(async () => ({ ok: true, type: "auth:state", value: { isAuthenticated: false } })) }); expect(dom.window.document.querySelector("button")?.textContent).toContain( "登录" ); }); test("renders the dev auth panel when enabled", async () => { dom.window.document.body.innerHTML = "
"; await bootPopup({ config: { enableDevAuthPanel: true }, document: dom.window.document, sendMessage: vi.fn(async () => ({ ok: true, type: "auth:state", value: { accessTokenExpiresAt: 1700000000000, isAuthenticated: true, resource: "https://api.example.test", scopes: ["openid", "profile"], tokenAvailable: true, userInfo: { email: "dev@example.com", name: "Dev" } } })) }); expect(dom.window.document.body.textContent).toContain("resource"); expect(dom.window.document.body.textContent).toContain("token"); }); test("renders a protected api test button in the dev panel", async () => { dom.window.document.body.innerHTML = "
"; await bootPopup({ config: { enableDevAuthPanel: true }, document: dom.window.document, sendMessage: vi.fn(async () => ({ ok: true, type: "auth:state", value: { isAuthenticated: true, tokenAvailable: true } })) }); expect( dom.window.document.querySelector('[data-popup-test-protected-api="button"]') ).not.toBeNull(); }); test("clicking the dev button runs the protected api client and prints the result", async () => { const fetchProtectedApi = vi.fn(async () => ({ message: "authorized", ok: true, source: "mock-protected-api" })); const sendMessage = vi.fn(async () => ({ ok: true, type: "auth:state", value: { isAuthenticated: true, tokenAvailable: true } })); dom.window.document.body.innerHTML = "
"; await bootPopup({ config: { enableDevAuthPanel: true }, document: dom.window.document, fetchProtectedApi, sendMessage }); ( dom.window.document.querySelector( '[data-popup-test-protected-api="button"]' ) as HTMLButtonElement | null )?.click(); await Promise.resolve(); expect(fetchProtectedApi).toHaveBeenCalledTimes(1); expect(dom.window.document.body.textContent).toContain("authorized"); expect(dom.window.document.body.textContent).toContain("mock-protected-api"); }); test("clicking sign-out sends the auth:sign-out message", async () => { const sendMessage = vi .fn() .mockResolvedValueOnce({ ok: true, type: "auth:state", value: { isAuthenticated: true, userInfo: { email: "dev@example.com", name: "Dev" } } }) .mockResolvedValueOnce({ ok: true, type: "auth:ack" }) .mockResolvedValueOnce({ ok: true, type: "auth:state", value: { isAuthenticated: false } }); dom.window.document.body.innerHTML = "
"; await bootPopup({ document: dom.window.document, sendMessage }); ( dom.window.document.querySelector('[data-popup-sign-out="button"]') as | HTMLButtonElement | null )?.click(); await Promise.resolve(); expect(sendMessage).toHaveBeenCalledWith({ type: "auth:sign-out" }); }); test("shows the auth error when sign-in fails", async () => { const sendMessage = vi .fn() .mockResolvedValueOnce({ ok: true, type: "auth:state", value: { isAuthenticated: false } }) .mockResolvedValueOnce({ error: "redirect_uri_mismatch", ok: false, type: "auth:error" }); dom.window.document.body.innerHTML = "
"; await bootPopup({ document: dom.window.document, sendMessage }); ( dom.window.document.querySelector('[data-popup-sign-in="button"]') as | HTMLButtonElement | null )?.click(); await Promise.resolve(); expect(dom.window.document.body.textContent).toContain( "redirect_uri_mismatch" ); }); });