import { afterEach, describe, expect, it, vi } from 'vitest'; import { fetchState } from './useGameState'; // The hook's fetch logic (lib/useGameState.ts) against a mocked global fetch — the polling // loop itself is plain setInterval and covered by e2e (panes.spec.ts renders from it). const SNAPSHOT = { account: { cash: 20_000, reputation: 10 }, simState: { clockMs: 1_750_000_000_000 }, planes: [], packages: [], }; afterEach(() => { vi.unstubAllGlobals(); }); describe('fetchState', () => { it('GETs /api/state with no-store and returns the parsed snapshot on success', async () => { const fetchMock = vi.fn(async () => ({ ok: true, status: 200, json: async () => SNAPSHOT })); vi.stubGlobal('fetch', fetchMock); await expect(fetchState()).resolves.toEqual(SNAPSHOT); expect(fetchMock).toHaveBeenCalledTimes(1); expect(fetchMock).toHaveBeenCalledWith('/api/state', { cache: 'no-store' }); }); it('throws with the HTTP status on a non-2xx response', async () => { vi.stubGlobal('fetch', vi.fn(async () => ({ ok: false, status: 500, json: async () => ({}) }))); await expect(fetchState()).rejects.toThrow('GET /api/state → HTTP 500'); }); it('throws on a network failure (no response at all)', async () => { vi.stubGlobal('fetch', vi.fn(async () => { throw new Error('fetch failed'); })); await expect(fetchState()).rejects.toThrow('fetch failed'); }); });