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

198 lines9,812 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 parseAllowances,
6 parseCredit,
7 parseDecision,
8 parseEmail,
9 parseGoodwill,
10 parsePayment,
11 parseSales,
12 parseSalesNote,
13 parseSlugList,
14 parseTerms,
15} from "./forms.ts";
16
17const NOW = new Date("2026-10-04T12:00:00Z");
18
19function form(entries: Record<string, string>): FormData {
20 const data = new FormData();
21 for (const [name, value] of Object.entries(entries)) data.set(name, value);
22 return data;
23}
24
25test("comped terms keep a ceiling and an end date, and name who set them", () => {
26 const result = parseTerms(form({ kind: "comped", note: "g1t's own", ceiling: "500", until: "2026-12-31", discount: "40" }), "owner@g1t.sh", NOW);
27 assert.deepEqual(result, {
28 ok: true,
29 value: {
30 kind: "comped",
31 discountPercent: 0,
32 ceilingMicros: 500_000_000,
33 note: "g1t's own",
34 until: "2026-12-31T23:59:59Z",
35 setBy: "owner@g1t.sh",
36 setAt: NOW.toISOString(),
37 },
38 });
39});
40
41test("standard terms clear everything but the note", () => {
42 const result = parseTerms(form({ kind: "standard", note: "back to normal", ceiling: "5", until: "2027-01-01" }), "a@g1t.sh", NOW);
43 assert.ok(result.ok);
44 assert.equal(result.value.ceilingMicros, null);
45 assert.equal(result.value.until, null);
46});
47
48test("terms are refused without a note, with a bad discount, or ending in the past", () => {
49 assert.equal(parseTerms(form({ kind: "comped", note: "" }), "a", NOW).ok, false);
50 assert.equal(parseTerms(form({ kind: "custom", note: "x", discount: "101" }), "a", NOW).ok, false);
51 assert.equal(parseTerms(form({ kind: "custom", note: "x" }), "a", NOW).ok, false);
52 assert.equal(parseTerms(form({ kind: "custom", note: "x", discount: "20", until: "2026-10-01" }), "a", NOW).ok, false);
53 assert.equal(parseTerms(form({ kind: "custom", note: "x", discount: "20", until: "2026-02-30" }), "a", NOW).ok, false);
54 assert.equal(parseTerms(form({ kind: "free", note: "x" }), "a", NOW).ok, false);
55});
56
57test("workspace lists take commas, spaces and lines, once each", () => {
58 assert.deepEqual(parseSlugList("acme, Acme-labs\nbeta beta"), { ok: true, value: ["acme", "acme-labs", "beta"] });
59 assert.equal(parseSlugList("acme, bad--slug").ok, false);
60 assert.equal(parseSlugList("../etc").ok, false);
61});
62
63test("invoice emails are one address", () => {
64 assert.deepEqual(parseEmail(" Billing@Acme.com "), { ok: true, value: "billing@acme.com" });
65 assert.equal(parseEmail("a@b").ok, false);
66 assert.equal(parseEmail("a@b.com, c@d.com").ok, false);
67 assert.equal(parseEmail("a@@b.com").ok, false);
68 assert.equal(parseEmail("").ok, false);
69});
70
71test("credits are positive and capped", () => {
72 assert.deepEqual(parseCredit("25.50"), { ok: true, value: 25_500_000 });
73 assert.equal(parseCredit("0").ok, false);
74 assert.equal(parseCredit("10000.01").ok, false);
75});
76
77test("a sales record: a stage, an owner's email or nobody, a next step and its day", () => {
78 assert.deepEqual(parseSales(form({ stage: "contacted", owner: " Me@G1t.sh ", nextStep: "Call about\n terms", nextAt: "2026-10-09" })), {
79 ok: true,
80 value: { stage: "contacted", owner: "me@g1t.sh", nextStep: "Call about terms", nextAt: "2026-10-09" },
81 });
82 assert.deepEqual(parseSales(form({ stage: "none", owner: "", nextStep: "", nextAt: "" })), {
83 ok: true,
84 value: { stage: "none", owner: null, nextStep: null, nextAt: null },
85 });
86 assert.equal(parseSales(form({ stage: "closed" })).ok, false);
87 assert.equal(parseSales(form({ stage: "lead", owner: "not an email" })).ok, false);
88 assert.equal(parseSales(form({ stage: "lead", nextStep: "x".repeat(201) })).ok, false);
89 assert.equal(parseSales(form({ stage: "lead", nextStep: "Call", nextAt: "2026-02-30" })).ok, false);
90 assert.equal(parseSales(form({ stage: "lead", nextStep: "Call", nextAt: "next week" })).ok, false);
91 // A date needs a step to go with it.
92 assert.equal(parseSales(form({ stage: "lead", nextAt: "2026-10-09" })).ok, false);
93});
94
95test("a sales note is required, and not endless", () => {
96 assert.deepEqual(parseSalesNote("Spoke to Ana; wants an enterprise quote."), { ok: true, value: "Spoke to Ana; wants an enterprise quote." });
97 assert.equal(parseSalesNote("").ok, false);
98 assert.equal(parseSalesNote("x".repeat(2001)).ok, false);
99});
100
101
102test("allowances: the plan without its price, pool shares, and staff's overrides", () => {
103 assert.deepEqual(parseAllowances(form({})), {
104 ok: true,
105 value: {
106 plan: false,
107 ossRepoMicros: null,
108 trialMicros: null,
109 maxConcurrentAgents: null,
110 runCapMicros: null,
111 issueCapMicros: null,
112 auditRetentionDays: null,
113 hold: null,
114 },
115 });
116 assert.deepEqual(
117 parseAllowances(form({ plan: "on", oss: "5", trial: "2.50", agents: "20", runCap: "25", issueCap: "500", auditDays: "365", hold: " Card disputed;\nwaiting on the bank " })),
118 {
119 ok: true,
120 value: {
121 plan: true,
122 ossRepoMicros: 5_000_000,
123 trialMicros: 2_500_000,
124 maxConcurrentAgents: 20,
125 runCapMicros: 25_000_000,
126 issueCapMicros: 500_000_000,
127 auditRetentionDays: 365,
128 hold: "Card disputed; waiting on the bank",
129 },
130 },
131 );
132 assert.equal(parseAllowances(form({ oss: "lots" })).ok, false);
133 assert.equal(parseAllowances(form({ trial: "5000" })).ok, false);
134 assert.equal(parseAllowances(form({ agents: "0" })).ok, false);
135 assert.equal(parseAllowances(form({ agents: "101" })).ok, false);
136 assert.equal(parseAllowances(form({ agents: "2.5" })).ok, false);
137 assert.equal(parseAllowances(form({ runCap: "0.05" })).ok, false);
138 assert.equal(parseAllowances(form({ runCap: "1000.01" })).ok, false);
139 assert.equal(parseAllowances(form({ issueCap: "10000.01" })).ok, false);
140 // Audit log days: shorter or longer than the plan's, up to 400.
141 assert.equal((parseAllowances(form({ auditDays: "3" })) as { value: { auditRetentionDays: number } }).value.auditRetentionDays, 3);
142 assert.equal((parseAllowances(form({ auditDays: "400" })) as { value: { auditRetentionDays: number } }).value.auditRetentionDays, 400);
143 assert.equal(parseAllowances(form({ auditDays: "0" })).ok, false);
144 assert.equal(parseAllowances(form({ auditDays: "401" })).ok, false);
145 assert.equal(parseAllowances(form({ auditDays: "30.5" })).ok, false);
146 assert.equal(parseAllowances(form({ auditDays: "a year" })).ok, false);
147 assert.equal(parseAllowances(form({ hold: "x".repeat(201) })).ok, false);
148});
149
150test("a bank transfer: an amount, its reference, a note, and the slug typed out", () => {
151 const ok = { amount: "1,500", reference: " TRX 0042 ", note: "Invoice INV-7, by wire", confirmation: "acme" };
152 assert.deepEqual(parsePayment(form(ok), "acme"), { ok: true, value: { amountMicros: 1_500_000_000, reference: "TRX 0042", note: "Invoice INV-7, by wire" } });
153 assert.equal(parsePayment(form({ ...ok, amount: "0" }), "acme").ok, false);
154 assert.equal(parsePayment(form({ ...ok, amount: "100000.01" }), "acme").ok, false);
155 assert.equal(parsePayment(form({ ...ok, reference: "" }), "acme").ok, false);
156 assert.equal(parsePayment(form({ ...ok, note: "" }), "acme").ok, false);
157 assert.equal(parsePayment(form({ ...ok, confirmation: "Acme" }), "acme").ok, false);
158});
159
160test("a decision: approve as asked or at another amount; decline needs a note", () => {
161 assert.deepEqual(parseDecision(form({ id: "lr_1", decision: "approve" })), {
162 ok: true,
163 value: { id: "lr_1", decision: "approve", amountMicros: null, note: "" },
164 });
165 assert.deepEqual(parseDecision(form({ id: "lr_1", decision: "approve", amount: "750", note: "Half now." })), {
166 ok: true,
167 value: { id: "lr_1", decision: "approve", amountMicros: 750_000_000, note: "Half now." },
168 });
169 assert.equal(parseDecision(form({ id: "lr_1", decision: "approve", amount: "0.50" })).ok, false);
170 assert.equal(parseDecision(form({ id: "lr_1", decision: "approve", amount: "1000000.01" })).ok, false);
171 assert.equal(parseDecision(form({ id: "lr_1", decision: "decline" })).ok, false);
172 assert.deepEqual(parseDecision(form({ id: "lr_1", decision: "decline", note: "After a month of payments.", amount: "5" })), {
173 ok: true,
174 value: { id: "lr_1", decision: "decline", amountMicros: null, note: "After a month of payments." },
175 });
176 assert.equal(parseDecision(form({ id: "../x", decision: "approve" })).ok, false);
177 assert.equal(parseDecision(form({ id: "lr_1", decision: "maybe" })).ok, false);
178});
179
180test("goodwill: no amount is the one-click credit; a reason when one is needed; a day not in the future", () => {
181 const never = () => false;
182 const always = () => true;
183 assert.deepEqual(parseGoodwill(form({}), never, NOW), { ok: true, value: { amountMicros: null, reason: "", day: null } });
184 assert.deepEqual(parseGoodwill(form({ amount: "60", reason: "Looping agent on #12, owner caught it late.", day: "2026-10-03" }), always, NOW), {
185 ok: true,
186 value: { amountMicros: 60_000_000, reason: "Looping agent on #12, owner caught it late.", day: "2026-10-03" },
187 });
188 assert.equal(parseGoodwill(form({ amount: "60", reason: "oops" }), always, NOW).ok, false);
189 assert.equal(parseGoodwill(form({ amount: "0" }), never, NOW).ok, false);
190 assert.equal(parseGoodwill(form({ amount: "10000.01" }), never, NOW).ok, false);
191 assert.equal(parseGoodwill(form({ day: "2026-10-05" }), never, NOW).ok, false);
192 assert.equal(parseGoodwill(form({ day: "2026-02-30" }), never, NOW).ok, false);
193 // The check is given the amount typed, or null for the one-click credit.
194 const seen: (number | null)[] = [];
195 parseGoodwill(form({ amount: "12.50" }), (amount) => (seen.push(amount), false), NOW);
196 parseGoodwill(form({}), (amount) => (seen.push(amount), false), NOW);
197 assert.deepEqual(seen, [12_500_000, null]);
198});