import { describe, expect, it, vi } from "vitest"; import type { DocumentId } from "@shared/ids"; import { createEventBus } from "./bus"; const docId = "doc_test" as DocumentId; const minimalDoc = { id: docId, mediaType: "application/pdf", createdAt: "2026-05-25T00:00:00.000Z", updatedAt: "2026-05-25T00:00:00.000Z", }; describe("EventBus", () => { it("delivers typed events to the registered listener", () => { const bus = createEventBus(); const spy = vi.fn(); bus.on("DocumentImported", spy); const result = bus.emit({ type: "DocumentImported", documentId: docId, document: minimalDoc }); expect(spy).toHaveBeenCalledOnce(); expect(spy.mock.calls[0]![0]).toMatchObject({ type: "DocumentImported", documentId: docId }); expect(result.listenerCount).toBe(1); expect(result.errors).toEqual([]); }); it("does not deliver an event to listeners of a different type", () => { const bus = createEventBus(); const spy = vi.fn(); bus.on("AnnotationCreated", spy); bus.emit({ type: "DocumentImported", documentId: docId, document: minimalDoc }); expect(spy).not.toHaveBeenCalled(); }); it("delivers every event to onAny listeners", () => { const bus = createEventBus(); const spy = vi.fn(); bus.onAny(spy); bus.emit({ type: "DocumentImported", documentId: docId, document: minimalDoc }); bus.emit({ type: "EvidenceItemActivated", evidenceItemId: "ev_x" as never }); expect(spy).toHaveBeenCalledTimes(2); }); it("returns an unsubscribe function from on()", () => { const bus = createEventBus(); const spy = vi.fn(); const off = bus.on("DocumentImported", spy); off(); bus.emit({ type: "DocumentImported", documentId: docId, document: minimalDoc }); expect(spy).not.toHaveBeenCalled(); }); it("captures listener errors and still calls subsequent listeners", () => { const bus = createEventBus(); const boom = new Error("listener exploded"); const a = vi.fn(() => { throw boom; }); const b = vi.fn(); bus.on("DocumentImported", a); bus.on("DocumentImported", b); const result = bus.emit({ type: "DocumentImported", documentId: docId, document: minimalDoc }); expect(a).toHaveBeenCalledOnce(); expect(b).toHaveBeenCalledOnce(); expect(result.errors).toEqual([boom]); expect(result.listenerCount).toBe(2); }); });