Commit the screen-reader harness as test/manual - #3600
Merged
Conversation
The suite is jsdom, so every accessibility claim this package makes is pinned as markup and nothing observes what a screen reader does with it. That is this repo's blind spot rather than a shared one, since svg-injector ships no ARIA behaviour of its own. The harness that answered the loading-announcement question was built outside the repo and would have been rebuilt from scratch next time, along with the wrong turns it already encodes: the instrument check that distinguishes insertion from mutation, the request-count check behind a cached remount, and the port choice WebKit blocks. React now comes out of node_modules rather than esm.sh. It ships no ES module build, so the server wraps the CJS files it does ship and the page loads them as classic scripts ahead of any module, with generated ESM shims behind the import map. The harness needs no network and has no second React version to keep in step with package.json. AGENTS.md gains the paragraph stating the blind spot and pointing at the harness, which is the half of this that did not exist before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The suite runs in jsdom, which has no accessibility layer and no paint, so every accessibility claim this package makes is pinned as markup: that
role="img"is set, that the<title>and<desc>nodes exist, thataria-labelledbypoints at their IDs. Nothing observes what assistive technology does with any of it. That is this repo's blind spot rather than a shared one, since@tanem/svg-injectorships no ARIA behaviour of its own — the wiring inbeforeEachand theloadingelement this package mounts and unmounts are the whole accessibility contract.The harness that answered the loading-announcement question was built outside the repo and would have been rebuilt from scratch next time, along with the wrong turns it already encodes: an instrument check that distinguishes a mutated live region from an inserted one, a request-count check behind each cached remount, and a port choice that WebKit blocks and Chromium quietly does not.
This commits it as
test/manual/, following the same shape@tanem/svg-injectorused for its transport checks: outside the run, deliberately not wired into CI, since the instrument is a real screen reader and automating it would mean simulating the thing it exists to escape. Jest'stestMatchistest/*.spec.ts?(x), so nothing new is picked up, andfilesinpackage.jsonisdistandsrc, so nothing new is published.AGENTS.mdgains the paragraph stating the blind spot and pointing at the harness. That instruction did not exist before and is half the point of the change.React comes from node_modules, not esm.sh
The harness previously pinned React through esm.sh, which meant a first load needed network and a second React version had to be kept in step with
package.jsonby hand.React ships no ES module build, so
server.mjsnow serves the CJS files it does ship, wrapped in amodule/exports/require/processshim, andindex.htmlloads them as classic scripts ahead of any module. The import map pointsreactandreact-dom/clientat generated ESM shims over those globals, whose named exports are read off the real module as it is served — so a React upgrade that adds an export needs no edit here. The named exports matter becausedist/react-svg.mjsdoesimport * as React from 'react'; a default-only shim would hand it an empty namespace.Two details are worth knowing before editing that code:
./cjs/*, so the files are located through each package'spackage.jsonrather than resolved directly.The harness is also covered by lint and format now instead of being excluded with the rest of the git-ignored scratch area.
sort-keysis off for it, becauseapp.mjs's step table is in the order the steps are run in.Verification
npm testgreen, React matrix included.The page itself ran end to end in Playwright chromium and then in stock Chrome 151: React 19.2.4 loaded from
node_modules, all six steps ran, both cached remounts reported0 requests served, the control held its loading element for 2509ms, and the console carried nothing but React's DevTools notice. The server's own hit counter corroborates the cache hits independently — exactly one request per icon across the whole session, none during either cached case.No screen reader was running for that check, so it says only that the harness works. It is recorded in the README separately from the VoiceOver result for that reason. The Safari/VoiceOver measurement is carried across unchanged: no announcement, and lifetime is not the variable, because VoiceOver ignores a live region that arrives with its content already in it.
🤖 Generated with Claude Code