import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { renderHook, waitFor, act } from "@testing-library/react"; let esInstances: { onmessage?: (e: MessageEvent) => void; onerror?: () => void; onopen?: () => void; close: ReturnType }[] = []; class MockEventSource { onmessage: ((e: MessageEvent) => void) | null = null; onerror: (() => void) | null = null; onopen: (() => void) | null = null; close = vi.fn(); constructor(_url: string) { esInstances.push(this); } } vi.stubGlobal("EventSource", MockEventSource); vi.mock("swr", () => ({ default: vi.fn().mockReturnValue({ data: { roomId: "ROOM01", userCount: 2, match: null, matchType: null, matchLikes: 0, runnerUps: [], likeCounts: {}, swipeCounts: {}, restaurants: [], creatorId: "user-1", locked: false, users: ["user-1", "user-2"], userProfiles: {}, scene: "eat", }, error: null, isLoading: false, mutate: vi.fn(), }), })); import { useRoomPolling } from "./useRoomPolling"; beforeEach(() => { esInstances = []; }); afterEach(() => { vi.clearAllMocks(); }); describe("useRoomPolling", () => { it("returns room data from SWR", () => { const { result } = renderHook(() => useRoomPolling("ROOM01")); expect(result.current.userCount).toBe(2); expect(result.current.users).toEqual(["user-1", "user-2"]); expect(result.current.scene).toBe("eat"); }); it("creates EventSource connection", () => { renderHook(() => useRoomPolling("ROOM01")); expect(esInstances.length).toBeGreaterThan(0); }); it("returns defaults when no roomId", () => { const { result } = renderHook(() => useRoomPolling(undefined)); expect(result.current.userCount).toBe(2); }); it("returns notFound from error state", async () => { const useSWR = vi.mocked((await import("swr")).default); useSWR.mockReturnValue({ data: undefined, error: new Error("NOT_FOUND"), isLoading: false, mutate: vi.fn(), } as never); const { result } = renderHook(() => useRoomPolling("ROOM01")); expect(result.current.notFound).toBe(true); }); it("cleans up EventSource on unmount", () => { const { unmount } = renderHook(() => useRoomPolling("ROOM01")); const es = esInstances[esInstances.length - 1]; unmount(); expect(es.close).toHaveBeenCalled(); }); });