End-to-End Testing with Cypress
In this page:
describe("feature", () => {
it("description", () => {
cy.visit("/path");
cy.get("selector").type("text");
cy.contains("button", "label").click();
cy.contains("expected text").should("be.visible");
});
});
What Makes a Test 'End-to-End'
Unlike unit or integration tests that check isolated pieces, an end-to-end (E2E) test drives your ACTUAL running app in a real browser, simulating a complete user journey from start to finish — like visiting a signup page, filling the form, submitting, and confirming a welcome message appears.
Example: What Makes a Test 'End-to-End'
// Run in your local React project (npm install required)
// cypress/e2e/login.cy.js
describe('Login flow', () => {
it('logs in successfully', () => {
cy.visit('/login');
cy.get('input[name=email]').type('[email protected]');
cy.get('button').contains('Log In').click();
cy.contains('Welcome back!').should('be.visible');
});
});
Core Cypress Commands
cy.visit(url) navigates to a page, cy.get(selector) finds elements (similar in spirit to Testing Library's queries, but CSS-selector-based), and commands like .click() or .type() interact with them, all chained together to describe a full user flow.
Example: Core Cypress Commands
// Run in your local React project (npm install required)
describe('Search feature', () => {
it('shows results after searching', () => {
cy.visit('/search');
cy.get('input[type=search]').type('react{enter}');
cy.get('.result-item').should('have.length.greaterThan', 0);
});
});
Automatic Retrying and Avoiding Flaky Tests
Cypress automatically retries most assertions for a few seconds before failing, which handles a lot of async timing (like waiting for an API response to render) without manual sleeps or arbitrary waits.
This built-in retrying reduces, though doesn't fully eliminate, timing-related test flakiness.
Example: Automatic Retrying and Avoiding Flaky Tests
// Run in your local React project (npm install required)
// Avoid this (fixed, unreliable wait):
// cy.wait(2000);
// cy.get('.result').should('exist');
// Prefer this (Cypress retries automatically until it appears or times out):
cy.get('.result', { timeout: 10000 }).should('exist');
- Writing E2E tests for every small detail instead of reserving them for critical, full user journeys.
- Making E2E tests depend on real, external, unpredictable data instead of a controlled test environment.
- Not waiting properly for async content, causing tests to fail intermittently ('flaky tests') depending on timing.
- Cypress is a popular end-to-end testing tool that drives a real browser to simulate complete user flows.
- cy.visit(), cy.get(), and cy.click() are core commands for navigating and interacting with a real page.
- Cypress automatically retries assertions for a short time, reducing (but not eliminating) timing-related flakiness.
- E2E tests are slower than unit tests, so they're reserved for critical, high-value user flows.
Requires npm install cypress — runs a real browser via Cypress's test runner, not this preview sandbox.
Chapter Quiz — Complete all 9 topics to unlock
0/9 topics done
Complete these topics first: