Skip to content
Back to skills

Screen Reader Test Author

ASecurity

Builds the full manual-accessibility artifact surface: step-by-step screen-reader test scripts for NVDA (Windows), JAWS (Windows), VoiceOver (macOS / iOS), or TalkBack (Android) with per-step keystroke + expected announcement; per-archetype WCAG 2.2 checklists (references/wcag-checklist.md); per-widget keystroke matrices pairing expected NVDA and VoiceOver announcements with the WCAG SC each row verifies (references/widget-matrix.md); and a guided NVDA / VoiceOver session protocol that merges...

  • 10 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 12, 2026
testinggoawstestingdocumentation

Works with

  • cursor

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned October 12, 2026

npx -y skills add testland/qa --skill screen-reader-test-author --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Screen Reader Test Author?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Screen Reader Test Author
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/testland-screen-reader-test-author/badge)](https://www.skillsdirectory.com/skills/testland-screen-reader-test-author)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: screen-reader-test-author
description: "Builds the full manual-accessibility artifact surface: step-by-step screen-reader test scripts for NVDA (Windows), JAWS (Windows), VoiceOver (macOS / iOS), or TalkBack (Android) with per-step keystroke + expected announcement; per-archetype WCAG 2.2 checklists (references/wcag-checklist.md); per-widget keystroke matrices pairing expected NVDA and VoiceOver announcements with the WCAG SC each row verifies (references/widget-matrix.md); and a guided NVDA / VoiceOver session protocol that merges script + checklist into a signed pass/fail session report. Use when authoring an accessibility-acceptance test, checklist, or widget matrix the team will run before sign-off, when scripting a manual a11y audit, OR when walking a tester through a guided screen-reader session."
---

# screen-reader-test-author

## Overview

Automated tools (axe-core, pa11y, Lighthouse) catch ~30-40% of
accessibility issues - the structural ones. The remaining 60-70%
require **manual screen-reader testing** by an actual human using
NVDA / JAWS / VoiceOver / TalkBack. The team needs a repeatable
script that any tester (not just the original author) can follow.

This skill takes a user flow and produces that script: per-step
keystroke + expected announcement. Two sibling artifact shapes live in
references/: a per-archetype WCAG 2.2 checklist generator for
spec-review-time acceptance criteria
([references/wcag-checklist.md](references/wcag-checklist.md)) and
per-widget keystroke matrices for hand-run NVDA / VoiceOver passes
([references/widget-matrix.md](references/widget-matrix.md)). The
"Running the session" section below turns script + checklist into a
guided, signed session.

## When to use

- A high-stakes feature ships and needs accessibility sign-off.
- Automated a11y tools are green but the team wants confidence
  the actual screen-reader experience is good.
- Onboarding a new accessibility tester - they need a script to
  follow until they internalize the conventions.
- Documenting an "a11y regression repro" when a bug ships.

## Step 1 - Pick the screen reader

Most a11y audit conventions cover at least:

| Screen reader | Platform             | Browser pairing              |
|---------------|----------------------|------------------------------|
| NVDA          | Windows              | Firefox or Chrome            |
| JAWS          | Windows              | Chrome or Edge               |
| VoiceOver     | macOS / iOS / iPadOS | Safari (macOS); Safari (iOS) |
| TalkBack      | Android              | Chrome                       |

For the most-coverage-per-effort, test **NVDA + Firefox** and
**VoiceOver + Safari** - these are also the WAI-recommended pairs.

Start each script by naming the SR + browser + OS combination.

## Step 2 - Define the flow

A flow is a sequence of user goals. Don't write step-by-step
keystrokes upfront - that's Step 3. The flow is at user-intent
level:

```yaml
flow_name: "User edits their profile email"
preconditions:
  - User is logged in.
  - User is on the /profile page.
  - Screen reader is on; browser virtual cursor is at the page heading.

steps:
  - intent: "Navigate to the profile-edit form via main nav"
  - intent: "Tab through the form to the email field"
  - intent: "Edit the email value to a new valid email"
  - intent: "Submit the form"
  - intent: "Hear the success confirmation announcement"
```

## Step 3 - Per intent, capture keystrokes + expected announcement

For each intent, the script row lists three things:

- **Keystroke** - the actual key combo the tester presses.
- **Expected announcement** - what the screen reader should say.
- **Why** - the WCAG SC or APG pattern the announcement satisfies.

NVDA browse mode navigates with quick-keys (`H` by heading, `F` by
form field); VoiceOver uses VO (Ctrl+Option) chords:

| Action                | VoiceOver shortcut                          |
|-----------------------|---------------------------------------------|
| Read next / previous  | VO + Right / Left arrow                      |
| Next heading          | VO + Cmd + H                                 |
| Next form control     | VO + Cmd + J                                 |
| Activate (Enter)      | VO + Space                                   |
| Web rotor             | VO + U (form / heading / link list overlay) |

A minimal NVDA + Firefox excerpt for the flow "User edits their
profile email":

| Keystroke  | Expected announcement                                    |
|------------|----------------------------------------------------------|
| H          | "Edit profile, heading level 2" - moves to next heading. |
| F          | "Email, edit, blank" - jumps to the first form field.    |
| Tab, Enter | "Save changes, button", then a live region announces "Profile saved". |

Full per-reader scripts (NVDA + Firefox and VoiceOver + Safari) for
this flow, with the WCAG / APG mapping in the "Why" column:
[references/screen-reader-scripts.md](references/screen-reader-scripts.md).

VoiceOver announcements are sometimes more verbose than NVDA's (role
words like "edit text" where NVDA says "edit"); that is a vendor
convention, not a bug to suppress.

