Skip to content
This repository was archived by the owner on Jul 30, 2020. It is now read-only.

Commit 840fc0a

Browse files
authored
fix(act): improve async act detection (#50)
1 parent 06fe158 commit 840fc0a

File tree

6 files changed

+349
-42
lines changed

6 files changed

+349
-42
lines changed

cleanup-after-each.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
afterEach(require('./dist').cleanup);
1+
afterEach(() => {
2+
return require('./dist/cleanup-async')();
3+
});

src/__tests__/new-act.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
let asyncAct;
2+
3+
jest.mock('react-test-renderer', () => ({
4+
act: cb => {
5+
return cb();
6+
},
7+
}));
8+
9+
beforeEach(() => {
10+
jest.resetModules();
11+
asyncAct = require('../act-compat').asyncAct;
12+
jest.spyOn(console, 'error').mockImplementation(() => {});
13+
});
14+
15+
afterEach(() => {
16+
console.error.mockRestore();
17+
});
18+
19+
test('async act works when it does not exist (older versions of react)', async () => {
20+
const callback = jest.fn();
21+
await asyncAct(async () => {
22+
await Promise.resolve();
23+
await callback();
24+
});
25+
expect(console.error).toHaveBeenCalledTimes(0);
26+
expect(callback).toHaveBeenCalledTimes(1);
27+
28+
callback.mockClear();
29+
console.error.mockClear();
30+
31+
await asyncAct(async () => {
32+
await Promise.resolve();
33+
await callback();
34+
});
35+
expect(console.error).toHaveBeenCalledTimes(0);
36+
expect(callback).toHaveBeenCalledTimes(1);
37+
});
38+
39+
test('async act recovers from errors', async () => {
40+
try {
41+
await asyncAct(async () => {
42+
await null;
43+
throw new Error('test error');
44+
});
45+
} catch (err) {
46+
console.error('call console.error');
47+
}
48+
expect(console.error).toHaveBeenCalledTimes(1);
49+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
50+
Array [
51+
Array [
52+
"call console.error",
53+
],
54+
]
55+
`);
56+
});
57+
58+
test('async act recovers from sync errors', async () => {
59+
try {
60+
await asyncAct(() => {
61+
throw new Error('test error');
62+
});
63+
} catch (err) {
64+
console.error('call console.error');
65+
}
66+
expect(console.error).toHaveBeenCalledTimes(1);
67+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
68+
Array [
69+
Array [
70+
"call console.error",
71+
],
72+
]
73+
`);
74+
});
75+
76+
/* eslint no-console:0 */

src/__tests__/no-act.js

+72-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,80 @@
1-
import { act } from '../';
1+
let act, asyncAct;
2+
3+
beforeEach(() => {
4+
jest.resetModules();
5+
act = require('..').act;
6+
asyncAct = require('../act-compat').asyncAct;
7+
jest.spyOn(console, 'error').mockImplementation(() => {});
8+
});
9+
10+
afterEach(() => {
11+
console.error.mockRestore();
12+
});
213

314
jest.mock('react-test-renderer', () => ({}));
415

516
test('act works even when there is no act from test renderer', () => {
617
const callback = jest.fn();
718
act(callback);
819
expect(callback).toHaveBeenCalledTimes(1);
20+
expect(console.error).toHaveBeenCalledTimes(0);
21+
});
22+
23+
test('async act works when it does not exist (older versions of react)', async () => {
24+
const callback = jest.fn();
25+
await asyncAct(async () => {
26+
await Promise.resolve();
27+
await callback();
28+
});
29+
expect(console.error).toHaveBeenCalledTimes(0);
30+
expect(callback).toHaveBeenCalledTimes(1);
31+
32+
callback.mockClear();
33+
console.error.mockClear();
34+
35+
await asyncAct(async () => {
36+
await Promise.resolve();
37+
await callback();
38+
});
39+
expect(console.error).toHaveBeenCalledTimes(0);
40+
expect(callback).toHaveBeenCalledTimes(1);
41+
});
42+
43+
test('async act recovers from errors', async () => {
44+
try {
45+
await asyncAct(async () => {
46+
await null;
47+
throw new Error('test error');
48+
});
49+
} catch (err) {
50+
console.error('call console.error');
51+
}
52+
expect(console.error).toHaveBeenCalledTimes(1);
53+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
54+
Array [
55+
Array [
56+
"call console.error",
57+
],
58+
]
59+
`);
60+
});
61+
62+
test('async act recovers from sync errors', async () => {
63+
try {
64+
await asyncAct(() => {
65+
throw new Error('test error');
66+
});
67+
} catch (err) {
68+
console.error('call console.error');
69+
}
70+
expect(console.error).toHaveBeenCalledTimes(1);
71+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
72+
Array [
73+
Array [
74+
"call console.error",
75+
],
76+
]
77+
`);
978
});
79+
80+
/* eslint no-console:0 */

