Playing with experimental network stubbing feature in Cypress

September 28th, 2020
5 min read

EDIT: Experimental network stubbing was released with v6 and .route2() command was renamed to .intercept(). Also, .route() command was deprecated in this version. To see how you can migrate your .route() commands to .intercept(), I recommend reading my blogpost on it. You’ll find examples and many useful links there.

In the beginning of September, Cypress released a new experimental feature called experimentalNetworkStubbing. I was watching development on Github for a while and was really excited when I started seeing some rapid movement on the issue. I decided to have a closer look into what it does. I share code examples here, but if you want to play with this I have put together a quick and dirty repo. Clone → npm install, → npm start → npx cypress open and you’re good to go.

With version 5.1.0 or higher, you can enable this feature by adding following line into your cypress.json file:

Copy to clipboard
undefined

This enables you to use .route2() command which is described in Cypress documentation. Imagine .route() command, but on steroids. You’ll see in a minute.

The power of .route()

If anyone ever asked me about my favourite command in Cypress, it would be .route(). With a simple syntax you can watch your api call being made:

Copy to clipboard
undefined

After our app is opened, it loads a list of items from database. To do that, it calls a GET request to the /todos url. Response comes back as a simple json file which is then rendered in our app. If you want to change this response and provide your app with your own json list of items, just add another parameter:

Copy to clipboard
undefined

This is simple, yet very powerful thing you do to test your application. .route() command enables you to look into any xhr request your application makes and test it. You can combine your api and ui tests into one.

The problem with this command though, is that you can only work with xhr requests. This rules out fetch requests, or other assets loaded via network. If you tried to route fetch request, you would end up like this:

The power of .route2()

With .route2() command you can route fetch requests just as you would do with XHR. Pretty neat.

Copy to clipboard
undefined

That’s not all though. You can route static files such as css or images. This can become super handy if you want to test a website with lazy loaded images:

Copy to clipboard
undefined

But there’s more! With .route2() command you can not only change response of your api call, but also request itself. Let’s say we want to add a custom header to our request to let the server know that these are coming from application that is being tested at the moment. You can manipulate your request headers like this:

Copy to clipboard
undefined

This new header cannot be observed in network panel in DevTools, because the request manipulation actually happens outside of browser - before the request is sent to the server. Because of that, DevTools show the original request headers. But in the terminal where you ran your npm start command, you can see that I’m logging all request headers for POST /todos request and our newly added header is visible there:

Copy to clipboard
undefined

In the same way we have changed our headers, we are able to change request body. Our application takes title of todo item from our text input. Once we hit enter key, that input is sent via fetch request to our server. When using .route2() we can actually change what is being sent to server, or even add our own data.

Copy to clipboard
undefined

All these examples can be found in a repo that I have put together for this blog. Feel free to play around with it and let me know on Twitter, what you think of this new feature. In my perspective Cypress team has done amazing job here, and I’m excited about possibilities this change will bring.

EDIT: Gleb Bahmutov from Cypress wrote a really cool blog on differences between .route() and .route2() commands, where he demonstrates some cool stuff you can do with .route2(). You should definitely check it out.

Let’s keep in touch

From time to time I send some useful tips to your inbox and let you know about upcoming events. Sign up if you want to stay in loop.

is required.

I treat your email address like I would my own. That means no ads. Just notifications of when I do cool stuff. Unsubscribe anytime. Click here to read about how I handle your data