import { describe, expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import {
clampPercent,
resetPhrase,
usageAccessibleText,
usageLevel,
usageValueText,
UsageMeter,
UsageMeterGroup,
UsageReadout,
usageResets,
} from "./usage-meter";
describe("usage levels", () => {
test("a status tone only below 10% left", () => {
expect(usageLevel(22)).toBe("healthy");
expect(usageLevel(10)).toBe("healthy");
expect(usageLevel(9.9)).toBe("low");
expect(usageLevel(8)).toBe("low");
expect(usageLevel(0)).toBe("exhausted");
expect(usageLevel(-3)).toBe("exhausted");
});
test("a missing reading is unknown, never zero", () => {
expect(usageLevel(null)).toBe("unknown");
expect(usageLevel(undefined)).toBe("unknown");
expect(usageLevel(Number.NaN)).toBe("unknown");
expect(usageValueText(null)).toBe("Not reported yet");
});
test("machines measure what's used, so the tone flips near full", () => {
expect(usageLevel(32, "used")).toBe("healthy");
expect(usageLevel(94, "used")).toBe("low");
expect(usageLevel(100, "used")).toBe("exhausted");
expect(usageValueText(32, "used")).toBe("32% used");
});
test("values are clamped and rounded, and exhausted says so", () => {
expect(clampPercent(21.6)).toBe(22);
expect(clampPercent(140)).toBe(100);
expect(clampPercent(-5)).toBe(0);
expect(usageValueText(21.6)).toBe("22% left");
expect(usageValueText(0)).toBe("Limit reached");
});
test("the accessible text names the window, the value and the reset", () => {
expect(
usageAccessibleText({ label: "Weekly", percent: 22, resetsLabel: "Mon 28 Sep, 09:00" }),
).toBe("Weekly: 22% left, resets Mon 28 Sep, 09:00");
expect(usageAccessibleText({ label: "5-hour", percent: 64 })).toBe("5-hour: 64% left");
});
test("relative days read lowercase after Resets, dates stay as they are", () => {
expect(resetPhrase("Today, 17:10")).toBe("today, 17:10");
expect(resetPhrase("Tomorrow, 09:00")).toBe("tomorrow, 09:00");
expect(resetPhrase("Mon 28 Sep, 09:00")).toBe("Mon 28 Sep, 09:00");
expect(usageAccessibleText({ label: "5-hour", percent: 64, resetsLabel: "Today, 17:10" })).toBe(
"5-hour: 64% left, resets today, 17:10",
);
expect(
renderToStaticMarkup(),
).toContain("Resets today, 17:10");
});
});
describe("UsageMeter", () => {
test("loading reserves the reset-time line instead of moving later sections down", () => {
const html = renderToStaticMarkup();
expect(html).toContain('aria-busy="true"');
expect(html).toContain("h-4.5 w-32");
expect(html).not.toContain("Not reported yet");
});
test("a known reading is a meter with a text value", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain('role="meter"');
expect(html).toContain('aria-valuenow="22"');
expect(html).toContain('aria-valuetext="Weekly: 22% left, resets Mon 28 Sep, 09:00"');
expect(html).toContain("Resets Mon 28 Sep, 09:00");
expect(html).toContain("width:22%");
});
test("an exhausted reading draws no fill and keeps the reset time", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain('data-level="exhausted"');
expect(html).toContain("Limit reached");
expect(html).toContain("width:0%");
expect(html).toContain("Resets Mon 28 Sep, 09:00");
});
test("an unknown reading is not announced as a meter", () => {
const html = renderToStaticMarkup();
expect(html).not.toContain('role="meter"');
expect(html).toContain('role="group"');
expect(html).toContain("Not reported yet");
});
test("labels are never abbreviated in any look or density", () => {
for (const variant of ["bar", "text", "ring"] as const) {
for (const density of ["full", "compact"] as const) {
const html = renderToStaticMarkup(
,
);
expect(html).toContain("5-hour");
expect(html).not.toMatch(/>5h<|>Wk);
}
}
});
test("the bar look reads as text in a row: bar in the sheet, text in the row", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain("22% left");
expect(html).not.toContain("width:");
expect(html).toContain('role="meter"');
});
test("compact meters are phrasing content, so they fit inside a row's text", () => {
const html = renderToStaticMarkup(
,
);
expect(html).not.toContain("
{
const html = renderToStaticMarkup(
undefined}
refreshDisabledReason="Reconnect research@acme.dev to check its usage."
/>,
);
expect(html).toContain("Checked 4 min ago");
expect(html).toContain('aria-label="Check usage now"');
expect(html).toContain('aria-disabled="true"');
expect(html).toContain("Reconnect research@acme.dev to check its usage.");
});
});
describe("UsageReadout", () => {
// Thursday 15 October 2026, 10:00 UTC.
const NOW = Date.parse("2026-10-15T10:00:00Z");
const weeklyReset = "2026-10-19T07:00:00Z";
const fiveHourReset = "2026-10-15T13:20:00Z";
test("reads as a sentence with a small bar, and names the reset for screen readers", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain("78% left this week");
expect(html).toContain('role="meter"');
expect(html).toMatch(/aria-valuetext="78% left this week\. Resets Mon 19 Oct, \d\d:\d\d"/);
expect(html).toContain("w-16");
});
test("shows when each limit resets, the shown window first and the others by name", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain('data-slot="usage-readout-resets"');
expect(html).toMatch(/>Resets Mon \d\d:\d\d · 5-hour \d\d:\d\d);
expect(html).toMatch(/title="Resets Mon 19 Oct, \d\d:\d\d; 5-hour resets today, \d\d:\d\d"/);
});
test("a reached limit still says when it resets, and past resets are left out", () => {
const html = renderToStaticMarkup(
,
);
expect(html).toContain("Limit reached");
expect(html).toMatch(/>5-hour resets \d\d:\d\d);
expect(html).not.toMatch(/>Resets /);
});
test("without reset times there is no second line", () => {
const html = renderToStaticMarkup();
expect(html).not.toContain("usage-readout-resets");
expect(html).not.toContain("title=");
});
test("usageResets puts the shown window first and drops a reset in the same minute", () => {
expect(
usageResets(
[
{ label: "Weekly", percent: 40, resetsAt: Date.parse(weeklyReset) },
{ label: "5-hour", percent: 90, resetsAt: Date.parse(fiveHourReset) },
{ label: "Weekly · Opus", percent: 70, resetsAt: Date.parse(weeklyReset) },
{ label: "Extra usage", percent: null },
],
"5-hour",
),
).toEqual([
{ at: Date.parse(fiveHourReset) },
{ label: "Weekly", at: Date.parse(weeklyReset) },
]);
});
test("a missing reading says why in words, and an empty window says so", () => {
expect(
renderToStaticMarkup(
,
),
).toContain("Usage unavailable");
expect(renderToStaticMarkup()).toContain(
"Limit reached",
);
});
});