Skip to content

Commit

Permalink
chore: use versioned render in profilingCache test (facebook#28242)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoxyq authored and AndyPengc12 committed Apr 15, 2024
1 parent dbe5610 commit eaa78ce
Showing 1 changed file with 183 additions and 50 deletions.
233 changes: 183 additions & 50 deletions packages/react-devtools-shared/src/__tests__/profilingCache-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
import type Store from 'react-devtools-shared/src/devtools/store';

import {getVersionedRenderImplementation} from './utils';

describe('ProfilingCache', () => {
let PropTypes;
let React;
Expand Down Expand Up @@ -39,8 +41,11 @@ describe('ProfilingCache', () => {
Scheduler = require('scheduler');
});

const {render, getContainer} = getVersionedRenderImplementation();

// @reactVersion >= 16.9
it('should collect data for each root (including ones added or mounted after profiling started)', () => {
// @reactVersion <= 18.2
it('should collect data for each root (including ones added or mounted after profiling started) (legacy render)', () => {
const Parent = ({count}) => {
Scheduler.unstable_advanceTime(10);
const children = new Array(count)
Expand Down Expand Up @@ -151,6 +156,116 @@ describe('ProfilingCache', () => {
});
});

// @reactVersion >= 18
it('should collect data for each root (including ones added or mounted after profiling started) (createRoot)', () => {
const Parent = ({count}) => {
Scheduler.unstable_advanceTime(10);
const children = new Array(count)
.fill(true)
.map((_, index) => <Child key={index} duration={index} />);
return (
<React.Fragment>
{children}
<MemoizedChild duration={1} />
</React.Fragment>
);
};
const Child = ({duration}) => {
Scheduler.unstable_advanceTime(duration);
return null;
};
const MemoizedChild = React.memo(Child);

const RootA = ({children}) => children;
const RootB = ({children}) => children;
const RootC = ({children}) => children;

const containerA = document.createElement('div');
const containerB = document.createElement('div');
const containerC = document.createElement('div');

const rootA = ReactDOMClient.createRoot(containerA);
const rootB = ReactDOMClient.createRoot(containerB);
const rootC = ReactDOMClient.createRoot(containerC);

utils.act(() =>
rootA.render(
<RootA>
<Parent count={2} />
</RootA>,
),
);
utils.act(() =>
rootB.render(
<RootB>
<Parent count={1} />
</RootB>,
),
);
utils.act(() => store.profilerStore.startProfiling());
utils.act(() =>
rootA.render(
<RootA>
<Parent count={3} />
</RootA>,
),
);
utils.act(() =>
rootC.render(
<RootC>
<Parent count={1} />
</RootC>,
),
);
utils.act(() =>
rootA.render(
<RootA>
<Parent count={1} />
</RootA>,
),
);
utils.act(() => rootB.unmount());
utils.act(() =>
rootA.render(
<RootA>
<Parent count={0} />
</RootA>,
),
);
utils.act(() => store.profilerStore.stopProfiling());
utils.act(() => rootA.unmount());

const rootIDs = Array.from(
store.profilerStore.profilingData.dataForRoots.values(),
).map(({rootID}) => rootID);
expect(rootIDs).toHaveLength(3);

const originalProfilingDataForRoot = [];

let data = store.profilerStore.getDataForRoot(rootIDs[0]);
expect(data.displayName).toMatchInlineSnapshot(`"RootA"`);
expect(data.commitData).toHaveLength(3);
originalProfilingDataForRoot.push(data);

data = store.profilerStore.getDataForRoot(rootIDs[1]);
expect(data.displayName).toMatchInlineSnapshot(`"RootC"`);
expect(data.commitData).toHaveLength(1);
originalProfilingDataForRoot.push(data);

data = store.profilerStore.getDataForRoot(rootIDs[2]);
expect(data.displayName).toMatchInlineSnapshot(`"RootB"`);
expect(data.commitData).toHaveLength(1);
originalProfilingDataForRoot.push(data);

utils.exportImportHelper(bridge, store);

rootIDs.forEach((rootID, index) => {
const current = store.profilerStore.getDataForRoot(rootID);
const prev = originalProfilingDataForRoot[index];
expect(current).toEqual(prev);
});
});

// @reactVersion >= 16.9
it('should collect data for each commit', () => {
const Parent = ({count}) => {
Expand All @@ -171,13 +286,11 @@ describe('ProfilingCache', () => {
};
const MemoizedChild = React.memo(Child);

const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<Parent count={2} />, container));
utils.act(() => legacyRender(<Parent count={3} />, container));
utils.act(() => legacyRender(<Parent count={1} />, container));
utils.act(() => legacyRender(<Parent count={0} />, container));
utils.act(() => render(<Parent count={2} />));
utils.act(() => render(<Parent count={3} />));
utils.act(() => render(<Parent count={1} />));
utils.act(() => render(<Parent count={0} />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand Down Expand Up @@ -244,19 +357,13 @@ describe('ProfilingCache', () => {
}
}

const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<LegacyContextProvider />, container));
utils.act(() => render(<LegacyContextProvider />));
expect(instance).not.toBeNull();
utils.act(() => (instance: any).setState({count: 1}));
utils.act(() =>
legacyRender(<LegacyContextProvider foo={123} />, container),
);
utils.act(() =>
legacyRender(<LegacyContextProvider bar="abc" />, container),
);
utils.act(() => legacyRender(<LegacyContextProvider />, container));
utils.act(() => render(<LegacyContextProvider foo={123} />));
utils.act(() => render(<LegacyContextProvider bar="abc" />));
utils.act(() => render(<LegacyContextProvider />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand Down Expand Up @@ -574,25 +681,21 @@ describe('ProfilingCache', () => {
return null;
};

const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() =>
legacyRender(
render(
<Context.Provider value={true}>
<Component count={1} />
</Context.Provider>,
container,
),
);

// Second render has no changed hooks, only changed props.
utils.act(() =>
legacyRender(
render(
<Context.Provider value={true}>
<Component count={2} />
</Context.Provider>,
container,
),
);

Expand All @@ -604,11 +707,10 @@ describe('ProfilingCache', () => {

// Fifth render has a changed context value, but no changed hook.
utils.act(() =>
legacyRender(
render(
<Context.Provider value={false}>
<Component count={2} />
</Context.Provider>,
container,
),
);

Expand Down Expand Up @@ -754,9 +856,7 @@ describe('ProfilingCache', () => {
};

utils.act(() => store.profilerStore.startProfiling());
utils.act(() =>
legacyRender(<Grandparent />, document.createElement('div')),
);
utils.act(() => render(<Grandparent />));
utils.act(() => store.profilerStore.stopProfiling());

expect(store).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -822,9 +922,7 @@ describe('ProfilingCache', () => {
};

utils.act(() => store.profilerStore.startProfiling());
await utils.actAsync(() =>
legacyRender(<Parent />, document.createElement('div')),
);
await utils.actAsync(() => render(<Parent />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand Down Expand Up @@ -880,12 +978,10 @@ describe('ProfilingCache', () => {
};
const MemoizedChild = React.memo(Child);

const container = document.createElement('div');

utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<Parent count={1} />, container));
utils.act(() => legacyRender(<Parent count={2} />, container));
utils.act(() => legacyRender(<Parent count={3} />, container));
utils.act(() => render(<Parent count={1} />));
utils.act(() => render(<Parent count={2} />));
utils.act(() => render(<Parent count={3} />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand Down Expand Up @@ -940,11 +1036,11 @@ describe('ProfilingCache', () => {

// @reactVersion >= 18.0.0
// @reactVersion <= 18.2.0
it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0]', () => {
const container = document.createElement('div');

it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (legacy render)', () => {
utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<React.Suspense />, container));
utils.act(() =>
legacyRender(<React.Suspense />, document.createElement('div')),
);
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand Down Expand Up @@ -981,13 +1077,51 @@ describe('ProfilingCache', () => {
`);
});

// This test is not gated.
// For this test we use the current version of react, built from source.
it('should handle unexpectedly shallow suspense trees', () => {
const container = document.createElement('div');
// @reactVersion >= 18.0.0
// @reactVersion <= 18.2.0
it('should handle unexpectedly shallow suspense trees for react v[18.0.0 - 18.2.0] (createRoot)', () => {
utils.act(() => store.profilerStore.startProfiling());
utils.act(() => render(<React.Suspense />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
const commitData = store.profilerStore.getDataForRoot(rootID).commitData;
expect(commitData).toMatchInlineSnapshot(`
[
{
"changeDescriptions": Map {},
"duration": 0,
"effectDuration": null,
"fiberActualDurations": Map {
1 => 0,
2 => 0,
},
"fiberSelfDurations": Map {
1 => 0,
2 => 0,
},
"passiveEffectDuration": null,
"priorityLevel": "Normal",
"timestamp": 0,
"updaters": [
{
"compiledWithForget": false,
"displayName": "createRoot()",
"hocDisplayNames": null,
"id": 1,
"key": null,
"type": 11,
},
],
},
]
`);
});

// @reactVersion > 18.2.0
it('should handle unexpectedly shallow suspense trees', () => {
utils.act(() => store.profilerStore.startProfiling());
utils.act(() => legacyRender(<React.Suspense />, container));
utils.act(() => render(<React.Suspense />));
utils.act(() => store.profilerStore.stopProfiling());

const rootID = store.roots[0];
Expand All @@ -1012,7 +1146,7 @@ describe('ProfilingCache', () => {
"updaters": [
{
"compiledWithForget": false,
"displayName": "render()",
"displayName": "createRoot()",
"hocDisplayNames": null,
"id": 1,
"key": null,
Expand Down Expand Up @@ -1105,13 +1239,12 @@ describe('ProfilingCache', () => {

const {Simulate} = require('react-dom/test-utils');

const container = document.createElement('div');
utils.act(() => legacyRender(<App />, container));
expect(container.textContent).toBe('Home');
utils.act(() => render(<App />));
expect(getContainer().textContent).toBe('Home');
utils.act(() => store.profilerStore.startProfiling());
utils.act(() => Simulate.click(linkRef.current));
utils.act(() => store.profilerStore.stopProfiling());
expect(container.textContent).toBe('About');
expect(getContainer().textContent).toBe('About');
});

// @reactVersion >= 18.0
Expand Down

0 comments on commit eaa78ce

Please sign in to comment.