CtrlK
BlogDocsLog inGet started
Tessl Logo
PluginPublic

testland/screen-reader-test-author

Use when a feature needs manual screen-reader testing before sign-off: step-by-step scripts for NVDA, JAWS, VoiceOver or TalkBack with keystrokes and expected announcements, WCAG 2.2 checklists per page type, widget keystroke matrices and a guided session with a signed report.

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files
name:
screen-reader-test-author
description:
Use when a feature needs manual screen-reader testing before sign-off: step-by-step scripts for NVDA, JAWS, VoiceOver or TalkBack with keystrokes and expected announcements, WCAG 2.2 checklists per page type, widget keystroke matrices and a guided session with a signed report.

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) and per-widget keystroke matrices for hand-run NVDA / VoiceOver passes (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 readerPlatformBrowser pairing
NVDAWindowsFirefox or Chrome
JAWSWindowsChrome or Edge
VoiceOvermacOS / iOS / iPadOSSafari (macOS); Safari (iOS)
TalkBackAndroidChrome

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:

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:

ActionVoiceOver shortcut
Read next / previousVO + Right / Left arrow
Next headingVO + Cmd + H
Next form controlVO + Cmd + J
Activate (Enter)VO + Space
Web rotorVO + U (form / heading / link list overlay)

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

KeystrokeExpected 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.

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:

FailureLikely cause
Announcement reads CSS class names or id attributesLabel 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 missingaria-expanded / aria-checked not set.
Position-in-set is missingaria-setsize / aria-posinset not set on list items.
Live region announcement doesn't fireRegion 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)

## 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) 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: 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, the default NVDA modifier key is Insert (or numpadZero with numLock off).
  • VoiceOver section (macOS): per WebAIM VoiceOver guide, 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.

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 (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).

Capture the session report

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

## 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-patternWhy it failsFix
Testing on only one screen readerNVDA bugs ≠ JAWS bugs ≠ VoiceOver bugs.At least two reader/browser pairs (NVDA+Firefox, VoiceOver+Safari).
Asking the developer to test their own workFamiliarity bias; the dev knows how it should sound.Independent tester or accessibility specialist; use the script blindly.
Recording expected announcements verbatim from one versionScreen-reader announcement strings change between versions.Test the announcement contains key elements (label, role, state); avoid string-equality.
Skipping the "Why" columnTester 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

Workspace
testland
Visibility
Public
Created
Last updated
Source
GitHub Actions
Repository
https://github.com/testland/qaVerified
Badge
testland/screen-reader-test-author badge