Files
fusion/packages/cli/src/commands/dashboard-tui/__tests__/log-ring-buffer.test.ts
gsxdsm b890c57a29 feat(cli): merge @fusion/tui into fn dashboard with Ink TUI
Replace the legacy ANSI-based DashboardTUI with an Ink/React rewrite
under packages/cli/src/commands/dashboard-tui/, delete the standalone
@fusion/tui package, and make `fn` (no args) launch the dashboard.

The new TUI keeps the existing 5-panel status mode (system, logs,
utilities, stats, settings) but adds an interactive mode (b/a/g) with
three views: a kanban board with project picker and per-task detail,
an agents list+detail with state management, and a settings editor.
Bordered focus-aware panels, solid-background help overlay, static
all-blue FUSION splash that adapts to small terminals. DashboardTUI
and DashboardLogSink public API are unchanged so dashboard.ts only
needed import-path updates plus interactiveData/loadingStatus wiring.

Also adds zod to @fusion/dashboard to satisfy a peer dep introduced
by pi-coding-agent 0.70.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 19:39:20 -07:00

68 lines
2.5 KiB
TypeScript

import { describe, it, expect, beforeEach } from "vitest";
import { LogRingBuffer } from "../log-ring-buffer.js";
describe("LogRingBuffer", () => {
let buffer: LogRingBuffer;
beforeEach(() => {
buffer = new LogRingBuffer();
});
it("stores entries and reports total count", () => {
buffer.push({ timestamp: new Date(), level: "info", message: "test1" });
buffer.push({ timestamp: new Date(), level: "warn", message: "test2" });
expect(buffer.total).toBe(2);
});
it("returns all entries in chronological order", () => {
buffer.push({ timestamp: new Date("2026-01-01T10:00:00"), level: "info", message: "first" });
buffer.push({ timestamp: new Date("2026-01-01T11:00:00"), level: "info", message: "second" });
const entries = buffer.getAll();
expect(entries.length).toBe(2);
expect(entries[0].message).toBe("first");
expect(entries[1].message).toBe("second");
});
it("caps at MAX_LOG_ENTRIES (1000)", () => {
for (let i = 0; i < 1500; i++) {
buffer.push({ timestamp: new Date(), level: "info", message: `entry-${i}` });
}
const entries = buffer.getAll();
expect(entries.length).toBe(1000);
expect(buffer.total).toBe(1500);
});
it("maintains chronological order when overwriting", () => {
for (let i = 0; i < 1500; i++) {
buffer.push({ timestamp: new Date(2026, 0, 1, 0, i), level: "info", message: `entry-${i}` });
}
const entries = buffer.getAll();
expect(entries.length).toBe(1000);
expect(entries[0].message).toBe("entry-500");
expect(entries[entries.length - 1].message).toBe("entry-1499");
});
it("clears all entries", () => {
buffer.push({ timestamp: new Date(), level: "info", message: "test" });
buffer.clear();
expect(buffer.getAll().length).toBe(0);
expect(buffer.total).toBe(0);
});
it("stores entries with different levels", () => {
buffer.push({ timestamp: new Date(), level: "info", message: "info msg" });
buffer.push({ timestamp: new Date(), level: "warn", message: "warn msg" });
buffer.push({ timestamp: new Date(), level: "error", message: "error msg" });
const entries = buffer.getAll();
expect(entries[0].level).toBe("info");
expect(entries[1].level).toBe("warn");
expect(entries[2].level).toBe("error");
});
it("stores entries with prefix", () => {
buffer.push({ timestamp: new Date(), level: "info", message: "msg", prefix: "engine" });
const entries = buffer.getAll();
expect(entries[0].prefix).toBe("engine");
});
});