Skip to content

node:test suite for app.js, make probe and CSP hashes, palette tool plates out of the shell, drink links from menu rows, Recipe dates and sitemap lastmod - #121

Merged
cjimti merged 1 commit into
mainfrom
probe-plates-unit-tests
Sep 13, 2026

Conversation

@cjimti

@cjimti cjimti commented Sep 13, 2026

Copy link
Copy Markdown
Owner

app.js tests (#114)

scripts/app.test.mjs runs assets/app.js in node under node:test, with no dependency and no package.json. The IIFE is taken off, a stub page stands in for the DOM, and boot runs on the real data, so app.js needs no test hook. make unit is part of make check.

  • 19 cases: every build amount and serve token decodes, the key tab agrees with the decoder, shelf codes round-trip every named shelf and the full bar, 21 bad codes open nothing, stand-ins, garnish never gating and foam bitters gating, Benedictine +3, Next bottles, QR version capacity with finder, timing and format bits, 18 malformed stores, and the row link click.
  • Checked against 13 deliberate breaks in app.js, swapping q and Q among them; each one fails a case.
  • scripts/unit-report.mjs prints the one-line summary, or each failure in full, including what the file wrote to stderr when boot itself fails.
  • The repo has no Python QR reference check, so the QR case tests the capacity at each version, the finder and timing patterns and the format bits. retired_bits is empty, so the retired-bit case covers nothing yet.

make probe and CSP hashes (#101, repo part)

  • scripts/probe.py: read-only, follows no redirect. It checks http to https on the same path, HSTS, nosniff, Referrer-Policy, Permissions-Policy, and a CSP (enforced or report-only) whose script-src names every inline script hash from the tree. Not part of make verify.
  • On the live site today: the 3 redirects pass; HSTS, the three headers and the CSP are missing on both / and /drink/martini/ (10 checks).
  • stage.py prints the sha256 hashes after a stage. There are two, not three: the drink pages' GTM snippet is byte-identical to the one in index.html.
  • The Cloudflare settings are still to do, so this PR does not close Live origin: http serves the site as 200, no HSTS, no security headers; the Cloudflare settings, a CSP draft and a live probe #101.

Tool plates (#111)

  • make-tools.py writes each plate as a palette PNG of the one ink at eight evenly spaced alphas with tRNS: 938 KB to 188 KB (du 212K). Compared at the Info tab's display size, dark and light: worst pixel difference 9/255. Twelve or more levels go past 250 KB, and Pillow's 64-colour octree produced eight uneven levels anyway.
  • The plates are out of the worker SHELL and go network-first like the glasses.
  • check_assets.py requires colour type 3 with tRNS and refuses a plate in the shell.

Drink links, Recipe dates, lastmod (#112)

  • Each Menu row is a div with the expand button laid over the row, and the name is a link to /drink/<id>/ above it; the front page renders 185 of these links.
  • A plain click on the name expands the row and moves focus to the row's button. A modifier click is left to the browser.
  • The row text is the button's name through aria-labelledby and is aria-hidden, and the link has tabindex="-1", so a screen reader and a keyboard still get one control per row.
  • Recipe JSON-LD gains datePublished, dateModified and totalTime (PT3M stirred and shaken, PT2M built). The sitemap carries lastmod and drops changefreq and priority.
  • Dates live in the generated data/dates.json, keyed on a hash of each drink and seeded once from git history. make pages dates an edit to the day it runs and --check refuses a stale entry, so CI never asks git.

Tested

  • make verify passes: 292 checker cases, 19 unit cases.
  • Headless Chrome at 390 px and 1280 px, dark and light, and print media:
    • 185 row links, each row with its button first.
    • Cmd-click on a name opens the page in a new tab and leaves the row closed; a plain click, a click elsewhere on the row, Enter and Space all expand it.
    • Close in the wide aside returns focus to the row's button, and the button's accessible name is the full row text.
    • All 12 plates load on the Info tab in both themes.
  • All 185 Recipe JSON-LD blocks parse with valid dates.

Not verified

  • Plates offline through the worker (it only registers on https).
  • The link clicks in Safari and Firefox.
  • VoiceOver.
  • Rich Results Test.
  • Lighthouse.
  • make unit on the CI runner, which needs Node 20 or newer.

Closes #114. Closes #111. Closes #112. Refs #101.

…lates out of the shell, drink links from menu rows, Recipe dates and sitemap lastmod

scripts/app.test.mjs runs assets/app.js in node under node:test: the IIFE is taken off, a stub page stands in for the DOM, and boot runs on the real data. 19 cases cover build amounts and serve tokens, the key tab against the decoder, shelf code round trips and bad codes, stand-ins, garnish gating, Next bottles, QR version capacity and format bits, malformed stores, and the row link click. scripts/unit-report.mjs prints the house summary line. make unit is part of make check.

scripts/probe.py (make probe) reads the live origin without following redirects: http to https on the same path, HSTS, nosniff, Referrer-Policy, Permissions-Policy, and a CSP whose script-src names the hash of every inline script in the tree. It is not part of make verify. stage.py prints those sha256 hashes after a stage.

make-tools.py writes each plate as a palette PNG of the one ink at eight evenly spaced alphas with tRNS: 938 KB to 188 KB. The plates are out of the worker SHELL and go network-first. check_assets.py requires colour type 3 with tRNS and refuses a plate in the shell.

Menu rows are a div holding an overlay expand button and the text, with the name as a link to /drink/<id>/. A plain click on the name expands the row and moves focus to the button; a modifier click is left to the browser. The text is the button name through aria-labelledby and is aria-hidden, and the link has tabindex -1.

pages.py adds datePublished, dateModified and totalTime to the Recipe JSON-LD, and lastmod to the sitemap in place of changefreq and priority. Dates come from the generated data/dates.json, keyed on a hash of each drink and seeded from git history; make pages dates an edit to the day it runs and --check refuses a stale entry.

Closes #114. Closes #111. Closes #112. Refs #101.
@cjimti
cjimti merged commit 2dd3e76 into main Sep 13, 2026
1 check passed
@cjimti
cjimti deleted the probe-plates-unit-tests branch September 13, 2026 04:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment