gpt4 book ai didi

javascript - cypress xhr 请求重试 ontimeout

转载 作者:行者123 更新时间:2023-12-04 01:08:55 28 4
gpt4 key购买 nike

我正在尝试制作以下 XHR如果超时,请求重试。如果我删除 cy.wait('@formRequest') ,似乎测试并没有停止正确等待响应。但是如果我离开 cy.wait in,如果请求超时,测试将失败。所以我尝试在 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(...) 会在这里工作吗?我怀疑它不会因为那会混契约(Contract)步/异步代码,对吗? (对不起,我现在会自己玩,但我无法让它通过非法调用错误)。会 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
})
})

最佳答案

测试级重试
我会看看test-retries (Cypress v 5.0+) 处理超时问题,

const waitTime = 1000; // shortened for demo 

Cypress.Commands.add('form_request', (url, formData) => {

return cy
.request({
method: 'POST',
url,
body: formData,
timeout: waitTime
})
.then((resp) => {
if (resp.status !== 200) {
throw new Error(`Status not 200`)
}
return resp
})
})

let attempts = 0;

it('repeats', { retries: 3 }, () => {

const wait = attempts ? waitTime : 0; // initial wait = 0
const url = attempts < 2
? 'http://nothing' // initially use a non-reachable url
: 'http://example.com'; // 3rd attempt succeeds
attempts++;
cy.wait(wait).form_request(url, { name: 'Fred' })

})

请求级重试
如果您想在请求级别(而不是测试级别)重试,那么@Ackroydd 是正确的 - 您应该放弃 cy.route()因为,简而言之, Cypress 命令不是为了捕捉失败而构建的。
这是一个使用 jquery.ajax 的基本示例.您可能会使用类似 axios.retry 的东西获得更简洁的功能。 .
引用 Waiting for promises对于使用的 Cypress 模式。
递归请求
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}`);
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)
})
})
}
测试
it('retries form post', () => {

cy.wrap(null)
.then(
{ timeout: 30000 }, // timeout must be above maximum expected,
// i.e maxRetry * waits.retry
() => recursive_request('http://localhost:3000', { name: 'Fred' })
)
.then(result => console.log(result))

})
用于测试的不稳定服务器
const express = require("express");
const app = express();
const port = 3000;

const obj = {
name: 'Fred'
};

let attempt = 0;

app.post("*", (req, res) => {
if (attempt >= 3) {
attempt = 0; // reset to allow multiple test runs
res.status(201).json(obj)
}
});

app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});

关于javascript - cypress xhr 请求重试 ontimeout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65444767/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com