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