Skip to main content

Fixtures & Custom Commands

As your test suite grows, repetition accumulates. Cypress gives you two tools to fight it: fixtures for static test data, and custom commands for repeated interaction sequences.

Fixtures

Fixtures are JSON (or other) files stored in cypress/fixtures/. Load them with cy.fixture().

// cypress/fixtures/user.json
{
  "email": "alice@example.com",
  "password": "s3cr3t",
  "name": "Alice"
}
// Use in a test
cy.fixture('user').then((user) => {
  cy.get('#email').type(user.email)
  cy.get('#password').type(user.password)
})

// Or load as an alias
cy.fixture('user').as('currentUser')
cy.get('@currentUser').then((user) => {
  cy.get('#name').should('contain', user.name)
})

Custom Commands

Add reusable commands to cypress/support/commands.js:

// cypress/support/commands.js

Cypress.Commands.add('login', (email, password) => {
  cy.session(
    [email, password],
    () => {
      cy.visit('/login')
      cy.get('#email').type(email)
      cy.get('#password').type(password)
      cy.get('[data-cy="submit"]').click()
      cy.url().should('include', '/dashboard')
    },
    {
      cacheAcrossPecs: true,
    }
  )
})

Cypress.Commands.add('loginAsAdmin', () => {
  cy.fixture('admin-user').then((user) => {
    cy.login(user.email, user.password)
  })
})

Now every test can call cy.login() instead of repeating the login flow:

describe('Dashboard', () => {
  beforeEach(() => {
    cy.login('alice@example.com', 's3cr3t')
  })

  it('shows user profile', () => {
    cy.visit('/dashboard')
    cy.get('[data-cy="username"]').should('contain', 'Alice')
  })
})

cy.session() — Session Caching

cy.session() caches the browser session (cookies, localStorage) after the first login and restores it on subsequent runs. This saves the round-trip to the login page on every test.

First test:  cy.session()  runs login flow  caches session
Second test: cy.session()  restores cache  skips login (fast)

Command Reuse Visualiser

Custom command flow
Ctrl+Enter
HTML
CSS
JS
Preview

TypeScript Declarations

If you use TypeScript, add your commands to the global Cypress interface:

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

Now cy.login() gets autocomplete and type checking in your IDE.