import { describe, it, expect } from "vitest"; import { EventQueue } from "../src/queue.js"; import { TaskType, Complexity, Harness, Provider, Outcome, TaskCompletionEvent, } from "../src/types/events.js"; function makeEvent(id: string): TaskCompletionEvent { return { instance_id: "test-instance", event_id: id, schema_version: "1.0", timestamp: new Date().toISOString(), task_duration_ms: 1000, task_type: TaskType.IMPLEMENTATION, complexity: Complexity.MEDIUM, harness: Harness.CLAUDE_CODE, model: "claude-3-opus", provider: Provider.ANTHROPIC, estimated_input_tokens: 1000, estimated_output_tokens: 500, actual_input_tokens: 1100, actual_output_tokens: 550, estimated_cost_usd_micros: 50000, actual_cost_usd_micros: 55000, quality_gate_passed: true, quality_gates_run: [], quality_gates_failed: [], context_compactions: 0, context_rotations: 0, context_utilization_final: 0.5, outcome: Outcome.SUCCESS, retry_count: 0, }; } describe("EventQueue", () => { it("should enqueue and drain events", () => { const queue = new EventQueue(10); const event = makeEvent("e1"); queue.enqueue(event); expect(queue.size).toBe(1); expect(queue.isEmpty).toBe(false); const drained = queue.drain(10); expect(drained).toHaveLength(1); expect(drained[0].event_id).toBe("e1"); expect(queue.isEmpty).toBe(true); }); it("should respect maxSize with FIFO eviction", () => { const queue = new EventQueue(3); queue.enqueue(makeEvent("e1")); queue.enqueue(makeEvent("e2")); queue.enqueue(makeEvent("e3")); expect(queue.size).toBe(3); // Adding a 4th should evict the oldest (e1) queue.enqueue(makeEvent("e4")); expect(queue.size).toBe(3); const drained = queue.drain(10); expect(drained.map((e) => e.event_id)).toEqual(["e2", "e3", "e4"]); }); it("should drain up to maxItems", () => { const queue = new EventQueue(10); queue.enqueue(makeEvent("e1")); queue.enqueue(makeEvent("e2")); queue.enqueue(makeEvent("e3")); const drained = queue.drain(2); expect(drained).toHaveLength(2); expect(drained.map((e) => e.event_id)).toEqual(["e1", "e2"]); expect(queue.size).toBe(1); }); it("should remove drained items from the queue", () => { const queue = new EventQueue(10); queue.enqueue(makeEvent("e1")); queue.enqueue(makeEvent("e2")); queue.drain(1); expect(queue.size).toBe(1); const remaining = queue.drain(10); expect(remaining[0].event_id).toBe("e2"); }); it("should report isEmpty correctly", () => { const queue = new EventQueue(5); expect(queue.isEmpty).toBe(true); queue.enqueue(makeEvent("e1")); expect(queue.isEmpty).toBe(false); queue.drain(1); expect(queue.isEmpty).toBe(true); }); it("should report size correctly", () => { const queue = new EventQueue(10); expect(queue.size).toBe(0); queue.enqueue(makeEvent("e1")); expect(queue.size).toBe(1); queue.enqueue(makeEvent("e2")); expect(queue.size).toBe(2); queue.drain(1); expect(queue.size).toBe(1); }); it("should return empty array when draining empty queue", () => { const queue = new EventQueue(5); const drained = queue.drain(10); expect(drained).toEqual([]); }); it("should prepend events to the front of the queue", () => { const queue = new EventQueue(10); queue.enqueue(makeEvent("e3")); queue.prepend([makeEvent("e1"), makeEvent("e2")]); expect(queue.size).toBe(3); const drained = queue.drain(10); expect(drained.map((e) => e.event_id)).toEqual(["e1", "e2", "e3"]); }); it("should respect maxSize when prepending", () => { const queue = new EventQueue(3); queue.enqueue(makeEvent("e3")); queue.enqueue(makeEvent("e4")); // Only 1 slot available, so only first event should be prepended queue.prepend([makeEvent("e1"), makeEvent("e2")]); expect(queue.size).toBe(3); const drained = queue.drain(10); expect(drained.map((e) => e.event_id)).toEqual(["e1", "e3", "e4"]); }); });