Today, we're elevating the power and scope of Cypress' network handling capabilities with the introduction of the cy.intercept
command in Cypress 6.0.
One of the most powerful and beloved features of Cypress are easy network stubbing and spying APIs via cy.route
and cy.server
commands. These commands enable mocking of network responses with test data or fixtures, creation of testing scenarios by delaying response times or manipulating status codes, and much more.
cy.intercept
is the next-generation successor to cy.route
by offering much more flexibility and granular control over handling of the network layer. You will now have out-of-the-box support for intercepting fetch calls, page loads, and resource loads in addition to the pre-existing support for XMLHttpRequests (XHR).
A Quick Dive Into cy.intercept
At first glance, the cy.route
and cy.intercept
APIs may seem similar. For example, to stub a network route with data from a fixture:
// With cy.route
cy.server()
cy.route("/articles", "fixture:great-articles.json")
// With cy.intercept
cy.intercept("/articles", { fixture: "great-articles.json" })
There are three differences between the use of these commands in the above snippet:
cy.intercept
does not require the use ofcy.server
. You can stop usingcy.server
once you fully switch tocy.intercept
.cy.route
can use a shorthand string pattern (fixture:*
) for specifying fixtures as the stubbed response. Withcy.intercept
, the same convenience is achieved with the second orStaticResponse
argument.- The third and invisible difference is that the default request method type with
cy.route
isGET
. This is not the case forcy.intercept
. In the above usage, the response would apply to all request method types. We would need to explicitly specify the method type we wish to intercept withcy.intercept
. Here is one way to do so:
// Stub GET requests to /articles with fixture
cy.intercept("GET", "/articles", { fixture: "great-articles.json" })
Now that we have seen some surface level differences, let's dive in a bit deeper. cy.intercept
offers two new powerful mechanisms: routeMatcher
and routeHandler
. These two are input arguments, and are used like so:
cy.intercept(routeMatcher, routeHandler?)
routeMatcher
is an object that declares granular matching of network calls. Beyond matching against a specific URL or path, you can also match routes against distinct headers and even basic auth credentials. For example, you can intercept and spy on a request to a specific URL that has a specific header:
cy.intercept({
// this RegExp matches any URL beginning with '<http://api.example.com/widgets>'
url: /^http:\\/\\/api\\.example\\.com\\/widgets/
headers: {
'x-requested-with': 'exampleClient'
}
}).as("widgets")
Check out the docs for a full list of matcher properties and usage patterns.
Once a route is matched, an associated routeHandler
can flexibly define what should happen with the interception. An interception can be used to make assertions on requests/responses, statically or dynamically stub responses, modify outgoing requests, and more. Let's take a look at some examples.
A routeHandler
can be defined as a function that receives a request (req
) object. For example, we can use this function to make assertions:
// Assert request body
cy.intercept('POST', '/organization', (req) => {
expect(req.body).to.include('Acme Company')
})
// Assert response body
cy.intercept('/projects', (req) => {
req.reply((res) => {
expect(res.body).to.include('My Project')
})
})
A routeHandler
function can also be used to dynamically modify an incoming response:
cy.intercept('/notification', (req) => {
req.reply((res) => {
// sends a fixture body instead of the existing 'res.body'
res.send({ fixture: 'success.json' })
// delays the response by 1000ms
res.delay(1000)
// throttles the response to 64kbps
res.throttle(64)
})
})
If dynamic stubbing is not desired, we can achieve the same behavior with a StaticResponse
object in place of a function for the routeHandler
:
cy.intercept('/notification', {
fixture: 'success.json',
delayMs: 1000
throttleKbps: 64
})
The versatility to dynamically handle interceptions is quite useful. For example, this functionality can be used to easily intercept specific GraphQL calls:
cy.intercept('POST', '/graphql', (req) => {
if (req.body.includes('mutation')) {
req.alias = 'gqlMutation'
}
})
// assert that a matching request has been made
cy.wait('@gqlMutation')
We've only seen a quick glance at what the new cy.intercept
API unlocks. Check out the docs and recipes for examples and usage patterns.
Migrating to cy.intercept
You may have already been enjoying the capabilities of cy.intercept
since v5.1 via its experimental predecessor, cy.route2
. After upgrading to v6.0, you can simply switch all instances of cy.route2
in your tests to cy.intercept
.
If you're currently happy with cy.route
, there is no rush to switch to cy.intercept
immediately, as cy.route
and cy.server
will be deprecated in the next major version release. However, switching over to the new cy.intercept
from cy.route
should be straightforward along with our docs. If you are ready to make the switch here are two tips to assist your migration:
- When stubbing responses of network routes protected by CORS and/or authentication make sure to include to appropriate headers:
cy.intercept(
{ method: "GET", url: "/bankAccounts" },
{
headers: {
"access-control-allow-origin": window.location.origin,
"Access-Control-Allow-Credentials": "true",
},
body: { results: [] },
}
);
- A 304 Not Modified status should be considered when making status code assertions on responses cached routes:
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
Upgrade to Cypress 6.0
In addition to cy.intercept
check out 6.0 changelog for a full list of fixes and breaking changes. Also make sure to check out the docs and the migration guide to assist with your upgrade.
The Cypress team has been working hard to deliver this versatile and truly useful network handling experience. We're excited to bring these new APIs to Cypress users, and as always we're eager to hear your feedback.
Happy Testing.