TestingBeginner

What Is Cypress? Features and Use Cases

Cypress is a JavaScript end-to-end testing framework that runs in the browser. Learn what Cypress is, its key features, and when to use it.

ObserveOne Team
6 min read

Cypress is an open-source JavaScript testing framework built for the modern web. It lets developers write fast, reliable end-to-end, integration, and component tests that run directly inside the browser alongside the application under test. Since its launch, Cypress has become one of the most popular alternatives to Selenium for front-end teams.

Definition: What Is Cypress?#

Cypress is a Node.js based testing tool that runs your tests in the same run loop as your application. Instead of driving the browser from the outside through a separate protocol, Cypress executes inside the browser, which gives it direct access to the DOM (document object model), the network layer, and your application code.

This architecture is the single biggest difference between Cypress and tools like Selenium or Playwright, and it shapes most of its strengths and limitations.

Key Characteristics#

  • Runs in the browser: Tests execute in the same context as your app, not over a remote driver
  • All-in-one: Test runner, assertion library, and mocking come bundled, no extra setup
  • Automatic waiting: Commands retry until elements are ready, so you rarely write manual waits
  • Time-travel debugging: The Test Runner snapshots each step so you can inspect exactly what happened
  • JavaScript and TypeScript first: Tests are written in the same language as most front-end code

Core Features of Cypress#

1. Automatic Waiting and Retries#

Cypress automatically waits for elements to exist and become actionable before it acts on them. You do not need explicit sleeps:

// Cypress retries this command until the button exists,
// is visible, and is enabled, or the timeout is reached
cy.get("[data-cy=submit]").click();

This removes the most common cause of flaky tests: race conditions between the test and the app.

2. Time-Travel Debugging#

The Cypress Test Runner takes a snapshot of your application at every command. You can hover over each step in the command log and see the exact state of the page at that moment, which makes failures far easier to diagnose.

3. Network Stubbing and Spying#

Cypress can intercept, stub, and assert on network requests, so you can test edge cases without a live backend:

// Stub the API response
cy.intercept("GET", "/api/users", {
statusCode: 200,
body: [{ id: 1, name: "Test User" }],
}).as("getUsers");
cy.visit("/users");
cy.wait("@getUsers");

4. Screenshots and Videos#

When a test fails in headless mode, Cypress automatically captures a screenshot, and it can record a full video of the run. This is useful for debugging failures in CI (continuous integration).

// Manual screenshot
cy.screenshot("after-login");

5. Component Testing#

Beyond end-to-end tests, Cypress can mount and test individual UI components in isolation for frameworks like React, Vue, and Angular, which sits between unit tests and full browser tests.

When to Use Cypress#

Cypress is a strong fit for:

1. End-to-End Testing of Web Apps#

Testing complete user journeys through a single web application.

Example use case: Verifying a signup flow from the form through to the welcome screen. See our end-to-end testing guide for the broader approach.

2. Front-End Teams Working in JavaScript#

Teams that already write JavaScript or TypeScript get a low learning curve, since tests use the same language and tooling as the app.

3. Fast Feedback During Development#

The interactive Test Runner reloads tests as you save, giving near-instant feedback while you build features.

4. Component Testing#

Validating individual components in a real browser without spinning up the whole app.

Cypress vs Alternatives#

Cypress is often weighed against Selenium and Playwright. Each makes a different architectural trade-off.

FeatureCypressSeleniumPlaywright
ArchitectureRuns inside browserDrives browser via WebDriverDrives browser via protocol
LanguagesJavaScript, TypeScriptMany (Java, Python, C#, etc.)JavaScript, Python, Java, .NET
Auto-waitBuilt-inManual waits requiredBuilt-in
Multi-tab / multi-originLimitedSupportedSupported
Browser supportChromium family, Firefox, WebKit (experimental)All major browsersChromium, Firefox, WebKit
SetupSingle dependencyRequires driver managementSingle installer

For a deeper head-to-head, read Cypress vs Selenium and What Is Playwright?.

Choose Cypress when you have a JavaScript front end, want fast developer feedback, and test a single web app.

Choose Selenium when you need multiple language bindings, broad browser coverage, or legacy support.

Choose Playwright when you need multi-tab or multi-origin flows, cross-browser parity, or non-JavaScript language support.

Limitations to Know#

Cypress is excellent within its design, but the in-browser architecture comes with constraints:

  • One browser tab at a time: Multi-tab scenarios are not natively supported
  • JavaScript and TypeScript only: No bindings for other languages
  • Cross-origin is restricted: Visiting multiple domains in one test needs cy.origin and has limits
  • No native Safari: WebKit support is experimental

If any of these are central to your tests, Playwright or Selenium may fit better.

Getting Started with Cypress#

Installation#

npm install cypress --save-dev

Open the Test Runner#

npx cypress open

This scaffolds the cypress/ folder, adds example specs, and opens the interactive runner where you can pick a browser.

Your First Test#

describe("homepage", () => {
it("loads and shows the title", () => {
cy.visit("https://example.cypress.io");
cy.contains("type").click();
cy.url().should("include", "/commands/actions");
});
});

Running Tests#

# Open the interactive Test Runner
npx cypress open
# Run all tests headlessly (for CI)
npx cypress run
# Run a single spec file
npx cypress run --spec "cypress/e2e/login.cy.js"

Best Practices#

  1. Use dedicated test selectors. Add data-cy attributes to key elements so tests do not break when styling or text changes:
<button data-cy="submit" type="submit">Sign in</button>
cy.get("[data-cy=submit]").click();
  1. Lean on automatic retries instead of fixed waits:
// Good: retries until the element is ready
cy.get("[data-cy=welcome]").should("be.visible");
// Avoid: brittle and slow
cy.wait(2000);
  1. Stub the network for unstable dependencies so tests stay fast and deterministic with cy.intercept.
  2. Keep tests independent. Each test should set up its own state rather than depending on a previous test.

Conclusion#

Cypress pairs an in-browser architecture with automatic waiting and time-travel debugging to give front-end teams a fast, friendly testing experience. It shines for JavaScript single-app end-to-end testing, with the trade-off of being scoped to one browser tab and the JavaScript ecosystem.

Whichever framework you pick, someone still has to write and maintain every test as the UI changes. ObserveOne's Autopilot takes a different path: it generates Playwright tests from a URL and self-heals selectors when the app shifts, so your coverage survives redesigns instead of breaking on every refactor.

Frequently Asked Questions

No. Unlike Selenium, Cypress does not use WebDriver or any external driver. It runs directly inside the browser, in the same run loop as your application. This gives it native access to the DOM, network layer, and app code, which is the core architectural difference behind most of its behavior.

Yes. The Cypress framework and its Test Runner are free and open source, so you can install, run, and use them without a license fee. Cypress also offers a separate paid cloud service for recording, parallelization, and analytics, but that is optional and not required to write or run tests.

No. Cypress handles one browser tab at a time, so multi-tab scenarios are not natively supported. Visiting multiple domains in a single test is also restricted and requires the cy.origin command, which has limits. For multi-tab or multi-origin flows, Playwright or Selenium are generally a better fit.

cy.wait with a fixed number pauses for a set time, which is brittle and slow because it ignores the actual page state. Automatic retries instead repeat a command until the element exists and becomes actionable or the timeout is reached. Relying on retries, not fixed waits, produces faster and more reliable tests.

Weighing your options on this stack?

Drop into the head-to-head pages, or browse the alternatives we recommend.

Alternatives shortlists

Ready for AI-Powered Testing?

ObserveOne monitors your selectors 24/7 and automatically heals them when websites change. Never deal with broken tests again.

Start Free Trial