diff --git a/backend/src/lib/event-bus.test.ts b/backend/src/lib/event-bus.test.ts new file mode 100644 index 0000000..2125987 --- /dev/null +++ b/backend/src/lib/event-bus.test.ts @@ -0,0 +1,51 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { getEventBus, _resetEventBus } from './event-bus.js'; + +describe('DomainEventBus', () => { + beforeEach(() => { _resetEventBus(); }); + + it('delivers event to subscriber', async () => { + const bus = getEventBus(); + const handler = vi.fn(); + bus.on('note.created', handler); + await bus.emit('note.created', { noteId: 'n1', workspaceId: 'w1', userId: 'u1', title: 'Test' }); + expect(handler).toHaveBeenCalledOnce(); + }); + + it('unsubscribe stops delivery', async () => { + const bus = getEventBus(); + const handler = vi.fn(); + const unsub = bus.on('note.created', handler); + unsub(); + await bus.emit('note.created', { noteId: 'n1', workspaceId: 'w1', userId: 'u1', title: 'Test' }); + expect(handler).not.toHaveBeenCalled(); + }); + + it('failing handler does not block others', async () => { + const bus = getEventBus(); + const good = vi.fn(); + bus.on('note.created', () => { throw new Error('boom'); }); + bus.on('note.created', good); + await bus.emit('note.created', { noteId: 'n1', workspaceId: 'w1', userId: 'u1', title: 'Test' }); + expect(good).toHaveBeenCalledOnce(); + }); + + it('singleton returns same instance', () => { + expect(getEventBus()).toBe(getEventBus()); + }); + + it('_resetEventBus creates fresh instance', () => { + const a = getEventBus(); + _resetEventBus(); + expect(getEventBus()).not.toBe(a); + }); + + it('removeAll clears handlers', async () => { + const bus = getEventBus(); + const handler = vi.fn(); + bus.on('note.created', handler); + bus.removeAll(); + await bus.emit('note.created', { noteId: 'n1', workspaceId: 'w1', userId: 'u1', title: 'Test' }); + expect(handler).not.toHaveBeenCalled(); + }); +}); diff --git a/backend/src/lib/event-bus.ts b/backend/src/lib/event-bus.ts index 03b8425..ade36f9 100644 --- a/backend/src/lib/event-bus.ts +++ b/backend/src/lib/event-bus.ts @@ -61,7 +61,7 @@ class DomainEventBus { async emit(event: K, payload: NoteLettEventMap[K]): Promise { const fns = this.handlers.get(event); if (!fns || fns.size === 0) return; - await Promise.allSettled([...fns].map(fn => fn(payload))); + await Promise.allSettled([...fns].map(fn => Promise.resolve().then(() => fn(payload)))); } removeAll(): void {