Geoff
Geoff

Reputation: 593

Cypress wait for API after button click

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 just timeout 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
}) 

Upvotes: 13

Views: 32915

Answers (4)

Sachithya Rivisara
Sachithya Rivisara

Reputation: 63

cy.server() and cy.route() are deprecated in Cypress 6.0.0 In a future release, support for cy.server() and cy.route() will be removed. Consider using cy.intercept() instead.

this worked for me...

ex:- see the screen shot

    cy.intercept('GET', 'http://localhost:4001/meta').as('route');
    cy.get(':nth-child(2) > .nav-link').click();
    cy.contains('Filter');
    cy.wait(['@route'], { responseTimeout: 15000 });

Upvotes: 2

MarcinW
MarcinW

Reputation: 61

Try this:

    cy.contains('button', 'Save').click();
    cy.get('[data-ng-show="user.manage"]', { timeout: 10000 }).should('be.visible').then(() => {
      `cy.get('[data-ng-show="user.manage"]').click();
   })

Upvotes: 0

Josh Pittman
Josh Pittman

Reputation: 7324

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.

Upvotes: 9

Brendan
Brendan

Reputation: 4649

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();

Upvotes: 12

Related Questions