cy.wait() timeout even though XHR requests were made (graphql requests)
See original GitHub issueCurrent behavior:
We have a project using Relay which uses a single GraphQL API endpoint. Due to route nesting, most pages in this project call the GraphQL endpoint several times (anywhere from 2 to 6 calls) causing a waterfall of API calls.
To test if a page has loaded correctly we define a beforeEach
block that starts cy.server()
and defines the route cy.route('POST', '/graphql').as('graphql')
. Then in the it(...)
block we cy.visit('/')
the page and then call cy.wait('@graphql')
as many times as the endpoint gets hit.
Now requests to the endpoint always happen in the same order but responses do not (which is to be expected). When responses come back cy.wait()
will sometimes get confused and timeout.
For example. Let’s say the page does 3 requests and so we wait 3 times. The first request comes back and the first wait will pick it up. Now the test is waiting for the second request to resolve but the third request comes back instead before the second one. The second wait will then pick up the third response and the test continues to the third wait. Then the second response comes back but the third wait will not pick it up and times out saying that a response never occurred.
It might be that the second request resolved last but before the third cy.wait()
call.
I hope this is not too confusing 😃
Here’s a screenshot of what I just explained. Note the response order in the console and that they all resolved correctly but cy.wait()
timed out anyways.
Here is the same test passing.
The more cy.wait()
s the higher the failure rate of the test. if you’re only waiting for two requests it rarely fails.
We get the same behavior if we call cy.wait(['@graphql', '@graphql', '@graphql'])
Here’s the example test code. I’ll be linking the repo below
/// <reference types="Cypress" />
const getQueryName = function(xhr) {
const regexp = /\w+Query/gm;
const match = xhr.requestBody.query.match(regexp);
return match[0];
};
context("Wait issue", () => {
beforeEach(() => {
cy.server();
cy.route({
method: "POST",
url: "**/next-js-with-relay-modern-example",
// optional route config added only for debugging
onRequest: xhr => console.log("onRequest:", getQueryName(xhr)),
onResponse: xhr => console.log("onResponse:", getQueryName(xhr)),
onAbort: args => console.log("onAbort:", args)
}).as("query");
});
it("does not timeout 01", () => {
// first we vist url which triggers
// waterfall calls to graphql endpoint
cy.visit("/");
// now we wait for requests to resolve
// NOTE: .then(...) added only for debugging
cy.wait("@query").then(xhr => cy.log("query1:", getQueryName(xhr)));
cy.wait("@query").then(xhr => cy.log("query2:", getQueryName(xhr)));
cy.wait("@query").then(xhr => cy.log("query3:", getQueryName(xhr)));
cy.wait("@query").then(xhr => cy.log("query4:", getQueryName(xhr)));
cy.wait("@query").then(xhr => cy.log("query5:", getQueryName(xhr)));
});
});
Desired behavior:
cy.wait()
picks up all responses correctly and does not timeout
Steps to reproduce: (app code and test code)
I have created an example project repo that you can clone and run locally
git clone git@github.com:daironmichel/cypress-wait-timeout-example.git
cd cypress-wait-timeout-example
yarn install
yarn dev
run test on cypress
yarn run cypress open
Run wait.spec.js
Note: You might need to run it 2 or 3 times to see it fail.
Versions
cypress 3.8.0
Issue Analytics
- State:
- Created 4 years ago
- Reactions:38
- Comments:39 (9 by maintainers)
I have also run into this issue with regular XHR requests. I created a test project that reproduces the issue by forcing a delay on the first request.
I was about to open up a new issue when I found this one, so I’ll just put my information and example here
Current behavior:
When you use a cy.wait() on an aliased route that matches two simultaneous requests, and the second request completes before the first one, cy.wait() yields the second request, and a second cy.wait() does not yield anything. Two requests were made that match the route, but only one is ever yielded.
Order of operations:
Desired behavior:
cy.wait() is able to yield both API calls that match the route, no matter the order in which they resolve.
Test code to reproduce
https://github.com/EricPalmer22/CypressExample
Versions
Cypress 4.1.0 Browser: Chrome
Any progress on this issue @jennifer-shehane?