How can I catch and log network failures in Cypress? For example, if any network request had a response with status code 500 or 404 or whatever, I want to log that request (the payload and the response). How can I do that?
-
When you say 'log', do you mean at a terminal, browser dev console, or test runner level? – jjhelguero Aug 01 '22 at 15:12
-
the terminal or the browser console, I just want to be able to see these errors – Hesham Moneer Aug 02 '22 at 08:19
2 Answers
Cypress will already log network failures in the runner log, but in case you are using cypress run
or just wanting a file of the failed requests
const networkFails = []
const saveNetworkFails = () => {
cy.writeFile('cypress/fixtures/networkFails.json', networkFails)
}
it('tests a page with network failures', () => {
cy.intercept('*', (request) => {
request.continue(response => {
if(response.statusMessage !== "OK") {
networkFails.push({request, response})
}
})
})
cy.visit('/');
cy.get('divx') // incorrect select, fails the test
});
after(() => {
saveNetworkFails() // runs after all tests, even when test fails
})
The after()
hook is an appropriate place to collect the failures, as you need to wait for all calls to complete.
I was under the impression that when a test failed the after()
hook did not run. Added a deliberate test failure, and still get the output log so that problem seems to be resolved.
This is a sample of the log
[
{
"request": {
"headers": {
"host": "jsonplaceholder.typicode.com",
"connection": "keep-alive",
"sec-ch-ua": "\".Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"",
"sec-ch-ua-mobile": "?0",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
"sec-ch-ua-platform": "\"Windows\"",
"accept": "*/*",
"origin": "http://localhost:49299",
"sec-fetch-site": "cross-site",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
"referer": "http://localhost:49299/",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8"
},
"url": "https://jsonplaceholder.typicode.com/todosx/200",
"method": "GET",
"httpVersion": "1.1",
"body": "",
"responseTimeout": 30000,
"query": {}
},
"response": {
"headers": {
"date": "Tue, 02 Aug 2022 00:44:04 GMT",
"content-type": "application/json; charset=utf-8",
"content-length": "2",
"connection": "keep-alive",
"x-powered-by": "Express",
"x-ratelimit-limit": "1000",
"x-ratelimit-remaining": "999",
"x-ratelimit-reset": "1659400611",
"access-control-allow-origin": "http://localhost:49299",
"vary": "Origin, Accept-Encoding",
"access-control-allow-credentials": "true",
"cache-control": "max-age=43200",
"pragma": "no-cache",
"expires": "-1",
"x-content-type-options": "nosniff",
"etag": "W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"",
"via": "1.1 vegur",
"cf-cache-status": "HIT",
"age": "459",
"expect-ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
"report-to": "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=FXxz%2F6N6WpJOsocFL%2FL34evrZrqa0bnDtWnLpqtCSOFXmdlqeDBdeuKAmxmHrpc7rAGfyvytfm5jbXAcWxXpcwEMA8rt%2FnDJgm6HQzCV%2FXFbtNEXLofmEAk%2FD5xYVsVKc%2Flbb2F%2B0%2Bu0SDTwqovs\"}],\"group\":\"cf-nel\",\"max_age\":604800}",
"nel": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}",
"server": "cloudflare",
"cf-ray": "7342c871cb55a8bf-SYD",
"alt-svc": "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
},
"url": "https://jsonplaceholder.typicode.com/todosx/200",
"method": null,
"httpVersion": "1.1",
"statusCode": 404,
"statusMessage": "Not Found",
"body": {}
}
}
]

- 23,754
- 3
- 20
- 37
-
This solution works perfectly except in one scenario: If the request has no response. Then, I get this error message, "A callback was provided to intercept the upstream response, but a network error occurred while making the request: Error: socket hang up." Any idea how to handle that? – Hesham Moneer Aug 22 '22 at 16:35
-
A request with no response would have to have a timeout to be noticed, maybe you would have to run the test long enough to notice it. You obviously could record something for each request and match up on each response, but it's going to get more complicated. – Fody Aug 22 '22 at 21:58
One way would be to have a general intercept that listens to every call, and logs any non-200/300 status. This can be done either immediately after the call returns, or at the conclusion of any test.
cy.intercept("**/**", (req) => { // matcher could be more specific to only your baseUrl
req.continue((res) => {
if (res.statusCode >= 400) {
console.log(res); // Cypress can't cy.log() here
}
});
}).as("myRequest"); // alias only needed if attempting to print failures after test
cy.get("@myRequest.all").then((calls: any) => { // grab all requests by the alias
calls.forEach((call) => {
if (call.response.statusCode >= 400) {
console.log(call.response); // We can console.log() or cy.log() here
cy.log(call.response);
}
});
});
Additionally, you could turn these into custom commands for re-usability, or place them in a beforeEach()
and afterEach()
in your support file, to have them behave as global before/afterEach.
Note: placing this intercept in a global beforeEach()
would most likely override any other intercepts you are attempting to use in tests.
Second Note: cy.request()
is unable to be intercepted by cy.intercept()
so keep that in mind that any requests made via cy.request()
will not be caught.

- 5,818
- 1
- 7
- 20