Skip to main content
rule

cypress — Cursor rule: what it does, how to install

Guides Cursor on Cypress E2E best practices, enforcing isolated tests, data-cy selectors, network interception, and session caching.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/cypress.mdc
Open on GitHub

What cypress does

This rule instructs Cursor to generate maintainable Cypress test suites across **/*.{js,ts,cy.js,cy.ts} files. It standardizes project layout around a single root cypress.config.ts, test specs in cypress/e2e, and custom helpers in cypress/support/commands.ts. Brittle selectors break when markup changes. Because of that, the rule enforces targeting elements via data-cy attributes and a reusable cy.getBySel() helper.

Instead of clicking through login forms in the UI, the agent implements programmatic authentication with cy.request() and saves sessions via cy.session(). This keeps test runs fast. It also eliminates hardcoded cy.wait() pauses that cause flaky runs. Network traffic gets intercepted with cy.intercept() and static payloads from cypress/fixtures. When testing flows that must leave the main domain, the rule requires wrapping those steps in cy.origin().

What it helps with

  • eliminate brittle CSS and DOM selectors by enforcing data-cy attributes
  • speed up authentication across specs using cy.session() and cy.request()
  • mock network calls with cy.intercept() and fixture files
  • prevent flaky tests by removing arbitrary millisecond cy.wait() calls

Example prompts for the agent

  • Write an E2E spec in cypress/e2e/checkout.cy.ts that locates form fields with data-cy
  • Add an apiLogin command in cypress/support/commands.ts using cy.session()
  • Intercept the /api/products route with cy.intercept() and return data from products.json

How to install cypress

Manually: put the files in place

.cursor/rules/cypress.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about cypress

How do I install cypress in Cursor?

Create .cursor/rules/cypress.mdc in the root of your project and paste the rule contents into the file.

What does the cypress rule do?

It guides Cursor to generate Cypress tests following established standards: isolated it blocks, data-cy selectors, request mocking with cy.intercept(), and no arbitrary sleep timers.

How does the rule handle user login?

It avoids slow UI form fills by executing programmatic logins through cy.request() and caching the authenticated state across tests with cy.session().

Source text

cypress.mdc · CC0-1.0
---
description: This guide defines definitive best practices for writing maintainable, performant, and reliable Cypress end-to-end tests, leveraging modern patterns and avoiding common pitfalls.
globs: **/*.{js,ts,cy.js,cy.ts}
---
# Cypress Best Practices

Cypress is our go-to for robust E2E testing. Follow these rules to ensure our test suite remains fast, stable, and easy to maintain.

## 1. Code Organization & Structure

Adhere to the standard Cypress folder structure. This promotes consistency and discoverability.

**Rule:** Keep a single `cypress.config.ts` at the root.
**Rule:** Place E2E tests in `cypress/e2e`.
**Rule:** Store reusable commands in `cypress/support/commands.ts`.
**Rule:** Use `cypress/fixtures` for static test data.

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

export default defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000', // Always set a global base URL
    retries: {
      runMode: 2, // Allow retries in CI for flaky tests
      openMode: 0,
    },
    setupNodeEvents(on, config) {
      // Implement cy.task() here for server-side operations
    },
  },
});
```

## 2. Test Isolation

Each test (`it` block) must be independent and not rely on the state of previous tests. This enables parallelization and makes debugging straightforward.

❌ **BAD:** Dependent tests
```typescript
// test-suite.cy.ts
describe('User Flow', () => {
  it('should register a user', () => { /* ... */ }); // Creates user
  it('should log in the registered user', () => { /* ... */ }); // Depends on previous test
});
```

✅ **GOOD:** Isolated tests using `beforeEach`
```typescript
// test-suite.cy.ts
describe('User Management', () => {
  beforeEach(() => {
    // Programmatically create user and log in via API or custom command
    cy.apiLogin('[email protected]', 'password123');
    cy.visit('/dashboard');
  });

  it('should display user dashboard', () => {
    cy.getBySel('dashboard-header').should('contain', 'Welcome, Test User');
  });

  it('should allow user to update profile', () => {
    cy.getBySel('profile-link').click();
    cy.getBySel('name-input').type('New Name');
    cy.getBySel('save-button').click();
    cy.getBySel('success-message').should('be.visible');
  });
});
```

## 3. Element Selection

Prioritize stable, test-specific attributes. This decouples selectors from styling or content changes.

**Rule:** Always use `data-cy` attributes for element selection.
**Rule:** Use `cy.contains()` only when the displayed text is critical to the test's purpose.

❌ **BAD:** Brittle selectors
```typescript
cy.get('.btn-primary').click(); // Coupled to styling
cy.get('#submitButton').click(); // Coupled to JS/CSS ID
cy.get('div:nth-child(2) > p').should('be.visible'); // Highly brittle DOM structure
```

✅ **GOOD:** Resilient selectors with `data-cy`
```typescript
// In cypress/support/commands.ts
Cypress.Commands.add('getBySel', (selector: string, ...args: any[]) => {
  return cy.get(`[data-cy="${selector}"]`, ...args);
});

