Founder & Lead Engineer, RAITHub
To test a web app for accessibility, run an automated axe-core scan on every key page, then check by hand: keyboard-only use, visible and unobscured focus, screen reader names and announcements, form labels and errors, 400% zoom and reflow, contrast, motion, target size and login. Test against WCAG 2.2 AA, and mark each line pass or fail with evidence.
If you would rather have this run for you, see how RAITHub would test this near the end. The checklist itself works for any team, with or without outside help.
What standard should you test against?
WCAG 2.2 level AA. W3C published WCAG 2.2 on 5 October 2023. It adds nine success criteria, six of them at level A or AA, and removes 4.1.1 Parsing (W3C: What's new in WCAG 2.2). In Europe, EN 301 549 version 4.1.1, published on 2 September 2026, moves its web baseline from WCAG 2.1 to 2.2 AA (National Disability Authority, Ireland). So 2.2 AA is the sensible target for anything you ship now.
This checklist covers what to test, not what any law requires of you. Legal obligations under the ADA, the European Accessibility Act or Section 508 depend on who you are and where you sell. This is general information; confirm with your adviser.
What does the checklist look like on one page?
| Area | Pass when | Automate or manual | Main WCAG criteria |
|---|---|---|---|
| Automated scan | axe-core reports no A/AA violations on each key page and state | Automate in CI | Many; mostly 1.1.1, 1.3.1, 1.4.3, 4.1.2 |
| Keyboard | Every action works with Tab, Shift+Tab, Enter, Space, arrows and Escape; no traps | Manual | 2.1.1, 2.1.2, 2.4.3 |
| Focus | Focus is always visible and never hidden behind sticky headers or banners | Manual | 2.4.7, 2.4.11 |
| Screen reader | Every control has a name, role and state; changes are announced | Manual | 1.3.1, 4.1.2, 4.1.3 |
| Forms and errors | Labels are programmatic; errors are described in text and linked to the field | Both | 1.3.1, 3.3.1, 3.3.2, 3.3.3 |
| Zoom and reflow | Content works at 400% zoom in a 320px-wide viewport without horizontal scrolling | Manual | 1.4.4, 1.4.10, 1.4.12 |
| Colour and contrast | Text 4.5:1 (3:1 for large text); UI parts 3:1; colour is never the only signal | Mostly automated | 1.4.1, 1.4.3, 1.4.11 |
| Motion and time | Auto-moving content can be paused; time limits can be extended | Manual | 2.2.1, 2.2.2 |
| New in WCAG 2.2 | Target size, dragging alternatives, consistent help, no redundant entry, accessible login | Manual | 2.5.7, 2.5.8, 3.2.6, 3.3.7, 3.3.8 |
What should you automate first?
An axe-core scan on every page and important state, run in CI on each pull request. Automated rules catch a large share of real issues: Deque's study of over 2,000 audits found its automated tests identified 57% of issues by volume (Deque). The 2026 WebAIM Million found the same six error types (low contrast, missing alt text, missing labels, empty links, empty buttons, missing page language) behind 96% of detected failures (WebAIM Million 2026). All six are machine-detectable.
Scan states, not only pages: an open modal, a form showing errors, an expanded menu. Playwright documents this pattern with @axe-core/playwright (Playwright accessibility testing docs):
import { test, expect } from '@playwright/test'
import AxeBuilder from '@axe-core/playwright'
const WCAG_AA = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa']
test('sign-up form with errors has no automatic violations', async ({ page }) => {
await page.goto('/signup')
await page.getByRole('button', { name: 'Create account' }).click() // submit empty
await expect(page.getByText('Enter your email')).toBeVisible()
const results = await new AxeBuilder({ page })
.include('form')
.withTags(WCAG_AA)
.analyze()
expect(results.violations).toEqual([])
})
Notice the test also finds elements by role and accessible name. A test that uses getByRole fails when a button loses its name, which is a cheap accessibility check in its own right.
How do you test keyboard access and focus?
Unplug the mouse, start at the address bar, and complete each key journey. This catches more serious issues per minute than any other manual check.
- Tab reaches every link, button and field, in an order that matches the visual layout.
- Focus is always visible, and never hidden behind a sticky header, cookie banner or chat widget (2.4.11 Focus Not Obscured, new in 2.2).
- Menus, tabs and comboboxes respond to the arrow keys the way the WAI-ARIA Authoring Practices describe.
- Modals move focus inside when they open, keep it there, close on Escape, and return focus to the button that opened them.
- A "skip to main content" link appears on first Tab and works.
- Nothing traps focus: you can always Tab out of an embedded map, editor or iframe.
- Custom controls built from
divelements can be reached and activated. If not, replace them with real buttons.
How do you test with a screen reader?
Use at least one pair your users are likely to use: NVDA with Firefox or Chrome on Windows, and VoiceOver with Safari on macOS and iOS. You are listening for four things.
- Names: every button, link and field announces a clear name. "Button" alone, or "link, image", is a failure.
- Structure: headings are in a logical order and landmarks (header, nav, main, footer) exist, so users can jump around.
- State: toggles, tabs and accordions announce expanded, selected or checked.
- Changes: toasts, "saved" messages, cart updates and live search results are announced without moving focus (4.1.3 Status Messages).
Images: decorative ones are silent; meaningful ones have alt text that says what the image tells a sighted user, not "image of".
How do you test forms and error messages?
- Every field has a visible label tied to it in code. Placeholder text is not a label.
- Required fields are marked in text, not only with colour or an asterisk without explanation.
- On a failed submit, errors are described in words, appear next to the field, are announced, and focus moves to the first error or an error summary.
- Fields for name, email, address and phone use the right
autocompletevalues, so browsers and password managers can fill them. - Users are not asked for the same information twice in one process, unless it is for security or the old value is offered for reuse (3.3.7 Redundant Entry, new in 2.2).
What do the WCAG 2.2 additions mean in practice?
| Criterion (level) | What to check |
|---|---|
| 2.4.11 Focus Not Obscured (AA) | The focused element is at least partly visible, even with sticky bars open |
| 2.5.7 Dragging Movements (AA) | Anything done by dragging (kanban cards, sliders, reordering) also works with single clicks or taps |
| 2.5.8 Target Size Minimum (AA) | Click targets are at least 24 by 24 CSS pixels, or spaced so a 24px circle around each does not overlap another |
| 3.2.6 Consistent Help (A) | Help links, chat or contact details sit in the same place on every page that has them |
| 3.3.7 Redundant Entry (A) | Multi-step flows prefill or offer earlier answers |
| 3.3.8 Accessible Authentication Minimum (AA) | Login does not require a memory or puzzle test; paste and password managers work, and CAPTCHAs have an alternative |
Source: WCAG 2.2 (W3C Recommendation). A common SaaS failure is a login form that blocks paste into the password field. That fails 3.3.8 and frustrates every password-manager user.
How do you test zoom, reflow, colour and motion?
- Zoom the browser to 200%, then 400%. At 400% on a 1280px window, the page behaves like a 320px viewport: content reflows into one column with no horizontal scrolling, except for data tables and maps (1.4.10 Reflow).
- Apply the text-spacing bookmarklet: increased line, letter and word spacing must not clip text (1.4.12).
- Check contrast on hover, focus, disabled and error states, not only the default. Placeholder text and chart labels fail often.
- Never use colour alone: an error field needs an icon or text too, and a chart needs labels or patterns.
- Auto-playing carousels and video have a pause control; animations respect
prefers-reduced-motion. - Session time-outs warn the user and let them extend.
The same checks apply in right-to-left layouts; our Arabic RTL web app QA checklist covers the mirroring issues on top. And accessibility is one line of the wider pre-launch QA checklist.
How long does this take to do yourself?
Adding the axe-core tests to an existing Playwright suite takes about 2 to 4 hours if you know Playwright. The manual pass takes about half a day to a day per key journey for someone who has done it before, longer the first time. The main risk of doing it yourself is false confidence: a green scanner and a quick Tab-through miss screen reader, focus and authentication issues that block real users.
Buy, build or hire?
| Option | Choose this when | Limits |
|---|---|---|
| A tool or SaaS testing platform | You want scheduled scans and alerts across many pages | Machine-detectable issues only; no judgement on focus order or meaning |
| Freelancers or crowdtesting | You want occasional manual passes, or feedback from assistive-technology users | Quality and WCAG mapping vary; fixes rarely included |
| An in-house QA hire | You ship UI every week and want accessibility owned inside the team | Specialist skills are scarce; one person needs cover |
| A managed QAaaS team | You want an audit, fixes described per issue, and CI gates kept current | You still own the fixes, unless engineering is in scope |
Pricing for each route is in accessibility audit cost.
How RAITHub would test this
Through its accessibility testing service, part of QA as a service, RAITHub would:
- agree the sample: templates, components, key journeys and each user role
- run axe-core on every page and state in the sample, then the manual checks above against WCAG 2.2 AA
- report each issue with its success criterion, severity, steps to reproduce and a specific fix
- add the axe checks and role-based locators to your automated test suite in your CI, then retest after your fixes
You can buy this as a fixed-price one-off audit, within a monthly QA plan, or with a dedicated QA team that RAITHub manages and bills monthly. Testers are never placed under your management. The audit reports against WCAG 2.2 AA; it does not certify legal compliance with the ADA, the EAA or Section 508. RAITHub has no accessibility case study yet, so judge it on the sample report and the free 15-minute call. Then you get a written fixed quote. Request an accessibility audit.
Frequently asked questions
What is the minimum accessibility testing a web app needs?
An automated axe-core scan of key pages and states in CI, plus a manual keyboard-only pass through every key journey. Add a screen reader pass before a major launch.
Which screen reader should I test with?
At least NVDA on Windows with Firefox or Chrome, and VoiceOver on macOS or iOS with Safari. Together they cover most users you will meet.
What changed in WCAG 2.2 for web apps?
Six new A and AA criteria: focus not obscured, dragging alternatives, a 24px minimum target size, consistent help, no redundant entry, and accessible authentication. 4.1.1 Parsing was removed.
Can automated tools test accessibility completely?
No. They find a large share of issues by volume, but cannot judge focus order, meaningful alt text, or whether a screen reader user can finish a task.
Does passing this checklist make my app legally compliant?
Passing it means your app meets the checks listed. Legal compliance depends on the law that applies to you and how it is enforced. This is general information; confirm with your adviser.
How often should we run accessibility tests?
Automated checks on every pull request; a manual keyboard pass on each release that changes UI; a fuller manual audit before a major launch or redesign.
Related posts
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.