Testland
Browse all skills & agents

cypress-testing

Authors and improves Cypress E2E tests - installs Cypress, configures `cypress.config.ts`, authors `cy.*` command chains, refactors existing specs (`cy.wait(ms)` sleeps into assertions, repeated flows into `cy.session` custom commands), and debugs with the time-travel GUI; Cypress Cloud for parallel runs and recording. Use for both greenfield test authoring and improving hand-written specs already in the codebase. For automated refactor of raw Cypress Studio recordings specifically, use a dedicated codegen-review pass.

Install with skills.sh (any agent)

npx skills add testland/qa --skill cypress-testing
View source

cypress-testing

Overview

Per cy-overview (opens in new window):

"Cypress is described as 'a next generation front end testing tool built for the modern web.'"

Differentiators (cy-overview (opens in new window)):

  • Time Travel Debugging: "Cypress takes snapshots as your tests run. Hover over commands in the Command Log to see exactly what happened at each step."
  • Automatic Waiting: "Never add waits or sleeps to your tests. Cypress automatically waits for commands and assertions before moving on."
  • Reliability: "The testing approach avoids Selenium/WebDriver architecture, resulting in fast, consistent and reliable tests that are flake-free."

When to use

  • The team has invested in Cypress; a migration is unlikely.
  • The test author values the time-travel debugger / GUI experience.
  • Component testing is needed (Cypress supports React / Angular / Vue / Svelte component testing).
  • Single-browser focus is acceptable (Chromium-first; Firefox / Edge supported but secondary).

For cross-browser including WebKit, see playwright-testing.

How to use

  1. Install Cypress and scaffold the project (npm install --save-dev cypress, npx cypress open).
  2. Set baseUrl, specPattern, and retries in cypress.config.ts.
  3. Add @testing-library/cypress so specs select by role / label, not by CSS class.
  4. Author each flow as a describe / it block; lean on auto-waiting assertions instead of cy.wait(ms).
  5. Extract repeated auth into a cy.session-backed custom command called from beforeEach.
  6. Run headless in CI (npx cypress run); debug failures by replaying commands in the time-travel GUI.
  7. For scale, record + parallelize via Cypress Cloud and upload screenshot artifacts on failure (see references/ci-and-cloud.md).

Step 1 - Install

npm install --save-dev cypress
npx cypress open   # first run scaffolds the project

The interactive setup creates cypress.config.ts + cypress/ directory.

Step 2 - Configure

// cypress.config.ts
import { defineConfig } from 'cypress';

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    specPattern: 'cypress/e2e/**/*.cy.{ts,tsx}',
    video: true,
    screenshotOnRunFailure: true,
    retries: { runMode: 2, openMode: 0 },
  },
  component: {
    devServer: {
      framework: 'react',
      bundler: 'vite',
    },
  },
});

Step 3 - Author E2E tests

// cypress/e2e/checkout.cy.ts
describe('Checkout flow', () => {
  beforeEach(() => {
    cy.visit('/login');
    cy.get('[data-testid="email"]').type('user@example.com');
    cy.get('[data-testid="password"]').type('test-password');
    cy.get('[data-testid="signin-btn"]').click();
    cy.contains('Welcome').should('be.visible');
  });

  it('completes checkout end-to-end', () => {
    cy.visit('/products/BOOK-001');
    cy.contains('button', /add to cart/i).click();
    cy.get('[data-testid="cart-count"]').should('have.text', '1');

    cy.visit('/checkout');
    cy.get('[name="card"]').type('4242 4242 4242 4242');
    cy.contains('button', /place order/i).click();
    cy.contains('Order confirmed', { timeout: 10000 }).should('be.visible');
  });
});

Per cy-overview (opens in new window), assertions auto-wait - no cy.wait(2000) needed.

Step 4 - Use cypress-testing-library

For accessibility-first selectors:

npm install --save-dev @testing-library/cypress
// cypress/support/commands.ts
import '@testing-library/cypress/add-commands';

// Now in tests:
cy.findByRole('button', { name: /sign in/i }).click();
cy.findByLabelText('Email').type('user@example.com');

findByRole (from cypress-testing-library) is the Cypress equivalent of Playwright's getByRole - preferred for accessibility-aware testing.

Step 5 - Custom commands

// cypress/support/commands.ts
declare global {
  namespace Cypress {
    interface Chainable {
      login(email: string, password: string): Chainable<void>;
    }
  }
}

Cypress.Commands.add('login', (email, password) => {
  cy.session([email, password], () => {
    cy.visit('/login');
    cy.findByLabelText('Email').type(email);
    cy.findByLabelText('Password').type(password);
    cy.findByRole('button', { name: /sign in/i }).click();
    cy.url().should('not.include', '/login');
  });
});

