| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | |
| 4 | import { |
| 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 | |
| 26 | const form = (fields: Record<string, string>) => ({ get: (name: string) => fields[name] ?? null }); |
| 27 | |
| 28 | test("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 | |
| 38 | test("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 | |
| 55 | test("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 | |
| 61 | test("every outcome has words", () => { |
| 62 | for (const key of ["approved", "dismissed", "revoked", "granted"]) assert.ok(INVITES_DONE[key]); |
| 63 | }); |
| 64 | |
| 65 | test("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 | |
| 75 | test("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 | |
| 82 | test("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. |
| 92 | const NOW = Date.UTC(2026, 9, 8, 12); |
| 93 | |
| 94 | test("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 | |
| 101 | test("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 | |
| 122 | test("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 | |
| 136 | test("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 | }); |