E. E. Ozkan
E. E. Ozkan

Reputation: 127

Cypress cy.wait() only waits for the first networkcall, need to wait for all calls

I would like to wait until the webpage is loaded with items. Each is getting retreived with a GET.

And I would like to wait on all these items until the page is loaded fully. I already made a interceptions for these. Named: 4ItemsInEditorStub

I have tried cy.wait('@4ItemsInEditorStub.all') But this gives an timeout error at the end.

enter image description here

How can I let Cypress wait untill all "4ItemsInEditorStub" interceptions are completed?

Upvotes: 1

Views: 1864

Answers (4)

Fody
Fody

Reputation: 32118

Network idle testing looks good, but you might find it difficult to set the right time period, which may change each time you run (depending on network speed).

Take a look at my answer here Test that an API call does NOT happen in Cypress.

Using a custom command you can wait for a maximum number of calls without failing if there are actually less calls.

For example, if you have 7 or 8 calls, setting the maximum to 10 ensures you wait for all of them

Cypress.Commands.add('maybeWaitAlias', (selector, options) => {
  const waitFn = Cypress.Commands._commands.wait.fn
  return waitFn(cy.currentSubject(), selector, options)
    .then((pass) => pass, (fail) => fail)
})

cy.intercept(...).as('allNetworkCalls')

cy.visit('/');

// up to 10 calls
Cypress._.times(10, () => {
  cy.maybeWaitAlias('@allNetworkCalls', {timeout:1000}) // only need short timeout
})

// get array of all the calls
cy.get('@allNetworkCalls.all')
  .then(calls => {
    console.log(calls)
  })

Upvotes: 1

TesterDick
TesterDick

Reputation: 10560

There is a package cypress-network-idle that makes the job simple

cy.waitForNetworkIdlePrepare({
  method: 'GET',
  pattern: '**/api/item/*',
  alias: 'calls',
})
cy.visit('/')
// now wait for the "@calls" to finish 
cy.waitForNetworkIdle('@calls', 2000)  // no further requests after 2 seconds 

Installation

# install using NPM
npm i -D cypress-network-idle
# install using Yarn
yarn add -D cypress-network-idle

In cypress/support/e2e.js

import 'cypress-network-idle'

Upvotes: 1

jjhelguero
jjhelguero

Reputation: 2565

You can either hard code a long enough wait (ie. cy.wait(3_000)) to cover the triggered request time and then use cy.get('@4ItemsInEditorStub.all')

cy.wait(10_000)
cy.get('@4ItemsInEditorStub.all')
// do some checks with the calls

or you can use unique intercepts and aliases to wait on all 4

cy.intercept('/your-call').as('4ItemsInEditorStub1')
cy.intercept('/your-call').as('4ItemsInEditorStub2')
cy.intercept('/your-call').as('4ItemsInEditorStub3')
cy.intercept('/your-call').as('4ItemsInEditorStub4')

cy.visit('')

cy.wait([
  '@4ItemsInEditorStub1',
  '@4ItemsInEditorStub2',
  '@4ItemsInEditorStub3',
  '@4ItemsInEditorStub4',
])

Upvotes: 0

agoff
agoff

Reputation: 7164

Trying to wait on alias.all won't work -- Cypress has no idea what .all means in this context, or what value it should have. Even after your 4 expected calls are completed, there could be a fifth call after that (Cypress doesn't know). alias.all should only be used with cy.get(), to retrieve all yielded calls by that alias.

Instead, if you know that it will always be four calls, you can just wait four times.

cy.wait('4ItemsInEditorStub')
  .wait('4ItemsInEditorStub')
  .wait('4ItemsInEditorStub')
  .wait('4ItemsInEditorStub');

Upvotes: 0

Related Questions