id: web-testing title: The app has a test runner, not regexes over source status: continuous repos: [headquarters] dependsOn: [] exitCriterion: > A test can render a screen and assert on what the accessibility tree says, rather than on the source that produced it. #
web-testing #
npm test builds and runs node --test over web/scripts. That is enough for
the checks that read dist/ and for destinations.ts — node strips the types
off a .ts import on its own now. What it cannot reach is anything that needs
a DOM, and the app is mostly things that need a DOM.
The route predicate in router.ts is the first thing worth covering and still
is not.
How far the fake goes #
dom.test.mjs is the first test that needed a DOM and got it from a
twenty-line fake document rather than a runner. That works because el()
touches one method.
render.test.mjs is the limit: parentage, contains, replaceChildren and
one activeElement, which is enough to hold render()'s focus rule from both
sides. It already asserts that the only selector ever passed is h1, because
answering a real one would mean writing a query engine.
router.ts reads window.location and renders, and faking that is where the
fake stops paying.
What the absence costs #
signin-form.test.mjs is the bill. The thing worth asserting is what the
accessibility tree says about the rendered form, and with no DOM it asserts the
source shapes that produce it instead. Every one of those is a regex on a file,
and they will all have to be rewritten the day there is a runner.
That is the argument for doing this: not that the current tests are wrong, but that they are written against the wrong thing and the cost of the rewrite grows with every one added.