import { act, cleanup, render, screen } from "@testing-library/react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { BorrowConfirmationOverlay } from "../BorrowConfirmationOverlay"; describe("BorrowConfirmationOverlay", () => { beforeEach(() => { vi.useFakeTimers(); }); afterEach(() => { cleanup(); vi.useRealTimers(); }); it("auto-denies after countdown reaches zero and progress transition ends", async () => { const onAllow = vi.fn(); const onDeny = vi.fn(); const { container } = render( , ); expect(screen.getByText("允许借用标签页?")).toBeTruthy(); for (let i = 0; i < 5; i++) { await act(async () => { await vi.advanceTimersByTimeAsync(1000); }); } expect(screen.getByText("0 秒后自动拒绝")).toBeTruthy(); const progressCircle = container.querySelectorAll("svg circle")[1]; expect(progressCircle).toBeTruthy(); await act(() => { const event = new TransitionEvent("transitionend", { bubbles: true }); Object.defineProperty(event, "propertyName", { value: "stroke-dashoffset", configurable: true, }); progressCircle!.dispatchEvent(event); }); await act(async () => { await vi.advanceTimersByTimeAsync(150); }); expect(onDeny).toHaveBeenCalledTimes(1); expect(onAllow).not.toHaveBeenCalled(); }); it("auto-denies via timer fallback when progress transitionend never fires", async () => { const onAllow = vi.fn(); const onDeny = vi.fn(); render( , ); for (let i = 0; i < 5; i++) { await act(async () => { await vi.advanceTimersByTimeAsync(1000); }); } expect(screen.getByText("0 秒后自动拒绝")).toBeTruthy(); // No transitionend — the PROGRESS_TRANSITION_MS fallback must still deny. await act(async () => { await vi.advanceTimersByTimeAsync(1000); }); await act(async () => { await vi.advanceTimersByTimeAsync(150); }); expect(onDeny).toHaveBeenCalledTimes(1); expect(onAllow).not.toHaveBeenCalled(); }); it("only invokes onDeny once when deny is clicked repeatedly", async () => { const onAllow = vi.fn(); const onDeny = vi.fn(); render( , ); const denyButton = screen.getByRole("button", { name: "拒绝" }); denyButton.click(); denyButton.click(); await vi.advanceTimersByTimeAsync(150); expect(onDeny).toHaveBeenCalledTimes(1); expect(onAllow).not.toHaveBeenCalled(); }); });