Skip to content
146 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 INVITES_DONE,
6 MAX_BULK,
7 MAX_SHARED_USES,
8 dayAfter,
9 domainsLine,
10 doneMessage,
11 invitesHref,
12 joinedThrough,
13 normalizeDomain,
14 parseGrant,
15 parseIds,
16 parseMintEmail,
17 parseNote,
18 parseSharedInvite,
19 parseTab,
20 parseWaitlistStatus,
21 sharedInviteLink,
22 sharedStatus,
23 usesLine,
24} from "./invites.ts";
25
26const form = (fields: Record<string, string>) => ({ get: (name: string) => fields[name] ?? null });
27
28test("the page opens on the waitlist, and each tab has an address", () => {
29 assert.equal(parseTab(null), "waitlist");
30 assert.equal(parseTab("tree"), "tree");
31 assert.equal(parseTab("nope"), "waitlist");
32 assert.equal(invitesHref("invites", { q: "g1t-k7m2", empty: "" }), "/invites?tab=invites&q=g1t-k7m2");
33 assert.equal(parseWaitlistStatus(null), "waiting");
34 assert.equal(parseWaitlistStatus("all"), "all");
35 assert.equal(parseWaitlistStatus("dismissed"), "dismissed");
36});
37
38test("a grant names who, how many and why", () => {
39 assert.deepEqual(parseGrant(form({ target: "user", name: "@Ada", amount: "10", note: "Launch partner" })), {
40 ok: true,
41 value: { target: "user", name: "ada", amount: 10, note: "Launch partner" },
42 });
43 assert.deepEqual(parseGrant(form({ target: "workspace", name: "acme", amount: "-5", note: "Abuse" })), {
44 ok: true,
45 value: { target: "workspace", name: "acme", amount: -5, note: "Abuse" },
46 });
47 assert.equal(parseGrant(form({ target: "team", name: "acme", amount: "5", note: "why" })).ok, false);
48 assert.equal(parseGrant(form({ target: "user", name: "not a name", amount: "5", note: "why" })).ok, false);
49 assert.equal(parseGrant(form({ target: "user", name: "ada", amount: "0", note: "why" })).ok, false);
50 assert.equal(parseGrant(form({ target: "user", name: "ada", amount: "1.5", note: "why" })).ok, false);
51 assert.equal(parseGrant(form({ target: "user", name: "ada", amount: "5000", note: "why" })).ok, false);
52 assert.equal(parseGrant(form({ target: "user", name: "ada", amount: "5", note: "" })).ok, false);
53});
54
55test("a minted invite is for one address, or for anyone", () => {
56 assert.deepEqual(parseMintEmail(""), { ok: true, value: null });
57 assert.deepEqual(parseMintEmail(" Ada@Example.com "), { ok: true, value: "ada@example.com" });
58 assert.equal(parseMintEmail("ada@").ok, false);
59});
60
61test("every outcome has words", () => {
62 for (const key of ["approved", "dismissed", "revoked", "granted"]) assert.ok(INVITES_DONE[key]);
63});
64
65test("several requests are decided at once, each once", () => {
66 const ticked = (ids: string[]) => ({ getAll: (name: string) => (name === "ids" ? ids : []) });
67 assert.deepEqual(parseIds(ticked(["wl_01jb2k", "wl_01jb2m", "wl_01jb2k"])), { ok: true, value: ["wl_01jb2k", "wl_01jb2m"] });
68 assert.equal(parseIds(ticked([])).ok, false);
69 assert.equal(parseIds(ticked(["inv_01jb2k", "wl_<script>"])).ok, false);
70 const many = Array.from({ length: MAX_BULK + 1 }, (_, n) => `wl_${n.toString(36)}`);
71 assert.equal(parseIds(ticked(many)).ok, false);
72 assert.equal(parseIds(ticked(many.slice(0, MAX_BULK))).ok, true);
73});
74
75test("an approval's note is optional and short", () => {
76 assert.deepEqual(parseNote(" Welcome aboard. "), { ok: true, value: "Welcome aboard." });
77 assert.deepEqual(parseNote(""), { ok: true, value: null });
78 assert.deepEqual(parseNote(null), { ok: true, value: null });
79 assert.equal(parseNote("x".repeat(501)).ok, false);
80});
81
82test("the flash says how many were decided", () => {
83 assert.equal(doneMessage("approved", "3"), "Approved 3 requests. Each invite is on its way.");
84 assert.equal(doneMessage("dismissed", "2"), "Dismissed 2 requests.");
85 assert.equal(doneMessage("approved", null), INVITES_DONE.approved);
86 assert.equal(doneMessage("approved", "1"), INVITES_DONE.approved);
87 assert.equal(doneMessage("nope", "4"), null);
88 assert.equal(doneMessage(null, null), null);
89});
90
91// 2026-10-08T12:00:00Z.
92const NOW = Date.UTC(2026, 9, 8, 12);
93
94test("shared links have their own tab", () => {
95 assert.equal(parseTab("shared"), "shared");
96 assert.equal(invitesHref("shared"), "/invites?tab=shared");
97 assert.ok(INVITES_DONE["shared-created"]);
98 assert.match(INVITES_DONE["shared-revoked"]!, /ones it made stay/);
99});
100
101test("a shared link needs a label, 1 to 1000 uses, and a day within a year", () => {
102 const ok = parseSharedInvite(form({ label: " Cloudflare judges ", max_uses: "40", expires_on: "2026-10-14", domains: "" }), NOW);
103 assert.deepEqual(ok, { ok: true, value: { label: "Cloudflare judges", maxUses: 40, expiresOn: "2026-10-14", domains: [] } });
104 // No day: identity's 14 days.
105 const later = parseSharedInvite(form({ label: "Judges", max_uses: "1" }), NOW);
106 assert.ok(later.ok && later.value.expiresOn === null);
107 assert.ok(!parseSharedInvite(form({ label: "", max_uses: "10" }), NOW).ok);
108 assert.ok(!parseSharedInvite(form({ label: "x".repeat(81), max_uses: "10" }), NOW).ok);
109 for (const uses of ["0", "1001", "-3", "2.5", "ten", ""]) {
110 const parsed = parseSharedInvite(form({ label: "Judges", max_uses: uses }), NOW);
111 assert.ok(!parsed.ok && parsed.error.includes(String(MAX_SHARED_USES)), uses);
112 }
113 assert.ok(parseSharedInvite(form({ label: "Judges", max_uses: "1000" }), NOW).ok);
114 // Today works; yesterday, a day past a year, and days that do not exist do not.
115 assert.ok(parseSharedInvite(form({ label: "Judges", max_uses: "5", expires_on: "2026-10-08" }), NOW).ok);
116 assert.ok(parseSharedInvite(form({ label: "Judges", max_uses: "5", expires_on: "2027-10-08" }), NOW).ok);
117 for (const day of ["2026-10-07", "2027-10-09", "2026-02-30", "14/10/2026"]) {
118 assert.ok(!parseSharedInvite(form({ label: "Judges", max_uses: "5", expires_on: day }), NOW).ok, day);
119 }
120});
121
122test("a shared link's domains are tidied, checked and capped", () => {
123 const parsed = parseSharedInvite(form({ label: "Judges", max_uses: "5", domains: "@Cloudflare.com, flagon.io cloudflare.com" }), NOW);
124 assert.ok(parsed.ok);
125 assert.deepEqual(parsed.value.domains, ["cloudflare.com", "flagon.io"]);
126 const bad = parseSharedInvite(form({ label: "Judges", max_uses: "5", domains: "localhost" }), NOW);
127 assert.ok(!bad.ok && bad.error.startsWith("localhost is not an email domain"));
128 const many = Array.from({ length: 11 }, (_, n) => `d${n}.com`).join(",");
129 assert.ok(!parseSharedInvite(form({ label: "Judges", max_uses: "5", domains: many }), NOW).ok);
130 assert.equal(normalizeDomain(" @EXAMPLE.com. "), "example.com");
131 assert.equal(normalizeDomain("-bad.com"), null);
132 assert.equal(domainsLine([]), "Any email address");
133 assert.equal(domainsLine(["cloudflare.com", "flagon.io"]), "Only addresses at cloudflare.com, flagon.io");
134});
135
136test("a shared link reads as its state, its uses and its address", () => {
137 assert.deepEqual(sharedStatus("live"), { label: "Live", tone: "lavender" });
138 assert.equal(sharedStatus("used_up").label, "Used up");
139 assert.equal(sharedStatus("expired").label, "Expired");
140 assert.equal(sharedStatus("revoked").tone, "danger");
141 assert.equal(usesLine({ uses: 3, maxUses: 40 }), "3 of 40 used");
142 assert.equal(sharedInviteLink("g1t-k7m2-q9xd"), "https://g1t.sh/register?invite=g1t-k7m2-q9xd");
143 assert.equal(joinedThrough("Cloudflare judges"), "Joined through Cloudflare judges");
144 assert.equal(dayAfter(NOW, 14), "2026-10-22");
145 assert.equal(dayAfter(NOW, 0), "2026-10-08");
146});