SaaS Accessibility Testing Checklist: What to Test Before Each Release
A SaaS application has specific accessibility challenges that generic checklists don't address: authenticated dashboards, complex data tables, modals triggered by user actions, real-time updates, and multi-step workflows. This checklist is organized by what to check at different stages of development and before release.
Why SaaS Products Specifically
Accessibility testing guidance typically focuses on marketing websites with relatively static content. SaaS applications are different:
- Most content is behind authentication — automated crawlers and most audit tools miss it
- Dynamic content (live data, notifications, loading states) creates ARIA challenges
- Complex data tables are common and hard to make accessible
- Multi-step workflows (setup wizards, checkout flows) require careful focus management
- Role-based UIs (admin vs user views) have different accessibility profiles
This checklist addresses these realities.
Automated Testing (Every PR)
Run these automatically in your CI pipeline on every pull request. Don't wait for manual audits to find these issues.
axe-core Integration
Add to your test suite (JavaScript example):
import { configureAxe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('dashboard page has no axe violations', async () => {
render(<Dashboard user={testUser} />);
const results = await axe(document.body);
expect(results).toHaveNoViolations();
});For Playwright:
import AxeBuilder from '@axe-core/playwright';
test('settings page accessibility', async ({ page }) => {
await page.goto('/settings');
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});Pages to cover with automated checks:
- Login page
- Dashboard / home view
- Primary feature pages (at least 3)
- Settings page
- Account/profile page
- Billing page
- Any page with complex data tables
Lighthouse Accessibility Audit
Run in CI and enforce a minimum score:
lighthouse https://app.yourproduct.com/dashboard \
--only-categories=accessibility \
--chrome-flags="--headless" \
--output=json \
| jq '.categories.accessibility.score'Minimum acceptable score: 0.90 (90%). Below this, the PR should not merge.
Note: Lighthouse scores and axe-core violations are not the same metric. Run both.
Keyboard Navigation (Every Feature)
Test every new feature with keyboard only before merging.
Core Navigation
- Every interactive element is reachable by Tab
- Tab order follows visual flow (left-to-right, top-to-bottom)
- Skip navigation link is the first focusable element, jumps to main content
- Focus is always visible (meets WCAG 2.4.11 — not completely hidden by overlapping content)
- No keyboard traps (can always Tab away from any element)
Actions and Interactions
- Buttons activate with Enter and Space
- Links activate with Enter
- Dropdowns open on Enter/Space and close on Escape
- Modals trap focus and return it to the trigger when closed
- Date pickers and custom selects are keyboard operable
- Drag-and-drop functionality has a keyboard alternative (WCAG 2.5.7)
After State Changes
After any action that changes page state (submitting a form, filtering a table, loading new data):
- Focus is managed to a logical position (moved to the new content or a status message)
- The change is announced to screen readers via a live region
Screen Reader Testing (Weekly or Per Sprint)
Run this manually with NVDA+Firefox and VoiceOver+Safari.
Page Orientation
- Page title is descriptive (
<title>includes page name and product name) - H1 exists and describes the current page
- Heading hierarchy is logical (no skipping from H1 to H3)
- Landmark regions exist:
<header>,<main>,<nav>,<footer> - Navigation: "You are on page X" type context is communicated
Forms
- Every input has an associated
<label>(for/id, or aria-label, or aria-labelledby) - Required fields are marked
required(announced as "required" by screen reader) - Error messages are associated with inputs via
aria-describedby - Error messages use
role="alert"for dynamic injection - Placeholder text is not the only label (fails if placeholder disappears on focus)
- Groups of related inputs use
<fieldset>and<legend>
Data Tables
<th>elements havescope="col"orscope="row"- Complex tables use
idandheadersattributes for cell associations - Table has a
<caption>or is labeled viaaria-label - Empty cells are not left blank — use a dash or "N/A" with visually hidden text
Authentication Flow (WCAG 3.3.8)
- Login/signup doesn't require solving a visual puzzle (CAPTCHA must have audio alternative)
- Password managers can autofill (inputs have correct
autocompleteattributes) - "Forgot password" flow is fully keyboard accessible
- MFA flow is keyboard accessible
Dashboard and App Core
- Data visualizations have text alternatives (charts describe their data in text or table form)
- Status indicators use text, not just color (e.g., "Active" not just a green dot)
- Loading states are announced (use
aria-liveregions oraria-busy) - Notification badges include text ("3 new notifications", not just "3")
- Tooltips are accessible via keyboard (not just hover)
Mobile and Touch
- Target sizes are at least 24×24 CSS pixels (WCAG 2.5.8)
- Content is readable at 200% zoom without horizontal scrolling
- Content is readable at 400% zoom (text reflows, no loss of functionality)
- Orientation is not locked (works in both portrait and landscape)
- Touch target spacing prevents accidental activation of adjacent elements
Release Checklist (Before Every Release)
Run this list before shipping to production.
Automated
- axe-core violations: 0 (or reviewed and accepted with documented exceptions)
- Lighthouse accessibility score: ≥ 90
- Color contrast ratio: 4.5:1 for normal text, 3:1 for large text (can use browser tools or WebAIM Contrast Checker)
New or Changed UI Components
For each new or modified component in this release:
- Keyboard interaction verified
- Screen reader announcement verified (name, role, state)
- Focus management verified (if component triggers changes)
- Error states are accessible
Flows Changed This Release
For each user flow modified:
- Complete the flow with keyboard only
- Complete the flow with NVDA (Windows) or VoiceOver (macOS)
- Verify no regressions in previously tested flows
Content
- All new images have alt text (decorative images have
alt="") - New video content has captions
- New documents (PDFs) are tagged for accessibility
- New icons used standalone have accessible names
Regression Detection
Manual testing catches issues but doesn't prevent regressions between audits. A label disappears from an input after a refactor; a modal loses its focus trap; a chart loses its text alternative.
Automated regression monitoring fills this gap. HelpMeTest can run test scenarios against your live application continuously — verifying that your key forms are properly labeled, your modals open and close with correct focus management, and your critical user flows remain keyboard accessible.
The free plan includes 10 tests running continuously. A small set of accessibility-focused tests covering your signup flow, login, and primary feature workflow provides a baseline that catches the most common category of regression: structural accessibility failures introduced during feature development.
Common SaaS Accessibility Anti-Patterns
These appear frequently in SaaS products and are often missed by automated tools:
1. Unlabeled icon buttons in toolbars Toolbars full of icon buttons with no accessible names. axe-core catches this, but only if you run it against the logged-in state.
2. Custom dropdowns without ARIA
<!-- Fail: looks like a select, works like nothing -->
<div class="custom-select" onclick="toggle()">
<div class="selected-value">Option A</div>
<div class="dropdown-items">...</div>
</div>3. Data tables using divs Marketing dashboards built with CSS Grid and div elements instead of <table>, <th>, <td>. Screen reader users see a wall of numbers with no context.
4. Announcements only in the page title "3 new alerts" visible in the page title but not in the page body. Screen reader users navigating within the page miss it entirely.
5. Session timeout with no warning Users get logged out with no accessible warning. Add an aria-live region that announces the session expiry countdown.
Keeping It Sustainable
Perfect accessibility testing isn't realistic for most teams. Prioritize:
- Automated checks in CI — zero cost once set up, prevents new issues
- Keyboard testing for every new feature — quick, catches focus management issues
- Screen reader testing on critical flows — monthly, before major releases
- Full WCAG audit — annually, or when entering enterprise sales
Build the habit gradually. Start with automated axe-core in CI and keyboard testing as part of your definition of done. Add screen reader testing once those are stable.