@samitouri / QOS-React / commits / bf7e210cb5

tests[react-devtools]: added tests for Compiler integration (#31241)

Adds tests for Compiler integration. This includes: - Tests against Compiler from source. - Versioned (18.2 - <19) tests against Compiler from npm. For tests against React 18.2, I had to download `react-compiler-runtime` from npm and put it to `react/compiler-runtime.js`.

Ruslan Lesiutin committed Oct 17, 2024 at 09:02 UTC bf7e210cb5672685bfe992a3b253880f5a3d47f5
3 files changed +120 -1
.github/workflows/devtools_regression_tests.yml
+1
@@ -103,6 +103,7 @@ jobs:
103 - "16.8" # hooks
104 - "17.0"
105 - "18.0"
106 + - "18.2" # compiler polyfill
107 continue-on-error: true
108 steps:
109 - uses: actions/checkout@v4
packages/react-devtools-shared/src/__tests__/compiler-integration-test.js new
+101
@@ -0,0 +1,101 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +import {getVersionedRenderImplementation} from './utils';
11 +
12 +describe('CompilerIntegration', () => {
13 + global.IS_REACT_ACT_ENVIRONMENT = true;
14 + let React;
15 + let act;
16 + let useMemoCache;
17 +
18 + beforeEach(() => {
19 + React = require('react');
20 + require('react-dom');
21 + require('react-dom/client');
22 + useMemoCache = require('react/compiler-runtime').c;
23 +
24 + const utils = require('./utils');
25 + act = utils.act;
26 + });
27 +
28 + afterEach(() => {
29 + jest.restoreAllMocks();
30 + });
31 +
32 + const {render} = getVersionedRenderImplementation();
33 +
34 + // @reactVersion >= 18.2
35 + it('By default, component display names should not have Forget prefix', () => {
36 + const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
37 + const reactDOMFiberRendererInterface = hook.rendererInterfaces.get(1);
38 + expect(reactDOMFiberRendererInterface).not.toBeFalsy();
39 +
40 + const Foo = () => {
41 + // eslint-disable-next-line no-unused-vars
42 + const [val, setVal] = React.useState(null);
43 +
44 + return (
45 + <div>
46 + <Bar />
47 + </div>
48 + );
49 + };
50 + const Bar = () => <div>Hi!</div>;
51 +
52 + act(() => render(<Foo />));
53 +
54 + expect(
55 + reactDOMFiberRendererInterface
56 + .getDisplayNameForElementID(2)
57 + .indexOf('Forget'),
58 + ).toBe(-1);
59 + expect(
60 + reactDOMFiberRendererInterface
61 + .getDisplayNameForElementID(3)
62 + .indexOf('Forget'),
63 + ).toBe(-1);
64 + });
65 +
66 + // For React 18.2, this will install uMC polyfill from react-compiler-runtime available on npm.
67 + // @reactVersion >= 18.2
68 + it('If useMemoCache used, the corresponding displayName for a component should have Forget prefix', () => {
69 + const hook = global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
70 + const reactDOMFiberRendererInterface = hook.rendererInterfaces.get(1);
71 + expect(reactDOMFiberRendererInterface).not.toBeFalsy();
72 +
73 + const Foo = () => {
74 + // eslint-disable-next-line no-unused-vars
75 + const $ = useMemoCache(1);
76 + // eslint-disable-next-line no-unused-vars
77 + const [val, setVal] = React.useState(null);
78 +
79 + return (
80 + <div>
81 + <Bar />
82 + </div>
83 + );
84 + };
85 + const Bar = () => <div>Hi!</div>;
86 +
87 + act(() => render(<Foo />));
88 +
89 + // useMemoCache is only used by Foo component
90 + expect(
91 + reactDOMFiberRendererInterface
92 + .getDisplayNameForElementID(2)
93 + .indexOf('Forget'),
94 + ).toBe(0);
95 + expect(
96 + reactDOMFiberRendererInterface
97 + .getDisplayNameForElementID(3)
98 + .indexOf('Forget'),
99 + ).toBe(-1);
100 + });
101 +});
scripts/ci/download_devtools_regression_build.js
+18 -1
@@ -82,11 +82,12 @@ async function downloadRegressionBuild() {
82 );
83 await exec(`mv ${movePackageString} ${buildPath}`);
84
85 + const reactVersion = semver.coerce(version).version;
86 // For React versions earlier than 18.0.0, we explicitly scheduler v0.20.1, which
87 // is the first version that has unstable_mock, which DevTools tests need, but also
88 // has Scheduler.unstable_trace, which, although we don't use in DevTools tests
89 // is imported by older React versions and will break if it's not there
89 - if (semver.lte(semver.coerce(version).version, '18.0.0')) {
90 + if (semver.lte(reactVersion, '18.0.0')) {
91 await exec(`npm install --prefix ${REGRESSION_FOLDER} scheduler@0.20.1`);
92 }
93
@@ -108,6 +109,22 @@ async function downloadRegressionBuild() {
109 )} ${buildPath}`
110 );
111 }
112 +
113 + if (semver.gte(reactVersion, '18.2.0') && semver.lt(reactVersion, '19')) {
114 + console.log(chalk.white(`Downloading react-compiler-runtime\n`));
115 + await exec(
116 + `npm install --prefix ${REGRESSION_FOLDER} react-compiler-runtime`
117 + );
118 +
119 + console.log(
120 + chalk.white(
121 + `Moving react-compiler-runtime to react/compiler-runtime.js\n`
122 + )
123 + );
124 + await exec(
125 + `mv ${REGRESSION_FOLDER}/node_modules/react-compiler-runtime/dist/index.js ${buildPath}/react/compiler-runtime.js`
126 + );
127 + }
128 }
129
130 async function main() {