diff --git a/README.md b/README.md index af8dca5..6ced56b 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,11 @@ chromium --headless --virtual-time-budget=8000 --dump-dom \ http://127.0.0.1:8777/selftest.html | grep -oE '(PASS|FAIL) [0-9/]+' ``` -Or open `selftest.html`. 29 assertions over the stages below detection. +Or open `selftest.html`. 41 assertions over the stages below detection, plus a +wiring cross-check: every `el('id')` in `app.js` must exist in `index.html`. A +knob wired in one but not the other throws during wiring, which aborts the rest +of the module and leaves a blank page — a symptom that points nowhere near its +cause, and which has happened twice. The ring-simplicity check is the load-bearing one. Because `hold` parts *cut* between poses instead of interpolating, a ring whose vertex order is wrong diff --git a/js/selftest.js b/js/selftest.js index 06b01e0..24cae67 100644 --- a/js/selftest.js +++ b/js/selftest.js @@ -45,6 +45,37 @@ const spreadX = (frames, slot) => { /* ---- the tests ---- */ +// Cross-check every el('id') in app.js against the ids in index.html. +// +// This bug class has bitten twice: a knob wired in app.js but absent from the +// markup throws during wiring, which aborts the rest of the module and leaves a +// blank page. The symptom ("nothing happens") points nowhere near the cause, so +// it is worth an automated check rather than vigilance. +export async function runWiring() { + const out = []; + try { + const [app, html] = await Promise.all([ + fetch('./js/app.js').then((r) => r.text()), + fetch('./index.html').then((r) => r.text()), + ]); + const ids = new Set([...app.matchAll(/\bel\(\s*['"]([\w-]+)['"]\s*\)/g)].map((m) => m[1])); + const list = app.match(/for \(const id of \[([\s\S]*?)\]\)/); + if (list) { + for (const m of list[1].matchAll(/'([\w]+)'/g)) { ids.add(m[1]); ids.add(m[1] + 'v'); } + } + const have = new Set([...html.matchAll(/id="([\w-]+)"/g)].map((m) => m[1])); + const missing = [...ids].filter((i) => !have.has(i)); + out.push({ name: `every el() id exists in index.html (${ids.size} checked)`, + pass: missing.length === 0, detail: missing.join(', ') }); + const unused = [...have].filter((i) => !ids.has(i)); + out.push({ name: 'no orphaned ids in index.html', pass: unused.length === 0, + detail: unused.join(', ') }); + } catch (e) { + out.push({ name: 'wiring check ran', pass: false, detail: e.message }); + } + return out; +} + export function run() { results.length = 0; diff --git a/selftest.html b/selftest.html index 7fa7360..0fa0d31 100644 --- a/selftest.html +++ b/selftest.html @@ -7,10 +7,11 @@

running…