From ce1119535da5195e7fba91f33c05db0292fa223a Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Thu, 1 Feb 2024 10:47:00 +0000 Subject: [PATCH] chore: add single versioned implementation of act for DevTools tests --- .../src/__tests__/utils.js | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/packages/react-devtools-shared/src/__tests__/utils.js b/packages/react-devtools-shared/src/__tests__/utils.js index 1a74c1fee9c61..7c310fa219af4 100644 --- a/packages/react-devtools-shared/src/__tests__/utils.js +++ b/packages/react-devtools-shared/src/__tests__/utils.js @@ -7,6 +7,8 @@ * @flow */ +import semver from 'semver'; + import typeof ReactTestRenderer from 'react-test-renderer'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; @@ -14,6 +16,8 @@ import type Store from 'react-devtools-shared/src/devtools/store'; import type {ProfilingDataFrontend} from 'react-devtools-shared/src/devtools/views/Profiler/types'; import type {ElementType} from 'react-devtools-shared/src/frontend/types'; +import {ReactVersion} from '../../../../ReactVersions'; + export function act( callback: Function, recursivelyFlush: boolean = true, @@ -73,6 +77,48 @@ export async function actAsync( } } +const requestedReactVersion = process.env.REACT_VERSION || ReactVersion; +export async function actImplementation(callback: Function): Promise { + // This is for React < 18, where act was distributed in react-dom/test-utils. + if (semver.lt(requestedReactVersion, '18.0.0')) { + return require('react-dom/test-utils').act(callback); + } + + const React = require('React'); + // This is for React 18, where act was distributed in react as unstable. + if (React.unstable_act) { + return React.unstable_act(callback); + } + + // This is for React > 18, where act is marked as stable. + if (React.act) { + return React.act(callback); + } + + throw new Error("Couldn't find any available act implementation"); +} + +export async function actModern(callback: Function): Promise { + const {act: actTestRenderer} = require('react-test-renderer'); + + // act from react-test-renderer has some side effects on React DevTools + // it injects the renderer for DevTools, see ReactTestRenderer.js + await actImplementation(() => { + actTestRenderer(() => { + callback(); + }); + }); + + // Flush Bridge operations + while (jest.getTimerCount() > 0) { + await actImplementation(() => { + actTestRenderer(() => { + jest.runAllTimers(); + }); + }); + } +} + export function beforeEachProfiling(): void { // Mock React's timing information so that test runs are predictable. jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));