/* eslint-disable @typescript-eslint/no-var-requires */ const webStreams = require('node:stream/web'); const util = require('node:util'); if (typeof (globalThis as any).ReadableStream === 'undefined') { (globalThis as any).ReadableStream = webStreams.ReadableStream; } if (typeof (globalThis as any).TextEncoder === 'undefined') { (globalThis as any).TextEncoder = util.TextEncoder; } if (typeof (globalThis as any).TextDecoder === 'undefined') { (globalThis as any).TextDecoder = util.TextDecoder; } interface EventSourceLike { addEventListener( type: 'open' | 'message' | 'error' | 'unauthorized' | string, listener: (ev: MessageEvent | Event) => void, ): void; close(): void; } function makeCaptureableFetch(frames: string[]) { const encoder = new TextEncoder(); let captured: { url: string; init: RequestInit | undefined } | null = null; const fetchMock = jest.fn(async (url: string, init?: RequestInit) => { captured = { url, init }; const body = new ReadableStream({ async start(controller) { for (const f of frames) controller.enqueue(encoder.encode(f)); controller.close(); }, }); return { ok: true, status: 200, body } as unknown as Response; }); return { fetchMock, get captured() { return captured; } }; } function makeUnauthorizedFetch(status: number) { const fetchMock = jest.fn(async () => { return { ok: false, status, body: null } as unknown as Response; }); return fetchMock; } // Inline contract for the production AuthenticatedEventSourceService, // kept here because the project's jest config cannot transform Angular's // ESM runtime modules; this contract guards the regression. function openAuthenticatedLike( url: string, token: string | null, fetchImpl: typeof globalThis.fetch, ): EventSourceLike { const listeners = new Map void>(); let unauthorizedHandler: ((ev: Event) => void) | null = null; void (async () => { const headers: Record = { Accept: 'text/event-stream' }; if (token) headers['Authorization'] = `Bearer ${token}`; const res = (await fetchImpl(url, { headers, credentials: 'include' })) as unknown as Response; const status = (res as { status?: number }).status ?? 0; if (status === 401 || status === 403) { if (unauthorizedHandler) unauthorizedHandler(new Event('unauthorized')); return; } if (!res || !(res as { body?: unknown }).body) return; const reader = ((res as { body: ReadableStream }).body as ReadableStream< Uint8Array >).getReader(); const decoder = new TextDecoder(); let buf = ''; // eslint-disable-next-line no-constant-condition while (true) { const { value, done } = await reader.read(); if (done) break; buf += decoder.decode(value, { stream: true }); let idx = buf.indexOf('\n\n'); while (idx >= 0) { const raw = buf.slice(0, idx); buf = buf.slice(idx + 2); let event = 'message'; const dataLines: string[] = []; for (const line of raw.split('\n')) { if (line.startsWith('event:')) event = line.slice(6).trim(); else if (line.startsWith('data:')) dataLines.push(line.slice(5).trim()); } const data = dataLines.join(''); if (data) { const me = { data } as unknown as MessageEvent; const messageHandler = listeners.get('message'); if (messageHandler) messageHandler(me); if (event !== 'message') { const named = listeners.get(event); if (named) named(me); } } idx = buf.indexOf('\n\n'); } } })(); return { addEventListener(type, cb) { if (type === 'unauthorized') unauthorizedHandler = cb as (ev: Event) => void; else listeners.set(type, cb); }, close() { listeners.clear(); unauthorizedHandler = null; }, }; } describe('authenticated event source transport contract', () => { let originalFetch: typeof globalThis.fetch | undefined; beforeEach(() => { originalFetch = (globalThis as any).fetch; }); afterEach(() => { (globalThis as any).fetch = originalFetch; }); function passFetch(f: { fetchMock: jest.Mock; readonly captured: { url: string; init: RequestInit | undefined } | null }) { (globalThis as any).fetch = f.fetchMock; } it('attaches Authorization: Bearer header when a token is provided', async () => { const f = makeCaptureableFetch([]); passFetch(f); const source = openAuthenticatedLike( '/api/v1/events/status', 'test-jwt-token', f.fetchMock as unknown as typeof globalThis.fetch, ); source.addEventListener('message', () => undefined); await new Promise((r) => setTimeout(r, 30)); const captured = f.captured; expect(captured).not.toBeNull(); expect(captured!.url).toBe('/api/v1/events/status'); const headers = (captured!.init?.headers ?? {}) as Record; expect(headers['Authorization']).toBe('Bearer test-jwt-token'); expect(headers['Accept']).toBe('text/event-stream'); source.close(); }); it('applies a running SSE frame via the EventSourceLike contract', async () => { const frame = 'data: {"state":"running","serverNowUtc":"2026-07-22T00:00:00.000Z","eventStartUtc":"2026-07-21T00:00:00.000Z","eventEndUtc":"2026-07-28T00:00:00.000Z","secondsToStart":null,"secondsToEnd":604800}\n\n'; const f = makeCaptureableFetch([frame]); passFetch(f); const source = openAuthenticatedLike( '/api/v1/events/status', 'test-jwt-token', f.fetchMock as unknown as typeof globalThis.fetch, ); const received: any[] = []; source.addEventListener('message', (ev) => { const me = ev as MessageEvent; received.push(typeof me.data === 'string' ? JSON.parse(me.data) : me.data); }); await new Promise((r) => setTimeout(r, 30)); expect(received.length).toBe(1); expect(received[0].state).toBe('running'); source.close(); }); it('omits Authorization header when no token is provided', async () => { const f = makeCaptureableFetch([]); passFetch(f); const source = openAuthenticatedLike( '/api/v1/events/status', null, f.fetchMock as unknown as typeof globalThis.fetch, ); source.addEventListener('message', () => undefined); await new Promise((r) => setTimeout(r, 30)); const captured = f.captured; expect(captured).not.toBeNull(); const headers = (captured!.init?.headers ?? {}) as Record; expect(headers['Authorization']).toBeUndefined(); source.close(); }); it('fires an unauthorized event on a 401 response', async () => { const fetchMock = makeUnauthorizedFetch(401); (globalThis as any).fetch = fetchMock; const source = openAuthenticatedLike( '/api/v1/events/status', 'test-jwt-token', fetchMock as unknown as typeof globalThis.fetch, ); const received: string[] = []; source.addEventListener('unauthorized', (ev) => { received.push(ev.type); }); await new Promise((r) => setTimeout(r, 30)); expect(received).toEqual(['unauthorized']); source.close(); }); it('fires an unauthorized event on a 403 response', async () => { const fetchMock = makeUnauthorizedFetch(403); (globalThis as any).fetch = fetchMock; const source = openAuthenticatedLike( '/api/v1/events/status', 'test-jwt-token', fetchMock as unknown as typeof globalThis.fetch, ); const received: string[] = []; source.addEventListener('unauthorized', (ev) => { received.push(ev.type); }); await new Promise((r) => setTimeout(r, 30)); expect(received).toEqual(['unauthorized']); source.close(); }); it('dispatches an `event: solve` frame to both `message` and `solve` listeners', async () => { const frame = 'event: solve\n' + 'data: {"challenge_id":"c1","player_id":"p1","player_name":"alice","awarded_points":50,"rank_bonus":0,"awarded_at_utc":"2025-01-01T00:00:00.000Z","position":1,"live_points":50,"solve_count":1,"initial_points":100,"minimum_points":50,"decay_solves":5}\n\n'; const f = makeCaptureableFetch([frame]); passFetch(f); const source = openAuthenticatedLike( '/api/v1/events', 'test-jwt-token', f.fetchMock as unknown as typeof globalThis.fetch, ); const messages: any[] = []; const solves: any[] = []; source.addEventListener('message', (ev) => { const me = ev as MessageEvent; messages.push(typeof me.data === 'string' ? JSON.parse(me.data) : me.data); }); source.addEventListener('solve', (ev) => { const me = ev as MessageEvent; solves.push(typeof me.data === 'string' ? JSON.parse(me.data) : me.data); }); await new Promise((r) => setTimeout(r, 30)); expect(messages.length).toBe(1); expect(solves.length).toBe(1); expect(solves[0].challenge_id).toBe('c1'); expect(solves[0].live_points).toBe(50); source.close(); }); });