我希望能够保存/持久化/保留由 cy.request() 设置的cookie或localStorage令牌,这样我就不必在每次测试中使用自定义命令登录。这应该适用于像jwt(json web tokens)这样存储在客户端localStorage中的令牌。
更新这个线程,现在已经有了更好的解决方案来保留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
来自Cypress 文档
保留 cookie:默认情况下,Cypress 在每次测试前自动清除所有 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 之前,配置键是“whitelist”,而不是“preserve”。
用于持久化 localStorage:目前还没有内置方法,但是您可以手动实现,因为清除本地存储的方法已经作为 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)
}
}
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");
});
});
我对本地存储不确定,但是对于 cookie,我最终做了以下操作,以便在测试之间 仅一次 存储所有 cookie。
beforeEach(function () {
cy.getCookies().then(cookies => {
const namesOfCookies = cookies.map(c => c.name)
Cypress.Cookies.preserveOnce(...namesOfCookies)
})
})
Cypress.Cookies.defaults
会在此后的每个测试运行中保留更改。我认为这不是理想的做法,因为这增加了测试套件之间的耦合度。以下是对我有用的解决方案:
Cypress.LocalStorage.clear = function (keys, ls, rs) {
return;
before(() => {
LocalStorage.clear();
Login();
})
Cypress支持清除cookie的控制:https://docs.cypress.io/api/cypress-api/cookies.html
2023年更新的Cypress v12或更高版本:
自Cypress版本12以来,您可以使用新的cy.session()。
它会缓存和恢复cookies、localStorage和sessionStorage(即会话数据),以便在测试之间重新创建一致的浏览器上下文。
以下是如何使用它:
// Caching session when logging in via page visit
cy.session(name, () => {
cy.visit('/login')
cy.get('[data-test=name]').type(name)
cy.get('[data-test=password]').type('s3cr3t')
cy.get('form').contains('Log In').click()
cy.url().should('contain', '/login-successful')
})
尝试这个,这在我的情况下有效
// Save session data
let savedCookies;
let savedLocalStorage;
let savedSessionStorage;
before(() => {
// Save session data
cy.visit('https://example.com/login'); // Visit the login page
// Log in and save session data
cy.get('#username').type('your_username');
cy.get('#password').type('your_password');
cy.get('#login-button').click();
// Save cookies
cy.getCookies().then((cookies) => {
savedCookies = cookies;
});
// Save localStorage
savedLocalStorage = window.localStorage;
// Save sessionStorage
savedSessionStorage = window.sessionStorage;
});
// Restore session data
beforeEach(() => {
// Restore cookies
cy.clearCookies();
savedCookies.forEach((cookie) => {
cy.setCookie(cookie.name, cookie.value, {
domain: cookie.domain,
path: cookie.path,
secure: cookie.secure,
httpOnly: cookie.httpOnly,
expiry: cookie.expires,
});
});
// Restore localStorage
Object.keys(savedLocalStorage).forEach((key) => {
window.localStorage.setItem(key, savedLocalStorage.getItem(key));
});
// Restore sessionStorage
Object.keys(savedSessionStorage).forEach((key) => {
window.sessionStorage.setItem(key, savedSessionStorage.getItem(key));
});
});
// Your Cypress test code
describe('My tests', () => {
it('Test 1', () => {
// The user is already logged in due to the before() hook
// Your test assertions
});
it('Test 2', () => {
// The user is still logged in due to the before() hook
// Your test assertions
});
// More tests...
});
我可以看到建议使用白名单。但在期间似乎不起作用。 分别在before()和beforeEach()中尝试了以下方法:
Cypress.Cookies.defaults({
whitelist: "token"
})
并且
Cypress.Cookies.preserveOnce('token');
但似乎没有一个方法有效。但在使用cypress open
即图形界面模式时,这两种方法都很好用。有没有任何想法,我做错了什么?