57dc91585d
Internal SmartGift build of a Claude Code monitoring dashboard. Lanes: a durable unit of parallel agent work, one per working directory, tracked across session restarts. Managed lanes are git worktrees the dashboard provisions and can reset or remove behind a three-check destroy guard and a counted preflight; adopted lanes are directories you already own and are never destroyable. Pipelines: a lane moves through pipeline stages. A stage the agent declares with evidence renders green; a stage inferred from the tool-event stream renders dashed amber and never counts as done. Detection is forward-only within a 30-minute window, and never writes the declared stage. Workspace: one page at /run with a lane grid, the selected lane's pipeline, and a full Claude console behind a disclosure.
97 lines
2.4 KiB
TypeScript
97 lines
2.4 KiB
TypeScript
/**
|
|
* @file eventBus.test.ts
|
|
* @description Unit tests for the eventBus module to ensure correct subscription, publishing, and unsubscription behavior in the agent dashboard application.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import { describe, it, expect, vi } from "vitest";
|
|
import { eventBus } from "../eventBus";
|
|
import type { WSMessage } from "../types";
|
|
|
|
function makeMsg(type: WSMessage["type"] = "new_event"): WSMessage {
|
|
return {
|
|
type,
|
|
data: {
|
|
id: 1,
|
|
session_id: "s1",
|
|
agent_id: null,
|
|
event_type: "PreToolUse",
|
|
tool_name: "Bash",
|
|
summary: "test",
|
|
data: null,
|
|
created_at: new Date().toISOString(),
|
|
},
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
describe("eventBus", () => {
|
|
it("should call subscriber when message is published", () => {
|
|
const handler = vi.fn();
|
|
const unsub = eventBus.subscribe(handler);
|
|
|
|
const msg = makeMsg();
|
|
eventBus.publish(msg);
|
|
|
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
expect(handler).toHaveBeenCalledWith(msg);
|
|
|
|
unsub();
|
|
});
|
|
|
|
it("should support multiple subscribers", () => {
|
|
const h1 = vi.fn();
|
|
const h2 = vi.fn();
|
|
const u1 = eventBus.subscribe(h1);
|
|
const u2 = eventBus.subscribe(h2);
|
|
|
|
eventBus.publish(makeMsg());
|
|
|
|
expect(h1).toHaveBeenCalledTimes(1);
|
|
expect(h2).toHaveBeenCalledTimes(1);
|
|
|
|
u1();
|
|
u2();
|
|
});
|
|
|
|
it("should stop calling handler after unsubscribe", () => {
|
|
const handler = vi.fn();
|
|
const unsub = eventBus.subscribe(handler);
|
|
|
|
eventBus.publish(makeMsg());
|
|
expect(handler).toHaveBeenCalledTimes(1);
|
|
|
|
unsub();
|
|
|
|
eventBus.publish(makeMsg());
|
|
expect(handler).toHaveBeenCalledTimes(1); // still 1
|
|
});
|
|
|
|
it("should not fail when publishing with no subscribers", () => {
|
|
expect(() => eventBus.publish(makeMsg())).not.toThrow();
|
|
});
|
|
|
|
it("should handle unsubscribe called multiple times", () => {
|
|
const handler = vi.fn();
|
|
const unsub = eventBus.subscribe(handler);
|
|
|
|
unsub();
|
|
unsub(); // second call should be harmless
|
|
|
|
eventBus.publish(makeMsg());
|
|
expect(handler).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("should not add duplicate handler references", () => {
|
|
const handler = vi.fn();
|
|
const u1 = eventBus.subscribe(handler);
|
|
const u2 = eventBus.subscribe(handler); // same ref, Set deduplicates
|
|
|
|
eventBus.publish(makeMsg());
|
|
expect(handler).toHaveBeenCalledTimes(1); // Set prevents double-add
|
|
|
|
u1();
|
|
u2();
|
|
});
|
|
});
|