Top Cypress Features for Test Automation
Explore Cypress features for end-to-end, component, API, accessibility, and network testing, with practical setup, code, tradeoffs, and troubleshooting.
Cypress combines browser-based end-to-end and component testing with HTTP requests, network interception, retry-ability, debugging tools, and accessibility checks. Use end-to-end tests for critical user journeys, component tests for focused browser behavior, API tests for service contracts and setup, and stubs for controlled edge cases. These features complement one another; no single test type covers every failure mode.
This guide explains what the main Cypress features do, when each is useful, how to configure them, and where their limits are. Product behavior below follows the Cypress testing-types guide and other official Cypress documentation.
1. End-to-end testing for real user journeys
End-to-end (E2E) tests drive the application in a browser through workflows such as signing in, checking out, or moving between pages while data persists. They are valuable for checking that the UI, application logic, and backend work together along a critical path.
Use E2E tests for a small set of high-value journeys and smoke checks before deployment. They need a running application and usually require reliable test data and environment setup, so they take more infrastructure and maintenance than focused component tests.
describe('checkout', () => {
it('completes an order', () => {
cy.visit('/products/sku-123');
cy.get('[data-cy=add-to-cart]').click();
cy.get('[data-cy=checkout]').click();
cy.get('[data-cy=order-confirmation]').should('be.visible');
});
});
Prefer stable selectors such as dedicated data-cy attributes. Avoid tying tests to incidental styling classes or long chains of DOM structure that can change during refactoring. Seed or reset state deliberately so one run does not depend on the leftovers from another.
2. Component testing in a real browser
Cypress Component Testing mounts a component directly in a real browser. That lets you check rendering, interaction, CSS, and browser behavior without setting up a complete user journey. Cypress documents mount libraries for React, Angular, Vue, and Svelte.
import Button from './Button';
describe('<Button />', () => {
it('calls its handler when clicked', () => {
const onClick = cy.stub().as('onClick');
cy.mount(<Button onClick={onClick}>Save</Button>);
cy.contains('button', 'Save').click();
cy.get('@onClick').should('have.been.calledOnce');
});
});
The example uses a React-style mount; use the mount function and setup appropriate to your framework. Component tests can use Cypress’s automatic waiting, command snapshots, browser DevTools, spies and stubs, network interception, and clock control. They can share a Cypress project with E2E tests.
Choose component or end-to-end tests by scope
| Question | Component test | End-to-end test |
|---|---|---|
| What is exercised? | A mounted component and its browser behavior | A user workflow through the running application |
| Does it need the full backend? | Often no; dependencies can be controlled | Usually needs application and test data infrastructure |
| Best fit | States, interactions, rendering, and component edge cases | Critical journeys, integration, persistence, and deployment smoke checks |
| Main tradeoff | Does not prove the whole application flow works | More setup and maintenance, and failures can involve more layers |
Use both when the application warrants it: cover component states close to the component and reserve E2E coverage for workflows whose integration matters.
3. API testing with Cypress commands
Cypress can send HTTP requests and assert on their responses. API tests are useful for CRUD behavior, error handling, permission boundaries, GraphQL response shapes, data seeding, and preparing authentication state for a browser test. They complement UI testing: an API assertion cannot establish that a user can complete the corresponding flow in the interface.
describe('projects API', () => {
it('returns the created project', () => {
cy.request({
method: 'POST',
url: '/api/projects',
body: { name: 'Release checklist' },
}).then((response) => {
expect(response.status).to.eq(201);
expect(response.body.name).to.eq('Release checklist');
});
});
});
Adapt the route, authentication, and expected status to your application. Keep test data isolated and avoid relying on a particular record being present unless the test itself creates or seeds it.
4. Automatic waiting, retry-ability, and test retries
Cypress retry-ability and failed-test retries solve different problems. Linked queries and assertions are retried while the application changes, which helps with dynamic pages and removes many arbitrary sleeps. Separately, the test-retries configuration can rerun a test that failed; it is off by default.
// cypress.config.js
const { defineConfig } = require('cypress');
module.exports = defineConfig({
retries: {
runMode: 2,
openMode: 0,
},
});
This allows up to two additional attempts in run mode and no automatic rerun in open mode. Cypress’s documented example also uses retries: 2 as a shorthand. A test that passes only on a later attempt is still evidence of instability; use retries to expose and diagnose flakes, not to treat them as fixed.
Prefer a condition tied to the behavior under test over a fixed wait:
// Condition-based: waits for the expected UI state.
cy.get('[data-cy=results]').should('be.visible');
// Fixed delay: use only when a known timing requirement calls for it.
cy.wait(500);
Queries and assertions can only retry the chain Cypress recognizes. A one-time side effect, such as clicking, should not be repeated as though it were a query. Put assertions after the action and wait for an observable result.
5. Network interception and stubbing with cy.intercept()
cy.intercept() can observe requests, wait for them, assert on request or response details, and stub a response body, status, headers, or delay. Stubs make edge cases reproducible without changing a server. Real responses exercise the actual client-server path and are important for critical integration coverage, but need server availability and suitable data.
it('shows an empty state when there are no projects', () => {
cy.intercept('GET', '/api/projects', {
statusCode: 200,
body: [],
}).as('getProjects');
cy.visit('/projects');
cy.wait('@getProjects');
cy.get('[data-cy=empty-state]').should('be.visible');
});
To assert on a real response, register an intercept without a static response and wait on its alias:
cy.intercept('GET', '/api/projects').as('getProjects');
cy.visit('/projects');
cy.wait('@getProjects').its('response.statusCode').should('eq', 200);
The Cypress guide on intercepting network requests says that when requests are not stubbed, this guarantees the client-server contract is working. Read that as a statement about the real response reaching the application; it does not guarantee every production data condition is covered. Seed data, server state, and test environment still matter. A balanced suite keeps real responses for important paths and stubs other cases when controlled inputs make tests clearer and faster.
6. Debugging with the command log and snapshots
The Cypress runner provides a visual command log, snapshots, readable errors and stack traces, and access to browser DevTools while a test runs. These help inspect the state around a command and distinguish application behavior from test assumptions. Cypress Component Testing also supports visual inspection in the browser.
When a test fails, start at the first failed assertion or command. Inspect the preceding snapshot, relevant request and response, and browser console. Check whether the selector matched the intended element, whether the app reached the expected state, and whether test data or environment state differed. Recorded-run capabilities in Cypress Cloud can help teams review CI failures; feature availability may depend on the current plan.
7. Cross-browser runs and Cypress Cloud workflows
Cypress’s feature overview describes local and CI execution in Firefox and Chrome-family browsers, including Edge. Running critical tests in the browsers your users rely on can expose browser-specific behavior. Browser availability and setup can change, so check the current browser documentation for supported versions and launch requirements.
Cypress Cloud adds team and recorded-run workflows. Its documented capabilities include Test Replay, parallelization, spec prioritization, Auto Cancellation, integrations, analytics, and UI Coverage. Some Cloud capabilities are plan-gated; check current packaging and pricing before choosing a plan. The local Cypress App and Cloud are separate considerations: a team can use the testing features locally and decide independently whether recorded CI collaboration is useful.
8. Accessibility testing as a layer on functional tests
Accessibility checks can be added to functional tests with community plugins such as cypress-axe, with ordinary Cypress assertions, or through Cypress Accessibility Cloud. Scan important flows such as sign-up and checkout, and add explicit assertions for labels, accessible names, keyboard behavior, and focus where relevant.
Automated scanners detect violations of known rules; they cannot prove a page is fully accessible. Keep manual review and keyboard testing in the process. A clean automated scan is one signal, not a certification.
9. A practical feature selection checklist
- Identify the behavior and the failure you need to catch.
- Use a component test for isolated rendering and interactions.
- Use an API test for service behavior, permissions, and data setup.
- Use E2E coverage for critical journeys and integration across the running app.
- Use real network responses where the actual server contract matters.
- Stub controlled error, empty, delayed, or unusual responses when that makes edge cases repeatable.
- Add accessibility checks to meaningful flows, and retain manual review.
- Enable failed-test retries only as a diagnostic aid; investigate tests that pass on another attempt.
- Consider Cloud workflow features against team needs and verify current plan availability.
10. Common problems and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| Element not found or assertion times out | The page has not reached the expected state, selector is brittle, or data is missing | Use a stable test selector, assert on an observable state, and verify setup and seeded data. |
| Test passes after a retry but fails initially | Flaky timing, shared state, or an intermittent dependency | Inspect the first failure, remove arbitrary sleeps, isolate test data, and stabilize the dependency. |
| Intercept wait times out | Route matcher does not match, request never fires, or alias was registered too late | Register the intercept before visiting or triggering the action; check method, URL, and query matching. |
| Stubbed test passes while the feature fails against the server | The stub does not validate server behavior or may diverge from the real response | Retain a real-response test for the important path and keep stubs focused on controlled cases. |
| API test returns unauthorized or unexpected data | Authentication, permissions, environment, or fixture state differs from assumptions | Set up credentials and test data explicitly; assert expected status and response shape. |
| Component test differs from full application behavior | The mount omits providers, styles, routing, or dependencies used by the app | Configure the component test support setup to include the required context and styles; use E2E coverage for integration behavior. |
| Accessibility scan is clean but users encounter barriers | Automated rules do not cover every accessibility issue | Add keyboard and focus checks, explicit accessible-name assertions, and manual review. |
11. Performance, reliability, and cost considerations
Component and API tests can give focused feedback without exercising a complete browser journey. E2E tests provide broader integration coverage but need more environment setup and can be affected by backend and data state. Stubs reduce dependency on server conditions for selected scenarios; real requests validate the path that stubs bypass. Choose by the failure you want to catch rather than making every test use one strategy.
For reliability, isolate data, make setup explicit, select stable elements, wait on meaningful conditions, and keep retries visible as a signal. Avoid treating a successful later attempt as proof that a test is stable. For cost, the Cypress App supports local testing; Cypress Cloud and premium capabilities may be paid or plan-gated. Verify current plan details before budgeting because availability and pricing can change.
12. Or skip the browser setup
If the goal is a screenshot of a live page rather than an interactive Cypress test, ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It returns a PNG, JPEG, WebP, or PDF from one GET request. It complements Cypress: use Cypress to test behavior and ScreenshotNeo when you need a captured page image.
See the ScreenshotNeo API documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
Cookie banners are accepted like a visitor and removed along with 60+ known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card.
FAQ
Can Cypress test APIs without opening a page?
Yes. Cypress can issue HTTP requests and assert on responses. Use browser tests as well when the user-visible flow is part of what needs verification.
Do retries make flaky tests reliable?
No. Query retry-ability handles changing application state; configured failed-test retries rerun a failure. A test that needs another attempt still warrants investigation.
Can accessibility scans certify a site?
No. They identify violations of known automated rules. Manual review and checks such as keyboard navigation and focus behavior are still needed.
Should every network request be stubbed?
No. Keep real responses where the server contract matters and use stubs for cases that benefit from controlled, repeatable inputs.


