Something went wrong. Try again.
Web frontend and supporting services for lance.blue
Something went wrong. Try again.
4.1 kB · 111 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112/** * A player's matches are an address before they are a page. * * The same three things have to agree about `/matches/<handle-or-did>` as * about the profile's own prefix, and none of them can see the others: * destinations.ts parses the address, Astro builds one file for every address * under it, and a rewrite in front of the bucket puts the two together. * * There is a fourth thing here that the profile does not have. This address * replaced a hash route, `#operations`, and that route died silently: the * router's set of hash routes is derived from the masthead's destinations, so * taking Operations off the bar took its address with it and the account * menu's Your matches led to the front page for anybody who pressed it. The * checks below are what say the replacement is not the same kind of thing. * * Run with `npm test`. */import { test } from "node:test";import assert from "node:assert/strict";import { existsSync } from "node:fs";import { readFile } from "node:fs/promises";import { fileURLToPath } from "node:url";
import { actorFromMatchesPath, matchesHref, routeForHash,} from "../src/destinations.ts";
const src = fileURLToPath(new URL("../src/", import.meta.url));
test("the prefix has a page behind it", () => { assert.ok( existsSync(`${src}pages/matches/index.astro`), "nothing builds /matches, so every player's record is a 404", );});
test("an address names a handle or a DID, and both survive the trip", () => { assert.equal( actorFromMatchesPath("/matches/alice.example.com"), "alice.example.com", ); assert.equal( actorFromMatchesPath("/matches/did:plc:abc123"), "did:plc:abc123", ); assert.equal( actorFromMatchesPath("/matches/did%3Aplc%3Aabc123"), "did:plc:abc123", ); assert.equal( actorFromMatchesPath("/matches/@alice.example"), "@alice.example", ); // A trailing slash is the same page, not a dead end. assert.equal( actorFromMatchesPath("/matches/did:plc:abc123/"), "did:plc:abc123", ); // Nobody named. assert.equal(actorFromMatchesPath("/matches/"), null); assert.equal(actorFromMatchesPath("/matches"), null); // The profile's prefix is not this one, and neither is anything else. assert.equal(actorFromMatchesPath("/profile/@alice.example"), null); // A malformed escape is not an address, and must not throw on the way out. assert.equal(actorFromMatchesPath("/matches/%E0%A4%A"), null);});
test("the address the site writes is the one it can read back", () => { const did = "did:plc:abc123"; assert.equal( matchesHref({ did, handle: "alice.example" }), "/matches/@alice.example", ); assert.equal(matchesHref({ did, handle: null }), `/matches/${did}`); assert.equal( actorFromMatchesPath(matchesHref({ did, handle: "alice.example" })), "@alice.example", ); assert.equal(actorFromMatchesPath(matchesHref({ did, handle: null })), did);});
// What went wrong last time, held as a check rather than as a comment.test("#operations is not a route, and nothing links to one", async () => { assert.equal(routeForHash("#operations"), null); const account = await readFile(`${src}account.ts`, "utf8"); const pilot = await readFile(`${src}screens/pilot.ts`, "utf8"); for (const [name, source] of [ ["account.ts", account], ["screens/pilot.ts", pilot], ]) { assert.ok( !/#operations/.test(source), `${name} links to a hash route that no longer resolves`, ); }});
test("a row about somebody else offers no way into their match", async () => { const list = await readFile(`${src}screens/match-list.ts`, "utf8"); // The Resume button hands the waiting screen a session, and waiting for a // match is something only the player in it can do. The link into a running // match is the API's to withhold - it sends no url to anybody else - but // this one is the browser's. assert.match( list, /session &&\s*isOwn\(view\) &&\s*\(match\.status === "starting"/, "Resume is offered on a stranger's row", );});