AI writes frontend tests that pass forever and verify nothing, and generates UI that looks right to everyone except a keyboard or a screen reader. This module installs the countermeasures: mutation-checked tests, agent-authored E2E with ARIA snapshots, disciplined flake healing, and the three-layer accessibility audit no automation can replace.
Kavya leads frontend on a healthcare-scheduling product. The team adopted AI test generation two months ago; coverage climbed from 61% to 89%. Everyone relaxed.
A refactor breaks appointment cancellation — the confirm button dispatches the wrong action. Every test stays green. The bug ships; a clinic calls.
She reads the generated suite for the cancellation flow. The tests render the component, assert the mock was called, and snapshot the DOM. Not one asserts what the user sees or what the action does. 89% coverage, near-zero verification.
While she's in there, an accessibility complaint lands: the new booking dialog traps keyboard users — generated markup, div-buttons, no focus management. The axe CI job? Never wired to the new package.
Mutation testing goes in — 41% of the generated assertions die on the first Stryker run. Behavior-first tests replace them. The a11y gate becomes unskippable, and release week gets a manual keyboard-and-screen-reader pass, every time.
Kavya's green suite is the signature failure of AI-era frontend quality: verification theater. Models produce tests that exercise code without constraining behavior, because "tests that pass" is the visible success criterion and "tests that would fail if the feature broke" is not. The same generative fluency produces markup that renders beautifully and excludes anyone not using a mouse. Both failures are invisible in review and expensive in production — and both have mechanical countermeasures, which this module installs: mutation testing to score assertion quality, accessible queries to force behavior-first tests, ARIA snapshots to make E2E deterministic, root-cause discipline for flake healing, and a three-layer accessibility audit that knows exactly what machines cannot see.
The fix for verification theater starts with what generated tests are allowed to say. Constrain generation to RTL's accessible-query doctrine — getByRole, getByLabelText, user-visible assertions — and forbid the two theater staples: mock-call assertions as primary verification, and wholesale DOM snapshots. The prompt shape:
Generate RTL tests for [component]. Rules:
- Query only via accessible queries (getByRole, getByLabelText).
No test-ids, no container.querySelector.
- Each test: simulate a user action, assert user-visible outcome
(visible text, role state, enabled/disabled, navigation).
- No snapshot tests. Mock assertions only as secondary checks.
- Cover: happy path, each validation error, submit failure,
disabled-while-pending, empty state.
Accessible queries do double duty: they make tests resemble real usage and they fail on inaccessible markup — a div-button has no role to query, so the test can't be written against it. The doctrine quietly enforces a11y at test-authoring time.
Then prove the suite with mutation testing. StrykerJS mutates your component code — inverts conditions, drops calls, swaps operators — and reruns the tests; assertions that never fail are decorative, and the mutation score is the number coverage pretends to be. Kavya's 41% first-run kill-rate gap is typical for unconstrained generated suites. The loop: generate under constraints, run Stryker, feed surviving mutants back to the model ("these mutations survived — strengthen the assertions that should have caught them"), iterate to threshold. Lab 05 runs exactly this loop against a form component with a stated score to clear.
Coverage measures what ran; mutation score measures what would have been caught. AI inflates the first without moving the second — which is why mutation testing graduated from luxury to standard equipment the year test generation went mainstream.
Playwright MCP lets an agent drive the real app — navigate, click, fill, observe — and then emit the spec for what it just did. This kills the blank-page cost of E2E, but raw agent output has two habitual defects: selector fragility and nondeterminism. The countermeasures are part of the workflow, not afterthoughts:
getByRole('button', { name: 'Cancel appointment' }), never CSS-path selectors that die on the next refactor. Same doctrine as RTL, same a11y side benefit.toMatchAriaSnapshot captures the accessibility tree, not the pixel or DOM soup. It is resilient to cosmetic change, sensitive to structural and semantic change, and readable in review — the right default assertion for generated E2E.waitForTimeout), ordering assumptions on parallel data, and time/locale dependencies. Generated specs record what happened once; your review makes them specify what must always happen.The full test-agent trio — planner (proposes what to test), generator (writes specs), healer (repairs breaks) — is production-real in Playwright's ecosystem. The healer deserves its own discipline: when it proposes a fix for a red test, classify the root cause first — timing, selector, test data, environment, or actual regression. Accept fixes that eliminate the flake class (replace the hard wait with a web-first assertion); reject fixes that paper over it (bump the timeout, retry harder) — and never let a healer "heal" a genuine regression into a passing test. That last case is the healer's most dangerous failure mode, and only a human who reads the diff can catch it.
A healer agent measures success as "the test went green." A regression also goes green if you weaken the assertion. Every healer-proposed fix needs a human answer to one question before merge: did this change what the test tolerates?
Screenshot suites (Chromatic, Percy, Argos — or the Playwright setup from M4) generate review fatigue: hundreds of diffs per PR, most of them intentional restyles or anti-aliasing noise. The AI-era workflow adds a pre-classification pass — a vision model sorts each diff into intentional (matches the PR's stated styling change), regression (unrelated visual damage), or flake (rendering noise) — and humans review only the regression pile plus a sample of the rest. Treat vendor "AI review" claims with the standard skepticism: audit the classifier monthly by hand-reviewing a random slice of what it auto-approved. The efficiency is real; unaudited, so is the drift.
Accessibility verification has a hard structural fact at its center: automated scanners catch roughly a third of WCAG failures by volume, AI-guided testing extends coverage substantially further, and a stubborn remainder is machine-invisible — detectable only by a human at a keyboard or behind a screen reader. The three-layer audit is built on that fact, and knowing which layer catches what is the skill:
axe-core / Lighthouse / Accessibility Insights FastPass. Catches: missing alt, contrast failures, missing labels, invalid ARIA, duplicate IDs. Fast, free, unskippable in CI. Blind to: whether the alt text is meaningful, whether focus order makes sense, whether the experience is usable.
Deque's Intelligent Guided Tests and equivalents: the tool walks the page structure, asks you targeted questions ("is this the page's main heading?"), and maps answers to WCAG. Extends coverage deep into what pure scanners miss — keyboard operability checks, heading logic, name/role/value fitness. Vendor speed claims (4x) are vendor claims; the coverage extension is real.
Unplug the mouse: tab through every flow — reachability, visible focus, no traps, logical order. Then NVDA (free, Windows) or VoiceOver (built-in, macOS/iOS): do announcements make sense? Is dynamic content announced? Machine-invisible by nature: only this layer experiences the UI the way an AT user does.
Lab 07 seeds a page with ten defects — four automatable, four guided-detectable, two manual-only — and passing requires not just finding all ten but correctly identifying which two no machine could have found. That classification is the audit skill in miniature.
Auditing catches; prevention is cheaper. Both halves from M2 apply with a11y-specific content — and they're the difference between accessibility as heroics and accessibility as infrastructure:
aria-live for dynamic regions. Generated div-buttons stop at the source.| Defect class | Caught by | Prevented by |
|---|---|---|
| Missing labels, contrast, invalid ARIA | Layer 1 (axe, CI) | Instruction-file constraints |
| Illogical heading/focus order | Layer 2 (guided) | APG-referenced generation |
| Focus trap in a dialog | Layer 3 (keyboard pass) | Pattern-compliant primitives from your design system |
| Incoherent screen-reader experience | Layer 3 (NVDA/VoiceOver) | Semantic-first generation + manual gate on new flows |
One paragraph of legal clarity, because it changes team behavior: accessibility obligations — ADA, the European Accessibility Act, EN 301 549, India's RPwD Act — attach to the published product, not to its authorship process. A lawsuit, a procurement bar, or a regulator does not care that a model generated the markup; the operator ships it, the operator answers for it. Provenance never transfers liability. Teams that internalize this stop treating the a11y gate as friction on AI velocity and start treating it as the thing that makes AI velocity safe to use.
Scenario questions in this domain love the layer-classification trap: given a defect, which audit layer catches it? Anchor on the two manual-only classes — focus/keyboard experience and screen-reader coherence — and remember that automated scanning is the floor at roughly a third of issues, not the audit.
This module's playbooks: pb-22 (Behavior-First Component Tests), pb-23 (Mutation-Check Your Generated Tests), pb-24 (Agent-Authored E2E via Playwright MCP), pb-25 (Flaky E2E Healing Without Papering Over the Cause), pb-26 (Visual-Regression Triage with AI Pre-Classification), pb-27 (NL Mobile Journeys as Exploration, Deterministic Suites as Gates), plus the accessibility set: pb-29 (Three-Layer Audit), pb-30 (A11y Constraints and CI Gates), pb-31 (Alt-Text Pipeline), pb-32 (Keyboard and Focus Repair Against APG), and pb-33 (Accessible Streaming AI UI). Labs: 05 (mutation-proofed tests), 06 (agent E2E plus flake hardening), 07 (the ten-seed three-layer audit), and 09 (the provenance PR review, where several of these defects hide).
AI's tests must be proven, not trusted — mutation score is the proof. AI's markup must be audited in three layers, and the last layer is irreducibly human: a keyboard, a screen reader, and an engineer who knows that "the scan passed" covers a third of the law and none of the experience.