src/__tests__/old-act.js

+73-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,51 @@
1-
import { asyncAct } from '../act-compat';
1+
let asyncAct;
2+
3+
beforeEach(() => {
4+
jest.resetModules();
5+
asyncAct = require('../act-compat').asyncAct;
6+
jest.spyOn(console, 'error').mockImplementation(() => {});
7+
});
8+
9+
afterEach(() => {
10+
console.error.mockRestore();
11+
});
212

313
jest.mock('react-test-renderer', () => ({
414
act: cb => {
5-
const promise = cb();
15+
cb();
616
return {
717
then() {
8-
console.error('blah, do not do this');
9-
return promise;
18+
console.error(
19+
'Warning: Do not await the result of calling TestRenderer.act(...), it is not a Promise.',
20+
);
1021
},
1122
};
1223
},
1324
}));
1425

1526
test('async act works even when the act is an old one', async () => {
16-
jest.spyOn(console, 'error').mockImplementation(() => {});
1727
const callback = jest.fn();
1828
await asyncAct(async () => {
29+
console.error('sigil');
1930
await Promise.resolve();
2031
await callback();
32+
console.error('sigil');
2133
});
22-
expect(console.error.mock.calls).toMatchInlineSnapshot(`Array []`);
34+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
35+
Array [
36+
Array [
37+
Array [
38+
"sigil",
39+
],
40+
],
41+
Array [
42+
"It looks like you're using a version of react-test-renderer that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least [email protected] to remove this warning.",
43+
],
44+
Array [
45+
"sigil",
46+
],
47+
]
48+
`);
2349
expect(callback).toHaveBeenCalledTimes(1);
2450

2551
// and it doesn't warn you twice
@@ -32,6 +58,46 @@ test('async act works even when the act is an old one', async () => {
3258
});
3359
expect(console.error).toHaveBeenCalledTimes(0);
3460
expect(callback).toHaveBeenCalledTimes(1);
61+
});
3562

36-
console.error.mockRestore();
63+
test('async act recovers from async errors', async () => {
64+
try {
65+
await asyncAct(async () => {
66+
await null;
67+
throw new Error('test error');
68+
});
69+
} catch (err) {
70+
console.error('call console.error');
71+
}
72+
expect(console.error).toHaveBeenCalledTimes(2);
73+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
74+
Array [
75+
Array [
76+
"It looks like you're using a version of react-test-renderer that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least [email protected] to remove this warning.",
77+
],
78+
Array [
79+
"call console.error",
80+
],
81+
]
82+
`);
3783
});
84+
85+
test('async act recovers from sync errors', async () => {
86+
try {
87+
await asyncAct(() => {
88+
throw new Error('test error');
89+
});
90+
} catch (err) {
91+
console.error('call console.error');
92+
}
93+
expect(console.error).toHaveBeenCalledTimes(1);
94+
expect(console.error.mock.calls).toMatchInlineSnapshot(`
95+
Array [
96+
Array [
97+
"call console.error",
98+
],
99+
]
100+
`);
101+
});
102+
103+
/* eslint no-console:0 */

0 commit comments

Comments
 (0)