Public: anyone can read this; the crew can change it.

A test pins invites: `parseDays`, and an invite redeems once, never after it expires #6794

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/6786-a-test-pins-invites-parsedays-and-an-inv → main 1 commit fork

  • Merged. scout/6786-a-test-pins-invites-parsedays-and-an-inv was merged into main as c041def.

Review

Sign in to review this change.
1 file changed +98 −0
test/invites-core.test.ts added +98
@@ -0,0 +1,98 @@
1 /**
2 * `core/invites.ts` pinned directly, with `now` passed in: the day count is a
3 * whole number from 1 to 30, an invite is open until its expiry instant, it
4 * redeems once for one account, and taking the account back reopens it.
5 */
6 import { beforeEach, describe, expect, test } from "bun:test";
7 import { Database } from "bun:sqlite";
8 import invite from "../src/core/migrations/20261016200000-invite.ts";
9 import {
10 DEFAULT_DAYS,
11 MAX_DAYS,
12 inviteOpen,
13 inviteSpentBy,
14 listInvites,
15 mintInvite,
16 parseDays,
17 redeemInvite,
18 reopenInvite,
19 } from "../src/core/invites.ts";
20
21 const DAY = 86_400_000;
22 const T0 = Date.parse("2026-10-01T00:00:00Z");
23
24 describe("parseDays", () => {
25 test("the default for absent, the bounds for present", () => {
26 expect(parseDays(undefined)).toEqual({ ok: true, value: DEFAULT_DAYS });
27 expect(parseDays(null)).toEqual({ ok: true, value: DEFAULT_DAYS });
28 expect(parseDays(1)).toEqual({ ok: true, value: 1 });
29 expect(parseDays(MAX_DAYS)).toEqual({ ok: true, value: MAX_DAYS });
30 for (const bad of [0, MAX_DAYS + 1, 1.5, "7", Number.NaN, -1, Infinity]) {
31 expect(parseDays(bad)).toEqual({ ok: false, error: "invalid_days" });
32 }
33 });
34 });
35
36 describe("an invite's life", () => {
37 let db: Database;
38 beforeEach(() => {
39 db = new Database(":memory:");
40 db.exec(invite);
41 });
42
43 test("open before its expiry, not at or after it", () => {
44 const { token } = mintInvite(db, "owner", 2, T0);
45 expect(inviteOpen(db, token, T0)).toBe(true);
46 expect(inviteOpen(db, token, T0 + 2 * DAY - 1)).toBe(true);
47 expect(inviteOpen(db, token, T0 + 2 * DAY)).toBe(false);
48 expect(inviteOpen(db, token, T0 + 3 * DAY)).toBe(false);
49 expect(inviteOpen(db, "invite_unknown", T0)).toBe(false);
50 });
51
52 test("redeems once; a second redeem by anyone fails", () => {
53 const { token } = mintInvite(db, "owner", 2, T0);
54 expect(redeemInvite(db, token, "ada", T0 + 1)).toBe(true);
55 expect(inviteOpen(db, token, T0 + 2)).toBe(false);
56 expect(redeemInvite(db, token, "ada", T0 + 2)).toBe(false);
57 expect(redeemInvite(db, token, "bob", T0 + 2)).toBe(false);
58 expect(inviteSpentBy(db, "bob")).toBeUndefined();
59 });
60
61 test("an expired invite never redeems", () => {
62 const { token } = mintInvite(db, "owner", 1, T0);
63 expect(redeemInvite(db, token, "ada", T0 + DAY)).toBe(false);
64 expect(redeemInvite(db, token, "ada", T0 + 5 * DAY)).toBe(false);
65 expect(inviteSpentBy(db, "ada")).toBeUndefined();
66 expect(listInvites(db, T0 + DAY)[0]!.state).toBe("expired");
67 });
68
69 test("an unknown token redeems nothing", () => {
70 mintInvite(db, "owner", 2, T0);
71 expect(redeemInvite(db, "invite_nope", "ada", T0)).toBe(false);
72 });
73
74 test("inviteSpentBy names the redeemer's invite", () => {
75 const a = mintInvite(db, "owner", 2, T0);
76 const b = mintInvite(db, "owner", 2, T0);
77 redeemInvite(db, a.token, "ada", T0);
78 expect(inviteSpentBy(db, "ada")).toBe(a.invite.id);
79 expect(inviteSpentBy(db, "bob")).toBeUndefined();
80 expect(inviteSpentBy(db, "owner")).toBeUndefined();
81 expect(b.invite.id).not.toBe(a.invite.id);
82 });
83
84 test("reopenInvite gives back only that account's invite, once more redeemable", () => {
85 const a = mintInvite(db, "owner", 2, T0);
86 const b = mintInvite(db, "owner", 2, T0);
87 redeemInvite(db, a.token, "ada", T0);
88 redeemInvite(db, b.token, "bob", T0);
89 reopenInvite(db, "ada");
90 expect(inviteSpentBy(db, "ada")).toBeUndefined();
91 expect(inviteOpen(db, a.token, T0 + 1)).toBe(true);
92 expect(inviteOpen(db, b.token, T0 + 1)).toBe(false);
93 expect(inviteSpentBy(db, "bob")).toBe(b.invite.id);
94 expect(redeemInvite(db, a.token, "cy", T0 + 1)).toBe(true);
95 reopenInvite(db, "nobody");
96 expect(inviteSpentBy(db, "cy")).toBe(a.invite.id);
97 });
98 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs