Accessibility
How the markup is audited
The audit no longer rests on a code review, but on an automated check replayed every time the tests run.
tests/php/Unit/Accessibility/MarkupFixtureTest.phpasks every field type to render itself, in its normal state and then in error, and writes the result totests/js/fixtures/a11y/.tests/js/accessibility.test.jsloads those documents into jsdom and submits them to axe-core.
The point that matters is that the audited markup is produced by the rendering code, never transcribed by hand into the test. A transcription would stay compliant while the real markup drifted; a real output fails the audit the moment a field loses its label or its ARIA association.
The escaping stand-ins of the unit bootstrap (esc_attr, esc_html, checked,
selected) reproduce WordPress’s exactly — two calls to htmlspecialchars and
two comparisons. The markup under examination is therefore the markup that would
actually be served.
To replay the audit:
composer test:unit # regenerates the documents
npm run test:unit:js # audits them
What the audit caught
Putting it in place revealed two real defects, both invisible on reading:
aria-requiredon afieldset(critical violation, five field types). Afieldset’s implicit role isgroup, which does not accept that attribute: it was therefore invalid and plainly ignored by screen readers, at the very moment we believed we were announcing that the field was required. Radio button and rating groups now declarerole="radiogroup", which does accept it; checkbox groups and composite fields no longer write it at all, the requirement being carried by the visible asterisk, by each sub-field’srequiredattribute, and by server-side validation.- A consent checkbox with no label (critical violation). The consent text being configurable, clearing it produced an empty label, and so a mute checkbox. Rendering now falls back to the default wording.
Limits we accept
- Colour contrast. axe-core’s
color-contrastrule is disabled in this audit, for two reasons that compound: jsdom does not implement the canvas axe uses to measure colours, and the documents under examination load no stylesheet — so there would be nothing to measure. The contrast of the public stylesheets stays verified by hand. - The
regionrule. Disabled as well: the audited documents are isolated form fragments, with no header and no navigation. The rule would be judging the test’s scaffolding, not the field. - Keyboard behaviour. axe-core analyses a static tree. Moving between steps, adding a row to a repeater and shifting focus after an error are matters for interaction tests, not for this audit.
- Page markup. The complete render — progress bar, multi-step pagination — is not covered here: it requires a real WordPress, and therefore the integration suite.
