mrkeyoor.com_
Sat 19 Sept 10:52 UTC
npmTestingupdated 19 Sept 2026

cypress review

Cypress is a browser test runner for end-to-end and component tests. Specs use Cypress's queued `cy.*` commands while an app shows the browser, command history, DOM snapshots, requests, screenshots, and failures. It can drive Chromium-family browsers, Firefox, Electron, and experimental WebKit; stub traffic with `cy.intercept()`; retry queries and assertions; and run framework components through adapters. Version 15.21.0 adds `cypress tap`, a CLI bridge that can inspect and rerun an open Cypress session for an AI agent. It also adds a guest-telemetry disable switch, deprecates `cy.exec()` in favor of `cy.task()`, and fixes WebKit interception hangs, runtime `blockHosts` overrides, Windows spec-list refresh, and several assertion and retry-reporting bugs.

Verdict

Cypress 15.21.0 is a strong fit when browser-test debugging and retried DOM commands matter more than ordinary async control. Start elsewhere when WebKit certainty, popup workflows, or service-free distributed execution are hard requirements.

We installed it

Lab card: what happened when we installed cypressScreenshot of cypress documentation
Install✓ · 25s162 packages on disk · 33 MB
ImportESM import works · require() works · CommonJS package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does cypress install cleanly?

Yes. In a fresh container with an empty cache, npm install cypress finished in 25 seconds, leaving 162 packages and 33 MB on disk. npm audit reported no known vulnerabilities.

Can cypress run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does cypress work with both ESM and CommonJS?

Yes. Both import 'cypress' and require('cypress') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does cypress include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

cypress or playwright: which should you use?

playwright: Choose it for first-class Chromium, Firefox, and WebKit projects plus popup and multi-page control. Cypress 15.21.0 is a strong fit when browser-test debugging and retried DOM commands matter more than ordinary async control.

When should you not use cypress?

Safari-engine coverage is a release gate. Cypress still labels WebKit support experimental, while Playwright treats WebKit as a normal browser project.

API stability3/5Core commands such as `visit`, `get`, `contains`, `intercept`, `request`, fixtures, aliases, and assertions remain recognizable across the 15.x line. The runner still makes breaking changes at major boundaries, and its command queue differs from standard promise code. Version 15.21.0 deprecates `cy.exec()` and `execTimeout` in favor of `cy.task()` and `taskTimeout`, giving existing suites a clear migration but also another command contract to update.
Docs5/5The official site separates installation, configuration, command reference, retry behavior, test isolation, cross-origin work, browsers, CI providers, component adapters, TypeScript, screenshots, videos, and troubleshooting. The advanced installation page documents cache paths, mirrors, proxy variables, binary verification, and system dependencies. Trade-offs are documented too, including command scheduling and browser constraints, so readers can find limits before committing a suite.
Maintenance5/5Cypress 15.21.0 shipped on August 18, 2026, and the repository was pushed on August 25. GitHub reports 50,999 stars, 1,064 open issues and pull requests, an unarchived repository, and active work on the develop branch. The release includes a new CLI capability plus fixes for WebKit, Windows file watching, assertions, retries, environment display, and host blocking. The large open queue reflects a broad browser and framework surface, but releases remain frequent.
Ecosystem5/5npm counted 7,294,062 downloads in the latest completed week. Cypress has official component adapters, CI recipes, Docker images, reporters, browser launch hooks, plugins, and Cypress Cloud integration. The measured package includes its own TypeScript declarations and loads from both CommonJS and ESM projects. That reach lowers adoption cost, though adapters, browser versions, the cached executable, and optional Cloud workflows create more moving parts than a small test library.

Use it if

  • Frontend developers want an interactive runner where a failed command can be inspected with its DOM snapshot and network activity.
  • Tests need automatic retrying around DOM queries and assertions instead of hand-written polling loops.
  • The same team wants end-to-end tests and React, Vue, Angular, or Svelte component tests under one command model.
  • Network stubbing, browser storage control, screenshots, videos, and test isolation should be available from one runner.
Skip it if

Setup reality

We installed Cypress 15.21.0 in a clean Node 22 Bookworm container. npm finished in 25 seconds, left 162 packages using 33 MB, and reported no known vulnerabilities at any severity. The npm package declares 39 direct dependencies and no peers, contains bundled TypeScript declarations, and requires Node ^20.1.0 || ^22.0.0 || >=24.0.0. CommonJS require() and ESM import both worked. Our browser build failed in esbuild, which fits a Node-side test runner and installer rather than code meant for an application bundle.

Installing the npm package is only part of CI setup. Cypress keeps its executable in a global per-version cache and can download it during package installation. Cache the directory reported by cypress cache path, then run cypress verify in the job image. CYPRESS_CACHE_FOLDER moves that cache; CYPRESS_INSTALL_BINARY selects a mirror, local archive, URL, or disabled download. Linux containers also need the system libraries listed by Cypress. Official Cypress Docker images remove much of that OS work and make the included browser versions explicit.

The first cypress open creates a config and asks you to choose end-to-end or component testing. Put baseUrl, spec patterns, retries, timeouts, and setupNodeEvents in cypress.config.ts. Keep secrets in CYPRESS_* environment variables or CI secret storage. Values placed in config can reach browser-side test code, so do not assume the config file is a private credential boundary. Version 15.21.0 adds CYPRESS_DISABLE_GUEST_TELEMETRY for teams that also want anonymous open-mode and CLI reporting disabled.

