authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-05 00:19:33-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-05 00:19:33-07:00
log487d1766caba52579f07a3e5ebc6f276227e4382
tree2eb6a8ff16d2e014f2cdb20df9fef1f894967283
parent3bcde91f8215ec24eeffdd4abdee8fcb8a5e94f9
signature Signed by PGP key B5690EEEBB952194

refactor(web): test the live usage column builder (#9993)


2 files changed, 10 insertions(+), 26 deletions(-)

apps/web/src/components/usage/UsageProviderChart.test.ts+9-7
......@@ -1,6 +1,6 @@
11import { describe, expect, it } from "vite-plus/test";
22
3import { buildDayColumns, niceScale } from "./UsageProviderChart";
3import { buildPeriodColumns, niceScale } from "./UsageProviderChart";
44import { providersWithUsage } from "./usageProviders";
55
66describe("niceScale", () => {
......@@ -41,7 +41,7 @@ describe("niceScale", () => {
4141 });
4242});
4343
44describe("buildDayColumns", () => {
44describe("buildPeriodColumns", () => {
4545 const days = ["2026-08-01", "2026-08-02", "2026-08-03"];
4646 const byDay = new Map([
4747 [
......@@ -69,11 +69,13 @@ describe("buildDayColumns", () => {
6969 ]);
7070
7171 it("plots each day on its own", () => {
72 expect(buildDayColumns(days, byDay, "cost").map((column) => column.total)).toEqual([30, 0, 5]);
72 expect(buildPeriodColumns(days, byDay, "cost").map((column) => column.total)).toEqual([
73 30, 0, 5,
74 ]);
7375 });
7476
7577 it("reads the requested metric", () => {
76 expect(buildDayColumns(days, byDay, "tokens").map((column) => column.total)).toEqual([
78 expect(buildPeriodColumns(days, byDay, "tokens").map((column) => column.total)).toEqual([
7779 300, 0, 50,
7880 ]);
7981 });
......@@ -81,7 +83,7 @@ describe("buildDayColumns", () => {
8183 it("keeps band values absolute rather than cumulative", () => {
8284 // Regression: the bands were once stack offsets, which drew Claude Code
8385 // permanently above Codex regardless of which provider spent more.
84 const [first] = buildDayColumns(days, byDay, "cost");
86 const [first] = buildPeriodColumns(days, byDay, "cost");
8587
8688 expect(first?.bands).toEqual([
8789 { provider: "codex", value: 10 },
......@@ -91,7 +93,7 @@ describe("buildDayColumns", () => {
9193 });
9294
9395 it("reports the total as the sum of its bands", () => {
94 for (const column of buildDayColumns(days, byDay, "cost")) {
96 for (const column of buildPeriodColumns(days, byDay, "cost")) {
9597 const sum = column.bands.reduce((running, band) => running + band.value, 0);
9698 expect(column.total).toBeCloseTo(sum, 9);
9799 }
......@@ -125,7 +127,7 @@ describe("hourly chart columns", () => {
125127 ]);
126128
127129 expect(
128 buildDayColumns(
130 buildPeriodColumns(
129131 ["2026-08-11T08:37:00.000Z", "2026-08-11T09:37:00.000Z", "2026-08-11T10:37:00.000Z"],
130132 byHour,
131133 "cost",
apps/web/src/components/usage/UsageProviderChart.tsx+1-19
......@@ -54,7 +54,7 @@ function valueFor(
5454 return metric === "tokens" ? entry.totalTokens : entry.costUsd;
5555}
5656
57function buildPeriodColumns(
57export function buildPeriodColumns(
5858 periods: readonly string[],
5959 byPeriod: ReadonlyMap<string, DailyTotals | HourlyTotals>,
6060 metric: UsageChartMetric,
......@@ -169,24 +169,6 @@ export function niceScale(peak: number, count: number): { max: number; ticks: re
169169 return { max, ticks };
170170}
171171
172/**
173 * Turns the merged daily totals into one column per day.
174 *
175 * Values are absolute, not cumulative: each provider is drawn from the same
176 * zero baseline so the chart never implies that one provider is always larger.
177 *
178 * The chart paths and the hover readout both consume this, so the number under
179 * the cursor is by construction the number that was plotted rather than a
180 * second derivation that can drift from it.
181 */
182export function buildDayColumns(
183 days: readonly string[],
184 byDay: ReadonlyMap<string, DailyTotals>,
185 metric: UsageChartMetric,
186): readonly DayColumn[] {
187 return buildPeriodColumns(days, byDay, metric);
188}
189
190172export function UsageProviderChart({
191173 providers,
192174 days,