From 87395110586258d11c46594de04234fbef9e022a Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 15 Apr 2026 15:09:26 +0200 Subject: [PATCH] test(notifications): add SSE event handling tests for useNotificationStream Adds MockEventSource.simulate() helper and two tests covering: - unread notification via SSE prepends to list and increments unreadCount - read notification via SSE adds to list but does not increment unreadCount Fixes @saraholt: "SSE event handling not tested" Co-Authored-By: Claude Sonnet 4.6 --- .../useNotificationStream.svelte.test.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/frontend/src/lib/hooks/__tests__/useNotificationStream.svelte.test.ts b/frontend/src/lib/hooks/__tests__/useNotificationStream.svelte.test.ts index d195406d..143844c5 100644 --- a/frontend/src/lib/hooks/__tests__/useNotificationStream.svelte.test.ts +++ b/frontend/src/lib/hooks/__tests__/useNotificationStream.svelte.test.ts @@ -6,6 +6,7 @@ let lastEventSource: { close: ReturnType; onopen: (() => void) | null; onerror: (() => void) | null; + simulate: (type: string, data: string) => void; } | null = null; class MockEventSource { @@ -23,6 +24,13 @@ class MockEventSource { if (!this.listeners[type]) this.listeners[type] = []; this.listeners[type].push(fn); } + + simulate(type: string, data: string) { + const event = new MessageEvent(type, { data }); + for (const fn of this.listeners[type] ?? []) { + fn(event); + } + } } vi.stubGlobal('EventSource', MockEventSource); @@ -106,4 +114,29 @@ describe('createNotificationStream', () => { stream.destroy(); expect(lastEventSource!.close).toHaveBeenCalled(); }); + + it('SSE notification event prepends notification and increments unreadCount', async () => { + mockFetch.mockResolvedValue(new Response(JSON.stringify({ count: 0 }), { status: 200 })); + const stream = createNotificationStream(); + stream.init(); + + const notification = makeNotification({ id: 'sse-1', read: false }); + lastEventSource!.simulate('notification', JSON.stringify(notification)); + + expect(stream.notifications).toHaveLength(1); + expect(stream.notifications[0].id).toBe('sse-1'); + expect(stream.unreadCount).toBe(1); + }); + + it('SSE notification event with read:true does not increment unreadCount', async () => { + mockFetch.mockResolvedValue(new Response(JSON.stringify({ count: 0 }), { status: 200 })); + const stream = createNotificationStream(); + stream.init(); + + const notification = makeNotification({ id: 'sse-2', read: true }); + lastEventSource!.simulate('notification', JSON.stringify(notification)); + + expect(stream.notifications).toHaveLength(1); + expect(stream.unreadCount).toBe(0); + }); });