如何在Cypress自定义命令间共享Base64编码的会话Cookie值?
你的问题核心在于**getSession中生成的cookie是局部变量,且Cypress命令是异步执行的**,导致createThing无法直接获取到这个值。下面提供两种简洁可靠的解决方案:
方案1:通过命令链式传递Cookie值
这是最直接的方式,让getSession返回处理后的Cookie,再在测试用例中把它传递给createThing。
步骤1:修改getSession命令,返回Base64编码后的Cookie
去掉不必要的文件读写操作,直接用Cypress.Buffer完成Base64编码并返回结果:
Cypress.Commands.add('getSession', (email, password) => { return cy.request({ url: 'xxx', method: 'POST', body: { email, password } }) .then((response) => { expect(response.status).to.eq(200); const body = response.body; cy.log('Id - ' + body.customerId); // 补全你的完整Cookie字符串 const rawSession = `SESSIONID=${body.Cookies.SESSIONID};`; cy.log('raw session data - ' + rawSession); // 直接返回Base64编码后的字符串 return Cypress.Buffer.from(rawSession, 'utf8').toString('base64'); }); });
步骤2:修改createThing命令,接受Cookie参数
让命令支持传入Cookie值:
Cypress.Commands.add('createThing', (name, cookie) => { return cy.request({ url: 'xxx', method: 'POST', headers: { 'Cookie' : `client_token=${cookie}`, 'Content-Type' : 'application/json' }, body: { name } }) .then((response) => { expect(response.status).to.eq(200); cy.log(response.body); return response.body; // 可选,方便后续测试用例使用返回结果 }); });
步骤3:在测试用例中链式调用
利用Cypress的异步链式特性,确保getSession完成后再执行createThing:
/// <reference types="Cypress" /> describe('deletes a user thing', function() { it('create a thing via the api', function() { cy.getSession('xxxx', 'xxxxx') .then((encodedCookie) => { cy.createThing('thing', encodedCookie); }); }) })
方案2:使用Cypress环境变量存储Cookie
如果希望createThing不需要显式接收参数,可以把Cookie存到Cypress的环境变量中,让命令直接读取。
步骤1:修改getSession命令,将Cookie存入环境变量
Cypress.Commands.add('getSession', (email, password) => { return cy.request({ url: 'xxx', method: 'POST', body: { email, password } }) .then((response) => { expect(response.status).to.eq(200); const body = response.body; cy.log('Id - ' + body.customerId); const rawSession = `SESSIONID=${body.Cookies.SESSIONID};`; const encodedCookie = Cypress.Buffer.from(rawSession, 'utf8').toString('base64'); cy.log('base64 string - ' + encodedCookie); // 将Cookie存入Cypress环境变量 Cypress.env('SESSION_COOKIE', encodedCookie); return encodedCookie; }); });
步骤2:修改createThing命令,读取环境变量
Cypress.Commands.add('createThing', (name) => { const cookie = Cypress.env('SESSION_COOKIE'); // 提前校验,避免无Cookie时执行请求 if (!cookie) { throw new Error('请先调用getSession生成会话Cookie!'); } return cy.request({ url: 'xxx', method: 'POST', headers: { 'Cookie' : `client_token=${cookie}`, 'Content-Type' : 'application/json' }, body: { name } }) .then((response) => { expect(response.status).to.eq(200); cy.log(response.body); }); });
步骤3:测试用例中调用(可使用钩子提前生成Cookie)
/// <reference types="Cypress" /> describe('deletes a user thing', function() { // 在所有测试用例前生成一次会话 before(() => { cy.getSession('xxxx', 'xxxxx'); }); it('create a thing via the api', function() { cy.createThing('thing'); }) })
为什么你的原代码会报错?
- 变量作用域问题:
getSession中cy.readFile回调里的cookie是局部变量,外部的createThing根本访问不到。 - 异步执行顺序:Cypress命令是异步的,原测试用例中
cy.getSession和cy.createThing是顺序触发,但createThing可能在getSession完成前就执行了,此时Cookie还未生成。 - 不必要的文件IO:通过读写文件来做Base64编码完全多余,直接用
Cypress.Buffer就能完成,还能避免文件操作带来的性能问题和异步复杂度。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

