import { describe, expect, test } from "bun:test"; import { rangeWindow, type RangeKind } from "../src/client/analytics.ts"; import { trendChart } from "../src/client/trend-chart.ts"; const HOUR = 3_600_000; const format = (ms: number) => `${ms / HOUR}h`; const count = (html: string, text: string) => html.split(text).length - 1; const base = new Date(2026, 10, 8, 12); describe("trend chart", () => { for (const kind of ["day", "week", "month", "year"] as RangeKind[]) { test(`${kind}: every column has a label row, so all bars share one baseline`, () => { const range = rangeWindow(kind, 0, base); const html = trendChart(range.bins, range.bins.map(() => 0), format, +base); expect(count(html, 'class="trend-label"')).toBe(range.bins.length); }); test(`${kind}: every bin has a full name for the readout`, () => { for (const bin of rangeWindow(kind, 0, base).bins) expect(bin.name.length).toBeGreaterThan(1); }); } test("only the peak bar has a value label", () => { const { bins } = rangeWindow("month", 0, base); const trend = bins.map((_, i) => (i === 3 ? 3 * HOUR : i < 8 ? HOUR : 0)); const html = trendChart(bins, trend, format, +base); expect(count(html, 'class="trend-value"')).toBe(1); expect(html).toContain('3h'); }); test("a bin with no time has no bar", () => { const { bins } = rangeWindow("week", 0, base); const trend = bins.map((_, i) => (i === 0 ? HOUR : 0)); expect(count(trendChart(bins, trend, format, +base), 'class="trend-fill"')).toBe(1); }); test("each column gives its date and value to the readout", () => { const { bins } = rangeWindow("month", 0, base); const html = trendChart(bins, bins.map((_, i) => (i === 5 ? 2 * HOUR : 0)), format, +base); expect(html).toContain(`data-readout="${bins[5]!.name} · 2h"`); expect(html).toContain(`data-readout="${bins[6]!.name} · 0h"`); }); test("the readout starts on the peak, or says the period is empty", () => { const { bins } = rangeWindow("year", 0, base); const html = trendChart(bins, bins.map((_, i) => (i === 10 ? 5 * HOUR : 0)), format, +base); expect(html).toContain(`>Peak · ${bins[10]!.name} · 5h<`); expect(trendChart(bins, bins.map(() => 0), format, +base)).toContain(">No time logged in this period.<"); }); test("the current bin is marked", () => { const { bins } = rangeWindow("week", 0, base); const html = trendChart(bins, bins.map(() => 0), format, +base); expect(count(html, "trend-col current")).toBe(1); }); });