cypress: [Cypress 6.0.0] Overriding interceptors doesn't work.
Current behavior
With Version <6.0.0, if you used c.route with a stub, you could then use it again with a new stub and it would take the second fixture for the second request.
With version >6.0.0 It doesn’t happen, the override doesn’t work with cy.intercept and it always returns the initial fixture.
cy.intercept(
{
method: 'GET',
url: 'items',
},
{ fixture: 'items/empty-list.json' }
);
// Some more testing of the app, and then fetching again -
cy.intercept(
{
method: 'GET',
url: 'items',
},
{ fixture: 'items/list-1.json' }
);
The use case is very simple.
Imagine my app loads with 0 items, using a GET.
Then, I do some stuff, do a POST, and then GET those items again.
I want to stub it with [item], instead of the initial [].
So what happens is that it always return [], not [item] as it used to.
I’m quite sure it’s not a problem with my code, used to work perfectly fine till today.
The first image is the initial intercept, you can see it gets 2
The second image is what is shown for the second GET, the one that should’ve matched and return [item]

Desired behavior
I want to be able to override interceptors
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 185
- Comments: 55 (13 by maintainers)
Links to this issue
Commits related to this issue
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Add cypress tests The tests are still failing, because we can't redefine the intercept of the config. A workaround needs to be looked for. See issue: https://github.com/cypress-io/cypress/issues/9302... — committed to hedgedoc/react-client by ErikMichelson 3 years ago
- Update deprecated Cypress methods for network mocking - Replace cy.route() commands with cy.intercept() alternative - Removed cy.server() commands - Add a 'cy.dynamicIntercept()' command to save and ... — committed to davidebriani/astarte-dashboard by deleted user 3 years ago
- Add cypress tests The tests are still failing, because we can't redefine the intercept of the config. A workaround needs to be looked for. See issue: https://github.com/cypress-io/cypress/issues/9302... — committed to hedgedoc/react-client by ErikMichelson 3 years ago
- cypress: Migrate from cy.route API to cy.intercept API cy.route has been deprecated in cypress 6.0 in favor of cy.intercept and will be removed soon. So migrate code stubbing network requests to the... — committed to SoftwareHeritage/swh-web by anlambert 3 years ago
- fix(tests): don't override predefined intercepts Cypress v6 doesn't support overriding `cy.intercept` routes. Instead, we have to define them individually within each tests that they're referenced in... — committed to tutorbookapp/tutorbook by nicholaschiang 3 years ago
This issue blocks me to update to 6.0.0 version
Huge thanks for the Cypress team for all of their hard work on this and other new features. Complex feature changes and new APIs always have some rough edges. Always impressed with the quality of your work. 👏
We are currently looking into ways to make this possible with
cy.intercept()while still maintaining the value of the other features introduced incy.intercept(). There’s some investigation we need to do to ensure all use cases can be covered in a way that makes sense.For the future, it would be useful to mention this critical breaking change in your CHANGELOG or migration guides. All of these resources imply that
cy.interceptis pretty much a drop-in replacement forcy.route:There is nothing indicating the issues mentioned in this thread. I recommend you adjust both articles above and mention this difference for others attempting to upgrade.
I was really excited to use the new
interceptability to be able to dynamically respond to requests with different data based on query params or other URL-specific data. But this omission is even worse than the original problem: it altogether prevents us from testing failure cases. For example: testing that the UI responds as expected to when a given request responds with a200vs when it responds with a404. Is this not an expected use case? Is there an intended workaround I’m missing?The code for this is done in cypress-io/cypress#14543, but has yet to be released. We’ll update this issue and reference the changelog when it’s released.
@flotwig Yes, but for me
cy.interceptis an only reason to upgrade@bhaeussermann Thanks for sharing your feedback! This is very helpful.
We have not ruled out implementing overriding interceptors. It’s just very complex for us to design a clear API for people to override interceptors, have all of the new middleware features of intercept, AND possibly deliver the ‘times’ feature (because we believe this may be valuable outside of just this overwriting scenario).
The intercept should work how people intuitively expect it to work in all of these situations. We don’t want to release something that is confusing. Also we want to make sure that we don’t release an API that we later have to instantly retract due to confusion or introduce unnecessary breaking features, etc.
The team is working on it. Even though there’s not work directly on this exact PR.
The solution involving the “times” property does not seem practical for complex tests. The “counting” aspect seems very brittle, since if one request happened to be called once more than expected by the application, it would immediately be out of sync with the test. This seems like it would be a nightmare to maintain.
It also would not work for my project unless I’d make some drastic changes to my testing code. In a testing file we typically define a function that sets a number of default routes, and then override certain routes in different tests / contexts for testing special cases. Consider the following fictitious code as an illustration:
Being able to override certain routes is the simplest way of achieving the testing logic above. Anything else suggested in this thread would significantly impact the complexity of the testing code.
I don’t understand why allowing to override routes (eg. by matching routes from last backwards instead of forwards) is not a viable solution. Will someone please explain this to me?
This would seriously help us loads with our suite. Our example is a graphql single endpoint, and I want to change certain responses dependent on when we fire mutations. e.g. when we load a table, load with intiial mock data, after firing a successful create record mutation then responding with a new set of mock data to include that record. Structure wise within our tests and app I’m really happy with it, it just all relies on this being possible!
Hey everyone, i ran into the same issues and needed to intercept a route in a test multiple times with different responses, this is the current workaround:
It is indeed a huge blocker. And what @samijaber said:
Inability to overwrite or clear an interceptor should be explicitly stated in the docs.
In my case, I am testing my application to re-authenticate after a failing request and then to retry that failed request with the new credentials. No way to do that if I cannot override or clear the previous interceptor.
Awesome suggestion! Never thought of that! I did the following to use fixtures and also override different status codes:
@jennifer-shehane as for the api design, perhaps being explicit rather than implicit, with like a
cy.clearInterceptmethod could be considered?This would solve several use-cases for us and would be a really important update, not only for our not-so-simple upgrade to cypress 6+ but also for our current suite of tests in general. Having this implementation quickly would be rather significant for us.
+1
Once cy.intercept() is declared for some route, you can not override its behaviour. It is quite annoying and until fixed will block me to update since we usually mock a ‘200’ response, but we also need to test other ones.
Looking forward a pull request to fix it.
So what are we doing with this? Its been a while and I cannot be expected to create a separate context every time I want a different API response mocked on the same url. That’s not a valid solution given our test layouts.
I was hoping to use overriding as a test organization tactic. For example: having several interceptors in a beforeEach, and then having one interceptor override in the more specific test itself to change a single piece of data to test a specific thing. Thus reducing repetition by forcing every test to declare the same intercepts.
@manojhans The issue with cy.get() returning null was fixed in 6.2.0: https://github.com/cypress-io/cypress/issues/9306
We’ve been running into this problem as well - trying to return different stubs for the same request, so we can test different responses.
Our solution is to use
Cypress.config()to set a variable in each different test, and then check for that config variable incy.intercept.In
my-test.spec.ts:And in our
intercepts.jsfile:Values set by
Cypress.config()in a spec file are only in scope for the current spec file, so you don’t need to worry about polluting the global config scope.Hopefully there will be a way to clear/override intercepts introduced soon, but until then this method seems to work well for us!
(11th December 2020)
At this point in time, are you able to say wether interceptors will eventually get overriding behaviour @jennifer-shehane?
I am asking because this issue is preventing us from rolling out some internal tooling using
cy.intercept. If this is eventually going to be implemented, we can wait, but if not we should start building a workaround in our tooling.@ar7casper would the solution in https://github.com/cypress-io/cypress/pull/14513 solve your use-case?
It would use the first fixture just once on the very first request. And it would use the second fixture once, which would happen on the second request from the app
How about this quick monkey patch to solve the issue until an official solution is provided? Works for me with 6.6.0. Just put the following into your commands.js. Not sure about side effects but studying the code did not reveal any downsides of implementing a
clearInterceptthat way.Assume you have defined your intercept as follows
cy.intercept('GET', '.netlify/functions/subjects/[0-9]*').as('GET-one-subject')and calling it like that
cy.wait('@GET-one-subject')then you can clear it with
cy.clearIntercept('GET-one-subject')Here is the command
Update: This does not quite work as expected in all cases. Needs more investigation as more elements of the state seem to be touched.
I believe this is the crux of the issue https://github.com/cypress-io/cypress/blob/197f3097f7beaa09cd4dd1e2a0e9a39610f5ed69/packages/net-stubbing/lib/server/route-matching.ts#L110-L116
Assuming I understand everything correctly - it looks like the order by which the routes are being matched is the original order they’re pushed in.
Changing the code to this might solve it
From what I could tell, previously it let the driver do this matching instead https://github.com/cypress-io/cypress/blob/197f3097f7beaa09cd4dd1e2a0e9a39610f5ed69/packages/driver/src/cypress/server.js#L268-L277
Unfortunately, I don’t have much time setting up a local environment to test & verify that it’s indeed the issue - if anyone wants to do it they’re more than welcome to use my code diff 😃
@FrancoisCamus indeed 😃 Feel free to take a look at the issue comment in #14543 and let me know if it will cover your needs.
@diggabyte, an implementation like
cy.clearIntercept("@alias")is something my team has been desperately wanting since the beginning of our cypress adventure.@pszalanski, in my case, it would be a definitive and sensical way to clear/reset the usage of an intercept.
I.e. “This intercept is no longer registered/valid, is no longer watching/intercepting/stubbing this path and is no longer saving and queuing the requests/responses that can be fetched by
cy.wait("@alias")”It would explicitly do what
timeswould do implicitly. Instead of saying, “Afternuses, this intercept is no longer registered,” it would say, “Unregister this intercept now.”Like the
timesimplementation, this would solve several use-cases for my team. In contrast totimes, however,cy.clearInterceptwould be much easier for us to implement.cy.clearInterceptwould also be, for our cases, preferred over simply allowing intercept overrides (like before). Although it would require extra work for us to implement (as opposed to simply allowing overrides like withroute), it would be useful enough to us in other areas that it would be worth the effort to us.To stress the point and to summarize,
cy.clearInterceptwould be gold for us.timeswould work too, but something likecy.clearInterceptwould be the clear winner by far for my team.@artem-3dhubs can you give us an example of the test and the override logic you want to do?
PS: you can always create more complex programmatic intercepts with overrides yourself since
cy.interceptallows callbacks, like https://glebbahmutov.com/blog/cypress-intercept-problems/#no-overwriting-interceptors-again I feel like we are trying to create a nice syntax around itSame for me. I am using automatically recorded responses to process all the network requests an app does during the test. This logic runs before all the test cases in the test suite and sets up the mocks.
I would like to override some of the specific routes for the particular test case and assert the recorded response. That means I want to discard the previous intercept and apply the new one while keeping the same recorded mock. The
timesoption does not seem to help.I guess I could implement some workaround that will always use the global intercept, but it would be way more straightforward if native API just supported overriding same way as
routedid.Also the way I managed to process multiple mocked responses for the same route with the
routeAPI is by using undocumentednow('route', ...)command that I invoked in route’sonRequestcallback to shift to the next mocked response by effectively overriding the previous route.I was really excited to see the new intercept API that supported possibility to pass mocks at the actual request time. But overriding is still crucial to me.
Let me know if I am missing something or you need some more details about my use case.
Just wanted to add that I am also blocked from updating due to this.
@Tintef What works for me is using a global variable and changing it from within the test (in a ‘then’ callback)
@phishy we were thinking about this and here is how it breaks down in your particular case
Let’s say you set up intercepts in
beforeEachhook. Are they used in the hook itself? A common situation that the author of this issue is experiencing (and I had the same in todomvc tests) is you set up the intercepts and visit the site inside the hook. Let’s say start with empty dataGreat. Now let’s see you want to simulate an API error. What happens when the server says 404 to
GET /todosWell, the above test will NOT work. By the time you override the intercept, the
beforeEachhook has already finished running completely, and the original intercept has returned its empty list. Well, maybe you could trick it, and usecy.reloadinside the testOk, this should work. Or we could use the
{times: 1}approach. On the initial visit we expect the/todosrequest, so let’s set it upJust one more observation: you can always avoid overriding intercepts in my opinion by setting up a new test “stack” of hooks. In our example, we can avoid overriding and
times: 1syntax by:So I am pretty optimistic about
times: Nbeing explicit and declarative way to solve this problem for most (but not all, we understand that there are more case you might want to test) use cases.@flotwig You are right, but the cy.server() and cy.route() was marked as deprecated in Cypress 6.0.0. We then migrated to the intercept() method but now we are having some tests failing because is not overriding.
@jcdesousa shouldn’t block you from anything. cy.route is still available in 6.0.0
This is a blocker for us, we had to stop the migration due to this issue.