// In your test file
cy.getBySel('submit-button').click(); // Best practice
cy.getBySel('user-profile-name').should('contain', 'John Doe');
cy.contains('Submit Order').click(); // Only if "Submit Order" text is critical
```

## 4. Mocking Strategies

Control external dependencies to ensure fast, reliable, and deterministic tests.

**Rule:** Use `cy.intercept()` for all network requests (XHR/Fetch).
**Rule:** Use `cy.fixture()` to provide static response data.
**Rule:** Use `cy.stub()` for client-side function mocking.
**Rule:** For server-side setup/teardown, use `cy.task()` to execute Node.js code.

❌ **BAD:** Relying on live API responses
```typescript
it('should load products', () => {
  cy.visit('/products');
  cy.get('.product-card').should('have.length.gt', 0); // Fails if API is down or slow
});
```

✅ **GOOD:** Intercepting network requests with fixtures
```typescript
it('should load products from fixture', () => {
  cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('getProducts');
  cy.visit('/products');
  cy.wait('@getProducts');
  cy.getBySel('product-card').should('have.length', 3);
});
```

## 5. Avoiding Arbitrary Waits

Cypress automatically retries assertions. Avoid `cy.wait()` unless explicitly waiting for a network request to complete.

❌ **BAD:** Arbitrary waits
```typescript
cy.get('button').click();
cy.wait(2000); // Unnecessary, slows down tests, can cause flakiness
cy.get('.success-message').should('be.visible');
```

✅ **GOOD:** Leveraging Cypress's retry-ability
```typescript
cy.getBySel('submit-button').click();
cy.getBySel('success-message').should('be.visible'); // Cypress retries until visible
```
✅ **GOOD:** Waiting for specific network requests
```typescript
cy.intercept('POST', '/api/users', { statusCode: 201 }).as('createUser');
cy.getBySel('register-form').submit();
cy.wait('@createUser').its('response.statusCode').should('eq', 201);
```

## 6. Performance & Real-world Scenarios

Optimize test execution and simulate real user interactions effectively.

**Rule:** Log in programmatically via `cy.request()` or a custom command in `beforeEach` instead of using the UI. This is significantly faster.
**Rule:** Use `cy.session()` for persistent login state across tests within a spec file, reducing redundant login calls.
**Rule:** Leverage `cy.prompt()` (available 2025) for natural language test generation and self-healing selectors.

```typescript
// cypress/support/commands.ts
Cypress.Commands.add('apiLogin', (email, password) => {
  cy.session([email, password], () => { // Cache session for faster subsequent runs
    cy.request('POST', '/api/login', { email, password })
      .its('body.token')
      .then((token) => {
        localStorage.setItem('jwt', token); // Store token for authenticated requests
      });
  }, {
    cacheAcrossSpecs: true // Cache across spec files for even faster runs
  });
});

// In your test file
describe('Authenticated Features', () => {
  beforeEach(() => {
    cy.apiLogin('[email protected]', 'password123');
    cy.visit('/dashboard');
  });
  // ... tests ...
});
```

## 7. Test Naming & Readability

Write clear, descriptive test names that explain the intent and expected outcome.

❌ **BAD:** Vague test names
```typescript
it('test 1', () => { /* ... */ });
it('login works', () => { /* ... */ });
```

✅ **GOOD:** Descriptive test names
```typescript
describe('Authentication', () => {
  it('should allow a valid user to log in and redirect to dashboard', () => { /* ... */ });
  context('when credentials are invalid', () => {
    it('should display an error message for incorrect password', () => { /* ... */ });
  });
});
```

## 8. Avoiding External Sites

Keep E2E tests focused on our application. If an external origin is unavoidable, use `cy.origin()`.

❌ **BAD:** Automating external sites directly
```typescript
cy.visit('https://our-app.com');
cy.get('.external-link').click();
cy.url().should('include', 'external-provider.com');
cy.get('#external-form').type('data'); // Unreliable, out of our control
```

✅ **GOOD:** Using `cy.origin()` for controlled external interactions
```typescript
it('should handle OAuth redirect', () => {
  cy.visit('/login');
  cy.getBySel('oauth-login-button').click();

  cy.origin('https://external-oauth.com', () => {
    cy.get('#username').type('oauth_user');
    cy.get('#password').type('oauth_pass');
    cy.get('#submit').click();
  });

  cy.url().should('include', '/dashboard'); // Back to our app
});
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

All IDE rules for Testing and QA →

From the same set240

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor