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