/** * The waiting screen's moving parts, checked structurally: there is no DOM * under `npm test`, and both of the ways these break look fine in a build. * * The scanline is animation, so it needs a reduced-motion rule, and a rule * that is simply absent is invisible until somebody who set the preference * loads the screen. The scanline and Cancel are both cut with clip-path, * which clips an element's outline along with its background — so a focus * ring on one of them has to be an inset shadow, and an outlined one * disappears without any rule failing. * * 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"; const web = join(new URL(".", import.meta.url).pathname, ".."); const css = await readFile(join(web, "src/styles.css"), "utf8"); const screen = await readFile(join(web, "src/screens/waiting.ts"), "utf8"); test("every class the screen writes has a rule", () => { const classes = new Set( [...screen.matchAll(/className: "([^"]+)"/g)].flatMap((m) => m[1].split(/\s+/), ), ); for (const name of classes) { assert.ok(css.includes(`.${name}`), `no rule for .${name}`); } }); test("the scanline stops when motion is not wanted", () => { assert.match(css, /\.waiting-scan-sweep\s*{[^}]*animation:/); const reduced = [ ...css.matchAll( /@media \(prefers-reduced-motion: reduce\) {([\s\S]*?)\n}/g, ), ] .map((m) => m[1]) .join("\n"); assert.match(reduced, /\.waiting-scan-sweep[^}]*animation: none/); }); test("the cancel plate's focus ring is inset", () => { // The ring is set once, for every button and everything wearing .plate, and // Cancel is a button. A per-control copy is what this used to check. const rule = css.match( /button:focus-visible,\s*\.plate:focus-visible\s*{([^}]*)}/, )?.[1]; assert.ok(rule, "no shared focus-visible rule for plates"); assert.match(rule, /outline: 0/); assert.match(rule, /box-shadow: inset/); assert.match(css, /\.waiting-cancel\s*{[^}]*--notch:/); });