// Usage in tests:
beforeEach(() => {
  cy.login('user@example.com', 'pwd');
});

cy.session(...) caches the auth state across tests - reuse the login result, avoid re-running the login flow.

Step 6 - Run

# Open the GUI (interactive; great for development)
npx cypress open

# Headless (CI)
npx cypress run

# Single spec
npx cypress run --spec "cypress/e2e/checkout.cy.ts"

# Specific browser
npx cypress run --browser firefox
npx cypress run --browser chrome

Step 7 - Time-travel debugger

Per cy-overview (opens in new window): "Hover over commands in the Command Log to see exactly what happened at each step."

In cypress open mode:

  1. Run a test.
  2. Hover over commands in the left-side log.
  3. See the DOM snapshot for each step in the main browser pane.
  4. Click a command → freeze the state for inspection.

This is Cypress's killer feature - debugging by visually replaying the test.

Step 8 - Cypress Cloud + CI

Recording and parallel runs go through Cypress Cloud (paid; OSS alternative currents-integration in the qa-test-reporting plugin), and the GitHub Actions job wires cypress-io/github-action + screenshot artifacts on failure. Commands and the full workflow YAML: references/ci-and-cloud.md.

Worked example

A team has a hand-written checkout.cy.ts that logs in from scratch in every test and sleeps cy.wait(3000) before asserting the cart count. It flakes about 1 run in 5 on CI.

  1. The login block moves into a login custom command wrapped in cy.session(['user@example.com', pwd], ...), called from beforeEach - the auth flow now runs once and is cached.
  2. cy.wait(3000) is deleted; the check becomes cy.get('[data-testid="cart-count"]').should('have.text', '1'), which auto-retries until the count settles.
  3. CSS-class selectors like cy.get('.signin-btn') are replaced with cy.findByRole('button', { name: /sign in/i }) via cypress-testing-library.
  4. npx cypress run --spec cypress/e2e/checkout.cy.ts is green 20/20 locally; the GitHub Actions job records the run to Cypress Cloud.

Result: the flow runs faster (login cached, no fixed sleep) and the flake disappears because every wait is now assertion-driven.

Anti-patterns

Anti-patternWhy it failsFix
cy.wait(2000) between actionsDefeats Cypress's auto-wait; flaky.Trust assertions; chain commands.
cy.get('.button-class') (CSS class)Brittle; defeats findByRole patterns.cypress-testing-library + data-testid (Steps 3-4).
Cross-test state via global variablesTests order-dependent.cy.session() for auth; per-test fresh state.
Mixing Cypress + plain xUnit assertionsConfusing; two assertion styles.Cypress chains throughout.
Running Cypress against productionCypress can mutate state; pollutes prod data.Local / staging only.

Limitations

  • Single-browser-process architecture. Per cy-overview (opens in new window): "avoids Selenium/WebDriver architecture" - but this also means no native multi-domain testing (workarounds exist).
  • Same-tab restriction. Originally Cypress only tested same-tab; multi-tab support added later but with caveats.
  • No native mobile. Mobile via emulation only; for native, see appium-testing (in the qa-mobile plugin).
  • Cypress Cloud is paid. OSS-budget teams use currents-integration.

References

  • cy (opens in new window) - Cypress overview, key features (time-travel, automatic waiting, native browser access), three test types (E2E, component, accessibility).
  • playwright-testing, selenium-testing, webdriverio-testing - alternative E2E frameworks.
  • currents-integration - OSS analytics alternative to Cypress Cloud.

Cypress Cloud + CI integration

View source (opens in new window)

Cypress Cloud + CI integration

Operational detail split out of cypress-testing. The core authoring loop (config, specs, custom commands, the time-travel debugger) stays in SKILL.md; this file holds the recording / parallelization and the CI wiring.

Cypress Cloud (paid; optional)

# Record run to Cypress Cloud
npx cypress run --record --key <CYPRESS_RECORD_KEY>

# Parallel
npx cypress run --record --parallel

Cloud provides:

  • Parallel execution across N CI jobs.
  • Recording (replay any test from anywhere).
  • Per-test analytics.
  • Flaky-test detection.

OSS alternative: currents-integration (in the qa-test-reporting plugin) covers similar analytics for both Cypress + Playwright.

CI integration (GitHub Actions)

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: cypress-io/github-action@v6
        with:
          start: npm start
          wait-on: 'http://localhost:3000'
          browser: chrome
          record: true
        env:
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: cypress-screenshots
          path: cypress/screenshots

Related skills

browserstack-automate

