import { createTheme, ThemeProvider } from "@mui/material/styles"; import { act, fireEvent, render, screen } from "@testing-library/react"; import { signIn } from "next-auth/react"; import { useAuthStore } from "@/store/authStore"; import { SessionExpiryDialog } from "./SessionExpiryDialog"; jest.mock("next-auth/react", () => ({ signIn: jest.fn(), })); describe("SessionExpiryDialog", () => { beforeEach(() => { jest.useFakeTimers(); jest.mocked(signIn).mockReset().mockResolvedValue(undefined); useAuthStore.setState({ accessToken: null, sessionExpired: true, sessionExpiryReason: "unauthorized", }); }); afterEach(() => { act(() => useAuthStore.getState().clearSessionExpired()); jest.useRealTimers(); }); it("renders above every regular application overlay", () => { const theme = createTheme(); render( , ); const dialogRoot = screen.getByRole("dialog").closest(".MuiModal-root"); expect(dialogRoot).not.toBeNull(); expect(dialogRoot).toHaveStyle({ zIndex: theme.zIndex.tooltip + 1, }); }); it("shows the expired state before automatically starting login", () => { window.history.replaceState({}, "", "/network-simulation?tab=history"); render(); expect(screen.getByText("登录已过期")).toBeInTheDocument(); expect(screen.getByText("即将自动跳转到登录页面。")) .toBeInTheDocument(); expect(signIn).not.toHaveBeenCalled(); act(() => { jest.advanceTimersByTime(2_000); }); expect(signIn).toHaveBeenCalledTimes(1); expect(signIn).toHaveBeenCalledWith("keycloak", { callbackUrl: "/network-simulation?tab=history", redirect: true, }); }); it("allows a retry when starting automatic login fails", async () => { jest.mocked(signIn) .mockRejectedValueOnce(new Error("network unavailable")) .mockResolvedValueOnce(undefined); render(); await act(async () => { jest.advanceTimersByTime(2_000); }); fireEvent.click(screen.getByRole("button", { name: "重新认证" })); expect(signIn).toHaveBeenCalledTimes(2); }); });