65 lines
2.3 KiB
TypeScript
65 lines
2.3 KiB
TypeScript
|
|
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);
|
||
|
|
});
|
||
|
|
});
|