|
7 | 7 | * @flow
|
8 | 8 | */
|
9 | 9 |
|
| 10 | +import semver from 'semver'; |
| 11 | + |
10 | 12 | import typeof ReactTestRenderer from 'react-test-renderer';
|
11 | 13 |
|
12 | 14 | import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
|
13 | 15 | import type Store from 'react-devtools-shared/src/devtools/store';
|
14 | 16 | import type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types';
|
15 | 17 | import type {ElementType} from 'react-devtools-shared/src/frontend/types';
|
16 | 18 |
|
| 19 | +import {ReactVersion} from '../../../../ReactVersions'; |
| 20 | + |
17 | 21 | export function act(
|
18 | 22 | callback: Function,
|
19 | 23 | recursivelyFlush: boolean = true,
|
@@ -73,6 +77,48 @@ export async function actAsync(
|
73 | 77 | }
|
74 | 78 | }
|
75 | 79 |
|
| 80 | +const requestedReactVersion = process.env.REACT_VERSION || ReactVersion; |
| 81 | +export async function actImplementation(callback: Function): Promise<void> { |
| 82 | + // This is for React < 18, where act was distributed in react-dom/test-utils. |
| 83 | + if (semver.lt(requestedReactVersion, '18.0.0')) { |
| 84 | + return require('react-dom/test-utils').act(callback); |
| 85 | + } |
| 86 | + |
| 87 | + const React = require('React'); |
| 88 | + // This is for React 18, where act was distributed in react as unstable. |
| 89 | + if (React.unstable_act) { |
| 90 | + return React.unstable_act(callback); |
| 91 | + } |
| 92 | + |
| 93 | + // This is for React > 18, where act is marked as stable. |
| 94 | + if (React.act) { |
| 95 | + return React.act(callback); |
| 96 | + } |
| 97 | + |
| 98 | + throw new Error("Couldn't find any available act implementation"); |
| 99 | +} |
| 100 | + |
| 101 | +export async function actModern(callback: Function): Promise<void> { |
| 102 | + const {act: actTestRenderer} = require('react-test-renderer'); |
| 103 | + |
| 104 | + // act from react-test-renderer has some side effects on React DevTools |
| 105 | + // it injects the renderer for DevTools, see ReactTestRenderer.js |
| 106 | + await actImplementation(() => { |
| 107 | + actTestRenderer(() => { |
| 108 | + callback(); |
| 109 | + }); |
| 110 | + }); |
| 111 | + |
| 112 | + // Flush Bridge operations |
| 113 | + while (jest.getTimerCount() > 0) { |
| 114 | + await actImplementation(() => { |
| 115 | + actTestRenderer(() => { |
| 116 | + jest.runAllTimers(); |
| 117 | + }); |
| 118 | + }); |
| 119 | + } |
| 120 | +} |
| 121 | + |
76 | 122 | export function beforeEachProfiling(): void {
|
77 | 123 | // Mock React's timing information so that test runs are predictable.
|
78 | 124 | jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));
|
|
0 commit comments