Assert/check polling rate for stubbed requests in Cypress test

242 Views Asked by At

I have a Cypress test that uses stubbed responses with cy.intercept. The requests that we're intercepting are polling an endpoint in our back end - we make one request per second until a status property in the response has changed.

I'm pretty new to Cypress so I might have the wrong idea about what you can actually test, but what I'd like to check is how often a request is made to this endpoint, i.e. assert that the polling is done at the correct rate (once/sec).

Is this possible to do with Cypress? Or should I perhaps look into some other tool?


This is how we're stubbing the network calls (simplified):

cy.intercept(
  {
    method: 'GET',
    path: '/api/user',
  },
  {
    body: {
      id: '1',
      status: 'UPDATED', // This is the status that eventually stops the polling
      // etc.
    },
  }
).as('getUserUpdated');

cy.intercept(
  {
    method: 'GET',
    path: '/api/user',
    times: 2,
  },
  {
    body: {
      id: '1',
      status: 'CREATED',
      // etc.
    },
  }
).as('getUserCreated');
1

There are 1 best solutions below

1
On BEST ANSWER

Here's a simple script that polls the api for approx 10 seconds at 1 second intervals

<script>
  const intervalId = setInterval(() => {
    fetch('/api/user')
  }, 1000)

  setTimeout(() => {
    clearInterval(intervalId)
  }, 10_000)
</script>

If I want to test that with cy.intercept(), I would basically use the callback form of intercept and inside that record the time.

cy.intercept('/api/user', req => {
  polls.push(Date.now() - last)
  last = Date.now()          // update the last time to record time between polls
  req.reply({ id: '1', status: 'UPDATED'})
})

But the first interval time is distorted by the cy.visit() page load, so a second cy.interval() can catch and discard it - but you could just .slice() the polls array too.

Note the order of setting up cy.intercept() - the last one set up is the first one checked by Cypress (then it expires after 1 catch because of {times:1}).

let last = Date.now()
  
const polls = []
  
cy.intercept('/api/user', req => {
  polls.push(Date.now() - last)
  last = Date.now()
  req.reply({ id: '1', status: 'UPDATED'})
})
  
// This is just to consume the first call
// since the `cy.visit()` distorts the interval
cy.intercept('/api/user', { times: 1 }, req => {
  last = Date.now()
  req.reply({ id: '1', status: 'UPDATED'})
})
  
cy.visit('/');
cy.wait(10_000)
  .then(() => {
    cy.wrap(polls)
      .each(poll => {
        expect(poll).to.be.closeTo(1000, 50)      // best check is +/- 50 ms
      })
  })