import assert from "node:assert/strict";
import test from "node:test";
import * as React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import {
AccountSummaryPanel,
AnimatedUsageChart,
ChartShell,
ModelShareChart,
RadialMetric,
RangeSwitch,
RingMetrics,
SourceGrid,
StatsGrid,
TokenActivityPanel,
TokenMixPanel,
TrayStatusStrip,
UsageDetailPanel,
UsageOverviewPanel
} from "../../packages/ui/src/pages/tray/components/index.ts";
import { TrayApp } from "../../packages/ui/src/pages/tray/TrayApp.tsx";
import { TrayDetailApp } from "../../packages/ui/src/pages/tray/TrayDetailApp.tsx";
import { accountSnapshots, installBrowserGlobals, usageStats, usageTotals } from "./fixtures.ts";
installBrowserGlobals();
const componentVariants = {
account: "bar",
modelShare: "bars",
rings: "rings",
stats: "cards",
tokenFlow: "line",
tokenMix: "bars"
} as const;
test("UsageOverviewPanel renders every enabled overview tray module", () => {
const activeStats = usageStats("30d");
const html = renderToStaticMarkup(
);
assert.match(html, /openai \/ Primary Key/);
assert.match(html, /30d Token Flow/);
assert.match(html, /Activity/);
assert.match(html, /Today tokens/);
assert.match(html, /Token Mix/);
assert.match(html, /Circular metrics/);
assert.match(html, /Model Share/);
assert.match(html, /Syncing usage\.\.\./);
});
test("UsageDetailPanel renders configured detail widgets and empty state", () => {
const activeStats = usageStats("7d");
const html = renderToStaticMarkup(
undefined}
/>
);
const emptyHtml = renderToStaticMarkup(
undefined}
/>
);
assert.match(html, /Usage Detail/);
assert.match(html, /7d - OpenAI/);
assert.match(html, /7d tokens/);
assert.match(html, /Token Flow/);
assert.match(html, /Token Mix/);
assert.match(html, /Circular metrics/);
assert.match(html, /Model Share/);
assert.match(emptyHtml, /No tray modules enabled/);
});
test("TrayStatusStrip renders open and quit actions", () => {
const html = renderToStaticMarkup();
assert.match(html, /aria-label="Open CCR"/);
assert.match(html, /title="Open CCR"/);
assert.match(html, /12\.5K tokens/);
assert.match(html, /CCR/);
assert.match(html, /aria-label="Quit"/);
});
test("SourceGrid renders provider tabs with the selected state", () => {
const html = renderToStaticMarkup(
undefined}
/>
);
assert.match(html, />All<\/button>/);
assert.match(html, /border-teal-300\/35 bg-teal-300\/16 text-teal-50/);
assert.match(html, />OpenAI<\/button>/);
assert.match(html, />Anthropic<\/button>/);
});
test("AccountSummaryPanel covers empty and metered account states", () => {
const emptyHtml = renderToStaticMarkup();
const meteredHtml = renderToStaticMarkup(
undefined} />
);
assert.match(emptyHtml, /No account data configured/);
assert.match(meteredHtml, /openai \/ Primary Key/);
assert.match(meteredHtml, /5h quota/);
assert.match(meteredHtml, /42 requests/);
assert.match(meteredHtml, /style="\s*width:42%"/);
});
test("AccountSummaryPanel prioritizes Codex manual reset meter with expiration", () => {
const resetAt = new Date(Date.now() + 72 * 60 * 60 * 1000).toISOString();
const resetEffectiveAt = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const html = renderToStaticMarkup(
);
assert.match(html, /Primary quota/);
assert.match(html, /Manual resets/);
assert.match(html, /expires in/);
assert.match(html, /2 resets/);
assert.match(html, /width:/);
assert.doesNotMatch(html, /Secondary quota/);
});
test("RangeSwitch renders every usage range option", () => {
const html = renderToStaticMarkup( undefined} />);
assert.match(html, />Today<\/button>/);
assert.match(html, />24h<\/button>/);
assert.match(html, /bg-white\/14 text-slate-50/);
assert.match(html, />7d<\/button>/);
assert.match(html, />30d<\/button>/);
});
test("ChartShell renders title, meta, and children", () => {
const html = renderToStaticMarkup(
chart body
);
assert.match(html, /Token Flow/);
assert.match(html, /gpt-4\.1/);
assert.match(html, /chart body/);
});
test("StatsGrid renders cards, compact, and pill variants", () => {
const items = [
{ label: "Tokens", value: "12K" },
{ label: "Requests", value: "128" }
];
const cardsHtml = renderToStaticMarkup();
const compactHtml = renderToStaticMarkup();
const pillsHtml = renderToStaticMarkup();
assert.match(cardsHtml, /grid-cols-2/);
assert.match(compactHtml, /py-0\.5/);
assert.match(pillsHtml, /rounded-full/);
assert.match(`${cardsHtml}${compactHtml}${pillsHtml}`, /Tokens/);
assert.match(`${cardsHtml}${compactHtml}${pillsHtml}`, /12K/);
});
test("AnimatedUsageChart renders line, area, bar, and sparkline output", () => {
const series = usageStats().series;
const lineHtml = renderToStaticMarkup();
const areaHtml = renderToStaticMarkup();
const barHtml = renderToStaticMarkup();
const sparkHtml = renderToStaticMarkup();
assert.match(lineHtml, /aria-label="Usage chart"/);
assert.match(lineHtml, /line-chart-glow/);
assert.match(areaHtml, /fill="rgba\(45,212,191,.18\)"/);
assert.match(barHtml, / {
const html = renderToStaticMarkup();
assert.match(html, /Activity/);
assert.match(html, /Longest streak/);
assert.match(html, /aria-label="Activity Tokens"/);
assert.match(html, /Less/);
assert.match(html, /More/);
});
test("TokenMixPanel renders bars, stacked, and share chart variants", () => {
const totals = usageTotals();
const barsHtml = renderToStaticMarkup();
const stackedHtml = renderToStaticMarkup();
const donutHtml = renderToStaticMarkup();
assert.match(barsHtml, /Token Mix/);
assert.match(barsHtml, /Input/);
assert.match(stackedHtml, /bg-blue-400/);
assert.match(donutHtml, /aria-label="Share chart"/);
});
test("RingMetrics and RadialMetric render accessible radial charts", () => {
const ringsHtml = renderToStaticMarkup();
const radialHtml = renderToStaticMarkup(
);
assert.match(ringsHtml, /Circular metrics/);
assert.match(ringsHtml, /Success/);
assert.match(ringsHtml, /Cache/);
assert.match(radialHtml, /aria-label="Cache 24%"/);
assert.match(radialHtml, /12K/);
assert.match(radialHtml, /tokens/);
});
test("ModelShareChart renders populated variants and empty state", () => {
const rows = usageStats().models;
const barsHtml = renderToStaticMarkup();
const listHtml = renderToStaticMarkup();
const donutHtml = renderToStaticMarkup();
const emptyHtml = renderToStaticMarkup();
assert.match(barsHtml, /Model Share/);
assert.match(barsHtml, /gpt-4\.1/);
assert.match(listHtml, /1\. gpt-4\.1/);
assert.match(listHtml, /62%/);
assert.match(donutHtml, /aria-label="Share chart"/);
assert.match(emptyHtml, /No usage captured yet/);
});
test("TrayApp and TrayDetailApp render their shell components without browser runtime", () => {
const trayHtml = renderToStaticMarkup();
const detailHtml = renderToStaticMarkup();
assert.match(trayHtml, /Usage Overview/);
assert.match(trayHtml, /Open CCR/);
assert.match(detailHtml, /Usage Detail/);
assert.match(detailHtml, /OpenAI/);
});