Search code examples
cypresse2e-testing

Localstorage is null (Cypress e2e test) using cypress-localstorage-commands


I have a react app that has login page and dashboard page. Only after login, will redirect to dashboard page. If success login, auth info tokens are stored in localstorage.

I'm trying to login once when the cypress run a test file and don't want to relogin after each test cases. so, I am using cypress-localstorage-commands, but it is not working.

cypress ver: 12.17.2 cypress-localstorage-commands ver: 2.2.4

cypress.config.ts

import { defineConfig } from "cypress";

export default defineConfig({
  e2e : {
    setupNodeEvents(on, config) {
      require("cypress-localstorage-commands/plugin")(on, config);
      return config;
    },
    env: {
      LOCAL_STORAGE_MEMORY: "true",
    },
  }
});

cypress/support/e2e.ts

import "./commands";
import 'cypress-localstorage-commands';

cypress/support/commands.ts

/// <reference types="cypress" />

declare namespace Cypress {
  interface Chainable<Subject> {
     login(email ?: string, password ?: string): Chainable<any>;
  }
}

Cypress.Commands.add("login", (email = "admin@gmail.com", password = "admin") : void => {
  cy.visit("http://localhost:3000/login");
  
  cy.get("input[name=\"email\"]").type(email);
  cy.get("input[name=\"password\"]").type(password);
  cy.get("button[type=\"submit\"]").click();

  cy.wait(3000);
});

cypress/e2e/dashboard.ts

describe("Dashboard Page", () => {
  before(() => {
    cy.clearLocalStorageSnapshot();
    cy.login();
  });
  
  beforeEach(() => {
    cy.restoreLocalStorage();
    cy.visit(ANALYTICS_PATH);
  });
  afterEach(() => {
    cy.saveLocalStorage();
  });

  it("should navigate to the dashboard page and see its content", () => {
    cy.contains("Products").should("exist");
    cy.contains("Number of Products").should("exist");
    cy.contains("Carts").should("exist");
  });
});

It successfully login and I can see my dashboard page, but, after wait(3000), it gets back to login page and occurs this error:

  • contains Products
  • assert expected undefined to exist in the DOM

Solution

  • The sequence of steps is wrong, looking at this segment

      before(() => {
        cy.clearLocalStorageSnapshot();
        cy.login();
      });
      
      beforeEach(() => {
        cy.restoreLocalStorage();
        cy.visit(ANALYTICS_PATH);
      });
    

    The login sets localstorage value(s), but you are not saving LS until afterEach().

    Seems logical to move the save to after the login

      before(() => {
        cy.clearLocalStorageSnapshot();
        cy.login();
        cy.saveLocalStorage();
      });
      
      beforeEach(() => {
        cy.restoreLocalStorage();  // now there is something to restore!
        cy.visit(ANALYTICS_PATH);
      });
    

    But cy.session() is much simpler, and you can get rid of cypress-localstorage-commands.

    beforeEach(() => {
      cy.session('login', () => {
        cy.login();
      })
    })
    

    The above will only call login once despite being in beforeEach(), because it's a caching command.

    Now you can forget about localstorage calls altogether, Cypress session command is handling it all for you.