如何在赛普拉斯测试中加载页面后可靠地等待XHR请求?

时间:2018-04-11 20:06:59

标签: cypress

在我的应用程序中,当我访问某个页面时,会发出一些网络请求来获取数据并将其显示在页面上。之后,您单击按钮并填写字段以过滤该数据。

我有一个柏树测试,基本上会访问该页面,应用一些过滤器,并确保dom中的东西看起来正确:

it(`filters the data by 'price'`, () => {
  cy.server()
  cy.route('POST', 'http://my-api.biz/api').as('apiRequest')

  cy.visit('/')

  // initial page load loads the min and max price bounds for the UI,
  // as well as the data to initially populate the page. they happen
  // to hit the same URL with different POST params
  cy.wait(['@apiRequest', '@apiRequest'])

  cy.get('#price-filter-min').type('1000')
  cy.get('#price-filter-max').type('1400')

  // wait for data to get refreshed
  cy.wait('@apiRequest')

  cy
    .get('[data-test-column="price"]')
    .each($el => {
      const value = parseFloat($el.text())
      expect(value).to.be.gte(1000)
      expect(value).to.be.lte(1400)
    })
})

然而,有时cypress似乎加载页面,XHR请求等待之前,然后偶尔会失败:

  

赛普拉斯错误:超时重试:cy.wait()超时等待30000毫秒,第二次回复路线:' apiRequest'。没有发生任何反应。

因为它正在等待已经发生的请求。

是否有更好的方法来编写此测试?有没有办法访问页面并等待XHR请求,以避免这种竞争条件?

更新

我试图在一个孤立的测试用例中重新创建它,但这一切似乎都正常,所以可能有一些操作错误。

3 个答案:

答案 0 :(得分:7)

所以现在大部分答案都被弃用了。从 Cypress@6.4.0 开始,您应该使用 intercept()

这是我的做法:

cy.intercept({
      method: "GET",
      url: "http://my-api.biz/api/**",
    }).as("dataGetFirst");
cy.wait("@dataGetFirst");

就是这样。你可以做更多的事情,在等待时做一个断言链,但它本身已经是一个断言。

答案 1 :(得分:2)

您可以这样做

// Give an alias to request
cy.server().route("GET", /odata/locations/**).as('dataGetFirst')

// Visit site
cy.visit('admin/locations')

// Wait for response.status to be 200
cy.wait('@dataGetFirst').its('status').should('be', 200) 

// Continue

答案 2 :(得分:0)

由于您使用的是cy.visit('/'),我假设您在配置中设置了baseUrl。 cy.route()中的URL参数将baseUrl +作为幕后参数传递的字符串。

因此,发送POST请求的网址为http://my-api.biz/apihttp://my-api.biz/api或类似内容。

尝试将路线命令更改为:

cy.route('POST', '/api/foobar').as('apiRequest')

其他文档和示例: https://docs.cypress.io/guides/guides/network-requests.html#Fixtures