A comprehensive, production-grade learning repository for mastering Cypress E2E testing at Staff Engineer depth.
This is not a beginner tutorial. It's a deep-dive into Cypress architecture, test design, reliability, and CI strategy — the knowledge a Staff Engineer needs to own E2E testing for a production application.
| Area | Depth |
|---|---|
| Cypress Architecture | Runtime model, command queue, browser/Node split |
| Configuration | Multi-env configs, CI config, timeouts, reporters |
| Test Design | Patterns for auth, forms, tables, CRUD, error states |
| Network Strategy | Stubbing vs live backend, intercept patterns, API seeding |
| Authentication | cy.session, programmatic login, role-based testing |
| Reliability | Flake reduction, deterministic data, resilient selectors |
| CI/CD | Parallelization, artifacts, smoke tests, quarantine |
| Architecture | Custom commands vs helpers vs Page Objects |
| Debugging | Command log, screenshots, videos, triage workflow |
├── cypress/
│ ├── e2e/ # Test specs organized by feature
│ │ ├── auth/ # Login, logout, protected routes
│ │ ├── dashboard/ # Dashboard data, loading, errors
│ │ ├── forms/ # Form submission, validation
│ │ ├── tables/ # Sorting, filtering, pagination
│ │ ├── uploads/ # File upload testing
│ │ ├── error-handling/ # Error states, network failures
│ │ ├── search/ # Search and filtering flows
│ │ ├── crud/ # Full CRUD workflow tests
│ │ └── navigation/ # Protected routes, role-based access
│ ├── fixtures/ # Static test data
│ │ ├── users/ # User profile fixtures
│ │ ├── api-responses/ # API response fixtures
│ │ └── forms/ # Form data fixtures
│ ├── support/
│ │ ├── commands.ts # Custom Cypress commands
│ │ ├── e2e.ts # Support file (runs before each spec)
│ │ ├── selectors.ts # Centralized selector registry
│ │ ├── utils/
│ │ │ ├── intercept-helpers.ts # Reusable API intercept functions
│ │ │ └── test-helpers.ts # Pure utility functions
│ │ └── builders/
│ │ └── employee-builder.ts # Test data builder pattern
│ ├── configs/ # Environment-specific configs
│ │ ├── ci.config.ts # CI pipeline config
│ │ ├── staging.config.ts # Staging environment config
│ │ └── production-smoke.config.ts # Production smoke test config
│ ├── downloads/ # (gitignored) Downloaded files
│ ├── screenshots/ # (gitignored) Failure screenshots
│ └── videos/ # (gitignored) Test run videos
├── docs/ # Comprehensive documentation
│ ├── cypress-overview.md # What Cypress is, where it fits
│ ├── cypress-architecture.md # Deep architecture dive
│ ├── cypress-configurations.md # Configuration reference
│ ├── querying-and-assertion-strategy.md
│ ├── network-stubbing-and-api-strategy.md
│ ├── auth-testing-strategies.md
│ ├── reliable-e2e-patterns.md
│ ├── page-object-vs-app-actions.md
│ ├── flake-reduction.md
│ ├── debugging-guide.md
│ ├── ci-cd-strategy.md
│ ├── anti-patterns.md
│ └── staff-level-revision-cheatsheet.md
├── src/ # Sample app (test target)
├── .github/workflows/ # CI pipeline definitions
│ ├── cypress-ci.yml # PR/push E2E pipeline
│ └── cypress-smoke-schedule.yml # Scheduled smoke tests
├── scripts/
│ └── run-e2e-local.sh # Local test runner script
├── cypress.config.ts # Primary Cypress config
├── package.json
├── tsconfig.json
└── vite.config.ts
# Install dependencies
npm install
# Open Cypress Test Runner (interactive)
npm run cy:open
# Run all tests headlessly
npm run cy:run
# Run specific test suites
npm run cy:run:auth # Auth tests only
npm run cy:run:smoke # Smoke tests only
# Run with specific browser
npm run cy:run:chrome
npm run cy:run:firefox
# Run with environment-specific config
npm run cy:run:ci # CI config
npm run cy:run:staging # Staging config
npm run cy:run:prod-smoke # Production smokeOnly login.cy.ts tests the login UI. Every other spec uses cy.login() (programmatic, via API). This saves 2-5 seconds per test.
Most specs stub API responses for speed and determinism. The staging config runs against the real backend for integration confidence.
Builders (buildEmployee().withRole('admin').build()) are preferred over fixture files for data that varies between tests.
All data-testid selectors live in selectors.ts. When the UI changes a testid, fix it in one place.
Local development should surface flakes immediately. CI tolerates transient issues but tracks retry rates.
- Start with docs: Read
docs/cypress-overview.mdanddocs/cypress-architecture.md - Understand config: Study
cypress.config.tsand the variants incypress/configs/ - Learn the support layer: Read
commands.ts,selectors.ts,intercept-helpers.ts - Study test patterns: Go through specs in order: auth → dashboard → forms → tables
- Go deeper: Read remaining docs on flake reduction, CI/CD, anti-patterns
- Self-assess: Use
docs/staff-level-revision-cheatsheet.mdfor interview prep
Every spec and support file includes inline comments explaining:
- What it does
- Why it exists
- When to use it
- When not to use it
- Common mistakes to avoid
- Staff-level tradeoffs
| Type | Scope | When to Run | Config |
|---|---|---|---|
| Smoke | Critical paths only | Every deploy, every 30min | production-smoke.config.ts |
| Regression | All E2E tests | Every PR | ci.config.ts |
| Local | All or targeted | During development | cypress.config.ts |
| Staging | Full suite, live backend | Pre-release | staging.config.ts |
| Aspect | Cypress | Playwright |
|---|---|---|
| Architecture | In-browser, same event loop | Out-of-process, CDP/WebSocket |
| Multi-tab | Not supported | Supported |
| Multi-browser | Chrome, Firefox, Edge | Chrome, Firefox, Safari, Edge |
| Parallelism | Via Cypress Cloud or manual split | Built-in, free |
| Network mocking | cy.intercept (powerful) | route.fulfill (similar) |
| Retries | Built-in | Built-in |
| Component testing | Yes | Yes |
| Mobile testing | Viewport only | Device emulation |
| Learning curve | Lower | Higher |
| Community | Mature, large | Growing fast |
| Best for | Teams already using it, simpler setups | New projects, multi-browser needs |
MIT — Use this for learning, adapt for your projects.