From 96b2f6bd6247a1945d34120b5258165807c5a416 Mon Sep 17 00:00:00 2001 From: SandObserver <260779319+SandObserver@users.noreply.github.com> Date: Sun, 9 Aug 2026 18:25:06 -0400 Subject: [PATCH] Docs: correct three claims that no longer match the code The frontend guide told contributors the widget `?v=` was manual and to bump it when a widget's files changed. It has not been manual since entryVersions: the release hashes each entry file into the manifest and widget-types.js reads it from there, so following the guide meant hand-editing a value the build owns. Two tests pin the mechanism. The contributor guide claimed no test dependencies while c8 and Playwright are installed. The Playwright config claimed tests for drag reordering, focus and Persian mirroring; the five specs cover listing, adding, editing, reload persistence and widget type. --- CONTRIBUTING.md | 5 +++-- docs/frontend.md | 2 +- playwright.config.js | 8 ++++---- ui/test/cache-busting.test.mjs | 25 +++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 676757bb..9231f728 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,8 +10,9 @@ If a feature seems to need a dependency or a build step, open an issue first. ## Development -The frontend is static; edit files under `ui/` and reload. Tests use Node's -built-in runner, with no test dependencies. +The frontend is static; edit files under `ui/` and reload. Unit tests use Node's +built-in runner and need nothing installed; coverage and the browser tests use +the dev tooling in the root `package.json`. An export whose name starts with `_` exists for the tests and is not part of what the module offers: `_internals` for functions reached directly, `_reset*` diff --git a/docs/frontend.md b/docs/frontend.md index 8243d2fe..3d3a23e7 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -34,4 +34,4 @@ Each of these is a single batch request: the server fetches every configured bad ## Cache busting -`?v=` on `/css/` and `/js/` URLs is a content hash rewritten at release by `scripts/bump-cache-busting.js`; do not edit it. `?v=` on `/widgets/` URLs in `widget-types.js` is manual: bump it when you change a widget's own files. +`?v=` is a content hash rewritten at release by `scripts/bump-cache-busting.js`; do not edit one by hand. On `/css/` and `/js/` URLs the script rewrites the literal in the source. Widget iframe URLs are built from the manifest rather than written literally, so the script hashes each widget's entry files into `entryVersions` in its `widget.json`, and `widget-types.js` reads the hash from there when it builds the URL. diff --git a/playwright.config.js b/playwright.config.js index a7330bc7..0a5e7cd5 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,10 +1,10 @@ // @ts-check /* End-to-end tests, run against the container the release publishes. - The unit suites cover logic without a DOM. These cover the things only a - browser shows: that a form saves what it displays, that a drag reorders and - the order survives a reload, that focus stays where it should, and that the - interface mirrors in Persian. + The unit suites cover logic without a DOM. These cover what only a browser + shows: that the admin form saves what it displays, that an edit changes only + what was edited, and that a saved change survives a reload. Drag reordering, + focus handling and the Persian mirroring are not covered here yet. Two browsers on purpose. WebKit is not decoration: the documented support floor is Safari 16.2, and the last two layout and keyboard problems found by diff --git a/ui/test/cache-busting.test.mjs b/ui/test/cache-busting.test.mjs index 1b507d80..89c68f12 100644 --- a/ui/test/cache-busting.test.mjs +++ b/ui/test/cache-busting.test.mjs @@ -99,3 +99,28 @@ test('the workflows call the shared checks rather than listing their own', () => assert.match(workflow, /uses: \.\/\.github\/actions\/checks/, `${name} bypasses the shared checks`); } }); + +/* The documented rule, against the mechanism. + + docs/frontend.md told contributors that the widget `?v=` was manual and to + bump it by hand when a widget's files changed. It has not been manual since + entryVersions existed: the release hashes each entry file into the manifest + and widget-types.js reads it from there. A contributor following the document + would have hand-edited a value the build owns. + + Pinned by mechanism rather than by sentence: what must stay true is that no + widget URL carries a literal stamp and that the manifest is where the value + comes from. */ +test('the widget cache version comes from the manifest, not a hand-written literal', () => { + const src = fs.readFileSync(path.join(root, 'js/widget-types.js'), 'utf8'); + assert.match(src, /entryVersions\?\.\[file\]/, 'widget-types.js no longer reads the manifest hash'); + const literal = /['"`]\/widgets\/[^'"`]*\?v=\d/.exec(src); + assert.equal(literal, null, `a hand-written widget stamp is back: ${literal && literal[0]}`); +}); + +test('the frontend guide describes the mechanism that exists', () => { + const doc = fs.readFileSync(path.join(root, '..', 'docs', 'frontend.md'), 'utf8'); + const section = doc.slice(doc.indexOf('## Cache busting')); + assert.match(section, /entryVersions/, 'the guide does not mention where the widget hash lives'); + assert.doesNotMatch(section, /is manual/, 'the guide tells contributors to bump a stamp the build owns'); +});