Skip to content

Commit bf7bb9d

Browse files
authored
Update errors recipe (#717)
* show example with waiting for an error * update unhandled project rejection spec file
1 parent 3db5c4c commit bf7bb9d

File tree

5 files changed

+70
-30
lines changed

5 files changed

+70
-30
lines changed

examples/fundamentals__errors/README.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ If an application throws an error, it fails the Cypress test automatically.
1010

1111
You can see how to ignore such errors in [cypress/integration/app-error.js](./cypress/integration/app-error.js) spec file.
1212

13+
```js
14+
// inspect the caught error
15+
cy.on('uncaught:exception', (e) => {
16+
if (e.message.includes('Things went bad')) {
17+
// we expected this error, so let's ignore it
18+
// and let the test continue
19+
return false
20+
}
21+
// on any other error message the test fails
22+
})
23+
```
24+
25+
Make sure the test is long enough or waits for the error to happen!
26+
1327
See short video about this topic here: [https://www.youtube.com/watch?v=DwVezYq4zPM](https://www.youtube.com/watch?v=DwVezYq4zPM)
1428

1529
## Test fails
@@ -22,13 +36,7 @@ You can listen to the "fail" events and return false to NOT fail the test, as [c
2236

2337
## Unhandled promise rejections in the application
2438

25-
If the application code creates an unhandled rejected promise, Cypress does NOT see it by default and continues with the test. If you want to fail the test, listen to the unhandled promise event and throw an error.
26-
27-
![Test failing after an application has unhandled rejected promise](./images/unhandled-promise.gif)
28-
29-
You can register your own unhandled promise event listener during `cy.visit` as [cypress/integration/unhandled-promise.js](./cypress/integration/unhandled-promise.js) shows. Or you can register the window handler for all tests using `Cypress.on('window:before:load')` call, see [cypress/integration/unhandled-promise2.js](./cypress/integration/unhandled-promise2.js).
30-
31-
You can also watch a small video explaining it here: [https://www.youtube.com/watch?v=VY9yVle8LRQ](https://www.youtube.com/watch?v=VY9yVle8LRQ)
39+
Cypress v7+ automatically fails the test if the application has an unhandled promise rejection event. See the [cypress/integration/unhandled-promise.js](./cypress/integration/unhandled-promise.js) spec file.
3240

3341
## Unhandled promise rejections in the test code
3442

examples/fundamentals__errors/app.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ document.getElementById('promise').addEventListener('click', () => {
1414
new Promise((resolve, reject) => {
1515
setTimeout(() => {
1616
console.log('application is about to reject a promise')
17-
reject('Did not handle this promise')
17+
// important: reject with an Error object
18+
reject(new Error('Did not handle this promise'))
1819
}, 1000)
1920
})
2021
})

examples/fundamentals__errors/cypress/integration/app-error.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,42 @@ describe('App error', () => {
3636
cy.visit('index.html')
3737
cy.get('button#error').click()
3838
// the error happens after 1000ms
39+
// we can use hard-coded wait, see the other test
40+
// to learn how to avoid an unnecessary wait
3941
cy.wait(1500)
4042
})
43+
44+
// if the test finishes before the error is thrown -
45+
// the test is still passing!
46+
// NOTE: just a demo of the test that does not wait for an error
47+
it.skip('does not wait for the error', () => {
48+
cy.visit('index.html')
49+
cy.get('button#error').click()
50+
// the thrown error is "lost" because the test finishes
51+
})
52+
53+
// we can avoid hard-coded waits in the test
54+
// by using Cypress retry-ability
55+
// https://on.cypress.io/retry-ability
56+
it('waits for the error', () => {
57+
// place any caught errors in this object
58+
const caught = {
59+
message: null,
60+
}
61+
62+
cy.on('uncaught:exception', (e) => {
63+
caught.message = e.message
64+
65+
// ignore the error
66+
return false
67+
})
68+
69+
cy.visit('index.html')
70+
cy.get('button#error').click()
71+
72+
// waits for the error and confirms the message
73+
cy.wrap(caught).should((c) => {
74+
expect(c.message).to.include('Things went bad')
75+
})
76+
})
4177
})

examples/fundamentals__errors/cypress/integration/unhandled-promise.js

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,32 @@
22

33
/* eslint-disable no-console */
44
describe('Unhandled promises', () => {
5-
// NOTE: this test will pass in Cypress < 7.0 and fail in Cypress 7.0+
6-
it.skip('does not affect the Cypress test', () => {
5+
// NOTE: this test fails in Cypress 7.0+
6+
it.skip('fail the Cypress test', () => {
77
cy.visit('index.html')
88
cy.get('button#promise').click()
99
// the unhandled promise happens after 1000ms
1010
cy.wait(1500)
11-
// but our test happily finishes
1211
})
1312

14-
// NOTE: skipping the test because it shows how to fail the test for real
15-
it.skip('fails Cypress test if we register our own handler', () => {
16-
// we can install our handler to listen for unhandled rejected promises
17-
// in the application code and fail the test
18-
cy.visit('index.html', {
19-
onBeforeLoad (win) {
20-
// https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event
21-
win.addEventListener('unhandledrejection', (event) => {
22-
const msg = `UNHANDLED PROMISE REJECTION: ${event.reason}`
13+
it('handles the promise rejection', () => {
14+
// place any caught errors in this object
15+
const caught = {
16+
message: null,
17+
}
2318

24-
// fail the test
25-
throw new Error(msg)
26-
})
27-
},
19+
cy.on('uncaught:exception', (e, runnable, promise) => {
20+
caught.message = e.message
21+
22+
return false
2823
})
2924

30-
cy.get('button#promise').click()
31-
// the unhandled promise happens after 1000ms
32-
cy.wait(1500)
33-
})
25+
cy.visit('index.html')
3426

35-
afterEach(() => {
36-
console.log('afterEach')
27+
cy.get('button#promise').click()
28+
// waits for the error and confirms the message
29+
cy.wrap(caught).should((c) => {
30+
expect(c.message).to.include('Did not handle this promise')
31+
})
3732
})
3833
})
Binary file not shown.

0 commit comments

Comments
 (0)