Skip to content

cy.session() in Cypress

cy.session() is one of the most impactful commands for real-world Cypress suites, caching login state so most tests never need to repeat a full login. This lesson explains how it works and how to use it correctly.

What cy.session() Does

cy.session(id, setupFunction) runs the setup function (typically a login) only once per unique session id within a test run, caching cookies, local storage, and session storage afterward. On subsequent calls with the same id, Cypress restores that cached state instantly instead of re-running the setup.

Cypress.Commands.add('loginAs', (email, password) => {
  cy.session([email, password], () => {
    cy.request('POST', '/api/login', { email, password }).then((res) => {
      window.localStorage.setItem('authToken', res.body.token);
    });
  });
});

// usage in any test
cy.loginAs('user@example.com', 'SecurePass123!');
cy.visit('/dashboard');

The first test using this session id actually logs in; every subsequent test in the run restores the cached session almost instantly.

cy.session() Syntax

cy.session(id, setupFn)
cy.session(id, setupFn, {
  validate() { /* optional: confirm the session is still valid */ },
  cacheAcrossSpecs: true,
})
  • id can be a string or an array (like [email, password]), uniquely identifying this session.
  • validate() runs before reusing a cached session, and re-runs setup if it fails.
  • cacheAcrossSpecs: true extends caching beyond a single spec file, across the whole run.
  • cy.session() automatically clears cookies/storage before running the setup function.

cy.session() Cheat Sheet

Key behaviors and options to remember when using cy.session().

Aspect Behavior
First call with a given id Runs the full setup function
Later calls with the same id Restores cached cookies/storage instantly
validate() option Confirms cached session is still valid before reuse
cacheAcrossSpecs Extends caching across multiple spec files
State restored Cookies, localStorage, and sessionStorage

Validating a Cached Session Before Reuse

Providing a validate() function lets Cypress confirm a cached session is genuinely still usable, for example, that an auth token hasn't expired, before trusting it. If validation fails, Cypress automatically re-runs the setup function instead of proceeding with a stale session.

cy.session(email, () => {
  cy.request('POST', '/api/login', { email, password: 'x' });
}, {
  validate() {
    cy.request('/api/me').its('status').should('eq', 200);
  },
});

Pairing cy.session() with beforeEach

The common, recommended pattern combines cy.session() with beforeEach(), so every test starts fully authenticated without any repeated boilerplate, and without actually re-running the login setup for every single test.

beforeEach(() => {
  cy.loginAs('user@example.com', 'SecurePass123!');
  cy.visit('/dashboard');
});

it("shows the user's recent orders", () => {
  cy.get('[data-cy="order-row"]').should('have.length.greaterThan', 0);
});

Common Mistakes

  • Using a different session id unintentionally for what should be the same cached session, defeating the caching benefit.
  • Skipping validate() for suites with short-lived tokens, leading to confusing failures from a stale, expired session.
  • Assuming cy.session() persists across entirely separate Cypress runs, it does not, only within a single run.
  • Not calling cy.visit() after restoring a session, forgetting the browser still needs to load the target page.

Key Takeaways

  • cy.session() caches authentication state, running its setup function only once per unique id.
  • It dramatically speeds up suites where most tests simply require being logged in.
  • validate() confirms a cached session is still usable before reusing it.
  • Pairing cy.session() with beforeEach() is the standard, recommended pattern.

Pro Tip

Always pass a validate() function when your authentication uses short-lived tokens, without it, a suite can silently run many tests against an expired session, producing confusing failures far from the actual root cause (an old cached token).