Cypress wait for API after button click
Solution 1
Sounds like you'll want to wait for the routes. Something like this:
cy.server();
cy.route('GET', '/api/route1').as('route1');
cy.route('GET', '/api/route2').as('route2');
cy.route('GET', '/api/route3').as('route3');
cy.get('button').contains('Filter').click();
// setting timeout because you mentioned it can take up to 15 seconds.
cy.wait(['@route1', '@route2', 'route3'], { responseTimeout: 15000 });
// This won't execute until all three API calls have returned
cy.get('#something').click();
Solution 2
Rather than using a .wait
you can use a timeout parameter. That way if it finished faster, you don't have to wait.
cy.get('button').contains('Filter', {timeout: 15000}).click()
This is mentioned as one of the options parameters in the official docs here.
Related videos on Youtube
Geoff
Updated on September 15, 2022Comments
-
Geoff over 1 year
I've made a React app, which all works perfectly and I'm now writing some end to end tests using Cypress.
The React app all works on the same url, it's not got any routes, and api calls from inside the app are handled through button clicks.
The basis of the app is the end user selects some options, then presses filter to view some graphs that are dependant on the selected options.
cy.get('button').contains('Filter').click()
When the button is pressed in cypress, it runs the 3 api calls which return as expected, but looking over the cypress docs there is no easy way unless I use inline
cy.wait(15000)
which isn't ideal, as sometimes they return a lot faster, and sometimes they return slower, depending on the selected options.Edit 1 I've tried using server and route:
cy.server({ method: 'GET' }); cy.route('/endpoint1*').as('one') cy.route('/endpoint2*').as('two') cy.route('/endpoint3*').as('three') cy.get('button').contains('Filter').click() cy.wait(['@one', '@two', '@three'], { responseTimeout: 15000 })
Which gives me the error:
CypressError: Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: 'one'. No request ever occurred.
After further investigation
Changing from
responseTimeout
to justtimeout
fixed the error.cy.server({ method: 'GET' }); cy.route('/endpoint1*').as('one') cy.route('/endpoint2*').as('two') cy.route('/endpoint3*').as('three') cy.get('button').contains('Filter').click() cy.wait(['@one', '@two', '@three'], { timeout: 15000 }).then(xhr => { // Do what you want with the xhr object })
-
Geoff almost 5 yearsI'll try that when I'm next on it. Cheers.
-
Josh Pittman almost 5 yearsYour wait probably goes after the bit of code you posted, in which case you would want to add the timeout to the next assertion. It works the same way. Almost all of the cypress methods have a timeout parameter, not just 'contains'. Paste your next assertion in to question if you are having trouble.
-
Geoff almost 5 yearsLooks like exactly what I want, I tried it before, but didn't have the timeout on it, so explains exactly why it didn't work. I'll see Monday and reply then. Cheers.
-
Geoff almost 5 yearsI've edited the question with what happens trying this method.
-
Geoff almost 5 yearsThis works, but it's not very graceful the method in Brendans answer is how it's intended to be done with Cypress.
-
Josh Pittman almost 5 yearsI disagree. Your answer assumes you are working with restful APIs. When this question was first posted, this was not the case. My approach work with web sockets, streams, and graphql. More robust.
-
Josh Pittman almost 5 yearsDefine graceful. You added 5 extra lines and achieved the same as what I did in 15 colocated characters. Please leave both answers up because they are both useful approaches for different situations.
-
Geoff almost 5 yearsIt adds more code, sure, but the added code makes it a lot clearer what's intended to be done. It also gives the test access to the responses from the api calls.
-
Brendan almost 5 years@Geoff I see that
timeout
worked for you instead. You're likely on an older version of Cypress, that was split out in version 3.1.3. you'll need to change it toresponseTimeout
once you upgrade. docs.cypress.io/guides/references/changelog.html#3-1-3 -
Josh Pittman almost 5 yearsI agree, but my point is that this is a different requirement, not a better one. Perhaps change the question title to 'Cypress wait for rest api response' to better direct other people searching for the same issue.
-
Geoff almost 5 years
"cypress": "^3.3.2"
strange... although I have got this working with puttingresponseTimeout: 15000
in cypress.json.timeout
does work on it's own in the wait command. -
Geoff almost 5 yearsTaken on board, question changed.