如何在响应中匹配拦截

时间:2021-07-02 11:31:54

标签: cypress

这是一个代码示例 我做的第一件事是拦截请求,然后我想等到响应将在正文中包含预期状态。但测试在默认超时后失败 - 30000 毫秒,错误如下:

30000 毫秒后重试超时:预期“正在运行”等于“已完成”

所以测试失败了,因为状态是 Running,而预期是 Completed。在这种情况下如何增加超时时间?

 cy.intercept('GET', Cypress.config().baseUrl + 'api/scans/' + scanID).as('getStatus');

 cy.visit('/')

 cy.wait('@getStatus', {responseTimeout: 80000}).its('response.body.status')
   .should('eq', 'Completed')

2 个答案:

答案 0 :(得分:0)

响应超时不会被忽略,响应在您提供的超时内被捕获,但它具有与您预期的属性不同的属性。

我想因为状态可以是“正在运行”或“已完成”,所以有两个响应正在通过。 (也许还有两个请求)

我建议你等两次

cy.wait('@getStatus', {responseTimeout: 80000})
  .its('response.body.status').should('eq', 'Running')
cy.wait('@getStatus', {responseTimeout: 80000})
  .its('response.body.status').should('eq', 'Completed')

如果没有成功,请查看“网络”选项卡上发生的情况。

答案 1 :(得分:0)

继续 Hiram 的回答,如果您不知道要等待多少个请求,可以使用函数重复等待,直到所需状态到达。

当然,“已完成”状态可能永远不会到达,因此您要设置要检查的最大请求/响应数(代替超时)。

为了模拟您的情况,我使用了一个以 300 毫秒为间隔发出三个请求的简单网站。

响应体的 id 恰好与请求中的参数相同,因此我们要等待 response.body.id === 3

具有 3 个请求的简单应用

<script>
  setTimeout(() => fetch('https://jsonplaceholder.typicode.com/todos/1'), 300)
  setTimeout(() => fetch('https://jsonplaceholder.typicode.com/todos/2'), 600)
  setTimeout(() => fetch('https://jsonplaceholder.typicode.com/todos/3'), 900)
</script>

测试

it('waits for a particular response', () => {

  cy.visit('../app/intercept-last.html')

  cy.intercept('**/jsonplaceholder.typicode.com/todos/*')
    .as('todos')

  function waitFor(alias, partialResponse, maxRequests, level = 0) {
    if (level === maxRequests) {
      throw `${maxRequests} requests exceeded`         // fail the test
    }
    cy.wait(alias).then(interception => {
      const isMatch = Cypress._.isMatch(interception.response, partialResponse)
      if (!isMatch) {
        waitFor(alias, partialResponse, maxRequests, level+1)
      }
    })
  }

  waitFor('@todos', { body: { id: 3 } }, 100)         // if no error, value has arrived
  cy.get('@todos.last')                               // now use get() instead of wait()
    .its('response.body.id').should('eq', 3)          
})

你的测试

cy.intercept('GET', Cypress.config().baseUrl + 'api/scans/' + scanID)
  .as('getStatus')

cy.visit('/')

  function waitFor(alias, partialResponse, maxRequests, level = 0) {
    if (level === maxRequests) {
      throw `${maxRequests} requests exceeded`        
    }
    cy.wait(alias).then(interception => {
      const isMatch = Cypress._.isMatch(interception.response, partialResponse)
      if (!isMatch) {
        waitFor(alias, partialResponse, maxRequests, level+1)
      }
    })
  }

const timeout = 80_000                            // timeout you want to apply 
const pollingRate = 500                           // rate at which app sends requests
const maxRequests = (timeout / pollingRate) + 10; // number of polls plus a few more

waitFor('@getStatus', { body: { status: 'Completed' } }, maxRequests) 
cy.get('@getStatus.last')     
  .its('response.body.status').should('eq', 'Completed')