main
js 117 lines 2.84 KB
Raw
1 jest.useRealTimers();
2
3 let React;
4 let ReactTestRenderer;
5 let Scheduler;
6 let act;
7 let assertLog;
8
9 describe('ReactTestRenderer.act()', () => {
10 beforeEach(() => {
11 jest.resetModules();
12 React = require('react');
13 ReactTestRenderer = require('react-test-renderer');
14 Scheduler = require('scheduler');
15 act = ReactTestRenderer.act;
16
17 const InternalTestUtils = require('internal-test-utils');
18 assertLog = InternalTestUtils.assertLog;
19 global.IS_REACT_ACT_ENVIRONMENT = true;
20 });
21
22 // @gate __DEV__
23 it('can use .act() to flush effects', () => {
24 function App(props) {
25 const [ctr, setCtr] = React.useState(0);
26 React.useEffect(() => {
27 props.callback();
28 setCtr(1);
29 }, []);
30 return ctr;
31 }
32 const calledLog = [];
33 let root;
34 act(() => {
35 root = ReactTestRenderer.create(
36 <App
37 callback={() => {
38 calledLog.push(calledLog.length);
39 }}
40 />,
41 );
42 });
43
44 expect(calledLog).toEqual([0]);
45 expect(root.toJSON()).toEqual('1');
46 });
47
48 describe('async', () => {
49 // @gate __DEV__
50 it('should work with async/await', async () => {
51 function fetch(url) {
52 return Promise.resolve({
53 details: [1, 2, 3],
54 });
55 }
56 function App() {
57 const [details, setDetails] = React.useState(0);
58
59 React.useEffect(() => {
60 async function fetchDetails() {
61 const response = await fetch();
62 setDetails(response.details);
63 }
64 fetchDetails();
65 }, []);
66 return details;
67 }
68 let root;
69
70 await ReactTestRenderer.act(async () => {
71 root = ReactTestRenderer.create(<App />);
72 });
73
74 expect(root.toJSON()).toEqual(['1', '2', '3']);
75 });
76
77 // @gate __DEV__
78 it('should not flush effects without also flushing microtasks', async () => {
79 const {useEffect, useReducer} = React;
80
81 const alreadyResolvedPromise = Promise.resolve();
82
83 function App() {
84 // This component will keep updating itself until step === 3
85 const [step, proceed] = useReducer(s => (s === 3 ? 3 : s + 1), 1);
86 useEffect(() => {
87 Scheduler.log('Effect');
88 alreadyResolvedPromise.then(() => {
89 Scheduler.log('Microtask');
90 proceed();
91 });
92 });
93 return step;
94 }
95 let root;
96 await act(() => {
97 root = ReactTestRenderer.create(null);
98 });
99 await act(async () => {
100 root.update(<App />);
101 });
102 assertLog([
103 // Should not flush effects without also flushing microtasks
104 // First render:
105 'Effect',
106 'Microtask',
107 // Second render:
108 'Effect',
109 'Microtask',
110 // Final render:
111 'Effect',
112 'Microtask',
113 ]);
114 expect(root).toMatchRenderedOutput('3');
115 });
116 });
117 });