Receber por email
← Voltar para o catálogo

cypress-testing

Use this skill when writing Cypress e2e or component tests, creating custom commands, intercepting network requests, or integrating Cypress in CI. Triggers on Cypress, cy.get, cy.intercept, cypress component testing, custom commands, fixtures, cypress-cucumber, and any task requiring Cypress test automation.

185estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add AbsolutelySkilled/AbsolutelySkilled

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/cypress-testing/svg)](https://www.skillteca.com.br/skills/cypress-testing)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

When this skill is activated, always start your first response with the 🧢 emoji.

Cypress Testing

Cypress is a modern, developer-first end-to-end and component testing framework that runs directly in the browser. Unlike Selenium-based tools, Cypress operates inside the browser's execution context, giving it native access to the DOM, network layer, and application state. This skill covers writing reliable e2e tests, component tests, custom commands, network interception, auth strategies, and CI integration.

When to use this skill

Trigger this skill when the user:

  • Asks to write or debug a Cypress e2e test
  • Wants to set up Cypress component testing
  • Needs to intercept or stub network requests with cy.intercept
  • Asks how to use cy.get, cy.contains, or other Cypress commands
  • Wants to create reusable custom Cypress commands
  • Asks about fixtures, aliases, or the Cypress command queue
  • Is integrating Cypress into a GitHub Actions or other CI pipeline

Do NOT trigger this skill for:

  • Unit testing with Jest, Vitest, or similar (those don't use the Cypress runner)
  • Playwright or Puppeteer test authoring (different APIs entirely)

Key principles

  1. Never use arbitrary waits - cy.wait(2000) is a smell. Use cy.intercept aliases

(cy.wait('@alias')), cy.contains, or assertion retries. Cypress retries automatically for up to 4 seconds by default.

  1. Select by data-testid - Never select by CSS class, tag name, or text that

changes. Add data-testid="submit-btn" to elements and select with cy.get('[data-testid="submit-btn"]'). Classes are for styling; test IDs are for testing.

  1. Intercept network requests - never hit real APIs - Use cy.intercept to stub

all HTTP calls. Real API calls make tests slow, flaky, and environment-dependent. Stub responses with fixtures or inline JSON.

  1. Each test must be independent - Tests must not share state. Use beforeEach

to reset state, reseed fixtures, and re-stub routes. Never rely on test execution order. A test that only passes after another test ran is a bug.

  1. Use custom commands for reuse - Repeated multi-step setups (login, seed data,

navigate to a page) belong in cypress/support/commands.ts, not duplicated across spec files. Custom commands keep specs readable and DRY.

Core concepts

Command queue and chaining - Cypress commands are not synchronous. Each cy.* call enqueues a command that runs asynchronously. You cannot use const el = cy.get() and then use el later. Instead, chain commands: cy.get('.item').click().should('...'). Never mix async/await with Cypress commands - it breaks the queue.

Retry-ability - Cypress automatically retries cy.get, cy.contains, and most assertions until they pass or the timeout is exceeded. This is the correct alternative to cy.wait(N). Structure assertions so they express the desired end state; Cypress will poll until it's reached.

Intercept vs stub - cy.intercept(method, url) passively observes traffic. cy.intercept(method, url, response) stubs the response. Both return a route that can be aliased with .as('alias') and waited on with cy.wait('@alias'), which blocks until the matching request fires - the correct way to synchronize on async operations.

Component vs e2e - Component testing mounts a single component in isolation (like Storybook but with assertions). E2e testing visits a full running app in a real browser. Use component tests for UI logic and edge-case rendering; use e2e tests for critical user journeys. They use different cypress.config.ts specPattern entries.

Common tasks

Write a page object pattern test

The Page Object pattern encapsulates selectors and actions behind readable methods, decoupling tests from DOM structure.

// cypress/pages/LoginPage.ts
export class LoginPage {
  visit() {
    cy.visit('/login');
  }

  fillEmail(email: string) {
    cy.get('[data-testid="email-input"]').clear().type(email);
  }

  fillPassword(password: string) {
    cy.get('[data-testid="password-input"]').clear().type(password);
  }

  submit() {
    cy.get('[data-testid="login-btn"]').click();
  }

  errorMessage() {
    return cy.get('[data-testid="login-error"]');
  }
}

// cypress/e2e/login.cy.ts
import { LoginPage } from '../pages/LoginPage';

const login = new LoginPage();

describe('Login', () => {
  beforeEach(() => {
    cy.intercept('POST', '/api/auth/login').as('loginRequest');
    login.visit();
  });

  it('redirects to dashboard on valid credentials', () => {
    cy.intercept('POST', '/api/auth/login', { fixture: 'auth/success.json' }).as('loginRequest');
    login.fillEmail('user@example.com');
    login.fillPassword('password123');
    login.submit();
    cy.wait('@loginRequest');
    cy.url().should('include', '/dashboard');
  });

  it('shows error on invalid credentials', () => {
    cy.intercept('POST', '/api/auth/login', { statusCode: 401, body: { error: 'Invalid credentials' } }).as('loginRequest');
    login.fillEmail('wrong@example.com');
    login.fillPassword('wrongpass');
    login.submit();
    cy.wait('@loginRequest');
    login.errorMessage().should('be.visible').and('contain', 'Invalid credentials');
  });
});

Intercept and stub API responses

// cypress/fixtures/products.json
// { "items": [{ "id": 1, "name": "Widget", "price": 9.99 }] }

describe('Product listing', () => {
  it('renders products from API', () => {
    cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('getProducts');
    cy.visit('/products');
    cy.wait('@getProducts');
    cy.get('[data-testid="product-card"]').should('have.length', 1);
    cy.contains('Widget').should('be.visible');
  });

  it('shows empty state when no products', () => {
    cy.intercept('GET', '/api/products', { body: { items: [] } }).as('getProducts');
    cy.visit('/products');
    cy.wait('@getProducts');
    cy.get('[data-testid="empty-state"]').should('be.visible');
  });

  it('shows error state on 500', () => {
    cy.intercept('GET', '/api/products', { statusCode: 500 }).as('getProducts');
    cy.visit('/products');
    cy.wait('@getProducts');
    cy.get('[data-testid="error-banner"]').should('be.visible');
  });
});

Create custom commands with TypeScript

// cypress/support/commands.ts
Cypress.Commands.add('login', (email: string, password: string) => {
  cy.session(
    [email, password],
    () => {
      cy.request('POST', '/api/auth/login', { email, password })
        .its('body.token')
        .then((token) => {
          window.localStorage.setItem('auth_token', token);
        });
    },
    { cacheAcrossSpecs: true }
  );
});

Cypress.Commands.add('dataCy', (selector: string) => {
  return cy.get(`[data-testid="${selector}"]`);
});

// cypress/support/index.d.ts
declare namespace Cypress {
  interface Chainable {
    login(email: string, password: string): Chainable<void>;
    dataCy(selector: string): Chainable<JQuery<HTMLElement>>;
  }
}

// Usage in spec
cy.login('user@example.com', 'password123');
cy.dataCy('submit-btn').click();

Component testing setup

// cypress.config.ts
import { defineConfig } from 'cypress';
import { devServer } from '@cypress/vite-dev-server';

export default defineConfig({
  component: {
    devServer: {
      framework: 'react',
      bundler: 'vite',
    },
    specPattern: 'src/**/*.cy.{ts,tsx}',
  },
});

// src/components/Button/Button.cy.tsx
import React from 'react';
import { Button } from './Button';

describe('Button', () => {
  it('calls onClick when clicked', () => {
    const onClick = cy.stub().as('onClick');
    cy.mount(<Button onClick={onClick}>Submit</Button>);
    cy.get('button').click();
    cy.get('@onClick').should('have.been.calledOnce');
  });

  it('is disabled when loading', () => {
    cy.mount(<Button loading>Submit</Button>);
    cy.get('button').should('be.dis
Compartilhar X LinkedIn