如何在赛普拉斯测试中等待成功的响应

问题描述 投票:0回答:2

背景

我使用3台后端服务器为我的一个在线SaaS应用程序提供容错能力。所有重要的API调用,例如获取用户数据,都与所有3台服务器联系,并使用第一个成功解决的响应的值(如果有)。

export function getSuccessValueOrThrow$<T>(
        observables$: Observable<T>[],
        tryUntilMillies = 30000,
    ): Observable<T> {
        return race(
            ...observables$.map(observable$ => {
                return observable$.pipe(
                    timeout(tryUntilMillies),
                    catchError(err => {
                        return of(err).pipe(delay(5000), mergeMap(_err => throwError(_err)));
                    }),
                );
            })
        );
    }

getSuccessValueOrThrow $的调用如下:

const shuffledApiDomainList = ['server1-domain', 'server2-domain', 'server3-domain';
const sessionInfo = await RequestUtils.getSuccessValueOrThrow(
                        ...(shuffledApiDomainList.map(shuffledDomain => this.http.get<SessionDetails>(`${shuffledDomain}/file/converter/comm/session/info`))),
                    ).toPromise();

注意:如果一个请求比其他请求更快地解决,通常情况下,race rxjs函数将取消其他两个请求。在Chrome开发者网络标签上,它看起来像下面,由于太慢而取消了第一个发出的请求。

enter image description here

问题:

我使用/ file / converter / comm / session / info(我们称其为端点1)来获取一些与用户相关的数据。该请求分派给所有3个后端服务器。如果一个解决,则将取消其余2个请求,即它们将返回null。

在我的赛普拉斯E2E测试中,我有

cy.route('GET', '/file/converter/comm/session/info').as('getSessionInfo');
cy.visit('https://www.ps2pdf.com/compress-mp4');
cy.wait('@getSessionInfo').its('status').should('eq', 200)

如果将getSessionInfo别名挂钩到最终被getSuccessValueOrThrow$取消的请求上,这有时会失败,因为它不是成功的请求。下图显示了以getSessionInfo为别名的3个请求中有1个成功了,但是测试由于第一个请求失败,因此失败。

enter image description here

在赛普拉斯中,我如何等待成功,即状态= 200请求?

cypress e2e-testing
2个回答
0
投票

方法1

如果状态不是200,则使用.should()回调并重复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(),并专注于用户在页面上看到的内容-对实际页面内容进行断言。


0
投票

cy.wait()产生一个对象,其中包含XHR的HTTP请求和响应属性。您得到的错误是因为您正在XHR对象中寻找属性cy.wait(),但这是Response Object的属性。您首先必须转到响应对象:

status

编辑:由于我们的后端使用graphql,因此所有调用都使用单个cy.wait('@getSessionInfo').should(xhr => { expect(xhr.response).to.have.property('status', 200); }); 端点。因此,我不得不想出一种解决方案来区分每个呼叫。

我通过使用/graphqlonResponse()方法并在Cypress cy.route()对象中累积数据来做到这一点:

environment

然后您可以像这样使用它:

cy.route({
  method: 'GET',
  url: '/file/converter/comm/session/info',
  onResponse(xhr) {
    if (xhr.status === 200) {
      Cypress.env('sessionInfo200') = xhr;
    }
  }
})
© www.soinside.com 2019 - 2024. All rights reserved.