我目前正在使用赛普拉斯测试一些微服务。要测试REST api,我需要一个令牌来发出请求。此令牌仅可通过本地FE使用-下面给出的图片
我必须访问此FE才能仅获取令牌-没有其他方法可以访问此访问令牌。
现在我正在像这样操作
describe('Do some test',()=>{
it('first test',()=>{
//this fetches the value of the token from FE.
cy.get('css locator of the access token').invoke('val').then((token)=>{
let tok = token;
cy.request({
method: 'GET' //or POST
url: "http://localhost:3001/v1/api1.json",
headers:{
"Authorization": "Bearer "+token;
"Content-Type":"application/json"
}
}).as('firsttest').then(()=>{
cy.get('@firsttest').its('status').should('eql',200);
})
})
})
})
现在,此方法有效,并且我得到了正确的状态以及所有信息,但是我知道这不是组织测试的好方法,而且还会导致很多重复,因为如果我要移动的话,我必须一次又一次地获取令牌在it
块之外。
如何组织这种方式,使我可以一次获取token
值,然后在测试中使用它。.类似这样的东西
describe('Do first test',()=>{
beforeEach(()=>{
cy.get('get locator of the token').invoke('val').then((token)=>{
let tok = token;
})
})
it('fetch and use token',()=>{
cy.request({
method: 'GET' //or POST
url : 'http://someurl/path',
headers :{
"Authorization": "Bearer "+token; (from beforeEach block)
}
})
})
it('do another test using same token',()=>{
//do something
})
})
或者进一步简化为使获得token
的重复性最小化。
您可以在support / command.js中创建自定义方法。例如,在这里创建了一个名为“ Newlogin”的自定义方法]
Cypress.Commands.add('Newlogin', (email, password,env) => {
Cypress.log({
name: 'loginViaAuth0',
});
const options = {
method: 'POST',
url: env+'/oauth/token', // Token Url
failOnStatusCode: false,
form:true,
"body":'grant_type=password&userName='+email+'&Password='+password+'
};
cy.request(options)
});
现在您可以在与cy链接的任何地方访问此方法。例如
cy.Newlogin(username, password, env) /*Custom method defined in supports/command.js */
.its('body')
.then((resp) => {
resp = JSON.stringify(resp)
cy.log(resp)
const token = JSON.parse(resp).access_token
});
详细阐述评论,这是一个有效的示例。它假定包含令牌的UI将始终存在于每个测试中。
此解决方案的问题在于,将令牌检索逻辑放入beforeEach
将有效地防止在测试开始时出现cy.visit
。因此,可以将cy.visit
放入beforeEach
(在cy.get()
之上),或者提出其他解决方案。
// cypress/support/index.js
// override the `cy.request` to automatically supply the Authorization header
// ----------------------------------------------------------------------
const AuthorizationToken = Symbol();
Cypress.Commands.overwrite('request', (origFn, ...args) => {
// normalize arguments
// --------------------------------------------------------------------
let opts;
if ( args.length === 1 ) {
opts = typeof args[0] === 'string' ? { url: args[0] } : args[0];
} else {
opts = args.length === 2
? { url: args[0], body: args[1] }
: { method: args[0], url: args[1], body: args[2] }
}
// set the Auhtorization header (if exists)
// --------------------------------------------------------------------
if ( cy.request[AuthorizationToken] ) {
opts.headers = {
'Authorization': 'Bearer ' + cy.request[AuthorizationToken],
...opts.headers
};
}
// --------------------------------------------------------------------
return origFn(opts);
});
beforeEach(() => {
// (1) setup (for demonstraion purposes)
// ----------------------------------------------------------------------
cy.document().then( doc => {
doc.body.innerHTML = '<div class="token">2as24flx9</div>';
});
// (2) actual code
// ----------------------------------------------------------------------
cy.get('.token').invoke('text').then( token => {
cy.request[AuthorizationToken] = token;
});
});