or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configurations.mdindex.mdrules.md
tile.json

rules.mddocs/

Lint Rules

Collection of specialized ESLint rules that detect Cypress-specific code patterns and anti-patterns. The plugin provides 12 rules categorized into problem-type rules that catch potential errors and suggestion-type rules that enforce best practices.

Capabilities

Problem-Type Rules

Rules that detect code patterns likely to cause runtime errors or unexpected behavior in Cypress tests.

assertion-before-screenshot

Requires screenshots to be preceded by an assertion to ensure test stability.

/**
 * Requires screenshots to be preceded by an assertion
 * Category: Possible Errors
 * Recommended: false
 * Type: problem
 */
'assertion-before-screenshot': ESLintRule;

Usage Example:

// ❌ Incorrect - Screenshot without preceding assertion
cy.visit('/dashboard');
cy.screenshot('dashboard');

// ✅ Correct - Screenshot preceded by assertion
cy.visit('/dashboard');
cy.get('[data-cy=header]').should('be.visible');
cy.screenshot('dashboard');

// ✅ Correct - Multiple assertions before screenshot
cy.visit('/user-profile');
cy.get('[data-cy=avatar]').should('be.visible');
cy.get('[data-cy=user-name]').should('contain', 'John Doe');
cy.screenshot('user-profile-loaded');

no-assigning-return-values

Disallows assigning return values of cy calls, as Cypress commands return chainable objects rather than actual values.

/**
 * Disallows assigning return values of cy calls
 * Category: Possible Errors
 * Recommended: true (included in recommended config)
 * Type: problem
 */
'no-assigning-return-values': ESLintRule;

Usage Example:

// ❌ Incorrect - Cypress commands don't return actual values
const text = cy.get('[data-cy=element]').text();

// ✅ Correct - Use then() to access values
cy.get('[data-cy=element]').then(($el) => {
  const text = $el.text();
});

no-async-before

Disallows using async/await in Cypress before methods, as they can cause timing issues.

/**
 * Disallows using async/await in Cypress before methods
 * Category: Possible Errors
 * Recommended: false
 * Type: problem
 */
'no-async-before': ESLintRule;

no-async-tests

Disallows using async/await in Cypress test cases, as Cypress handles asynchronous operations automatically.

/**
 * Disallows using async/await in Cypress test cases
 * Category: Possible Errors
 * Recommended: true (included in recommended config)
 * Type: problem
 */
'no-async-tests': ESLintRule;

no-unnecessary-waiting

Disallows waiting for arbitrary time periods, promoting more reliable test patterns.

/**
 * Disallows waiting for arbitrary time periods
 * Category: Possible Errors
 * Recommended: true (included in recommended config)
 * Type: problem
 */
'no-unnecessary-waiting': ESLintRule;

Usage Example:

// ❌ Incorrect - Arbitrary waiting
cy.wait(5000);

// ✅ Correct - Wait for specific conditions
cy.wait('@apiRequest');
cy.get('[data-cy=loading]').should('not.exist');

unsafe-to-chain-command

Disallows actions within chains that can cause race conditions or unreliable test behavior.

/**
 * Disallows actions within chains
 * Category: Possible Errors
 * Recommended: true (included in recommended config)
 * Type: problem
 */
'unsafe-to-chain-command': ESLintRule;

Usage Example:

// ❌ Incorrect - Actions in the middle of chains are unsafe
cy.get('[data-cy=input]')
  .clear()          // Unsafe action
  .type('new text')
  .should('have.value', 'new text');

cy.get('[data-cy=button]')
  .click()          // Unsafe action
  .should('not.exist');

// ✅ Correct - Actions at the end of chains
cy.get('[data-cy=input]').clear();
cy.get('[data-cy=input]').type('new text');
cy.get('[data-cy=input]').should('have.value', 'new text');

cy.get('[data-cy=button]').should('be.visible');
cy.get('[data-cy=button]').click();

Suggestion-Type Rules

