Javascript Cypress:从API获取令牌,然后保存在本地存储中,并在另一个API中使用';然后返回第二个API的响应主体
我有一个API(我们称之为getToken),用于在其响应体中生成令牌。然后我调用该令牌并将其存储在另一个API的头中(我们称之为returnBody)。对于getTokenAPI使用Javascript Cypress:从API获取令牌,然后保存在本地存储中,并在另一个API中使用';然后返回第二个API的响应主体,javascript,json,automated-tests,cypress,Javascript,Json,Automated Tests,Cypress,我有一个API(我们称之为getToken),用于在其响应体中生成令牌。然后我调用该令牌并将其存储在另一个API的头中(我们称之为returnBody)。对于getTokenAPI使用localStorage是有意义的,因为此令牌可用于多个API。但是,如果我需要返回/显示后续API的响应体,例如returnBody,我对使用localStorage有疑问。在API的函数/命令中,它记录响应主体。但是,当我通过测试文件调用它时,它会生成null。 示例代码如下: commands.js: 测试文
localStorage
是有意义的,因为此令牌可用于多个API。但是,如果我需要返回/显示后续API的响应体,例如returnBody,我对使用localStorage
有疑问。在API的函数/命令中,它记录响应主体。但是,当我通过测试文件调用它时,它会生成null。
示例代码如下:
commands.js:
测试文件:
returnBody命令的body返回JSON响应。但是,从测试文件返回的值显示为空。您可能需要从
返回体任务返回响应体:
Cypress.Commands.add('returnBody',(url,token)=>{
返回cy.request({/*选项*/})
。然后(响应=>{
让body=JSON.stringify(response.body);
柏木原木(体);
返回正文;//添加此行
});
});
另一种选择是使用固定装置将令牌存储在cypress侧
fixture.json:
commands.js:
test.js
如中所述:“您不能从自定义命令返回第三方承诺,因为这会中断cypress命令之间的链接。这是因为.then方法不同。”
因此,只需将请求主体返回为:
Cypress.Commands.add('returnBody',(url,token)=>{
返回cy.request({/*选项*/})
.其(“机构”);
});
然后,在测试中,您可以执行以下操作:
it(“应该返回foo值”,()=>{
cy.returnBody(url,标记)。然后(返回的值=>{
cy.log(返回的_值);
expect(返回的_值).to.deep.equal(“foo值”);
})
})
我收到这个错误:CypressError:cy.then()失败,因为您混淆了异步和同步代码。@er123尝试将cy.log()
替换为Cypress.log()
我认为这与命令“log”无关。即使如此,我还是尝试了它,并得到了以下错误:CypressError:Cypress.log()只能用options对象调用。您的参数是:“null”。另外,很抱歉坦率地说,您的初始解决方案似乎是反模式的,其中一个返回整个cypress命令(cy.request),然后在内部,再次返回值(body)。感谢@javier brea,但这仍然在我的测试文件中返回空值:cy.returnBody(url,tokenJSON.token)。然后((返回的_值)=>{cy.log(返回的_值)})
。抱歉@er123,你说得对,回复承诺不起作用。我在这里找到了解决办法。我编辑了这个示例,测试了它,现在它可以工作了。是的,我最初使用cy.writeFile
尝试了这个方法,但是我的运行变得有点不稳定。我还必须将watchForFileChanges
设置为false
。虽然这是另一个很好的选择,但对于我的用例,我希望它运行得更快,并且这种方法可能会影响性能,因为我需要不断调用令牌,这将不断更新fixture文件,这是我在现阶段不太热衷于使用的另一层。
Cypress.Commands.add('getToken', () => { //API to generate token
cy.request({
method: 'POST',
url: 'https://someAPItoGenerateToken',
form: true, //sets to application/x-www-form-urlencoded
body: {
grant_type: 'credentials',
scope: 'all-apis'
},
auth: {
username: Cypress.env('api_username'),
password: Cypress.env('api_password')
}
})
.its('body')
.then(bearerToken => {
cy.setLocalStorage('bearerToken', JSON.stringify(bearerToken))
cy.log('Token generated: ' + bearerToken.token)
}
)
})
Cypress.Commands.add('returnBody', (url, token) => { //API to return some values
return cy.request({
method: 'GET',
url: url,
auth: {
bearer: token
}
})
.then((response) => {
// Stringify JSON the body.
let body = JSON.stringify(response.body)
cy.log(body)
})
})
describe('Return value of 2nd API', ()=> {
before(() => {
cy.getToken() //Run this once to generate token for the entire test suite
cy.saveLocalStorage()
})
beforeEach(() => {
cy.restoreLocalStorage()
})
it('Return value of 2nd API', () => {
cy.getLocalStorage('bearerToken').should('exist')
cy.getLocalStorage('bearerToken').then(bearerToken => {
const tokenJSON = JSON.parse(bearerToken)
const url = 'https://someAPItoReturnJSONbody'
cy.returnBody(url, tokenJSON.token).then((returned_value) => {
cy.log(returned_value)
})
})
})
})
{"bearerToken":""
.
.
.}
cy.fixture('testData.json').as('testData')
.
.
.then(bearerToken => {
this.testData.bearerToken = JSON.stringify(bearerToken)
cy.log('Token generated: ' + bearerToken.token)
}
)
describe('Return value of 2nd API', ()=> {
before(() => {
cy.getToken() //Run this once to generate token for the entire test suite
})
it('Return value of 2nd API', () => {
cy.fixture('testData.json').as('testData')
.then(testData => {
const tokenJSON = JSON.parse(testData.bearerToken)
const url = 'https://someAPItoReturnJSONbody'
cy.returnBody(url, tokenJSON.token).then((returned_value) => {
cy.log(returned_value)
})
})
})
})