## Step 4 - Define what counts as PASS

For each step, the announcement should:

1. **Identify the element type** - "button", "edit", "link",
   "heading level 2", etc.
2. **Read the visible label** verbatim - if the visible label is
   "Save changes", the SR should say "Save changes" (not "Submit"
   or the `id` attribute).
3. **Convey state** - for a checkbox, "checked" / "not checked";
   for a button, "expanded" / "collapsed" / "pressed".
4. **Convey position in a set** - for a tab, "1 of 4"; for a list
   item, "1 of 10".

Failures to flag:

| Failure                                                       | Likely cause                                          |
|---------------------------------------------------------------|-------------------------------------------------------|
| Announcement reads CSS class names or `id` attributes          | Label is missing; SR fell back to other text.         |
| Element type is wrong ("link" instead of "button")             | `<a>` used as a button; or `role="link"` on a button. |
| State is missing                                                | `aria-expanded` / `aria-checked` not set.             |
| Position-in-set is missing                                     | `aria-setsize` / `aria-posinset` not set on list items. |
| Live region announcement doesn't fire                          | Region added with content already present, OR `aria-live="off"`. |

## Step 5 - Wire to the test plan

The script becomes a **manual test** in the project's test plan.
Common formats:

### Markdown checklist (lightweight)

```markdown
## A11y Acceptance - User edits profile email

### NVDA + Firefox (Windows)

- [ ] Step 1: Pressing H twice lands on "Profile information" heading.
- [ ] Step 2: Pressing F lands on the email field; announces "Email, edit, blank".
- [ ] Step 3: After submit, a live region announces "Profile saved".

### VoiceOver + Safari (macOS)

- [ ] Step 1: VO+Cmd+H twice lands on "Profile information" heading.
- [ ] Step 2: VO+Cmd+J lands on email; announces "Email, edit text".
- [ ] Step 3: After submit, live region announces "Profile saved".

Sign-off: ___________________ Date: __________
```

### Test-management tool integration

For teams using TestRail / Xray / Zephyr - encode the flow as a
manual test case with one step per row, expected result per row.
The skill emits the matching format; per
`test-management-sync`
(when shipped) the test case can be uploaded automatically.

## Running the session

When a component has passed automated scans and static review and a human
tester needs a guided manual session to sign off acceptance, compose the
script (Steps 1-5) with the component's per-archetype checklist
([references/wcag-checklist.md](references/wcag-checklist.md)) into one
session package. Required inputs: the component's rendered URL, its
archetype, and either an existing script or the intent-level flow (Step 2
format). Without a rendered URL the pre-conditions cannot be defined - stop
and ask.

### Build the session package

Merge script + checklist into a single session document:

- Header: component name, archetype, URL, date, tester name (blank field),
  SR + browser pair.
- NVDA section (Windows): single-letter quick-navigation keys. Per
  [WebAIM NVDA guide][webaim-nvda]: H navigates headings, F form controls,
  B buttons, K links; Shift+letter moves backwards; NVDA+Space toggles
  Browse and Focus modes. Per the [NVDA user guide][nvda-ug], the default
  NVDA modifier key is Insert (or numpadZero with numLock off).
- VoiceOver section (macOS): per [WebAIM VoiceOver guide][webaim-vo], the
  VO keys are Control+Option; VO+Right/Left reads next/previous item;
  VO+Cmd+H navigates headings; VO+Cmd+J form controls; VO+Space activates;
  VO+U opens the Web Rotor.
- Checklist rows mapped to each script step, so the tester sees the WCAG SC
  being verified alongside the keystroke.

