乐闻世界logo
搜索文章和话题

Cypress 如何在执行测试代码之前在 localStorage 中设置令牌 token ?

9 个月前提问
5 个月前修改
浏览次数113

5个答案

1
2
3
4
5

在 Cypress 中,如果您想在运行测试用例之前在 localStorage 中设置令牌(token),可以使用Cypress的cy命令来实现。这通常会在beforeEach钩子中完成,以确保在每个测试运行前设置所需的状态。以下是一个示例:

javascript
describe('Token Setting in LocalStorage', () => { beforeEach(() => { cy.visit('/'); // 访问应用的初始页面 // 设置localStorage中的令牌 cy.window().then((win) => { win.localStorage.setItem('token', 'yourTokenValue'); }); }); // 这里写上测试用例 it('should have token set in localStorage', () => { // 测试localStorage中的令牌是否正确设置 cy.window().should((win) => { expect(win.localStorage.getItem('token')).to.eq('yourTokenValue'); }); }); });

在这个例子中,我们首先调用 cy.visit('/') 来加载应用程序的页面。然后,在 beforeEach 钩子中,我们通过 cy.window() 访问浏览器窗口对象,并利用该对象的 localStorage.setItem 方法来设置令牌。'yourTokenValue' 应该替换为实际的令牌值。

之后,每个 it 块中的测试用例都会在一个有令牌存在于 localStorage 的环境中运行。在测试用例中,我们还可以使用 expect 语句来确认 localStorage 中的令牌是否正确设置,这有助于验证设置操作是否成功。

请注意,有些情况下,您可能需要等待某些异步操作完成后再设置localStorage,或者您的应用程序可能在加载时清除localStorage,这时您应该确保 localStorage 在应用程序的初始化逻辑执行完毕后再进行设置。这可以通过在 cy.visit('/').then(() => { /* set localStorage here */ }) 回调中完成来确保正确的时序。

2024年6月29日 12:07 回复

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

shell
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:

shell
beforeEach(() => { cy.login() })
2024年6月29日 12:07 回复

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:

shell
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:

shell
before(() => { cy.login(); cy.saveLocalStorage(); }); beforeEach(() => { cy.restoreLocalStorage(); });
2024年6月29日 12:07 回复

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.

shell
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.

2024年6月29日 12:07 回复

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

shell
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

2024年6月29日 12:07 回复

你的答案