Skip to content

g1t/apps/sudo/app/lib/credits.test.ts

95 lines5,455 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { CONFIRM_OVER_MICROS, CREDIT_PRESETS, grantSummary, parseCreditAmount, parseCreditForm, parseExpiry, parseMonth, shortDay } from "./credits.ts";
5import { usd } from "./money.ts";
6
7const NOW = new Date("2026-10-07T12:00:00Z");
8
9function form(values: Record<string, string>): FormData {
10 const data = new FormData();
11 for (const [name, value] of Object.entries(values)) data.set(name, value);
12 return data;
13}
14
15test("the presets are $10, $20, $25, $50 and $100, each one step", () => {
16 assert.deepEqual([...CREDIT_PRESETS], [10, 20, 25, 50, 100]);
17 for (const dollars of CREDIT_PRESETS) {
18 assert.deepEqual(parseCreditAmount(String(dollars), ""), { ok: true, value: dollars * 1_000_000 });
19 assert.ok(dollars * 1_000_000 <= CONFIRM_OVER_MICROS, "no preset needs the slug typed");
20 }
21 // Only the presets offered; anything else is Custom.
22 assert.equal(parseCreditAmount("15", "").ok, false);
23 assert.deepEqual(parseCreditAmount("custom", "$12.40"), { ok: true, value: 12_400_000 });
24 assert.equal(parseCreditAmount("custom", "").ok, false);
25 assert.equal(parseCreditAmount("custom", "0").ok, false);
26 assert.equal(parseCreditAmount("custom", "10000.01").ok, false);
27 assert.deepEqual(parseCreditAmount("custom", "10,000"), { ok: true, value: 10_000_000_000 });
28});
29
30test("an expiry is never, 30, 90 or 365 days, or the end of a chosen day", () => {
31 assert.deepEqual(parseExpiry("none", "", NOW), { ok: true, value: null });
32 assert.deepEqual(parseExpiry("", "", NOW), { ok: true, value: null });
33 assert.deepEqual(parseExpiry("30", "", NOW), { ok: true, value: "2026-11-06T23:59:59Z" });
34 assert.deepEqual(parseExpiry("90", "", NOW), { ok: true, value: "2027-01-05T23:59:59Z" });
35 assert.deepEqual(parseExpiry("365", "", NOW), { ok: true, value: "2027-10-07T23:59:59Z" });
36 assert.deepEqual(parseExpiry("date", "2027-01-05", NOW), { ok: true, value: "2027-01-05T23:59:59Z" });
37 assert.equal(parseExpiry("date", "", NOW).ok, false);
38 assert.equal(parseExpiry("date", "2026-10-01", NOW).ok, false);
39 assert.equal(parseExpiry("date", "2040-01-01", NOW).ok, false);
40 assert.equal(parseExpiry("7", "", NOW).ok, false);
41});
42
43test("a small credit is one step; over $100 the slug is typed out", () => {
44 const small = parseCreditForm(form({ preset: "25", kind: "promotional", expires: "90", note: "Welcome to g1t" }), "acme", NOW);
45 assert.deepEqual(small, {
46 ok: true,
47 value: { amountMicros: 25_000_000, kind: "promotional", expiresAt: "2027-01-05T23:59:59Z", refundFor: null, refundDay: null, note: "Welcome to g1t" },
48 });
49 // $100 is still one step.
50 assert.ok(parseCreditForm(form({ preset: "100", kind: "goodwill", note: "Sorry" }), "acme", NOW).ok);
51 const big = form({ preset: "custom", amount: "250", kind: "goodwill", note: "Sorry about the outage" });
52 const refused = parseCreditForm(big, "acme", NOW);
53 assert.equal(refused.ok, false);
54 assert.match(refused.ok ? "" : refused.error, /type the workspace's slug, acme/);
55 big.set("confirmation", "acme");
56 assert.equal(parseCreditForm(big, "acme", NOW).ok, true);
57});
58
59test("a credit needs a kind and a note", () => {
60 assert.equal(parseCreditForm(form({ preset: "10", note: "x" }), "acme", NOW).ok, false);
61 assert.equal(parseCreditForm(form({ preset: "10", kind: "gift", note: "x" }), "acme", NOW).ok, false);
62 assert.equal(parseCreditForm(form({ preset: "10", kind: "goodwill" }), "acme", NOW).ok, false);
63});
64
65test("a refund says what it is for, never expires, and refunds a day that was", () => {
66 const refund = parseCreditForm(
67 form({ preset: "20", kind: "refund", refundFor: "the failed runs on Oct 2", refundDay: "2026-10-02", expires: "30", note: "Sorry" }),
68 "acme",
69 NOW,
70 );
71 // The expiry chosen before switching to Refund is ignored.
72 assert.deepEqual(refund, {
73 ok: true,
74 value: { amountMicros: 20_000_000, kind: "refund", expiresAt: null, refundFor: "the failed runs on Oct 2", refundDay: "2026-10-02", note: "Sorry" },
75 });
76 assert.equal(parseCreditForm(form({ preset: "20", kind: "refund", note: "Sorry" }), "acme", NOW).ok, false);
77 assert.equal(parseCreditForm(form({ preset: "20", kind: "refund", refundFor: "x", refundDay: "2026-10-09", note: "Sorry" }), "acme", NOW).ok, false);
78 assert.equal(parseCreditForm(form({ preset: "20", kind: "refund", refundFor: "x", refundDay: "2026-02-30", note: "Sorry" }), "acme", NOW).ok, false);
79});
80
81test("a grant reads in a line, as the Billing page says it", () => {
82 const open = { amountMicros: 25_000_000, leftMicros: 12_400_000, expiresAt: "2027-01-05T23:59:59Z", state: "open" as const };
83 assert.equal(grantSummary(open, usd, NOW), "$25.00 credit, $12.40 left, expires Jan 5, 2027");
84 assert.equal(grantSummary({ ...open, expiresAt: "2026-11-05T23:59:59Z" }, usd, NOW), "$25.00 credit, $12.40 left, expires Nov 5");
85 assert.equal(grantSummary({ ...open, expiresAt: null }, usd), "$25.00 credit, $12.40 left");
86 assert.equal(grantSummary({ ...open, state: "used", leftMicros: 0 }, usd), "$25.00 credit, all used");
87 assert.equal(grantSummary({ ...open, state: "expired", leftMicros: 0 }, usd), "$25.00 credit, expired");
88 assert.equal(shortDay("2026-11-05T23:59:59Z", NOW), "Nov 5");
89});
90
91test("a month filter is a month", () => {
92 assert.equal(parseMonth("2026-10"), "2026-10");
93 assert.equal(parseMonth("2026-13"), null);
94 assert.equal(parseMonth(null), null);
95});