[webaim-nvda]: https://webaim.org/articles/nvda/
[webaim-vo]: https://webaim.org/articles/voiceover/
[nvda-ug]: https://download.nvaccess.org/documentation/userGuide.html

### Walk the tester through it

1. Pre-conditions block: SR running, browser open to the URL, virtual
   cursor at page top (NVDA browse mode; VoiceOver with Web Rotor closed).
2. For each intent step: the keystroke, the expected announcement, the WCAG
   SC being verified, and a `[ ] PASS` / `[ ] FAIL` / `[ ] BLOCKED`
   checkbox.
3. After each overlay or composite step: a focus-return checkpoint per the
   [W3C APG dialog-modal pattern][apg-dialog] (focus must return to the
   trigger on close).
4. After each live-region step: a timing checkpoint (announce within
   1-2 s of state change; matches the `aria-live="polite"` contract per
   [WCAG SC 4.1.3 Status Messages][wcag-413]).

[apg-dialog]: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
[wcag-413]: https://www.w3.org/TR/WCAG22/#status-messages

### Capture the session report

Write the results to `a11y-sessions/<component>-<YYYY-MM-DD>-<sr>.md`:

```markdown
## Screen-Reader Session Report

**Component:** <name>  **Archetype:** <archetype>  **URL:** <url>
**Date:** <YYYY-MM-DD>  **Tester:** _______________
**SR + Browser:** NVDA + Firefox | VoiceOver + Safari

| Step | Intent | Keystroke | Expected announcement | WCAG SC | Result |
|------|--------|-----------|-----------------------|---------|--------|
| 1 | Navigate to component heading | H | "<Component>, heading level 2" | 1.3.1 / 2.4.6 | [ ] PASS [ ] FAIL [ ] BLOCKED |

### Summary

| Verdict | Count |
|---------|-------|
| PASS / FAIL / BLOCKED | N |

**Overall:** PASS / FAIL / INCOMPLETE

**Failures to remediate:**
1. <Step N>: <what was announced> vs. <expected> - likely cause + WCAG SC.

**Sign-off:** _______________ Date: __________
```

The session never modifies component source. iOS VoiceOver and TalkBack
(Android) have different gesture models - author a separate mobile script
(Step 1) rather than reusing the desktop session.

## Anti-patterns

| Anti-pattern                                                  | Why it fails                                                       | Fix |
|---------------------------------------------------------------|---------------------------------------------------------------------|-----|
| Testing on only one screen reader                              | NVDA bugs ≠ JAWS bugs ≠ VoiceOver bugs.                            | At least two reader/browser pairs (NVDA+Firefox, VoiceOver+Safari). |
| Asking the developer to test their own work                    | Familiarity bias; the dev knows how it should sound.                | Independent tester or accessibility specialist; use the script blindly. |
| Recording expected announcements verbatim from one version     | Screen-reader announcement strings change between versions.        | Test the announcement *contains* key elements (label, role, state); avoid string-equality. |
| Skipping the "Why" column                                      | Tester can't generalize from "this announcement was wrong" to "the underlying ARIA pattern is broken." | Always link to the WCAG SC or APG pattern. |

## Limitations

- **Manual.** Cannot fully automate; the tester is the QA
  instrument.
- **Vendor variance.** A test script that passes on NVDA might
  fail on JAWS due to vendor-specific announcement choices; the
  underlying code may be correct.
- **Mobile tests.** TalkBack and iOS VoiceOver have very different
  gesture sets from desktop SRs; mobile flows need separate
  scripts.

## References

- W3C WCAG 2.2 - https://www.w3.org/TR/WCAG22/
- WebAIM Screen Reader Survey - https://webaim.org/projects/screenreadersurvey/
- NVDA documentation - https://www.nvaccess.org/files/nvda/documentation/userGuide.html
- VoiceOver Getting Started - https://www.apple.com/accessibility/mac/vision/ + Apple developer docs
- [references/wcag-checklist.md](references/wcag-checklist.md) -
  per-archetype WCAG 2.2 checklist builder (spec-review acceptance
  criteria).
- [references/widget-matrix.md](references/widget-matrix.md) -
  per-widget keystroke matrices with expected NVDA / VoiceOver
  announcements per WCAG SC.
- `wcag-keyboard-navigation`,
  `aria-authoring-patterns` - patterns this skill references for the "Why" column.

Files in this skill

  • .tessl-plugin/plugin.json915 B
  • SKILL.md13.2 KB
  • references/screen-reader-scripts.md3.1 KB
  • references/wcag-checklist.md10.1 KB
  • references/widget-matrix.md25.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.