Skip to content
87 linesCodeBlameRaw
1/**
2 * One month, one number: the top bar's pill, Spend's "This month", Home's
3 * "this month so far" and Usage's "This range" all show the same figure for
4 * the same month, formatted the same way. Each surface's arithmetic is the
5 * pure function its loader or component calls; the loaders only fetch.
6 */
7import assert from "node:assert/strict";
8import { test } from "node:test";
9
10import type { Statement, UsageReport } from "@g1t/contracts";
11
12import { spendIn } from "./home.ts";
13import { money } from "./money.ts";
14import { monthSpan, spanFor, spentMicros } from "./spend.ts";
15import { pendingSentence, receipt, resolveRange } from "./usage.ts";
16
17const NOW = new Date("2026-10-10T18:30:00Z");
18
19/** A comped workspace in October: $10.401 on the ledger, $0.009 of storage metered and not yet closed, a 100% discount. */
20const report = {
21 from: "2026-10-01",
22 until: "2026-10-10",
23 totals: {
24 priceMicros: 10_410_000,
25 discountMicros: 10_410_000,
26 includedMicros: 0,
27 creditsMicros: 0,
28 chargedMicros: 0,
29 pendingMicros: 9_000,
30 pendingChargedMicros: 0,
31 costMicros: 8_670_000,
32 },
33 days: [],
34 products: [],
35 projects: [],
36 discountPercent: 100,
37 aiCreditMicros: 0,
38 creditMicros: 0,
39 plan: "paid",
40 free: false,
41} satisfies UsageReport;
42
43/** The same month's statement: the ledger's lines only, which is why Home no longer reads its total for the month. */
44const statement = {
45 groups: [{ key: "2026-10-09", label: "", chargedMicros: 0, lines: [{ kind: "Agent runs", count: 3, chargedMicros: 0, costMicros: 8_670_000, priceMicros: 10_401_000 }] }],
46 totals: { chargedMicros: 0, paidMicros: 0, costMicros: 8_670_000, entries: 3, priceMicros: 10_401_000 },
47} satisfies Pick<Statement, "groups" | "totals">;
48
49test("every page asks billing for the same month", () => {
50 const month = monthSpan(NOW);
51 assert.deepEqual(month, { from: "2026-10-01", until: "2026-10-10" });
52 // The pill and Spend (lib/spend.server.ts `loadUsage`, `loadPill`), Home (lib/home.server.ts `loadSpend`) and Usage (routes/workspace/usage.tsx `readFilters`).
53 assert.deepEqual(spanFor("month", NOW), month);
54 const { from, until } = resolveRange("cycle", {}, NOW);
55 assert.deepEqual({ from, until }, month);
56});
57
58test("the pill, Spend, Home and Usage show one figure for the month", () => {
59 // The top bar's pill, Workspace view (lib/spend.server.ts `loadPill`: `spentMicros(usage)`; components/spend.tsx `SpendPill`: `money(spent)`).
60 const pill = money(spentMicros(report));
61 // Spend's "Spent, This month" tile (routes/workspace/spend.tsx).
62 const spendTile = money(spentMicros(report));
63 // Home's "this month so far" (lib/home.server.ts `loadSpend` hands `spendIn` the report's figure; components/home.tsx `SpendCard`).
64 const home = spendIn([statement], { from: Date.parse("2026-10-09T00:00:00Z"), now: NOW.getTime() }, spentMicros(report));
65 const homeMonth = money(home.monthMicros!);
66 // Usage's "This range", first line (components/usage.tsx `IncludedAndCredit`: `receipt`, then `money(line.micros)`).
67 const lines = receipt(report.totals, report.discountPercent);
68 const usage = money(lines[0]!.micros);
69
70 assert.equal(pill, "$10.41");
71 assert.equal(spendTile, pill);
72 assert.equal(homeMonth, pill);
73 assert.equal(usage, pill);
74
75 // The statement alone, which Home used to show, is the $0.009 short that read as a rounding difference.
76 assert.equal(money(statement.totals.priceMicros), "$10.40");
77
78 // The rest of Usage's receipt for the same report, as the page writes each line.
79 assert.deepEqual(
80 lines.map((line) => `${line.label} ${line.minus ? "−" : ""}${money(line.micros)}`),
81 ["Usage at price $10.41", "Discount (100%) −$10.41", "Charged $0.00"],
82 );
83 assert.equal(
84 pendingSentence(report.totals),
85 "$0.009 of it is metered this month and not yet closed; nothing will be charged when the month closes, after your discount and included usage.",
86 );
87});