在 Cypress 中,在测试前在 localStorage 中设置一个令牌

In Cypress, set a token in localStorage before test

我想登录并在客户端设置一个 localStorage 令牌(特别是 jwt

如何按照 Cypress 文档中的建议,使用 cy.request 完成此操作?

下面是添加命令 cy.login() 的示例,您可以在任何 Cypress 测试中使用该命令,或者放入 beforeEach 挂钩。

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)
  })

})

那么在你的测试中:

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

我在这上面花了很多时间,最后我可以放心地得出结论,它永远不会对 OAuth 请求起作用。

它可能适用于本地服务器,但在您获取令牌进行身份验证时无效。

另外,您还可以使用 cypress-localstorage-commands 包在测试之间保留 localStorage,这样登录请求只会发出一次:

在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);
  })
});

然后,在你的测试中:

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

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

我已经使用了一段时间的 bkuceras 答案。最近我 运行 在整个测试过程中测试多个 roles/logins 时遇到了一个问题。基本上发生的事情是我以管理员身份登录并进行一项测试,然后我以非管理员身份登录并进行第二次测试。第一个测试 运行 很好并结束(赛普拉斯清除本地存储)但是当第二个测试开始时,第一个测试仍然有一些 xhr 请求 运行ning。这些 xhr 请求不再看到触发我的应用程序看到 401 未授权错误并清除本地存储的令牌(包括我设置的非管理员令牌)。现在第二次测试失败了,因为本地存储中没有该非管理员令牌。

最终我的解决方案是在测试前预取token,然后在visit的onBeforeLoad函数中设置token。这确保令牌不会在您的访问命令之前被任何竞争条件清除。

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

真的,这是一个非常独特的边缘案例,但希望它能对某人有所帮助,因为我花了很多时间寻找这个解决方案。

我认为应该为这个主题更新标题。 JWT 代币是本次讨论的主要内容!

主要问题是关于 JWT 令牌,但总的来说,所有现代应用程序都在使用 OIDC Microsoft article - v2-protocols-oidc / ADAL,这里是一个非常棘手的情况,仅通过 API 调用生成令牌来获取访问权限。 我发现 here 并将使用我的应用程序进行检查。但请确保您精通 JS 并得到开发团队的良好帮助 ;)

如果你是开放的实验模式,我强烈建议使用cy.session来存储令牌:

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)
    })
  })
})

更多信息请查看官方cypress文档: https://docs.cypress.io/api/commands/session