Cypress Testing Guide
The complete reference for Cypress — the developer-first frontend testing framework. Covers E2E tests, component testing, network interception, custom commands, and CI integration.
What is Cypress?
Cypress is a JavaScript testing framework built specifically for the modern web. Unlike Selenium-era tools that drive browsers through WebDriver, Cypress runs directly inside the browser alongside your application. This architecture enables unique features: time-travel debugging (hover over any command in the runner to see the DOM state at that moment), real-time test reloading, direct access to application code and network requests, and automatic retries on assertions.
Cypress unified E2E and component testing under one API. With Component Testing mode, you can mount a React or Vue component directly in Cypress without a full app running, test it with the same cy.get() and cy.contains() commands, and get screenshots and video. This makes Cypress the only tool that covers both granular component tests and full user journey tests in a single runner.
Installation
# Install Cypress
npm install --save-dev cypress
# Open interactive runner
npx cypress open
# Run headlessly (CI)
npx cypress run
# cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.cy.ts',
supportFile: 'cypress/support/e2e.ts',
video: false, // Enable for CI
screenshotOnRunFailure: true,
},
component: {
devServer: { framework: 'react', bundler: 'vite' },
},
}); Basic E2E Test: cy.visit, cy.get, cy.contains
// cypress/e2e/login.cy.ts
describe('Login flow', () => {
beforeEach(() => {
cy.visit('/login');
});
it('logs in with valid credentials', () => {
cy.get('[data-testid="email"]').type('[email protected]');
cy.get('[data-testid="password"]').type('secret{enter}');
cy.url().should('include', '/dashboard');
cy.contains('h1', 'Dashboard').should('be.visible');
});
it('shows error for wrong password', () => {
cy.get('[data-testid="email"]').type('[email protected]');
cy.get('[data-testid="password"]').type('wrong');
cy.get('button[type="submit"]').click();
cy.get('[role="alert"]').should('contain', 'Invalid credentials');
});
}); Network Stubbing with cy.intercept()
describe('Products page', () => {
it('shows products from API', () => {
// Stub the API response
cy.intercept('GET', '/api/products', {
statusCode: 200,
body: [
{ id: 1, name: 'Widget', price: 9.99 },
{ id: 2, name: 'Gadget', price: 19.99 },
],
}).as('getProducts');
cy.visit('/products');
cy.wait('@getProducts');
cy.contains('Widget').should('be.visible');
cy.contains('Gadget').should('be.visible');
});
it('shows empty state when API returns empty array', () => {
cy.intercept('GET', '/api/products', { body: [] }).as('getProducts');
cy.visit('/products');
cy.wait('@getProducts');
cy.contains('No products found').should('be.visible');
});
it('handles API error', () => {
cy.intercept('GET', '/api/products', { statusCode: 500 }).as('getProducts');
cy.visit('/products');
cy.wait('@getProducts');
cy.contains('Something went wrong').should('be.visible');
});
}); Custom Commands
// cypress/support/commands.ts
Cypress.Commands.add('login', (email: string, password: string) => {
// Programmatic login via API — much faster than UI login
cy.request('POST', '/api/auth/login', { email, password })
.then(({ body }) => {
window.localStorage.setItem('token', body.token);
});
});
// Use cy.session() to cache login across tests
Cypress.Commands.add('loginAs', (role: 'admin' | 'user') => {
cy.session(role, () => {
const creds = { admin: ['[email protected]', 'admin'], user: ['[email protected]', 'user'] };
cy.request('POST', '/api/auth/login', {
email: creds[role][0], password: creds[role][1],
}).then(({ body }) => {
window.localStorage.setItem('token', body.token);
});
});
});
// In tests:
// cy.login('[email protected]', 'password');
// cy.loginAs('admin'); Component Testing
// cypress/component/Button.cy.tsx
import Button from '../../src/components/Button';
describe('Button component', () => {
it('renders with correct label', () => {
cy.mount(<Button label="Click me" onClick={cy.stub()} />);
cy.contains('Click me').should('be.visible');
});
it('calls onClick when clicked', () => {
const onClick = cy.stub().as('onClick');
cy.mount(<Button label="Submit" onClick={onClick} />);
cy.get('button').click();
cy.get('@onClick').should('have.been.calledOnce');
});
it('is disabled when disabled prop is true', () => {
cy.mount(<Button label="Disabled" onClick={cy.stub()} disabled />);
cy.get('button').should('be.disabled');
});
}); Key Features
- Time-travel debugging — hover any command in the runner to inspect the DOM at that moment
- Automatic retry — assertions retry for up to 4 seconds before failing
- Real browser — runs in Chrome, Firefox, or Edge (not a headless simulation)
- Component testing — mount React/Vue/Angular components without a full app
- cy.intercept() — stub, spy on, or modify any HTTP request/response
- cy.session() — cache and restore login state for fast test setup
- Screenshots and video — automatic capture on failure, configurable
Comparison: Cypress vs Alternatives
| Feature | Cypress | Playwright | Selenium |
|---|---|---|---|
| Architecture | In-browser | External protocol | WebDriver |
| Browser support | Chrome/FF/Edge | Chrome/FF/Safari | All browsers |
| Component testing | Yes | No | No |
| Time-travel debug | Yes | Trace Viewer | No |
| Multi-tab support | No | Yes | Yes |
| Developer experience | Excellent | Excellent | Moderate |
Pros & Cons
Pros
- Best-in-class developer experience and interactive runner
- Time-travel debugging eliminates most debugging effort
- Component testing covers UI unit tests too
- cy.intercept() makes network stubbing effortless
- Runs in a real browser, not a simulation
- Excellent documentation and community
Cons
- No Safari/WebKit support (no real iOS browser testing)
- Cannot open multiple tabs in a single test
- JavaScript/TypeScript only (no Python, Java, etc.)
- Can be slow for large suites without Cloud parallelization
- Same-origin restrictions on cross-domain navigation
- Cypress Cloud required for CI parallelization
Frequently Asked Questions
What is Cypress and what makes it different from other E2E testing tools?▼
Cypress is a JavaScript end-to-end testing framework that runs directly inside the browser rather than controlling it from outside (as Selenium and Playwright do). This architecture gives Cypress native access to the DOM, network layer, and application code. Its standout features are time-travel debugging (see the DOM state at every command), automatic retries, real-time reloading, and an interactive test runner with screenshot and video recording built in.
What is the difference between Cypress E2E testing and Cypress Component Testing?▼
Cypress E2E tests navigate to a running web server URL and test the full application stack. Cypress Component Testing mounts individual components in isolation inside a real browser without a dev server, making it faster than E2E for UI-level unit tests. Component Testing supports React, Vue, Angular, Svelte, and Next.js, and shares the same cy.get/cy.contains API — making it a natural companion to E2E tests in a single tool.
How does cy.intercept() work?▼
cy.intercept() registers a network handler that intercepts HTTP requests matching a URL pattern or method before they leave the browser. You can let the real request through, stub it with a fixture, modify request/response headers, or simulate network failures. Unlike Playwright's page.route(), Cypress intercepts happen at the XHR/Fetch layer rather than the OS network layer, meaning the app's JavaScript sees the stubbed response as if it came from the real server.
How do I write reusable Cypress custom commands?▼
Add custom commands to cypress/support/commands.ts using Cypress.Commands.add(). A common pattern is a cy.login() command that programmatically sets a session token without going through the UI — dramatically faster than filling the login form on every test. Declare the TypeScript type in cypress/support/index.d.ts to get autocomplete. Use cy.session() to cache and restore session state across tests for even faster authentication.
Why do Cypress tests sometimes fail intermittently (flakiness)?▼
Cypress retries most assertions automatically for up to 4 seconds, but flakiness can occur when: (1) an assertion checks a value that updates after an async operation not tracked by Cypress; (2) tests share state via the DOM or application store between runs; (3) cy.wait() is used with a hard-coded duration instead of waiting for a specific network alias. Fix flakiness by using cy.intercept() aliases and cy.wait('@alias'), avoiding fixed waits, and clearing application state in beforeEach.
What is Cypress Cloud (formerly Cypress Dashboard)?▼
Cypress Cloud is the commercial SaaS platform for storing test recordings, screenshots, and videos from CI runs. It provides parallelization (distribute tests across multiple CI machines automatically), flake detection, test analytics, and GitHub/GitLab integrations for PR status checks. The Cypress open-source runner works without Cypress Cloud, but Cloud adds observability and parallelization for large test suites.
Related Products
on GumroadTypeScript Quick Reference Toolkit
5 practical reference files for TypeScript developers: cheatsheet, TS vs JS comparison, 20 utility types with real examples, tsconfig best practices template, and 15 common mistakes guide. Print it. Keep it on your desk.
Buy on Gumroad →DevToolkit Starter Kit
A ready-to-deploy developer tools website with 12 built-in tools. Astro + Preact + Tailwind. Deploy to Cloudflare Pages for free. Built-in SEO, dark mode, and ad-ready layout.
Buy on Gumroad →Developer Productivity Bundle
Stop rebuilding the same setup every project. 51 VSCode snippets, 40 Git aliases, 5 Docker Compose stacks, 5 GitHub Actions workflows, 5 README templates, and a dotfiles kit. Set up a professional dev environment in under an hour.
Buy on Gumroad →You Might Also Need
JS Prototype Chain Visualizer
Explore JavaScript prototype chains interactively. Visualize built-in types (Array, Map, Promise, Error) and custom classes with property lookup path diagrams.
Open free tool →
Jest Testing Framework Guide
Complete guide to Jest JavaScript testing framework. Learn describe/it/expect, mocking, snapshot testing, async tests, coverage, and best practices for unit and integration testing.
Open free tool →
JavaScript Formatter & Minifier
Format and beautify JavaScript code with proper indentation, or minify it to reduce bundle size. Handles strings, template literals, comments, and nested blocks. Runs in your browser.
Open free tool →
More Free Tools
Related Articles
Playwright vs Cypress vs Puppeteer 2026: Which Testing Tool Should You Choose?
Playwright vs Cypress vs Puppeteer 2026 — compare feature sets, performance, developer experience, parallel testing, CI costs, and browser support. Find the right E2E testing tool for your stack.
End-to-End Testing in 2026: Writing Tests That Don't Lie
E2E testing guide 2026: choose Playwright or Cypress, eliminate flakiness, structure test suites for CI/CD, and understand real application quality limits.
Test-Driven Development Guide 2026: Practical TDD That Actually Works
Learn TDD the practical way in 2026. Red-green-refactor workflow, real-world examples in JavaScript and Python, when TDD helps vs hurts, and how to introduce it to your team.
Modern JavaScript Testing 2026: Vitest vs Jest vs Playwright
Complete guide to JavaScript testing in 2026. Compare Vitest vs Jest for unit tests, Playwright vs Cypress for E2E, component testing, coverage tools, and CI/CD integration.
Modern TDD in 2026: Test-Driven Development with Vitest, Playwright & AI Copilots
Test-Driven Development has evolved. This practical guide covers modern TDD workflows using Vitest for unit tests, Playwright for E2E, MSW for API mocking, and how AI coding assistants (GitHub Copilot, Claude Code) are changing how we write tests first.
Enjoying this tool? Get more like it.
Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.
Unlock AI-Powered Dev Tools
- ⚡ AI Code Review, Doc Generator & SQL Builder
- ⚡ All premium templates & early access
- ⚡ Member discounts on Gumroad products
$9/mo after trial · Cancel anytime
Want the full toolkit?
Get DevPlaybook Pro
Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.
MIT licensed · Instant download · No subscription
See what's included → Browse all deals →