我是 Cypress 和 JavaScript 的新手。我想创建一个循环来执行具有不同值的请求,直到获得特定响应。
let continue_loop = 1;
loginLoop: for (let i = 1; i < 100; i++) {
cy.request({
// url: Cypress.env("web_api")+"/1.0/user/login",
url: Cypress.env("api").staging + "/1.0/user/login",
method: "POST",
failOnStatusCode: false,
body: {
email: "email" + i + "@email.com",
password: "Helloworld10",
},
}).then((response) => {
if (response.status == 403) {
continue_loop = 2;
}
});
if (continue_loop == 2) {
break loginLoop;
}
}
看起来
continue_loop
只能在then块中获取值2
,因为之后它总是返回1,所以循环永远不会中断。我也尝试使用 Cypress 别名,但结果相同。我怎样才能实现这个目标?
令人烦恼的是,Cypress 不使用 Promise,而是使用“具有 .then 函数的东西”。当然,我们可以通过包装它们然后等待 那些: 将这些变成
真正的承诺const MAX_FAIL_COUNT = ...;
for (let failures = 0, i = 1; failures < MAX_FAIL_COUNT && i < 100; i++) {
// Await the request with a simple wrapper
const response = await new Promise(resolve => cy.request(
...
).then(resolve));
// And don't use == unless your statement *only* works with type coercion
if (response.status === 403) {
failures++;
}
}
Cypress aliases 用于弥合同步代码(如 for 循环)和异步命令(如
cy.request()
)之间的差距。
你需要
break
条件引入循环中,continue_loop
是 true
这个可重现的示例展示了如何在 Cypress 测试中执行与
async/await
等效的逻辑。
let continue_loop = true
// set up the alias to control the loop
cy.wrap(continue_loop, {log:false}).as('continue')
// staring at 95 to keep the example short
// #101 will be a failing request
// loops 102 to 200 will be skipped
for (let i = 95; i < 200; i++) {
cy.get('@continue', {log:false}).then(continue_loop => {
if (continue_loop) {
cy.request({
url: `https://jsonplaceholder.typicode.com/posts/${i}`,
failOnStatusCode: false,
}).then((response) => {
// checking for any failed status here
if (response.status >= 400) {
continue_loop = false
cy.wrap(continue_loop, {log:false}).as('continue') // update the alias
}
})
}
})
}
使用 Promise 包装器适用于这个简单的命令,但对于更复杂的命令链可能会失败。
Cypress 在控制台中发出警告。
for (let i = 95; i < 200; i++) {
const response = await new Promise(resolve => {
cy.request({
url: `https://jsonplaceholder.typicode.com/posts/${i}`,
failOnStatusCode: false,
}).then(resolve)
})
if (response.status >= 400) {
break
}
}
控制台中抛出的警告
docs 中的这个示例是最简单的 IMO。
此模式使用递归而不是 for 循环。
function req(i) {
if (i > 200) return // highest number to try
cy.request({
url: `https://jsonplaceholder.typicode.com/posts/${i}`,
failOnStatusCode: false,
})
.then((response) => {
if (response.status >= 400) {
return
}
req(++i)
})
}
req(95) // pass in the starting number (I use 95 to keep the example short)