Skip to content
116 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { money } from "./money.ts";
5import { monthSpan, spanFor } from "./spend.ts";
6import { byProject, columns, defaultGrain, isStaff, pendingSentence, quantity, receipt, resolveRange, ticks, usageCsv } from "./usage.ts";
7
8const axisMoney = (micros: number) => money(micros, { compact: true });
9
10const NOW = new Date("2026-10-08T15:00:00Z");
11
12test("periods resolve to whole UTC days, both ends included", () => {
13 assert.deepEqual(resolveRange(null, {}, NOW), { period: "cycle", from: "2026-10-01", until: "2026-10-08" });
14 // The current cycle is the one "this month" Spend and the top bar ask billing for.
15 assert.deepEqual(resolveRange("cycle", {}, NOW), { period: "cycle", ...monthSpan(NOW) });
16 assert.deepEqual(spanFor("month", NOW), monthSpan(NOW));
17 assert.deepEqual(resolveRange("last_cycle", {}, NOW), { period: "last_cycle", from: "2026-09-01", until: "2026-09-30" });
18 assert.deepEqual(resolveRange("7d", {}, NOW), { period: "7d", from: "2026-10-02", until: "2026-10-08" });
19 assert.deepEqual(resolveRange("custom", { from: "2026-10-05", until: "2026-09-20" }, NOW), { period: "custom", from: "2026-09-20", until: "2026-10-05" });
20 // A custom range that is not days falls back to the cycle.
21 assert.equal(resolveRange("custom", { from: "yesterday", until: "2026-10-01" }, NOW).period, "cycle");
22 assert.equal(resolveRange("nonsense", {}, NOW).period, "cycle");
23});
24
25test("columns cover every day, stack products, and add up when cumulative", () => {
26 const days = [
27 { day: "2026-10-01", product: "agent", micros: 2_000_000 },
28 { day: "2026-10-01", product: "sandboxes", micros: 500_000 },
29 { day: "2026-10-03", product: "agent", micros: 1_000_000 },
30 ];
31 const daily = columns(days, "2026-10-01", "2026-10-03");
32 assert.deepEqual(daily.map((c) => c.total), [2_500_000, 0, 1_000_000]);
33 assert.equal(daily[0]!.parts.sandboxes, 500_000);
34 const running = columns(days, "2026-10-01", "2026-10-03", "day", true);
35 assert.deepEqual(running.map((c) => c.total), [2_500_000, 2_500_000, 3_500_000]);
36 assert.equal(running[2]!.parts.agent, 3_000_000);
37 // Weeks start on Monday: Oct 1 2026 is a Thursday.
38 const weekly = columns(days, "2026-10-01", "2026-10-08", "week");
39 assert.deepEqual(weekly.map((c) => c.key), ["2026-09-28", "2026-10-05"]);
40 assert.equal(weekly[0]!.total, 3_500_000);
41 assert.equal(columns(days, "2026-09-15", "2026-10-03", "month").length, 2);
42 assert.equal(defaultGrain("2026-10-01", "2026-10-31"), "day");
43 assert.equal(defaultGrain("2026-07-01", "2026-10-01"), "week");
44});
45
46test("the money axis has clean ticks, never the same label twice", () => {
47 assert.deepEqual(ticks(0), [0]);
48 const t = ticks(3_320_000);
49 assert.equal(t[0], 0);
50 assert.ok(t[t.length - 1]! >= 3_320_000);
51 const labels = t.map(axisMoney);
52 assert.equal(new Set(labels).size, labels.length, labels.join(" "));
53 const small = ticks(4_000).map(axisMoney);
54 assert.equal(new Set(small).size, small.length, small.join(" "));
55 assert.equal(axisMoney(2_000_000), "$2");
56 assert.equal(axisMoney(1_500_000_000), "$1.5K");
57});
58
59test("quantities read in their units", () => {
60 assert.equal(quantity(1_234_567, "tokens"), "1.2M tokens");
61 assert.equal(quantity(3_725, "seconds"), "1h 2m");
62 assert.equal(quantity(504_000_000, "bytes"), "504 MB");
63 assert.equal(quantity(1, "entries"), "1 entry");
64});
65
66test("the receipt shows usage at price, then what paid, then what is charged", () => {
67 const lines = receipt(
68 { priceMicros: 3_320_000, discountMicros: 3_320_000, includedMicros: 0, creditsMicros: 0, chargedMicros: 0, pendingMicros: 0, costMicros: 0 },
69 100,
70 );
71 assert.deepEqual(lines.map((l) => l.label), ["Usage at price", "Discount (100%)", "Charged"]);
72});
73
74test("grouping by project adds a project's meters together", () => {
75 const meter = (label: string, parts: [string, number][]) => ({
76 key: label, label, product: "agent", unit: "entries", quantity: 0, micros: 0, daily: [],
77 byProject: parts.map(([project, micros]) => ({ project, micros, quantity: 0 })),
78 });
79 const rows = byProject({
80 products: [{ key: "agent", label: "Agent", micros: 0, meters: [meter("Model tokens", [["acme/web", 300], ["acme/api", 500]]), meter("Agent rate", [["acme/web", 400]])] }],
81 });
82 assert.deepEqual(rows.map((r) => [r.project, r.micros]), [["acme/web", 700], ["acme/api", 500]]);
83});
84
85test("the CSV has a row per day and meter with anything on it", () => {
86 const csv = usageCsv({
87 from: "2026-10-01",
88 until: "2026-10-02",
89 products: [{ key: "agent", label: "Agent", micros: 0, meters: [{ key: "agent_models", label: "Model tokens", product: "agent", unit: "tokens", quantity: 0, micros: 0, daily: [0, 1_500_000], byProject: [] }] }],
90 });
91 assert.equal(csv, "day,product,meter,usd\n2026-10-02,Agent,Model tokens,1.500000\n");
92});
93
94test("test-mode hints are for g1t's own people", () => {
95 assert.ok(isStaff({ workspaces: [{ slug: "flagon-io" }] }));
96 assert.ok(!isStaff({ workspaces: [{ slug: "acme" }] }));
97 assert.ok(!isStaff(null));
98});
99
100test("the pending note says what the close will charge, with the fraction of a cent that explains a gap", () => {
101 // A comped workspace: $0.009 pending, nothing of it charged.
102 assert.equal(
103 pendingSentence({ pendingMicros: 9_000, pendingChargedMicros: 0 }),
104 "$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.",
105 );
106 assert.equal(
107 pendingSentence({ pendingMicros: 9_000, pendingChargedMicros: 6_300 }),
108 "$0.009 of it is metered this month and not yet closed; $0.0063 of it will be charged when the month closes, after your discount and included usage.",
109 );
110 assert.equal(
111 pendingSentence({ pendingMicros: 1_340_000, pendingChargedMicros: 1_340_000 }),
112 "$1.34 of it is metered this month and not yet closed; all of it will be charged when the month closes, after your discount and included usage.",
113 );
114 // An older billing, with no split yet.
115 assert.equal(pendingSentence({ pendingMicros: 9_000 }), "$0.009 of it is metered this month and not yet closed; it is charged when the month closes.");
116});