In Cypress, set a token in localStorage before test

BrowserE2e TestingCypress

Browser Problem Overview


I want to login and set a localStorage token on the client (specifically jwt)

How can I accomplish this using cy.request, as suggested in the Cypress Documentation?

Browser Solutions


Solution 1 - Browser

Here's an example of adding a command cy.login() that you can use in any Cypress test, or put in a beforeEach hook.

Cypress.Commands.add('login', () => { 
  cy.request({
    method: 'POST',
    url: 'http://localhost:3000/api/users/login',
    body: {
      user: {
        email: '[email protected]',
        password: 'jakejake',
      }
    }
  })
  .then((resp) => {
    window.localStorage.setItem('jwt', resp.body.user.token)
  })

})

Then in your test:

beforeEach(() => {
  cy.login()
})

Solution 2 - Browser

As an extra, you can also use the cypress-localstorage-commands package to persist localStorage between tests, so login request will be made only once:

In support/commands.js:

import "cypress-localstorage-commands";

Cypress.Commands.add('login', () => { 
  cy.request({
    method: 'POST',
    url: 'http://localhost:3000/api/users/login',
    body: {
      user: {
        email: '[email protected]',
        password: 'jakejake',
      }
    }
  })
  .its('body')
  .then(body => {
    cy.setLocalStorage("jwt", body.user.token);
  })
});

Then, in your tests:

before(() => {
  cy.login();
  cy.saveLocalStorage();
});

beforeEach(() => {
  cy.restoreLocalStorage();
});

Solution 3 - Browser

I've used something along the lines of bkuceras answer for a while now. Recently I've run into an issue when testing multiple roles/logins throughout tests. Basically what is happening is I log in as an admin and do one test, then I log in as a non admin and do a second test. The first test runs fine and ends (cypress clears local storage) however there are still some xhr requests running from the first test when the second test starts. These xhr requests no longer see the token which triggers my app to see a 401 unauthorized error and clear local storage (including my non admin token I have set). Now the 2nd test fails because that non admin token is not available in local storage.

Ultimately my solution was to prefetch the token before the test then set the token in the onBeforeLoad function of visit. This ensures the token is not cleared by any race condition before your visit command.

cy.visit('/app', {
    onBeforeLoad: function (window) {
        window.localStorage.setItem('token', myToken);
    }
})

Really this is a pretty unique edge case, but heres hoping it may help someone as I've spent many hours finding this solution.

Solution 4 - Browser

If you are open for the experimental mode, I highly recommend to use the cy.session to store the token:

Cypress.Commands.add('login', (username, password) => {
  cy.session([username, password], () => {
    cy.request({
      method: 'POST',
      url: '/login',
      body: { username, password },
    }).then(({ body }) => {
      window.localStorage.setItem('authToken', body.token)
    })
  })
})

For more information, please check the official cypress documentation: https://docs.cypress.io/api/commands/session

Solution 5 - Browser

I think that title should be updated for this topic. JWT token is main potin for this discussion!

The main question was about JWT token but in general, all modern applications are using OIDC Microsoft article - v2-protocols-oidc / ADAL and here is a very tricky situation to get an access using just generating tokens by API call. I found here that enter image description here and will check it with my app. But be sure that you are cool in JS and have good assistance from your DevTeam ;)

Solution 6 - Browser

I have spent so many hours on this and finally I can safely conclude that it will never work for OAuth requests.

It may work for local server but not when you getting token for authentication.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkucebView Question on Stackoverflow
Solution 1 - BrowserkucebView Answer on Stackoverflow
Solution 2 - BrowserJavier BreaView Answer on Stackoverflow
Solution 3 - BrowserLLaiView Answer on Stackoverflow
Solution 4 - BrowserMárk DénesView Answer on Stackoverflow
Solution 5 - BrowserRoman DenisenkoView Answer on Stackoverflow
Solution 6 - Browserapj585View Answer on Stackoverflow