import { afterEach, describe, expect, mock, test } from "bun:test"; import { startRealtimeRefresh, type RealtimeRefreshHandlers, } from "@/lib/realtime-refresh"; const cleanups: Array<() => void> = []; afterEach(() => { for (const clean of cleanups.splice(0)) clean(); }); function setup( filter: Parameters[0]["filter"], debounceMs = 10, ) { let handlers: RealtimeRefreshHandlers | undefined; const refresh = mock(() => {}); const cleanSubscription = mock(() => {}); const clean = startRealtimeRefresh({ filter, debounceMs, refresh, subscribe(nextHandlers) { handlers = nextHandlers; return { clean: cleanSubscription }; }, }); cleanups.push(clean); return { get handlers() { if (!handlers) throw new Error("Handlers were not registered."); return handlers; }, refresh, clean, cleanSubscription, }; } describe("leaderboard realtime refresh", () => { test("filters XP and VC events by leaderboard scope", async () => { const xp = setup({ kind: "xp" }); xp.handlers.onVc({ channelId: "1" }); xp.handlers.onXp(); await Bun.sleep(20); expect(xp.refresh).toHaveBeenCalledTimes(1); const selectedVc = setup({ kind: "vc", channelId: "2" }); selectedVc.handlers.onVc({ channelId: "1" }); await Bun.sleep(20); expect(selectedVc.refresh).not.toHaveBeenCalled(); selectedVc.handlers.onVc({ channelId: "2" }); await Bun.sleep(20); expect(selectedVc.refresh).toHaveBeenCalledTimes(1); const allVc = setup({ kind: "vc" }); allVc.handlers.onVc({ channelId: "any" }); await Bun.sleep(20); expect(allVc.refresh).toHaveBeenCalledTimes(1); }); test("refreshes after reconnect but not the initial connection", async () => { const subscription = setup({ kind: "xp" }); subscription.handlers.onOpen(); await Bun.sleep(20); expect(subscription.refresh).not.toHaveBeenCalled(); subscription.handlers.onOpen(); await Bun.sleep(20); expect(subscription.refresh).toHaveBeenCalledTimes(1); }); test("debounces event bursts and cleans timers and subscriptions", async () => { const subscription = setup({ kind: "xp" }, 20); subscription.handlers.onXp(); subscription.handlers.onXp(); subscription.handlers.onXp(); await Bun.sleep(30); expect(subscription.refresh).toHaveBeenCalledTimes(1); subscription.handlers.onXp(); subscription.clean(); await Bun.sleep(30); expect(subscription.refresh).toHaveBeenCalledTimes(1); expect(subscription.cleanSubscription).toHaveBeenCalledTimes(1); }); });