【发布时间】:2020-12-25 02:33:12
【问题描述】:
如果超时,我正在尝试发出以下XHR 请求重试。如果我删除cy.wait('@formRequest'),似乎测试不会停止以正确等待响应。但是如果我留下cy.wait,如果请求超时,测试将失败。所以我尝试向cy.request 调用(显示在第二个代码块中)添加一些回调(ontimeout),但这似乎也不起作用。如果响应不是 200 或者根本没有收到响应,我知道如何让这个 cypress 命令重试吗??
我对此很陌生,因此不胜感激。
提前致谢!
// this works, but doesn't handle timeout
Cypress.Commands.add('form_request', (url, formData) => {
function recursive_request (url, formData, attempt) {
let xhr
const maxRetry = 3
if (attempt > maxRetry) {
throw new Error(`form_request() max retry reached, ${maxRetry}`)
}
if (attempt !== 0) {
cy.log(`Backing off retry. Attempt: ${attempt}/${maxRetry}.`)
cy.wait(30000)
}
return cy
.server()
.route('POST', url)
.as('formRequest')
.window()
.then((win) => {
xhr = new win.XMLHttpRequest()
xhr.open('POST', url)
xhr.send(formData)
})
.wait('@formRequest')
.then((resp) => {
if (xhr.status !== 200) {
return recursive_request(url, formData, attempt + 1)
}
return resp
})
}
return recursive_request(url, formData, 0)
})
Cypress.Commands.add('form_request', (url, formData) => {
function recursive_request (url, formData, attempt) {
let xhr
const maxRetry = 3
if (attempt > maxRetry) {
throw new Error(`form_request() max retry reached, ${maxRetry}`)
}
if (attempt !== 0) {
cy.log(`Backing off retry. Attempt: ${attempt}/${maxRetry}.`)
cy.wait(30000)
}
return cy
.server()
// .route('POST', url)
.route({
'method': 'POST',
'url': url
}, {
ontimeout: (xhr) => {
return new Cypress.Promise ((resolve) => {
resolve(recursive_request(url, formData, attempt + 1))
})
},
onreadystatechange: (xhr) => {
if (xhr.status !== 200 && xhr.readyState === 4) {
return new Cypress.Promise ((resolve) => {
resolve(recursive_request(url, formData, attempt + 1))
})
}
}
})
.as('formRequest')
.window()
.then((win) => {
xhr = new win.XMLHttpRequest()
xhr.open('POST', url)
xhr.send(formData)
})
.wait('@formRequest')
.then((resp) => {
if (xhr.status !== 200) {
return recursive_request(url, formData, attempt + 1)
}
return resp
})
}
return recursive_request(url, formData, 0)
})
编辑: 我尝试制作以下自定义 cypress 命令。但是,我收到非法调用错误。查看有关 jQuery.ajax() 的文档,我不清楚它的非法之处。
我还有几个问题...
#1。传入 {timeout: 30000} 对象是如何工作的?这个叫什么?我对 Promise 链的基本理解是,你传入一些处理函数来使用之前调用产生的任何东西。没见过.then(arg, function () {...})这个图案,这叫什么?
#2。 cy.log(...) 会在这里工作吗?我怀疑它不会因为那会混合同步/异步代码,对吗? (对不起,我现在会自己玩,但我无法让它通过非法调用错误)。 const log = Cypress.log(...) 会在这里同步工作吗?
527 | }
528 |
> 529 | Cypress.$.ajax({
| ^
530 | url,
531 | method: 'POST',
532 | data: formData,
Cypress.Commands.add('form_request', (url, formData) => {
const waits = { request: 2000, retry: 10000 }
const maxRetry = 3
function recursive_request(url, formData, attempt = 0) {
return new Cypress.Promise((resolve) => {
if (attempt > maxRetry) {
throw new Error(`form_request() max retry reached, ${maxRetry}`)
}
const retry = (reason) => {
console.log(`${reason} - retrying in ${waits.retry}`) // #2
return setTimeout(() => {
recursive_request(url, formData, attempt + 1)
.then(data => resolve(data)); // resolve from recursive result
}, waits.retry)
}
Cypress.$.ajax({
url,
method: 'POST',
data: formData,
timeout: waits.request,
})
.done(function (data, textStatus, jqXHR) {
if (textStatus !== 'success') {
retry('Status not success')
}
resolve(data)
})
.catch(function (jqXHR, textStatus, errorThrown) {
retry(errorThrown)
})
})
}
cy.wrap(null)
.then({ timeout: 30000 }, // #1
() => {
return recursive_request(url, formData)
})
.then((result) => {
return result
})
})
【问题讨论】:
-
这能回答你的问题吗? stackoverflow.com/a/54081260/1727948
-
尝试将 ontimeout 回调移动到
xhr对象,参见XMLHttpRequest: timeout event -
@konekoya ,不幸的是没有,因为我正在尝试处理没有回应的情况。
-
您的数据不是代码所暗示的 formData。设置
contentType: false- contentType (default: 'application/x-www-form-urlencoded; charset=UTF-8') ... 传递 false 告诉 jQuery 不要设置任何内容类型标头我>。还有processData: false- processData(默认:true),如果要发送...其他未处理的数据,请将此选项设置为false。。 -
啊!解决了非法调用问题。谢谢!
标签: javascript xmlhttprequest cypress