/** * Tests for the 15-minute session keep-alive ping in useDraftAuthRecovery. * * Verifies that: * - A network TypeError (fetch throws) is silently swallowed and does NOT * set authDegraded, because a transient network drop should not trigger the * "Session Expired" overlay mid-draft. * - A null session response (in-band 401 / expired) DOES set authDegraded. * - A valid session response leaves authDegraded false. */ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { renderHook, act } from "@testing-library/react"; import { useDraftAuthRecovery } from "../useDraftAuthRecovery"; // --------------------------------------------------------------------------- // Mock auth-client // --------------------------------------------------------------------------- const { mockGetSession } = vi.hoisted(() => ({ mockGetSession: vi.fn(), })); vi.mock("~/lib/auth-client", () => ({ authClient: { getSession: mockGetSession }, })); // --------------------------------------------------------------------------- // Minimal hook params — only what the interval ping needs // --------------------------------------------------------------------------- function makeParams() { return { reconnectCount: 0, revalidate: vi.fn(), revalidatorState: "idle" as const, currentUserId: "user-1", userAutodraftSettings: null, draftPicks: [], season: {} as any, userQueue: [], timers: [], autodraftSettings: [], setPicks: vi.fn(), setCurrentPick: vi.fn(), setIsPaused: vi.fn(), setIsDraftComplete: vi.fn(), setQueue: vi.fn(), setTeamTimers: vi.fn(), setAutodraftStatus: vi.fn(), setIsSyncing: vi.fn(), setUserAutodraft: vi.fn(), }; } const FIFTEEN_MINUTES = 15 * 60 * 1000; // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- describe("useDraftAuthRecovery — session keep-alive ping", () => { beforeEach(() => { vi.useFakeTimers(); mockGetSession.mockReset(); }); afterEach(() => { vi.useRealTimers(); }); it("does NOT set authDegraded when getSession() throws a network TypeError", async () => { mockGetSession.mockRejectedValue(new TypeError("Failed to fetch")); const { result } = renderHook(() => useDraftAuthRecovery(makeParams())); expect(result.current.authDegraded).toBe(false); await act(async () => { vi.advanceTimersByTime(FIFTEEN_MINUTES); // flush the async callback await Promise.resolve(); }); expect(result.current.authDegraded).toBe(false); }); it("sets authDegraded when getSession() returns null data (session expired)", async () => { mockGetSession.mockResolvedValue({ data: null, error: { status: 401 } }); const { result } = renderHook(() => useDraftAuthRecovery(makeParams())); expect(result.current.authDegraded).toBe(false); await act(async () => { vi.advanceTimersByTime(FIFTEEN_MINUTES); await Promise.resolve(); }); expect(result.current.authDegraded).toBe(true); }); it("leaves authDegraded false when getSession() returns a valid session", async () => { mockGetSession.mockResolvedValue({ data: { userId: "user-1" }, error: null, }); const { result } = renderHook(() => useDraftAuthRecovery(makeParams())); await act(async () => { vi.advanceTimersByTime(FIFTEEN_MINUTES); await Promise.resolve(); }); expect(result.current.authDegraded).toBe(false); }); });