@samitouri / QOS-React-1 / commits / cb78d2f1f3

chore: use versioned render in profilingCache test (#28242)

Ruslan Lesiutin committed Feb 6, 2024 at 11:24 UTC cb78d2f1f3a09dcacf730273a584c769f69c47b3
1 file changed +183 -50
packages/react-devtools-shared/src/__tests__/profilingCache-test.js
+183 -50
@@ -10,6 +10,8 @@
10 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
11 import type Store from 'react-devtools-shared/src/devtools/store';
12
13 +import {getVersionedRenderImplementation} from './utils';
14 +
15 describe('ProfilingCache', () => {
16 let PropTypes;
17 let React;
@@ -39,8 +41,11 @@ describe('ProfilingCache', () => {
41 Scheduler = require('scheduler');
42 });
43
44 + const {render, getContainer} = getVersionedRenderImplementation();
45 +
46 // @reactVersion >= 16.9
43 - it('should collect data for each root (including ones added or mounted after profiling started)', () => {
47 + // @reactVersion <= 18.2
48 + it('should collect data for each root (including ones added or mounted after profiling started) (legacy render)', () => {
49 const Parent = ({count}) => {
50 Scheduler.unstable_advanceTime(10);
51 const children = new Array(count)
@@ -151,6 +156,116 @@ describe('ProfilingCache', () => {
156 });
157 });
158
159 + // @reactVersion >= 18
160 + it('should collect data for each root (including ones added or mounted after profiling started) (createRoot)', () => {
161 + const Parent = ({count}) => {
162 + Scheduler.unstable_advanceTime(10);
163 + const children = new Array(count)
164 + .fill(true)
165 + .map((_, index) => <Child key={index} duration={index} />);
166 + return (
167 + <React.Fragment>
168 + {children}
169 + <MemoizedChild duration={1} />
170 + </React.Fragment>
171 + );
172 + };
173 + const Child = ({duration}) => {
174 + Scheduler.unstable_advanceTime(duration);
175 + return null;
176 + };
177 + const MemoizedChild = React.memo(Child);
178 +
179 + const RootA = ({children}) => children;
180 + const RootB = ({children}) => children;
181 + const RootC = ({children}) => children;
182 +
183 + const containerA = document.createElement('div');
184 + const containerB = document.createElement('div');
185 + const containerC = document.createElement('div');
186 +
187 + const rootA = ReactDOMClient.createRoot(containerA);
188 + const rootB = ReactDOMClient.createRoot(containerB);
189 + const rootC = ReactDOMClient.createRoot(containerC);
190 +
191 + utils.act(() =>
192 + rootA.render(
193 + <RootA>
194 + <Parent count={2} />
195 + </RootA>,
196 + ),
197 + );
198 + utils.act(() =>
199 + rootB.render(
200 + <RootB>
201 + <Parent count={1} />
202 + </RootB>,
203 + ),
204 + );
205 + utils.act(() => store.profilerStore.startProfiling());
206 + utils.act(() =>
207 + rootA.render(
208 + <RootA>
209 + <Parent count={3} />
210 + </RootA>,
211 + ),
212 + );
213 + utils.act(() =>
214 + rootC.render(
215 + <RootC>
216 + <Parent count={1} />
217 + </RootC>,
218 + ),
219 + );
220 + utils.act(() =>
221 + rootA.render(
222 + <RootA>
223 + <Parent count={1} />
224 + </RootA>,
225 + ),
226 + );
227 + utils.act(() => rootB.unmount());
228 + utils.act(() =>
229 + rootA.render(
230 + <RootA>
231 + <Parent count={0} />
232 + </RootA>,
233 + ),
234 + );
235 + utils.act(() => store.profilerStore.stopProfiling());
236 + utils.act(() => rootA.unmount());
237 +
238 + const rootIDs = Array.from(
239 + store.profilerStore.profilingData.dataForRoots.values(),
240 + ).map(({rootID}) => rootID);
241 + expect(rootIDs).toHaveLength(3);
242 +
243 + const originalProfilingDataForRoot = [];
244 +
245 + let data = store.profilerStore.getDataForRoot(rootIDs[0]);
246 + expect(data.displayName).toMatchInlineSnapshot(`"RootA"`);
247 + expect(data.commitData).toHaveLength(3);
248 + originalProfilingDataForRoot.push(data);
249 +
250 + data = store.profilerStore.getDataForRoot(rootIDs[1]);
251 + expect(data.displayName).toMatchInlineSnapshot(`"RootC"`);
252 + expect(data.commitData).toHaveLength(1);
253 + originalProfilingDataForRoot.push(data);
254 +
255 + data = store.profilerStore.getDataForRoot(rootIDs[2]);
256 + expect(data.displayName).toMatchInlineSnapshot(`"RootB"`);
257 + expect(data.commitData).toHaveLength(1);
258 + originalProfilingDataForRoot.push(data);
259 +
260 + utils.exportImportHelper(bridge, store);
261 +
262 + rootIDs.forEach((rootID, index) => {
263 + const current = store.profilerStore.getDataForRoot(rootID);
264 + const prev = originalProfilingDataForRoot[index];
265 + expect(current).toEqual(prev);
266 + });
267 + });
268 +
269 // @reactVersion >= 16.9
270 it('should collect data for each commit', () => {
271 const Parent = ({count}) => {
@@ -171,13 +286,11 @@ describe('ProfilingCache', () => {
286 };
287 const MemoizedChild = React.memo(Child);
288
174 - const container = document.createElement('div');
175 -
289 utils.act(() => store.profilerStore.startProfiling());
177 - utils.act(() => legacyRender(<Parent count={2} />, container));
178 - utils.act(() => legacyRender(<Parent count={3} />, container));
179 - utils.act(() => legacyRender(<Parent count={1} />, container));
180 - utils.act(() => legacyRender(<Parent count={0} />, container));
290 + utils.act(() => render(<Parent count={2} />));
291 + utils.act(() => render(<Parent count={3} />));
292 + utils.act(() => render(<Parent count={1} />));
293 + utils.act(() => render(<Parent count={0} />));
294 utils.act(() => store.profilerStore.stopProfiling());
295
296 const rootID = store.roots[0];
@@ -244,19 +357,13 @@ describe('ProfilingCache', () => {
357 }
358 }
359
247 - const container = document.createElement('div');
248 -
360 utils.act(() => store.profilerStore.startProfiling());
250 - utils.act(() => legacyRender(<LegacyContextProvider />, container));
361 + utils.act(() => render(<LegacyContextProvider />));
362 expect(instance).not.toBeNull();
363 utils.act(() => (instance: any).setState({count: 1}));
253 - utils.act(() =>
254 - legacyRender(<LegacyContextProvider foo={123} />, container),
255 - );
256 - utils.act(() =>
257 - legacyRender(<LegacyContextProvider bar="abc" />, container),
258 - );
259 - utils.act(() => legacyRender(<LegacyContextProvider />, container));
364 + utils.act(() => render(<LegacyContextProvider foo={123} />));
365 + utils.act(() => render(<LegacyContextProvider bar="abc" />));
366 + utils.act(() => render(<LegacyContextProvider />));
367 utils.act(() => store.profilerStore.stopProfiling());
368
369 const rootID = store.roots[0];
@@ -574,25 +681,21 @@ describe('ProfilingCache', () => {
681 return null;
682 };
683
577 - const container = document.createElement('div');
578 -
684 utils.act(() => store.profilerStore.startProfiling());
685 utils.act(() =>
581 - legacyRender(
686 + render(
687 <Context.Provider value={true}>
688 <Component count={1} />
689 </Context.Provider>,
585 - container,
690 ),
691 );
692
693 // Second render has no changed hooks, only changed props.
694 utils.act(() =>
591 - legacyRender(
695 + render(
696 <Context.Provider value={true}>
697 <Component count={2} />
698 </Context.Provider>,
595 - container,
699 ),
700 );
701
@@ -604,11 +707,10 @@ describe('ProfilingCache', () => {
707
708 // Fifth render has a changed context value, but no changed hook.
709 utils.act(() =>
607 - legacyRender(
710 + render(
711 <Context.Provider value={false}>
712 <Component count={2} />
713 </Context.Provider>,
611 - container,
714 ),
715 );
716
@@ -754,9 +856,7 @@ describe('ProfilingCache', () => {
856 };
857
858 utils.act(() => store.profilerStore.startProfiling());
757 - utils.act(() =>
758 - legacyRender(<Grandparent />, document.createElement('div')),
759 - );
859 + utils.act(() => render(<Grandparent />));
860 utils.act(() => store.profilerStore.stopProfiling());
861
862 expect(store).toMatchInlineSnapshot(`
@@ -822,9 +922,7 @@ describe('ProfilingCache', () => {
922 };
923
924 utils.act(() => store.profilerStore.startProfiling());
825 - await utils.actAsync(() =>
826 - legacyRender(<Parent />, document.createElement('div')),
827 - );
925 + await utils.actAsync(() => render(<Parent />));
926 utils.act(() => store.profilerStore.stopProfiling());
927
928 const rootID = store.roots[0];
@@ -880,12 +978,10 @@ describe('ProfilingCache', () => {
978 };
979 const MemoizedChild = React.memo(Child);
980
883 - const container = document.createElement('div');
884 -
981 utils.act(() => store.profilerStore.startProfiling());
886 - utils.act(() => legacyRender(<Parent count={1} />, container));
887 - utils.act(() => legacyRender(<Parent count={2} />, container));
888 - utils.act(() => legacyRender(<Parent count={3} />, container));
982 + utils.act(() => render(<Parent count={1} />));
983 + utils.act(() => render(<Parent count={2} />));
984 + utils.act(() => render(<Parent count={3} />));
985 utils.act(() => store.profilerStore.stopProfiling());
986
987 const rootID = store.roots[0];
@@ -940,11 +1036,11 @@ describe('ProfilingCache', () => {
1036
1037 // @reactVersion >= 18.0.0
1038 // @reactVersion <= 18.2.0
943 - it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0]', () => {
944 - const container = document.createElement('div');
945 -
1039 + it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (legacy render)', () => {
1040 utils.act(() => store.profilerStore.startProfiling());
947 - utils.act(() => legacyRender(<React.Suspense />, container));
1041 + utils.act(() =>
1042 + legacyRender(<React.Suspense />, document.createElement('div')),
1043 + );
1044 utils.act(() => store.profilerStore.stopProfiling());
1045
1046 const rootID = store.roots[0];
@@ -981,13 +1077,51 @@ describe('ProfilingCache', () => {
1077 `);
1078 });
1079
984 - // This test is not gated.
985 - // For this test we use the current version of react, built from source.
986 - it('should handle unexpectedly shallow suspense trees', () => {
987 - const container = document.createElement('div');
1080 + // @reactVersion >= 18.0.0
1081 + // @reactVersion <= 18.2.0
1082 + it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (createRoot)', () => {
1083 + utils.act(() => store.profilerStore.startProfiling());
1084 + utils.act(() => render(<React.Suspense />));
1085 + utils.act(() => store.profilerStore.stopProfiling());
1086
1087 + const rootID = store.roots[0];
1088 + const commitData = store.profilerStore.getDataForRoot(rootID).commitData;
1089 + expect(commitData).toMatchInlineSnapshot(`
1090 + [
1091 + {
1092 + "changeDescriptions": Map {},
1093 + "duration": 0,
1094 + "effectDuration": null,
1095 + "fiberActualDurations": Map {
1096 + 1 => 0,
1097 + 2 => 0,
1098 + },
1099 + "fiberSelfDurations": Map {
1100 + 1 => 0,
1101 + 2 => 0,
1102 + },
1103 + "passiveEffectDuration": null,
1104 + "priorityLevel": "Normal",
1105 + "timestamp": 0,
1106 + "updaters": [
1107 + {
1108 + "compiledWithForget": false,
1109 + "displayName": "createRoot()",
1110 + "hocDisplayNames": null,
1111 + "id": 1,
1112 + "key": null,
1113 + "type": 11,
1114 + },
1115 + ],
1116 + },
1117 + ]
1118 + `);
1119 + });
1120 +
1121 + // @reactVersion > 18.2.0
1122 + it('should handle unexpectedly shallow suspense trees', () => {
1123 utils.act(() => store.profilerStore.startProfiling());
990 - utils.act(() => legacyRender(<React.Suspense />, container));
1124 + utils.act(() => render(<React.Suspense />));
1125 utils.act(() => store.profilerStore.stopProfiling());
1126
1127 const rootID = store.roots[0];
@@ -1012,7 +1146,7 @@ describe('ProfilingCache', () => {
1146 "updaters": [
1147 {
1148 "compiledWithForget": false,
1015 - "displayName": "render()",
1149 + "displayName": "createRoot()",
1150 "hocDisplayNames": null,
1151 "id": 1,
1152 "key": null,
@@ -1105,13 +1239,12 @@ describe('ProfilingCache', () => {
1239
1240 const {Simulate} = require('react-dom/test-utils');
1241
1108 - const container = document.createElement('div');
1109 - utils.act(() => legacyRender(<App />, container));
1110 - expect(container.textContent).toBe('Home');
1242 + utils.act(() => render(<App />));
1243 + expect(getContainer().textContent).toBe('Home');
1244 utils.act(() => store.profilerStore.startProfiling());
1245 utils.act(() => Simulate.click(linkRef.current));
1246 utils.act(() => store.profilerStore.stopProfiling());
1114 - expect(container.textContent).toBe('About');
1247 + expect(getContainer().textContent).toBe('About');
1248 });
1249
1250 // @reactVersion >= 18.0