| 1 | # Avoid using a callback in asynchronous tests and hooks (`no-done-callback`)
|
|---|
| 2 |
|
|---|
| 3 | When calling asynchronous code in hooks and tests, `jest` needs to know when the
|
|---|
| 4 | asynchronous work is complete to progress the current run.
|
|---|
| 5 |
|
|---|
| 6 | Originally the most common pattern to achieve this was to use callbacks:
|
|---|
| 7 |
|
|---|
| 8 | ```js
|
|---|
| 9 | test('the data is peanut butter', done => {
|
|---|
| 10 | function callback(data) {
|
|---|
| 11 | try {
|
|---|
| 12 | expect(data).toBe('peanut butter');
|
|---|
| 13 | done();
|
|---|
| 14 | } catch (error) {
|
|---|
| 15 | done(error);
|
|---|
| 16 | }
|
|---|
| 17 | }
|
|---|
| 18 |
|
|---|
| 19 | fetchData(callback);
|
|---|
| 20 | });
|
|---|
| 21 | ```
|
|---|
| 22 |
|
|---|
| 23 | This can be very error-prone however, as it requires careful understanding of
|
|---|
| 24 | how assertions work in tests or otherwise tests won't behave as expected.
|
|---|
| 25 |
|
|---|
| 26 | For example, if the `try/catch` was left out of the above code, the test would
|
|---|
| 27 | time out rather than fail. Even with the `try/catch`, forgetting to pass the
|
|---|
| 28 | caught error to `done` will result in `jest` believing the test has passed.
|
|---|
| 29 |
|
|---|
| 30 | A more straightforward way to handle asynchronous code is to use Promises:
|
|---|
| 31 |
|
|---|
| 32 | ```js
|
|---|
| 33 | test('the data is peanut butter', () => {
|
|---|
| 34 | return fetchData().then(data => {
|
|---|
| 35 | expect(data).toBe('peanut butter');
|
|---|
| 36 | });
|
|---|
| 37 | });
|
|---|
| 38 | ```
|
|---|
| 39 |
|
|---|
| 40 | When a test or hook returns a promise, `jest` waits for that promise to resolve,
|
|---|
| 41 | as well as automatically failing should the promise reject.
|
|---|
| 42 |
|
|---|
| 43 | If your environment supports `async/await`, this becomes even simpler:
|
|---|
| 44 |
|
|---|
| 45 | ```js
|
|---|
| 46 | test('the data is peanut butter', async () => {
|
|---|
| 47 | const data = await fetchData();
|
|---|
| 48 | expect(data).toBe('peanut butter');
|
|---|
| 49 | });
|
|---|
| 50 | ```
|
|---|
| 51 |
|
|---|
| 52 | ## Rule details
|
|---|
| 53 |
|
|---|
| 54 | This rule checks the function parameter of hooks & tests for use of the `done`
|
|---|
| 55 | argument, suggesting you return a promise instead.
|
|---|
| 56 |
|
|---|
| 57 | The following patterns are considered warnings:
|
|---|
| 58 |
|
|---|
| 59 | ```js
|
|---|
| 60 | beforeEach(done => {
|
|---|
| 61 | // ...
|
|---|
| 62 | });
|
|---|
| 63 |
|
|---|
| 64 | test('myFunction()', done => {
|
|---|
| 65 | // ...
|
|---|
| 66 | });
|
|---|
| 67 |
|
|---|
| 68 | test('myFunction()', function (done) {
|
|---|
| 69 | // ...
|
|---|
| 70 | });
|
|---|
| 71 | ```
|
|---|
| 72 |
|
|---|
| 73 | The following patterns are not considered warnings:
|
|---|
| 74 |
|
|---|
| 75 | ```js
|
|---|
| 76 | beforeEach(async () => {
|
|---|
| 77 | await setupUsTheBomb();
|
|---|
| 78 | });
|
|---|
| 79 |
|
|---|
| 80 | test('myFunction()', () => {
|
|---|
| 81 | expect(myFunction()).toBeTruthy();
|
|---|
| 82 | });
|
|---|
| 83 |
|
|---|
| 84 | test('myFunction()', () => {
|
|---|
| 85 | return new Promise(done => {
|
|---|
| 86 | expect(myFunction()).toBeTruthy();
|
|---|
| 87 | done();
|
|---|
| 88 | });
|
|---|
| 89 | });
|
|---|
| 90 | ```
|
|---|