in my app, when i visit a page it makes some network requests to fetch data and display it on the page. after that you click buttons and fill in fields to filter that data.
i have a cypress test that will basically visit the page, apply some filters, and make sure the stuff in the dom looks right:
it(`filters the data by 'price'`, () => { cy.server() cy.route('POST', 'http://my-api.biz/api').as('apiRequest') cy.visit('/') // initial page load loads the min and max price bounds for the UI, // as well as the data to initially populate the page. they happen // to hit the same URL with different POST params cy.wait(['@apiRequest', '@apiRequest']) cy.get('#price-filter-min').type('1000') cy.get('#price-filter-max').type('1400') // wait for data to get refreshed cy.wait('@apiRequest') cy .get('[data-test-column="price"]') .each($el => { const value = parseFloat($el.text()) expect(value).to.be.gte(1000) expect(value).to.be.lte(1400) }) })
however sometimes cypress seems to load the page, do the XHR requests before waiting, then sporadically it'll fail on:
CypressError: Timed out retrying: cy.wait() timed out waiting 30000ms for the 2nd response to the route: 'apiRequest'. No response ever occurred.
because it's waiting for a request that has already happened.
is there a better way to write this test? is there a way to visit a page and wait for XHR requests that avoids this race condition?
UPDATE
i've tried to re-create this in an isolated test case, but it all seems to be working right, so there's probably some operator error.
Wait for API response Cypress works great with http requests. If you are waiting for some resources to be loaded in your app, you can intercept a request and then create an alias for it. That alias will then be used with . wait() command.
With cypress, cy. visit() can be used to wait for a page to load.
Cypress automatically waits for the network call to complete before proceeding to the next command. // Anti-pattern: placing Cypress commands inside . then callbacks cy. wait('@alias') .
You can do something like this
// Give an alias to request cy.intercept({ method: 'GET', url: '/odata/locations/**', }).as('dataGetFirst'); // Visit site cy.visit('admin/locations'); // Wait for response.status to be 200 cy.wait('@dataGetFirst').its('response.statusCode').should('equal', 200) // Continue
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With