Author and run E2E tests on BrowserStack Automate - cloud grid covering 3000+ real device + browser combinations. Covers BROWSERSTACK_USERNAME + ACCESS_KEY auth, hub URL https://hub-cloud.browserstack.com/wd/hub, W3C capabilities + bstack:options (projectName, buildName, sessionName), BrowserStackLocal for testing against localhost / internal environments, parallel session limits, and CI integration. Use for cross-browser regression on real devices + browsers - distinct from running a single test framework locally, and from a matrix runner limited to the browser engines bundled on the local machine.

lambdatest-automate

Author and run E2E tests on LambdaTest - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers LT_USERNAME + LT_ACCESS_KEY auth, hub URL hub.lambdatest.com/wd/hub, W3C capabilities + LT:Options dict (build, name, project, smartUI, network, console, video, tunnel), LambdaTest Tunnel for internal apps. Use for cross-browser regression with LambdaTest as the cloud grid; complements BrowserStack + Sauce Labs.

playwright-testing

Authors and remediates Playwright E2E tests across Chromium, Firefox, WebKit - `npm init playwright@latest` scaffolding, `playwright.config.ts` browser projects, accessibility-first locators (`getByRole`/`getByLabelText`) to replace brittle CSS selectors, web-first assertions to eliminate `waitForTimeout` flakiness, Page Object pattern, trace viewer debugging, sharded parallel execution with merged HTML reporting, and GitHub Actions CI integration. Use for new test authoring, flakiness remediation, and CI setup; for reviewing codegen output specifically, use a dedicated codegen-review pass.

puppeteer-testing

Authors browser automation scripts using Puppeteer - Chrome / Chromium-only headless / headed automation, Page object via `page.*` API, network interception, PDF generation, screenshot capture, scraping. Distinct from Playwright (Puppeteer's older sibling, Chrome-only) - use Puppeteer for Chrome-only browser automation tasks (scraping, generating PDFs from HTML, screenshot pipelines) where Playwright's multi-browser support is unneeded overhead. Use when a project already depends on `puppeteer` / `puppeteer-core`, or when a Chrome-only script must emit PDFs, screenshots, or scraped data rather than assert on a page.

saucelabs-automate

Author and run E2E tests on Sauce Labs - cloud grid for cross-browser + real-device testing with W3C WebDriver, Cypress, Playwright, and Appium support. Covers SAUCE_USERNAME + SAUCE_ACCESS_KEY auth, regional hub URLs (us-west-1 / us-east-4 / eu-central-1), W3C capabilities, sauce:options dict (build, name, screenResolution, tunnelName), Sauce Connect Proxy for internal-environment testing. Use for cross-browser regression with Sauce Labs as the cloud grid; complements BrowserStack + LambdaTest as alternative providers.

selenium-testing

Authors Selenium WebDriver tests in any of its 6+ supported languages (Java, Python, JavaScript, C#, Ruby, Kotlin, PHP) - picks the appropriate language binding, configures WebDriver per browser, uses `By.*` locators with the team's accessibility-first preference where supported, runs locally + via Selenium Grid for distributed execution, parses results to JUnit XML. Use for legacy Selenium-locked stacks; new projects pick Playwright or Cypress.

testcafe-testing

Authors TestCafe E2E tests - `npm install testcafe`, fixture/test syntax, `Selector` API for queries, automatic-waits, no WebDriver required (TestCafe injects scripts via a proxy), supports any browser including remote / cloud farms. Use when the team prefers a no-WebDriver architecture and one of TestCafe's specific features (e.g., role-based auth) matters.

web-e2e-overview

Teaches web end-to-end testing from first principles: what browser-driven E2E covers and how it differs from unit and integration tests, a decision table for choosing between Playwright, Cypress, Selenium WebDriver, WebdriverIO, Puppeteer, TestCafe and the BrowserStack / Sauce Labs / LambdaTest cloud grids based on files already present in the repo, install and first-run commands for each, and the flakiness traps (fixed sleeps, CSS and XPath selectors, state shared between tests) that sink new suites. Use when a web application has no E2E coverage yet, when picking or replacing an E2E framework, or when a first browser test needs to go green end to end.

webdriverio-testing

Authors WebdriverIO E2E tests - `npm init wdio@latest` scaffolding, services architecture (sauce, browserstack, appium, devtools), reporters (spec, allure, junit), built-in Mocha/Jasmine/Cucumber framework integrations. WebdriverIO sits between Selenium (W3C protocol) and Playwright (modern API) - Selenium-protocol-compatible with rich plugin ecosystem. Use when the team needs WebDriver protocol + service-based device-farm integration.