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() {