Open ezrag26 opened 2 years ago
I just want to support this request and add some more context:
cy.intercept('**/modules/*').as('courseModuleData');
cy.intercept('**/lessons/*').as('courseLessonData');
// Trigger 1 - Triggers @courseLessonData' and '@courseModuleData' requests
// I'm not interested in these ones
cy.get('.module-overview__action a').click();
// Wait A - Commented out, not active
// cy.wait(['@courseLessonData', '@courseModuleData']);
// Trigger 2 - Triggers @courseLessonData' and '@courseModuleData' requests
// I want to wait for these ones
cy.get('.activity-select-right__submit').click();
// Wait B - Refers to the requests from the Trigger 1, not from Trigger 2
cy.wait(['@courseLessonData', '@courseModuleData']);
This seems to happen even when the previous requests (Trigger 1) have finished, I can see that Wait B passes straight away. This is a bit counter-intuitive, probably it should move to at least the next active request, but I believe it would be more intuitive if cy.wait
would target the last request triggered.
If I un-comment the Wait A, then it works fine and the Wait B waits for the requests made by Trigger 2. This seems to mean that cy. wait
relies on the order of the requests (Trigger 1 >> Wait B) and not on the order of the code/events (Trigger 2 >> Wait B).
I couldn't find this behavior documented in the docs. If that is right, it would be nice to have it documented.
Thanks!
If I un-comment the Wait A, then it works fine and the Wait B waits for the requests made by Trigger 2. This seems to mean that
cy. wait
relies on the order of the requests (Trigger 1 >> Wait B) and not on the order of the code/events (Trigger 2 >> Wait B).I couldn't find the behavior documented in the docs. If that is right, it would be nice to have it documented.
I do believe it's documented here regarding cy.wait()
, where it says:
Each time we use cy.wait() for an alias, Cypress waits for the next nth matching request.
So if there were 5 requests matched, no matter when the the 1st use of cy.wait()
is made, it will wait on the 1st matched request to finish, the 2nd use on the 2nd matched request, etc. And if the nth request already finished before that nth use of cy.wait()
, the code will immediately continue.
It seems that in your case you may have a more determinate behavior where you can wait on that first matched request (albeit it do nothing) as you know there will be just 1 before Trigger 2, while for me the number of matched requests will be unknown. But I do agree that our cases are both similar in that we don't care about the previous interceptions up until some specific trigger, and adding a feature like this would certainly seem to be useful.
I found https://github.com/bahmutov/cypress-wait-if-happens really helpful to achieve the desired functionality, among others (conditional requests).
cy.waitIfHappens({
alias: '@users',
timeout: 100,
lastCall: true,
yieldResponseBody: true,
})
.should('have.length', 4)
Interesting, I have thought about doing this before (looping through all the calls in order to get to the last one). I would still love a built-in solution from Cypress, but this is certainly more manageable and understandable than what I currently have in place.
Thanks for sharing the find!
I'm using Cypress mostly for Component Testing and this would be great, it would be even better if Cypress would reset the intercept
calls between tests, as now they're "global" and leaking over to the next test making it hard to manage them.
@piotrpalek You are referring to https://github.com/cypress-io/cypress/issues/20397.
The ask in this issue is to clear intercepts mid-test and/or provide a way to verify the intercept call out to verify the requests/responses.
I hit the same issue, found a workaround which will loop over the current list of intercepted requests and run cy.wait on any that haven't been waited on yet. Then can trigger the action and know that the next time I call wait it will be for the brand new request.
I've put this into a custom command so it's easy to call from the tests.
Cypress.Commands.add('clearInterceptList', (interceptAlias) => {
// clears the list of intercepted requests by waiting for each one
// intercept alias should be in the form '@postExample' etc.
cy.get(interceptAlias + '.all').then((browserRequests) => {
for (let request of browserRequests) {
if (request.responseWaited === false) {
cy.wait(interceptAlias)
}
}
})
})
Then can call this from the test like cy.clearInterceptList('@requestAlias')
etc.
I hit the same issue. The workaround from @dmbartle worked like a charm with a small mod: The request I was aliasing was being hit 6 times. I actually just wanted to wait on the last one. But because of Cypress speed (and my test flow) some times some of those requests were being canceled. When that happened the for loop was still invoking 6 waits, but because some were canceled a wait was just timing out. The fix is simple, only wait for the request if it was not received; which is the equivalent of a canceled request for the browser. if (request.requestWaited === false && request.state !== "Received") {
I hope this helps someone else until we get the real feature.
I have the same issue. Native cypress method to clear previously intercepted routes will be super useful. The workaround from @dmbartle works perfect for me with a small mod:
Cypress.Commands.add('clearInterceptList', (interceptAlias) => {
// clears the list of intercepted requests for the same alias by waiting for each one
cy.get(`@${interceptAlias}.all`).then((browserRequests: JQuery<HTMLElement>) => {
for (let request of browserRequests) {
const req = request as unknown as { responseWaited: boolean };
if (req.responseWaited === false) {
cy.wait(`@${interceptAlias}`)
}
}
})
});
Thank you @dmbartle .
What would you like?
I'd like to be able to clear previously intercepted routes so that waiting on an aliased intercept will now start from the next interception.
Example:
Why is this needed?
If the number of requests is unknown beforehand, using
cy.wait()
on the same alias is not useful.For example, I have a request that is called every X seconds, and I want to compare the state after taking some action. There may or may not have been one or more requests between:
I cannot rely on
cy.wait()
being called two times, or three times, etc.Currently I do the following:
But, as noted, it's not ideal to created a new
cy.intercept()
call and alias for really the same intercept.Other
23190 - discussion on the same point