Files
AgentCompany/tests/unit/selective-ipc.test.ts
T
ZacharyZhang-NYandClaude Opus 4.6 920a764856 feat(09-01): define granular event types, IPC channels, entity getters, and Zustand patch methods
- Add 5 granular event interfaces (TaskUpdated, RunUpdated, ApprovalUpdated, AgentUpdated, BudgetChanged) to DesktopEvent union
- Add 4 entity getter IPC channels (getTask, getAgent, getRun, getApproval) with Zod validation and company ownership checks
- Add getRun method to AppDatabase following existing getTask pattern
- Add 4 preload bridge methods for entity getters
- Add 8 patch/remove methods and refreshBadges to CompanySlice
- Add selective-ipc.test.ts with exhaustive union type tests
- Extend store.test.ts with 14 patch method tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:33:33 -04:00

118 lines
3.6 KiB
TypeScript

import { describe, it, expect } from "vitest";
import type {
DesktopEvent,
TaskUpdatedEvent,
RunUpdatedEvent,
ApprovalUpdatedEvent,
AgentUpdatedEvent,
BudgetChangedEvent,
} from "@shared/types";
describe("selective IPC event types", () => {
it("TaskUpdatedEvent discriminated by type field", () => {
const event: TaskUpdatedEvent = {
type: "task-updated",
taskId: "t-1",
action: "created",
};
expect(event.type).toBe("task-updated");
expect(event.taskId).toBe("t-1");
expect(event.action).toBe("created");
});
it("RunUpdatedEvent discriminated by type field", () => {
const event: RunUpdatedEvent = {
type: "run-updated",
runId: "r-1",
action: "completed",
};
expect(event.type).toBe("run-updated");
expect(event.runId).toBe("r-1");
expect(event.action).toBe("completed");
});
it("ApprovalUpdatedEvent discriminated by type field", () => {
const event: ApprovalUpdatedEvent = {
type: "approval-updated",
approvalId: "a-1",
action: "decided",
};
expect(event.type).toBe("approval-updated");
expect(event.approvalId).toBe("a-1");
expect(event.action).toBe("decided");
});
it("AgentUpdatedEvent discriminated by type field", () => {
const event: AgentUpdatedEvent = {
type: "agent-updated",
agentId: "ag-1",
action: "updated",
};
expect(event.type).toBe("agent-updated");
expect(event.agentId).toBe("ag-1");
expect(event.action).toBe("updated");
});
it("BudgetChangedEvent discriminated by type field", () => {
const event: BudgetChangedEvent = {
type: "budget-changed",
companyId: "c-1",
};
expect(event.type).toBe("budget-changed");
expect(event.companyId).toBe("c-1");
});
it("all five new event types are assignable to DesktopEvent union", () => {
const events: DesktopEvent[] = [
{ type: "task-updated", taskId: "t-1", action: "created" },
{ type: "run-updated", runId: "r-1", action: "status_changed" },
{ type: "approval-updated", approvalId: "a-1", action: "created" },
{ type: "agent-updated", agentId: "ag-1", action: "paused" },
{ type: "budget-changed", companyId: "c-1" },
];
expect(events).toHaveLength(5);
});
it("DesktopEvent union has all 14 members (9 original + 5 new)", () => {
// This is a compile-time check -- if any type is missing, TypeScript will error
const exhaustiveCheck = (event: DesktopEvent): string => {
switch (event.type) {
case "run-log":
return "run-log";
case "domain-changed":
return "domain-changed";
case "shortcut":
return "shortcut";
case "run-status":
return "run-status";
case "heartbeat-status":
return "heartbeat-status";
case "agent-message":
return "agent-message";
case "automation-fired":
return "automation-fired";
case "new-message":
return "new-message";
case "notification-click":
return "notification-click";
case "task-updated":
return "task-updated";
case "run-updated":
return "run-updated";
case "approval-updated":
return "approval-updated";
case "agent-updated":
return "agent-updated";
case "budget-changed":
return "budget-changed";
default: {
const _exhaustive: never = event;
return _exhaustive;
}
}
};
// Dummy call to avoid unused-var warning
expect(typeof exhaustiveCheck).toBe("function");
});
});