Cypress commands are scheduled, then executed later; they are not normal promises. Return Cypress chains from helpers, use aliases to share yielded values, and put operating-system work in cy.task(). The current release deprecates cy.exec(). Cross-origin flows need cy.origin(), and cached login state belongs in cy.session(). Parallel recording, load balancing, and historical run features are Cypress Cloud concerns, so decide early whether local CI sharding is enough.

Patterns

Set the application URL and retries configure-e2e

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    retries: { runMode: 2, openMode: 0 },
    setupNodeEvents(on, config) {
      return config
    },
  },
})

Start the application before `cypress run`. Retries rerun a failed test, while individual queries retry within their command timeout.

Submit a login form test-user-flow

describe('sign in', () => {
  it('opens the account page', () => {
    cy.visit('/login')
    cy.get('[data-cy=email]').type('ada@example.com')
    cy.get('[data-cy=password]').type('correct horse battery staple', { log: false })
    cy.get('[data-cy=submit]').click()
    cy.url().should('include', '/account')
  })
})

Cypress retries `get` and the URL assertion. `{ log: false }` keeps the typed password out of the Command Log.

Replace a network response stub-api-response

cy.intercept('GET', '/api/projects', {
  statusCode: 200,
  body: [{ id: 7, name: 'Atlas' }],
}).as('projects')

cy.visit('/projects')
cy.wait('@projects').its('response.statusCode').should('eq', 200)
cy.contains('Atlas').should('be.visible')

Register intercept before the application sends the request. This tests the UI contract without exercising the real API.

Wait for an application request inspect-real-request

cy.intercept('POST', '/api/orders').as('createOrder')
cy.get('[data-cy=buy]').click()
cy.wait('@createOrder').then(({ request, response }) => {
  expect(request.body.quantity).to.eq(2)
  expect(response?.statusCode).to.eq(201)
})

An intercept without a static response observes the real request and response.

Reuse authenticated browser state cache-login-session

beforeEach(() => {
  cy.session('admin', () => {
    cy.request('POST', '/api/login', { email: 'admin@example.com', password: Cypress.env('ADMIN_PASSWORD') })
  }, {
    validate() {
      cy.request('/api/me').its('status').should('eq', 200)
    },
  })
})

The setup must create cookies or storage that Cypress can restore. Validation prevents reuse of an expired session.

Complete a second-origin step test-cross-origin

cy.visit('/connect')
cy.contains('Continue').click()
cy.origin('https://login.example.net', { args: { email: 'ada@example.com' } }, ({ email }) => {
  cy.get('input[type=email]').type(email)
  cy.get('button[type=submit]').click()
})

Values passed into `cy.origin()` must be serializable. Commands in the callback execute against the named origin.

Load stable test data read-fixture

cy.fixture('users/ada.json').then((user) => {
  cy.intercept('GET', '/api/me', { body: user })
})

Fixture files live under the configured fixtures folder. Register the route before visiting code that calls it.

Move privileged work to Node run-node-task

// cypress.config.ts
setupNodeEvents(on, config) {
  on('task', {
    seedDatabase(name: string) {
      return seedDatabase(name).then(() => null)
    },
  })
  return config
}

// spec
cy.task('seedDatabase', 'empty-account')

A task must return a serializable value or promise and cannot resolve to undefined. Cypress 15.21.0 recommends tasks over deprecated `cy.exec()`.

Advance an application timer control-time

cy.clock(new Date('2026-08-25T12:00:00Z').getTime())
cy.visit('/countdown')
cy.tick(60_000)
cy.contains('Time expired').should('be.visible')

Call `cy.clock()` before application timers are created. Version 15.21.0 updates the faked performance object through newer fake timers.

Keep an assertion in the query chain retry-custom-check

cy.get('[data-cy=total]')
  .should('be.visible')
  .and('have.text', '$42.00')

Queries and attached assertions retry together. Extracting the element into a plain variable would lose that retry behavior.

Create a typed login command add-custom-command

// cypress/support/commands.ts
Cypress.Commands.add('loginByApi', (email: string, password: string) => {
  return cy.request('POST', '/api/login', { email, password })
})

// cypress/support/index.d.ts
declare global {
  namespace Cypress {
    interface Chainable {
      loginByApi(email: string, password: string): Chainable<Response<unknown>>
    }
  }
}
export {}

Load the command file from the support entry. Keep the declaration in TypeScript's included files.

Exercise a React component mount-react-component

import { mount } from 'cypress/react'
import { Counter } from './Counter'

describe('<Counter />', () => {
  it('increments', () => {
    mount(<Counter initial={1} />)
    cy.contains('button', 'Increase').click()
    cy.contains('output', '2').should('be.visible')
  })
})

Component testing needs the matching Cypress framework adapter and dev-server configuration selected during setup.

Alternatives

PackageRegistryPick it when
playwrightnpmChoose it for first-class Chromium, Firefox, and WebKit projects plus popup and multi-page control.
webdriverionpmChoose it for WebDriver or Appium ecosystems, including native-mobile automation.
puppeteernpmChoose it for browser scripting, scraping, and targeted Chrome or Firefox checks without Cypress's test UI.

More testing guides

pytest · chai · vitest · jsdom · playwright · coverage · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.