Skip to content
SDETRole
SDETRole

Cypress interview question

How does test isolation work in Cypress, and how do you cache login with cy.session?

intermediate 2–5 yrs #test-isolation#cy-session#authentication#login

Short answer

With testIsolation on (the default), Cypress clears cookies, localStorage, sessionStorage and the page before each test, so tests can't depend on each other. cy.session() caches and restores a logged-in session per id, with a validate callback, so you log in once (ideally via API) without sharing state.

Answer

Test isolation

Since Cypress 12, testIsolation is true by default for end-to-end tests. Before each test Cypress:

  • navigates the page to about:blank;
  • clears cookies, localStorage and sessionStorage in all domains.

Each test therefore starts from a clean browser. That is deliberate: tests that rely on the previous test having logged in, or added an item to the cart, fail in confusing ways when run alone, in a different order, or in parallel across CI machines.

You can set testIsolation: false in the config or on a describe block, but then you are responsible for state, and a failure early in the block cascades. I would only do it for a deliberately sequential flow, and I’d still prefer one longer test over several dependent ones.

The problem isolation creates

Logging in through the UI before every test is slow and makes every test depend on the login page. The answer is cy.session().

cy.session

cy.session(id, setup, options) runs setup the first time it sees a given id, then caches the resulting cookies, localStorage and sessionStorage. On later calls with the same id, it restores the cache instead of running setup again.

// cypress/support/commands.js
Cypress.Commands.add('loginByApi', (email, password) => {
  cy.session(
    ['user', email],
    () => {
      cy.request('POST', '/api/auth/login', { email, password })
        .its('body.token')
        .then((token) => {
          window.localStorage.setItem('authToken', token);
        });
    },
    {
      validate() {
        cy.request({
          url: '/api/me',
          headers: { Authorization: `Bearer ${window.localStorage.getItem('authToken')}` },
        }).its('status').should('eq', 200);
      },
      cacheAcrossSpecs: true,
    },
  );
});
describe('orders', () => {
  beforeEach(() => {
    cy.env(['BUYER_PASSWORD']).then(({ BUYER_PASSWORD }) => cy.loginByApi('buyer@example.com', BUYER_PASSWORD));
    cy.visit('/orders');
  });

  it('lists orders', () => {
    cy.get('[data-cy=order-row]').should('exist');
  });
});

Points worth calling out:

  • The id should include anything that changes the session, such as the user, so admin and buyer sessions don’t collide.
  • validate runs after restoring. If it fails, Cypress clears the session and runs setup again, which handles expired tokens.
  • cacheAcrossSpecs shares the session between spec files in the same run.
  • After cy.session(), the page is blank, so always cy.visit() afterwards.
  • API login in setup is faster than UI login. Keep one dedicated UI test for the login page itself.
  • Read secrets with cy.env() (Cypress 15.10+; the old Cypress.env() was removed in Cypress 16) or CI secrets, never hard-code them in specs.

What interviewers look for

  • Knowing what isolation clears and why it is on by default.
  • Using cy.session with a sensible id, validate and API-based setup.
  • Not turning isolation off to “speed things up” and creating order dependence.

Common mistakes

  • Forgetting to cy.visit() after the session is restored.
  • Using a constant id for different users.
  • Logging in through the UI in every beforeEach.

A strong answer covers

  • testIsolation clears state (cookies, storage, page) before every test
  • Tests must be independent and not rely on order
  • cy.session caches and restores session by id
  • validate callback and API-based login
Practise answering under time pressure

Type to search across SDETRole.

Full-text search by Pagefind · runs in your browser Open search page →