如何在Cypress测试中等待成功响应
背景 我使用3个后端服务器为我的一个在线SaaS应用程序提供容错。所有重要的API调用,如获取用户数据,请联系所有3台服务器,并使用第一个成功解析响应的值(如果有)如何在Cypress测试中等待成功响应,cypress,e2e-testing,Cypress,E2e Testing,背景 我使用3个后端服务器为我的一个在线SaaS应用程序提供容错。所有重要的API调用,如获取用户数据,请联系所有3台服务器,并使用第一个成功解析响应的值(如果有) 导出函数GetSuccessValueorRow$( 可观测$:可观测[], tryuntillies=30000, ):可见{ 复赛( …可观测$.map(可观测$=>{ 返回可观察的$.pipe( 超时(tryuntillies), catchError(err=>{ 返回(err).pipe(延迟(5000),合并映射(_er
导出函数GetSuccessValueorRow$(
可观测$:可观测[],
tryuntillies=30000,
):可见{
复赛(
…可观测$.map(可观测$=>{
返回可观察的$.pipe(
超时(tryuntillies),
catchError(err=>{
返回(err).pipe(延迟(5000),合并映射(_err=>throwError(_err));
}),
);
})
);
}
GetSuccessValueorRow$get调用如下:
const shuffledApiDomainList=['server1-domain'、'server2-domain'、'server3-domain';
const sessionInfo=wait RequestUtils.getsuccessvalueorhrow(
…(ShuffledApidDomainList.map(shuffledDomain=>this.http.get(`${shuffledDomain}/file/converter/comm/session/info`)),
).toPromise();
注意:如果一个请求的解析速度比其他请求快,通常情况下,race
rxjs函数将取消其他两个请求。在Chrome dev的网络选项卡上,它看起来像下面所示,第一个发送的请求由于太慢而被取消
问题:
我使用/file/converter/comm/session/info(我们称之为Endpoint 1)来获取一些与用户相关的数据。此请求被发送到所有3个后端服务器。如果有一个解析,则剩余的2个请求将被取消,即返回null
在我的Cypress E2E测试中
cy.route('GET','/file/converter/comm/session/info')。as('getSessionInfo');
参观https://www.ps2pdf.com/compress-mp4');
cy.wait('@getSessionInfo')。其('status')。应('eq',200)
如果自getSessionInfo别名被挂接到一个请求上,而该请求最终被getSuccessValueOrThrow$
取消,则此操作有时会失败,因为该请求不是成功的请求。下图显示了自getSessionInfo别名的3个请求中有1个成功,但自第一个请求失败后测试失败
在Cypress中,如何等待一个成功的请求,即status=200请求?生成一个包含XHR的HTTP请求和响应属性的对象。您得到的错误是因为您在XHR对象中查找属性status
,但它是响应对象的属性。您首先必须获取o响应对象:
cy.wait('@getSessionInfo').should(xhr => {
expect(xhr.response).to.have.property('status', 200);
});
编辑:因为我们的后端使用graphql,所以所有调用都使用单个
/graphql
端点。所以我必须想出一个解决方案来区分每个调用
我是通过使用cy.route()
的onResponse()
方法,并在Cypress对象中累积数据来实现的:
然后您可以这样使用它:
cy.wrap(Cypress.env()).should('have.property', 'sessionInfo200');
const isOk = cy.wait("@getSessionInfo").then((xhr) => {
return (xhr.status === 200);
});
生成一个包含XHR的HTTP请求和响应属性的对象。出现错误是因为您正在XHR对象中查找属性status
,但它是响应对象的属性。您首先必须访问响应对象:
cy.wait('@getSessionInfo').should(xhr => {
expect(xhr.response).to.have.property('status', 200);
});
编辑:因为我们的后端使用graphql,所以所有调用都使用单个
/graphql
端点。所以我必须想出一个解决方案来区分每个调用
我是通过使用cy.route()
的onResponse()
方法,并在Cypress对象中累积数据来实现的:
然后您可以这样使用它:
cy.wrap(Cypress.env()).should('have.property', 'sessionInfo200');
const isOk = cy.wait("@getSessionInfo").then((xhr) => {
return (xhr.status === 200);
});
方法1 使用
.should()
回调,如果状态不是200,则重复调用cy.wait
:
function waitFor200(routeAlias, retries = 2) {
cy.wait(routeAlias).then(xhr => {
if (xhr.status === 200) return // OK
else if (retries > 0) waitFor200(routeAlias, retries - 1); // wait for the next response
else throw "All requests returned non-200 response";
})
}
// Usage example.
// Note that no assertions are chained here,
// the check has been performed inside this function already.
waitFor200('@getSessionInfo');
// Proceed with your test
cy.get('button').click(); // ...
方法2
修改您首先要测试的内容。
很有可能-页面上有一些信息会告诉用户操作是否成功。例如,显示/隐藏微调器或进度条,或者只是更新页面内容以显示从后端获取的新数据
因此,在这种方法中,您将完全删除
cy.wait()
,并将重点放在用户在页面上看到的内容上—对实际页面内容做一些断言。方法1
使用.should()
回调,如果状态不是200,则重复调用cy.wait
:
function waitFor200(routeAlias, retries = 2) {
cy.wait(routeAlias).then(xhr => {
if (xhr.status === 200) return // OK
else if (retries > 0) waitFor200(routeAlias, retries - 1); // wait for the next response
else throw "All requests returned non-200 response";
})
}
// Usage example.
// Note that no assertions are chained here,
// the check has been performed inside this function already.
waitFor200('@getSessionInfo');
// Proceed with your test
cy.get('button').click(); // ...
方法2
修改您首先要测试的内容。
很有可能-页面上有一些信息会告诉用户操作是否成功。例如,显示/隐藏微调器或进度条,或者只是更新页面内容以显示从后端获取的新数据
因此,在这种方法中,您将完全删除cy.wait()
,并关注用户在页面上看到的内容-对实际页面内容进行一些断言。我像这样等待:
cy.wrap(Cypress.env()).should('have.property', 'sessionInfo200');
const isOk = cy.wait("@getSessionInfo").then((xhr) => {
return (xhr.status === 200);
});
我这样等待:
cy.wrap(Cypress.env()).should('have.property', 'sessionInfo200');
const isOk = cy.wait("@getSessionInfo").then((xhr) => {
return (xhr.status === 200);
});
根据文档,它看起来像是xhr对象具有status属性。顺便说一句,问题与我如何获取状态无关。问题是,正如我在问题中提到的,它只是有时会失败。你是对的,我读得太快了。请看我编辑过的答案。希望有帮助。根据文档,它看起来像xhr对象具有status属性。顺便说一句,问题与我如何获得状态无关。问题是,正如我在问题中提到的,它有时会失败。你是对的,我读得太快了。请参阅我编辑的答案。希望它能有所帮助。