How to Run Accessibility Tests with Cypress
Add automated accessibility scans to Cypress with cypress-axe, then cover keyboard behavior and application-specific expectations with explicit tests.
Run accessibility checks in Cypress by adding an automated scan to selected end-to-end or component tests, then writing explicit assertions for the behavior your application requires. A common in-test route is the community cypress-axe plugin, which adds cy.checkA11y() after setup. Scans catch known rule violations in the rendered state; keyboard, focus, content, and assistive-technology behavior still need deliberate tests and human review.
Cypress documents three complementary approaches: scan with cypress-axe inside tests, use the paid Accessibility feature in Cypress Cloud, and add product-specific Cypress assertions. None alone proves that an interface is fully accessible.
1. Choose an accessibility testing approach
| Approach | Where it runs | Useful for | Considerations |
|---|---|---|---|
cypress-axe |
In Cypress test execution | Fast feedback on selected pages and components in development or CI | Community plugin; scans add runtime as coverage grows. Follow its maintained setup documentation for current installation and support details. |
| Cypress Accessibility | Cypress Cloud, against captured test snapshots | Teams that want cloud reports from recorded Cypress runs | Paid premium product. The default ruleset has limits and includes non-WCAG Best Practices findings. |
| Explicit assertions and manual checks | Your test suite and review process | Expected labels, keyboard operation, focus behavior, meaningful content, and assistive-technology experience | Requires tests designed around your product and time for human review. |
These approaches complement one another. Pick representative, important journeys such as sign-up, checkout, and forms. Test meaningful states, including validation errors, expanded menus, dialogs, and success messages, rather than scanning only an empty or initial screen. Cypress recommends covering a component’s accessibility in a component test or workflow at least once.
2. Add an automated scan with cypress-axe
The exact install and support instructions for cypress-axe can change. Use the plugin’s maintained setup documentation for the current version-specific commands; the examples below show the test shape after the plugin is installed and its Cypress commands are registered as documented there.
// Example Cypress end-to-end test after cypress-axe setup
it('has no detected accessibility violations on the sign-up page', () => {
cy.visit('/signup');
cy.checkA11y();
});
checkA11y() scans the current page or component. Run it after the UI has reached the state you intend to inspect. If the page updates asynchronously, wait for a reliable application condition before scanning; otherwise, the scan may examine an incomplete state.
For an interaction-driven state, open it first and scan that state too:
it('scans the open navigation menu', () => {
cy.visit('/');
cy.get('[data-cy=menu-toggle]').click();
cy.get('[data-cy=primary-navigation]').should('be.visible');
cy.checkA11y();
});
Configure rules or scope scans according to the plugin’s current documentation and your team’s policy. Decide how findings affect test results: a strict scan can fail a test when violations are present, while a triage process can first establish a baseline and then prevent newly introduced issues. Do not silently suppress findings; document the reason, scope, and removal plan for each exception.
3. Test expectations a scanner cannot infer
A rule engine cannot know the intended name or behavior of every control. Add assertions for important product requirements, and test keyboard use explicitly.
Check accessible names and labels
it('exposes a labeled email field and named submit button', () => {
cy.visit('/signup');
cy.get('input[name=email]').should('have.attr', 'aria-label', 'Email address');
cy.findByRole('button', { name: 'Create account' }).should('be.visible');
});
The role-based query example assumes your project has a Testing Library Cypress query integration configured. If it does not, use the selectors and assertions already supported in your project, while checking the rendered accessible name with an appropriate testing approach. Prefer user-facing role and name queries when available because they exercise the semantics users rely on.
Check meaningful image alternatives
it('provides the expected alternative for the product image', () => {
cy.visit('/products/widget');
cy.get('[data-cy=product-image]')
.should('have.attr', 'alt', 'Blue ceramic travel mug');
});
Whether an image needs descriptive alternative text depends on its purpose. Decorative images should not be given misleading descriptions; verify the intended alternative behavior for the content.
Check keyboard operation and focus
Cypress identifies cy.press() as a way to dispatch native Tab events for keyboard-navigation checks. Use it to verify that users can reach and operate important controls and that focus moves as expected. Consult the current Cypress API documentation for supported keys and version requirements.
it('moves keyboard focus to the first sign-up control', () => {
cy.visit('/signup');
cy.press(Cypress.Keyboard.Keys.TAB);
cy.focused().should('have.attr', 'name', 'email');
});
For dialogs and menus, test the complete expected interaction: opening from the keyboard, focus placement, reachable controls, closing behavior, and where focus returns. A scan cannot infer the correct interaction model for your application.
4. Understand scan coverage and findings
An automated scan reports findings for the rules it ran against the state it examined. Treat a clean result as “no applicable violations found in this tested scope,” not as proof of WCAG conformance or a guarantee that the page works for every user.
Cypress Accessibility’s documented default ruleset uses Axe Core’s default coverage for WCAG 2.0 and 2.1 Level A and AA and includes Deque Best Practices. Three WCAG-tagged rules—color-contrast, no-autoplay-audio, and meta-refresh—are disabled by default in Cypress Accessibility. WCAG 2.2, Level AAA, experimental, and deprecated Axe Core rule groups are also off by default unless enabled for the project. Check the current configuration because defaults can change.
A Best Practices finding is not automatically a WCAG failure. Likewise, a default scan does not cover every success criterion. Cypress says its ruleset can be tuned for a target standard through its support process. Its Results API can be used to decide which findings block a CI build while keeping other findings visible.
For component tests, Cypress Accessibility skips page-level rules that do not sensibly apply to an isolated fragment, such as document title, language, main landmark, or top-level heading checks. Component-level rules such as button naming and image alternatives still apply. Use end-to-end tests for page structure and component tests for reusable component behavior.
5. Build a practical test workflow
- Select critical journeys. Start with tasks where an accessibility barrier would prevent a user from succeeding, such as account creation, checkout, or submitting a form.
- Choose representative states. Include loaded content, errors, dialogs, menus, and other important states users encounter.
- Scan at useful boundaries. Run scans after navigation and after meaningful state changes. Avoid scanning every minor intermediate render if it adds noise without useful coverage.
- Add intentional assertions. Verify the accessible names, form labels, image alternatives, keyboard interactions, and focus behavior your product requires.
- Review and prioritize findings. Investigate the affected element and user impact. Separate WCAG-tagged rules from Best Practices findings and confirm the rule and standard behind each result.
- Gate changes deliberately. Once findings are understood, make the chosen blocking rules part of CI. Preserve visibility into issues that do not yet block builds.
- Keep human review in the plan. Test keyboard-only operation and relevant assistive-technology experiences; review content and expected behavior.
Cypress repeats a Deque estimate that automation can detect up to 57% of issues that would appear in a manual accessibility audit. The cited Cypress page does not state the estimate’s year, and it is not a guarantee for a particular application. Automated checks are a useful layer, not a replacement for human judgment.
6. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
checkA11y is undefined |
The plugin command was not registered, or setup differs from the installed version. | Follow the maintained cypress-axe setup guide for your Cypress and plugin versions, including command registration. |
| The scan reports violations intermittently | The scan runs before asynchronous content or a state transition has settled. | Wait for a meaningful visible element or application condition before calling the scan. |
| A page-level finding appears in a component scan | The check may be running in a full-page context, or the finding may not apply to an isolated component. | Use component testing for fragment behavior and end-to-end scans for document structure; check the tool’s component rule handling. |
| A Best Practices result is treated as a WCAG failure | The report combines rule categories. | Inspect the rule tags and report category before describing or prioritizing the finding. |
| A clean scan gives false confidence | Only the current rendered state and enabled rules were evaluated. | Add missing states, explicit assertions, keyboard checks, and manual review; verify which rules are enabled. |
| The test suite becomes slow | Scans have been added to too many states or tests without considering runtime. | Prioritize critical journeys and high-value states, then retain component coverage where it gives reusable feedback. |
| A finding cannot be reproduced locally | CI and local runs may render different data, timing, or states. | Make the test state deterministic, wait for stable conditions, and record the route and state that produced the finding. |
7. Performance, reliability, and cost
In-test scans add work to Cypress execution, so scan a deliberate set of representative screens and states. More scans can improve regression coverage but also lengthen runs; prioritize critical workflows and reusable components, and keep setup and application state deterministic.
Reliability depends on scanning the intended rendered state. Wait for content that matters, avoid relying on arbitrary short delays where a visible condition is available, and keep exceptions visible for review. A pass is bounded by the rule set, page state, and elements included in the scan.
cypress-axe is a community plugin. Cypress Accessibility is a paid Cypress Cloud premium feature. Check the official product documentation for current availability, configuration, and pricing; this article does not assume a particular plan or price. Explicit Cypress assertions use your existing test workflow but require engineering and review time.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers, made by Yorker Media. It does not replace Cypress accessibility tests, but it can provide a clean screenshot of a page for visual review or AI-agent workflows. One GET request returns an image or PDF. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000. ScreenshotNeo is useful for capturing pages to inspect, while Cypress and accessibility tools remain responsible for testing semantics and interaction.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
FAQ
Can Cypress tests check keyboard accessibility?
Yes. Use Cypress keyboard events such as cy.press() to test expected navigation and focus, and write assertions for your application’s interaction requirements. A generic scan does not establish that keyboard use works correctly.
Does a passing scan mean my app conforms to WCAG?
No. It means the configured scanner found no applicable violations in the tested state. Rules have limits, some are disabled by default, and human review and product-specific tests are still needed.
Should I scan every page?
Cover representative critical journeys and important states, and include reusable components in component tests or workflows. Choose coverage based on user impact and the value of each scan.
Is Cypress Accessibility the same as cypress-axe?
No. cypress-axe runs scans in Cypress tests as a community plugin. Cypress Accessibility is a paid Cypress Cloud feature that analyzes captured test snapshots.
Sources
- Cypress: Accessibility Testing
- Cypress: Accessibility Testing Types
- Cypress: Axe Core Configuration
- Cypress: Accessibility Automation Principles
- Cypress:
cy.press()
For current plugin installation and support details, use the maintained cypress-axe documentation.


