I love using Sentry for tracking errors in my web applications. Recently I have added crash reporting to our open source 350-mass-cambridge-somerville/350-actions-client project in pull request #24 - see the app at https://www.maclimateactions.com/.
The entire web application is tested using Cypress - let's validate that the app is sending a crash report to Sentry service using an end-to-end test too. Let's start a placeholder test that opens the app and does nothing.
1 | describe('current action', () => { |
Once the test runs and stops, open the DevTools inside Cypress. Switch to the application's context using a drop down. A nice trick to throw an unhandled exception in the application, and not in the DevTools it to make it asynchronous - for example by using setTimeout
function. You can do setTimeout(() => { throw new Error('test error') }, 1000)
and see Sentry handler executing an XHR call.
Note: by default, Sentry uses fetch
protocol to send the error object to its service API. Since Cypress does not support stubbing fetch
requests yet, we force every client-side library to drop down to XHR using the example from "Stubbing window.fetch" recipe. We simply delete the window.fetch
property when every window is created.
1 | let polyfill |
Let's confirm this call happens. We need to prepare to intercept the call from the test. Look at the call's details, especially at the method and the destination URL.
Also look at the response object the Sentry service sends back to the caller.
Let's stub this route using cy.route
command and response with similar object.
1 | it('sends an error to Sentry', () => { |
The test runs - and we can see the stubbed XHR call to Sentry correctly detected (and stopped)
Great, but - a thrown error is still a thrown error, and Cypress treats is as a test failure. Thus we need to handle it as described in the blog post Testing Edge Data Cases with Network Stubbing and App Actions. We will expect uncaught:exception
event and will confirm it has our test error message and not some other actual application error.
1 | it('sends an error to Sentry', () => { |
The test passes. Let's confirm some of the fields the Sentry browser client sends to the service - it should have at least the error message.
1 | // confirm the call has happened |
Tip: writing XHR assertions this way is cumbersome, I suggest using helper library cy-spok in the blog post Asserting Network Calls from Cypress Tests.
See also
- Connecting crash reporting with end to end tests shows how to add additional test information to Sentry crashes happening during end-to-end tests
- Simple Ajax testing shows how to observe calls to Sentry from Node tests
- Know unknown unknowns with Sentry is probably my first blog post praising Sentry
Update 1: use cy.intercept
After updating to cy.intercept command, my Sentry test is much simpler:
1 | // intercept all network requests going to sentry.io |