Concept
Browser-based Execution
Unlike Jest/Vitest which run in Node.js simulating the DOM via jsdom, Cypress executes tests directly inside a real browser instance (Chrome, Firefox, Electron). This ensures tests match actual user renderings and browser features.
Cypress provides a domain-specific assertion engine:
describe('User Sign In flow', () => {
it('should authenticate user and display dashboard', () => {
cy.visit('/login'); // Navigate to path
cy.get('input[name="email"]').type('ada@example.com');
cy.get('input[name="password"]').type('password123');
cy.get('button[type="submit"]').click();
// Assert URL change
cy.url().should('include', '/dashboard');
// Assert DOM updates
cy.get('h1').should('contain', 'Welcome back, Ada');
});
});Automatic Waiting & Retry-ability
One of Cypress's primary features is Retry-ability. If an element does not mount instantly (due to loading delays), Cypress does not fail the test immediately. It retries queries and assertions automatically up to a timeout (default 4 seconds):
// Cypress queries and asserts continuously until either the element contains 'Loaded' or 4000ms expires
cy.get('.status-message').should('contain', 'Loaded');Common Mistakes
1. Hardcoding static sleep delays (cy.wait(5000))
Using manual wait steps like cy.wait(5000) slows down tests because the runner sleeps for 5 seconds even if the data loaded in 100 milliseconds. Always use alias routing assertions or count on Cypress's automatic retry-ability:
// ❌ WRONG: Hardcoded sleep
cy.wait(5000);
// CORRECT: Intercept and wait on API response
cy.intercept('GET', '/api/users').as('getUsers');
cy.wait('@getUsers'); // Only waits until the HTTP call returns2. Chaining assertions off mutable variables
Cypress command lines are asynchronous and return promise-like chains. Storing elements in local variables (like const btn = cy.get('button')) and referencing them in downstream assertions fails if the DOM re-renders in between. Always chain commands or use .then() wrappers:
cy.get('button').then(($btn) => {
const text = $btn.text();
// check value...
});Best Practices
- Use cy.intercept: Intercept, mock, or verify HTTP requests at the network boundary using Cypress's network interception tools.
- Isolate State: Clear browser cookies, storage, and reset databases before each test block runs to guarantee test isolation.
- Select by semantic elements: Rely on accessibility-driven selectors where possible (using Cypress Testing Library) rather than brittle CSS styling classes.