Rules that enforce best practices and coding standards for Cypress test maintainability.

no-chained-get

Disallows chaining multiple cy.get() calls, which can lead to confusing test logic.

/**
 * Disallows chain of cy.get() calls
 * Category: (not specified)
 * Recommended: false
 * Type: problem
 */
'no-chained-get': ESLintRule;

Usage Example:

// ❌ Incorrect - Chaining multiple cy.get() calls
cy.get('[data-cy=parent]')
  .get('[data-cy=child]')
  .click();

// ✅ Correct - Use find() or within() to scope searches
cy.get('[data-cy=parent]')
  .find('[data-cy=child]')
  .click();

// ✅ Correct - Use within() for scoped operations
cy.get('[data-cy=parent]').within(() => {
  cy.get('[data-cy=child]').click();
});

// ✅ Correct - Separate get() calls for different elements
cy.get('[data-cy=parent]').should('be.visible');
cy.get('[data-cy=child]').click();

no-debug

Disallows using cy.debug() calls in production test code to prevent debugging code from being committed.

/**
 * Disallows using cy.debug() calls
 * Category: Possible Errors
 * Recommended: false
 * Type: suggestion
 */
'no-debug': ESLintRule;

no-force

Disallows using force: true with action commands, encouraging proper element interaction patterns.

/**
 * Disallows using force: true with action commands
 * Category: Possible Errors
 * Recommended: false
 * Type: suggestion
 */
'no-force': ESLintRule;

Usage Example:

// ❌ Discouraged - Using force bypasses actionability checks
cy.get('button').click({ force: true });

// ✅ Better - Ensure element is actionable
cy.get('button').should('be.visible').click();

no-pause

Disallows using cy.pause() calls to prevent debugging code from being committed to production.

/**
 * Disallows using cy.pause() calls
 * Category: Possible Errors
 * Recommended: false
 * Type: suggestion
 */
'no-pause': ESLintRule;

no-xpath

Disallows using cy.xpath() calls, encouraging the use of more maintainable CSS selectors.

/**
 * Disallows using cy.xpath() calls
 * Category: (not specified)
 * Recommended: false
 * Type: suggestion
 */
'no-xpath': ESLintRule;

require-data-selectors

Requires data-* attribute selectors to promote stable, maintainable test selectors.

/**
 * Requires data-* attribute selectors
 * Category: Possible Errors
 * Recommended: false
 * Type: suggestion
 */
'require-data-selectors': ESLintRule;

Usage Example:

// ❌ Discouraged - Fragile selectors
cy.get('.btn-primary');
cy.get('#submit-button');

// ✅ Preferred - Stable data attributes
cy.get('[data-cy=submit-button]');
cy.get('[data-testid=user-profile]');

Rule Categories

By Recommendation Status

Recommended Rules (4) - Included in configs.recommended:

  • no-assigning-return-values
  • no-async-tests
  • no-unnecessary-waiting
  • unsafe-to-chain-command

Optional Rules (8) - Available but not enabled by default:

  • assertion-before-screenshot
  • no-async-before
  • no-chained-get
  • no-debug
  • no-force
  • no-pause
  • no-xpath
  • require-data-selectors

By Rule Type

Problem Rules (7) - Detect likely errors:

  • assertion-before-screenshot
  • no-assigning-return-values
  • no-async-before
  • no-async-tests
  • no-chained-get
  • no-unnecessary-waiting
  • unsafe-to-chain-command

Suggestion Rules (5) - Enforce best practices:

  • no-debug
  • no-force
  • no-pause
  • no-xpath
  • require-data-selectors

Rule Configuration

All rules can be individually configured in ESLint configuration:

export default [
  {
    plugins: {
      cypress: pluginCypress
    },
    rules: {
      // Error level
      'cypress/no-assigning-return-values': 'error',
      
      // Warning level
      'cypress/no-unnecessary-waiting': 'warn',
      
      // Disabled
      'cypress/no-debug': 'off'
    }
  }
];