Skip to content

Introduction to Cypress

Cypress is a modern, JavaScript-based end-to-end testing framework that runs inside the browser alongside your application. This introduction explains what Cypress is, how it works under the hood, and why teams choose it over older browser automation tools.

What Is Cypress?

Cypress is an open-source test automation tool created for testing anything that runs in a browser: web applications, APIs reachable from the browser, and increasingly, individual UI components. It ships as an all-in-one package containing a test runner, an assertion library, and mocking/stubbing utilities, so you do not need to wire together separate tools to get started.

The biggest architectural difference from older tools is that Cypress executes inside the same run loop as your application. Instead of sending remote commands over a network protocol like Selenium's WebDriver, Cypress operates directly in the browser, giving it native access to the DOM, network layer, and JavaScript execution context.

describe('homepage', () => {
  it('loads and shows a welcome message', () => {
    cy.visit('/');
    cy.get('[data-cy="welcome"]').should('be.visible');
  });
});

This is a complete, runnable Cypress test: visit a page, find an element with a data-cy attribute, and assert that it is visible.

How a Cypress Test Is Structured

describe('feature name', () => {
  it('does something specific', () => {
    // commands and assertions
  });
});
  • describe() groups related tests together into a readable block.
  • it() defines a single test case with a clear, human-readable description.
  • Inside it(), you chain Cypress commands like cy.visit() and cy.get().
  • Tests live in .cy.js (or .cy.ts) spec files inside a cypress/e2e folder by default.

Cypress at a Glance

A quick reference to the core ideas you will use in every Cypress test.

Concept Example Purpose
Visit a page cy.visit('/login') Load a URL in the test browser
Find an element cy.get('[data-cy="btn"]') Locate elements to interact with
Interact .click(), .type('text') Simulate user actions
Assert .should('be.visible') Verify expected state
Group tests describe('...', () => {}) Organize related tests
Define a test it('...', () => {}) A single test case
Network control cy.intercept('GET', '/api/*') Stub or spy on requests
Run headless cypress run Execute tests in CI
Run interactively cypress open Debug tests in the Test Runner

How Cypress Architecture Differs from Selenium

Selenium and similar WebDriver-based tools control a browser from an external process, sending commands over HTTP and waiting for responses. This out-of-process model works, but it means the test runner has no direct visibility into what is actually happening inside the page, leading to guesswork around timing.

Cypress instead injects its test runner directly into the browser and executes in the same event loop as your application code. This gives Cypress native access to the DOM, window, network requests, and JavaScript exceptions, which is what enables features like automatic waiting and time-travel debugging without extra configuration.

  • Runs in-browser, in the same run loop as your application.
  • Has native access to everything the application has access to.
  • Automatically waits for elements and assertions without manual sleeps.
  • Can intercept and modify network traffic without an external proxy.

What You Can Test with Cypress

Cypress supports several distinct testing types under one tool. End-to-end (E2E) testing drives your full application through a real browser, exactly as a user would. Component testing mounts individual UI components (React, Vue, Angular, and others) in isolation, without a full app running.

Cypress can also be used for lightweight API testing, since cy.request() lets you make raw HTTP calls and assert on the response, even without a browser UI involved.

Testing Type Description
End-to-end (E2E) Full user flows through a real browser
Component testing Individual components mounted in isolation
API testing Direct HTTP requests via cy.request()
Visual testing Screenshot comparisons via plugins

Common Mistakes

  • Assuming Cypress works exactly like Selenium; the in-browser architecture changes how waiting, iframes, and multi-tab scenarios are handled.
  • Thinking Cypress can only do end-to-end testing when it also supports component and API-style testing.
  • Skipping the official documentation's architecture guide, which explains many "why can't I do X" questions before they come up.
  • Expecting Cypress to control multiple browser tabs or multiple browsers at once within a single test.

Key Takeaways

  • Cypress is an all-in-one JavaScript testing framework combining a runner, assertions, and network control.
  • It runs inside the browser's run loop, unlike external WebDriver-based tools.
  • This architecture enables automatic waiting, time-travel debugging, and native network interception.
  • Cypress supports end-to-end, component, and lightweight API testing in one tool.

Pro Tip

Before writing your first real test, skim the official Cypress "Trade-offs" documentation page. Knowing upfront what Cypress intentionally does not support (like controlling two browsers at once) will save you time later.