| 1 | // Tests for the inviter-name hint's pure helpers (invitehint.js, #1436). |
| 2 | import test from "node:test"; |
| 3 | import assert from "node:assert/strict"; |
| 4 | import { inviterHintStash, readInviterHint, inviterHintTarget } from "../web/static/invitehint.js"; |
| 5 | |
| 6 | const NOW = 1_700_000_000_000; |
| 7 | |
| 8 | test("stash/read round trip, trimming and capping the name", () => { |
| 9 | const stored = inviterHintStash({ thread: "t1", name: " Paul ", now: NOW }); |
| 10 | assert.deepEqual(readInviterHint(stored, NOW + 1000), { thread: "t1", name: "Paul" }); |
| 11 | const long = inviterHintStash({ thread: "t1", name: "x".repeat(200), now: NOW }); |
| 12 | assert.equal(readInviterHint(long, NOW).name.length, 64); |
| 13 | }); |
| 14 | |
| 15 | test("read rejects garbage, empties, clock skew, and stale hints", () => { |
| 16 | assert.equal(readInviterHint("", NOW), null); |
| 17 | assert.equal(readInviterHint("not json", NOW), null); |
| 18 | assert.equal(readInviterHint(JSON.stringify({ v: 1, thread: "", name: "P", at: NOW }), NOW), null); |
| 19 | assert.equal(readInviterHint(JSON.stringify({ v: 1, thread: "t", name: " ", at: NOW }), NOW), null); |
| 20 | assert.equal(readInviterHint(inviterHintStash({ thread: "t", name: "P", now: NOW }), NOW - 1), null); |
| 21 | const weekPlus = NOW + 7 * 24 * 60 * 60 * 1000 + 1; |
| 22 | assert.equal(readInviterHint(inviterHintStash({ thread: "t", name: "P", now: NOW }), weekPlus), null); |
| 23 | }); |
| 24 | |
| 25 | const hint = { thread: "dm1", name: "Paul" }; |
| 26 | const threads = [{ id: "dm1", members: ["me", "inviter"] }, { id: "other", members: ["me", "x"] }]; |
| 27 | |
| 28 | test("target: fills the hinted DM's label-less other member", () => { |
| 29 | const roster = [{ user_id: "me", label: "Joiner" }, { user_id: "inviter", label: "" }]; |
| 30 | assert.deepEqual(inviterHintTarget(hint, threads, roster, "me"), { userId: "inviter", name: "Paul" }); |
| 31 | }); |
| 32 | |
| 33 | test("target: resolved once the real label decrypted — caller drops the stash", () => { |
| 34 | const roster = [{ user_id: "inviter", label: "Paul Campbell" }]; |
| 35 | assert.deepEqual(inviterHintTarget(hint, threads, roster, "me"), { resolved: true }); |
| 36 | }); |
| 37 | |
| 38 | test("target: null while thread or member not loaded yet (stash kept)", () => { |
| 39 | assert.equal(inviterHintTarget(hint, [], [], "me"), null); |
| 40 | assert.equal(inviterHintTarget(hint, threads, [], "me"), null); |
| 41 | assert.equal(inviterHintTarget(null, threads, [], "me"), null); |
| 42 | }); |
| 43 | |
| 44 | test("target: never labels an agent, never anyone outside the hinted DM", () => { |
| 45 | const roster = [{ user_id: "inviter", label: "", is_agent: true }, { user_id: "x", label: "" }]; |
| 46 | assert.equal(inviterHintTarget(hint, threads, roster, "me"), null); |
| 47 | }); |
| 48 | |