在赛普拉斯的测试中保留 cookie / localStorage 会话

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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

【讨论】:

你能解释一下这个解决方案是如何解决这个问题的吗? ***.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 模式下,这两种方法都可以正常工作。我有什么不足的地方吗?

【讨论】:

以上是关于在赛普拉斯的测试中保留 cookie / localStorage 会话的主要内容,如果未能解决你的问题,请参考以下文章

赛普拉斯在多项测试中冻结

赛普拉斯可以运行在赛普拉斯文件夹之外导入的测试文件吗?

赛普拉斯:测试元素是不是不存在

赛普拉斯:只运行一项测试

赛普拉斯 - 如何按顺序运行测试文件

赛普拉斯/GitLab CI/CD 集成 - 赛普拉斯不会在无头模式下启动