/** * The camo editor says things in two places, and the way it goes wrong is * always the same: something that is not a pattern writes to the line under * the Pattern label. Signing in used to put "Picked up where you left off, * saving to @you" there, above a grid of patterns it was not describing. * * The other half of the same rule is Save. With no account there is nothing to * save to, and a sentence saying so under the pattern grid is not what a * player who just pressed Save is looking at; the sign-in dialog is. * * Both checks are structural. There is nothing to catch at runtime: the wrong * line is still a line, it renders, and nothing errors. * * Run with `npm test`. */ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; const web = fileURLToPath(new URL("../", import.meta.url)); const source = await readFile(join(web, "src/camo/editor.ts"), "utf8"); /** The body of a top-level function in the editor, by its declaration. */ function body(declaration) { const start = source.indexOf(declaration); assert.notEqual(start, -1, `${declaration} moved or was renamed`); // Every nested block in this file closes at four spaces or deeper, so the // first two-space brace is the function's own. const end = source.indexOf("\n }", start); assert.notEqual(end, -1, `${declaration} has no end`); return { start, end, text: source.slice(start, end) }; } test("only the pattern picker writes the pattern hint", () => { const writes = [...source.matchAll(/patternHint\.textContent\s*=/g)]; assert.equal( writes.length, 1, "the pattern hint has more than one writer; a save, a sign-in or an " + "import would leave it describing something else", ); const marker = body("function markPattern(): void {"); const at = writes[0].index; assert.ok( at > marker.start && at < marker.end, "the pattern hint is written from outside markPattern", ); }); test("save with no account opens the sign-in dialog", () => { const save = body("function doSave("); assert.match( save.text, /if \(!repoSession\) \{[^}]*collection\.signIn\(\)/, "saving without an account should put the sign-in dialog up, not a message", ); });