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 C
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.
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: 'jake@jake.jake',
password: 'jakejake',
}
}
})
.its('body')
.then(body => {
cy.setLocalStorage("jwt", body.user.token);
})
});
Then, in your tests:
before(() => {
cy.login();
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
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.
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: 'jake@jake.jake',
password: 'jakejake',
}
}
})
.then((resp) => {
window.localStorage.setItem('jwt', resp.body.user.token)
})
})
Then in your test:
beforeEach(() => {
cy.login()
})
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 and will check it with my app. But be sure that you are cool in JS and have good assistance from your DevTeam ;)