【问题标题】:Preserve cookies / localStorage session across tests in Cypress在赛普拉斯的测试中保留 cookie / localStorage 会话
【发布时间】:2018-05-22 15:09:48
【问题描述】:

我想保存/持久化/保留由 cy.request() 设置的 cookie 或 localStorage 令牌,这样我就不必使用自定义命令登录每个测试。这应该适用于存储在客户端 localStorage 中的 jwt(json Web 令牌)之类的令牌。

【问题讨论】:

    标签: cookies token cypress


    【解决方案1】:

    要更新此线程,已经有更好的解决方案可用于保存 cookie(@bkucera);但是现在有一种解决方法可以在测试之间保存和恢复本地存储(以备不时之需)。我最近遇到了这个问题;并发现此解决方案有效。

    此解决方案是使用辅助命令并在测试中使用它们,

    内部 - cypress/support/<some_command>.js

    let LOCAL_STORAGE_MEMORY = {};
    
    Cypress.Commands.add("saveLocalStorage", () => {
      Object.keys(localStorage).forEach(key => {
        LOCAL_STORAGE_MEMORY[key] = localStorage[key];
      });
    });
    
    Cypress.Commands.add("restoreLocalStorage", () => {
      Object.keys(LOCAL_STORAGE_MEMORY).forEach(key => {
        localStorage.setItem(key, LOCAL_STORAGE_MEMORY[key]);
      });
    });
    

    然后在测试中,

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

    参考:https://github.com/cypress-io/cypress/issues/461#issuecomment-392070888

    【讨论】:

    • 我确实这样做了,但它对我不起作用:(我看到每次测试后钥匙都消失了
    【解决方案2】:

    来自赛普拉斯docs

    对于持久性 cookie:默认情况下,赛普拉斯会在每次测试之前自动清除所有 cookie,以防止状态建立。

    您可以使用 Cypress.Cookies api 配置要在测试中保留的特定 cookie:

    // now any cookie with the name 'session_id' will
    // not be cleared before each test runs
    Cypress.Cookies.defaults({
      preserve: "session_id"
    })
    

    注意:在 Cypress v5.0 之前,配置键是“白名单”,而不是“保留”。

    用于持久化 localStorage:它不是内置在 ATM 中的,但您现在可以手动实现它,因为清除本地存储的方法公开公开为 Cypress.LocalStorage.clear。

    您可以备份此方法并根据发送的密钥覆盖它。

    const clear = Cypress.LocalStorage.clear
    
    Cypress.LocalStorage.clear = function (keys, ls, rs) {
      // do something with the keys here
      if (keys) {
        return clear.apply(this, arguments)
      }
    
    }
    

    【讨论】:

    • 感谢对我来说也很好,现在在测试运行期间节省了大量时间
    • 注意:对于 cookie,现在似乎是 preserve 而不是 whitelist
    • 我很抱歉这里的新手:那么我应该在哪里包含这个方法?在 command.js 文件中?我怎么用它说,添加一个特定的键?谢谢
    【解决方案3】:

    您可以将自己的登录命令添加到 Cypress,并使用 cypress-localstorage-commands 包在测试之间持久化 localStorage。

    support/commands:

    import "cypress-localstorage-commands";
    
    Cypress.Commands.add('loginAs', (UserEmail, UserPwd) => {
      cy.request({
        method: 'POST',
        url: "/loginWithToken",
        body: {
          user: {
            email: UserEmail,
            password: UserPwd,
          }
        }
      })
        .its('body')
        .then((body) => {
          cy.setLocalStorage("accessToken", body.accessToken);
          cy.setLocalStorage("refreshToken", body.refreshToken);
        });
    });
    

    在您的测试中:

    describe("when user FOO is logged in", ()=> {
      before(() => {
        cy.loginAs("foo@foo.com", "fooPassword");
        cy.saveLocalStorage();
      });
    
      beforeEach(() => {
        cy.visit("/your-private-page");
        cy.restoreLocalStorage();
      });
    
      it('should exist accessToken in localStorage', () => {
        cy.getLocalStorage("accessToken").should("exist");
      });
    
      it('should exist refreshToken in localStorage', () => {
        cy.getLocalStorage("refreshToken").should("exist");
      });
    });
    

    【讨论】:

      【解决方案4】:

      这是对我有用的解决方案:

       Cypress.LocalStorage.clear = function (keys, ls, rs) {
          return;
      
       before(() => {
          LocalStorage.clear();
          Login();
        })
      

      Cypress 支持 cookie 清除控制:https://docs.cypress.io/api/cypress-api/cookies.html

      【讨论】:

      • 你能解释一下这个解决方案是如何解决这个问题的吗? stackoverflow.com/help/how-to-answer
      • 每个规范都有一个 describe() 包含一系列测试,开始时只有一次登录。每个测试都在一个 it() 中,我们希望在使用 JWT 登录时在 it() 之间保留 DOM 和 localStorage。
      • 请将其添加到您的答案中。
      • 这只是部分答案,您的函数缺少很多信息并且不完整。也许更新以显示整个过程。
      【解决方案5】:

      我不确定本地存储,但对于 cookie,我最终做了以下操作以在测试之间存储所有 cookie一次

      beforeEach(function () {
        cy.getCookies().then(cookies => {
          const namesOfCookies = cookies.map(c => c.name)
          Cypress.Cookies.preserveOnce(...namesOfCookies)
        })
      })
      

      根据文档,Cypress.Cookies.defaults 将维护此后每次测试运行的更改。在我看来,这并不理想,因为这会增加测试套件的耦合度。

      我在这个赛普拉斯问题中添加了更强大的响应:https://github.com/cypress-io/cypress/issues/959#issuecomment-828077512

      我知道这是一个老问题,但我想以任何一种方式分享我的解决方案,以防有人需要。

      【讨论】:

        【解决方案6】:

        为了保存一个 google token cookie,有一个库叫做 柏树社交登录
        似乎有其他 OAuth 提供者作为里程碑。
        它是 cypress 团队推荐的,可以在 cypress 插件页面上找到。

        https://github.com/lirantal/cypress-social-logins

        此赛普拉斯库使执行第三方登录成为可能 (想想 oauth)用于 GitHub、Google 或 Facebook 等服务。

        它通过将登录过程委托给 puppeteer 流程​​来实现 执行登录并返回应用程序的 cookie 测试,以便它们可以在持续时间内由调用赛普拉斯流程设置 测试。

        【讨论】:

          【解决方案7】:

          我可以看到使用白名单的建议。但它似乎在cypress run 期间不起作用。 分别在 before() 和 beforeEach() 中尝试了以下方法:

          Cypress.Cookies.defaults({
            whitelist: "token"
          })
          

          Cypress.Cookies.preserveOnce('token');
          

          但似乎没有一个工作。但是在 cypress open 即 GUI 模式下,这两种方法都可以正常工作。我有什么不足的地方吗?

          【讨论】:

            猜你喜欢
            • 2021-12-23
            • 2021-07-21
            • 1970-01-01
            • 1970-01-01
            • 2023-02-14
            • 1970-01-01
            • 1970-01-01
            • 2021-11-06
            • 1970-01-01
            相关资源
            最近更新 更多