Writing Actionable Accessibility Bug Reports
Permalink to "Writing Actionable Accessibility Bug Reports"An accessibility audit is only as useful as the bug reports it produces. “Grid not accessible with screen reader” gets triaged to the bottom of the backlog, because nobody can reproduce it or knows what to change. “Sorting the Amount column in the Invoices grid is not announced by NVDA 2024.3 + Chrome 128; expected ‘Sorted by Amount, ascending’; SC 4.1.3; the status region is mounted after the sort” gets fixed the same week.
This page gives a report structure for data-UI findings, examples for the common finding types, and guidance on severity and on turning reports into regression tests. It belongs to manual accessibility audits.
Spec reference
Permalink to "Spec reference"A report is not governed by WCAG, but it should reference it precisely:
- Criterion number and name — “SC 4.1.3 Status Messages (AA)”, not “WCAG”.
- Conformance level — A, AA or AAA, so product owners can prioritise against their target.
- Technique or failure reference where helpful — the WCAG understanding documents list common failures; naming the failure pattern (“status message not programmatically determined”) helps engineers search.
For screen reader findings, include the exact output. Screen reader speech is the observable behaviour; paraphrases like “reads it wrong” lose the information engineers need. Speech logs from NVDA’s Speech Viewer, VoiceOver’s caption panel or guidepup’s phrase log are ideal — see capturing NVDA speech logs for manual testing.
When a report is enough — and when to pair it with a test
Permalink to "When a report is enough — and when to pair it with a test"A report is enough for one-off issues in content or copy: a vague link name, an image missing alt text in a help page.
Pair a report with a regression test for anything in a component or a shared pattern: missing names, broken keyboard contracts, lost focus. Include the test in the fix, so the same bug cannot return — role queries for names, keyboard contract rows for focus, a status-region assertion for announcements, as described in accessibility testing recipes.
The misapplication to name is filing an audit as one giant ticket, “Fix accessibility issues on Invoices page (37 items)”. It cannot be estimated, assigned or closed. One finding per ticket, grouped with a label or an epic.
Annotated code example
Permalink to "Annotated code example"TITLE
Invoices grid: sorting a column is not announced to screen reader users
ENVIRONMENT
NVDA 2024.3, Chrome 128, Windows 11 23H2 · Build 2026.09.18 · /invoices (seeded dataset A)
STEPS
1. Load /invoices; wait for the grid.
2. Press H until "Open invoices, heading level 2" is announced.
3. Press Tab 4 times to reach the "Amount" column header button.
4. Press Enter.
EXPECTED
NVDA announces the new sort state and a status message:
"Amount, sorted ascending" (header state)
"Sorted by Amount, ascending." (status message, polite)
ACTUAL (NVDA Speech Viewer)
"Amount button column header not sorted"
[nothing further]
The rows are re-ordered visually. aria-sort="ascending" is set on the th.
CRITERION / IMPACT
SC 4.1.3 Status Messages (AA). Screen reader users cannot tell the sort happened
without re-reading the column; users who sort frequently lose significant time.
Severity: High (core task, no workaround other than manual checking).
SUGGESTED FIX
The status element is rendered conditionally ({message && …}),
so it is mounted with its text and not announced. Render it on first load and only
change its text. Pattern: /core-aria-keyboard-navigation-for-data-uis/aria-live-regions-for-dynamic-data/live-regions-in-react-without-lost-announcements/
REGRESSION TEST
Add to invoice-grid.spec: after Enter on "Amount", expect getByRole('status')
to have text "Sorted by Amount, ascending." (status element present before sort).
The actual result quotes the Speech Viewer and adds one DOM observation (“aria-sort is set”). That observation narrows the cause immediately: the header state is right, the announcement is missing. Good reports separate what was heard from what was inspected.
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"Templates for the other common finding types in data UIs:
| Finding type | Steps must include | Expected vs actual must quote |
|---|---|---|
| Missing or wrong name | How focus reached the element | The announced name (“button”) vs the needed one (“Delete INV-1042”) |
| Keyboard failure | Exact keys and starting focus | Where focus should land vs where it went (e.g. body) |
| Focus lost | The action that removed or re-rendered the element | document.activeElement after the action |
| Announcement missing or flooded | The action and timing | Speech log excerpt |
| Contrast / visibility | Theme, zoom level, state | Measured ratio vs required; screenshot |
| Reflow | Window size and zoom | What overflows; screenshot at 400% |
Integration context
Permalink to "Integration context"Findings from the keyboard-only audit script, zoom and reflow testing and high contrast audits all use this structure. Screen reader findings should be compared across readers before filing, to distinguish markup bugs from reader behaviour — see assistive technology behaviour differences.
When a finding is an automated-rule false positive rather than a bug, it goes to the suppression ledger instead of the backlog, per configuring axe-core rules and handling false positives.
Gotchas
Permalink to "Gotchas"Paraphrased speech. “It reads it weird” is not reproducible. Quote the output.
Missing starting point. “Tab to the button” from where? Start from a heading, landmark or page load.
Fix prescriptions that overreach. Suggest a pattern, not a rewrite. “Render the status region on mount” is actionable; “rebuild the grid with a different library” is not.
Design system notes
Permalink to "Design system notes"Provide the report template in the issue tracker, with fields for environment, steps, expected, actual, criterion, impact and suggested pattern. Label component-level findings with the design-system component name so they can be fixed once and shipped to every product.
Testing checklist
Permalink to "Testing checklist"FAQ
Permalink to "FAQ"What should an accessibility bug report include?
A specific title, the environment (assistive technology, browser, OS, build), exact reproduction steps from a known starting point, expected and actual results with quoted screen reader output, the WCAG criterion and level, the user impact, and a suggested fix or pattern.
How should screen reader output be recorded in a bug report?
Quote it exactly, from NVDA’s Speech Viewer, VoiceOver’s caption panel or a guidepup phrase log, and note separately anything you observed in the DOM, such as an attribute that was or was not set.
How do I decide the severity of an accessibility bug?
By impact on users’ tasks: whether it blocks a core task, whether there is a workaround, and how often users meet it. The WCAG level informs priority but does not set severity on its own.
Should one audit produce one ticket?
No. File one ticket per finding, grouped with a label or epic, so each can be estimated, assigned, fixed and verified independently.
Related
Permalink to "Related"- Capturing NVDA speech logs — evidence for the report
- Keyboard-only audit script — where many findings come from
- Configuring axe-core rules — when a report becomes a test