mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Added a second Profiling test (for CommitDetails) and fixed some module reset prolems
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
"<rootDir>/src/__tests__/setupTests"
|
||||
],
|
||||
"snapshotSerializers": [
|
||||
"<rootDir>/src/__tests__/profilingSummarySerializer",
|
||||
"<rootDir>/src/__tests__/storeSerializer"
|
||||
],
|
||||
"testMatch": [
|
||||
|
||||
@@ -1,5 +1,74 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 2: add child 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
<Child key="1">
|
||||
<Child key="2">
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 3: remove children 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 4: profiling stopped 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
<Child key="0">
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 5: CommitDetails: mount 1`] = `
|
||||
Object {
|
||||
"actualDurations": Map {
|
||||
1 => 14,
|
||||
2 => 14,
|
||||
3 => 2,
|
||||
4 => 2,
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"rootID": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 6: CommitDetails: add child 1`] = `
|
||||
Object {
|
||||
"actualDurations": Map {
|
||||
3 => 2,
|
||||
4 => 2,
|
||||
5 => 2,
|
||||
2 => 16,
|
||||
1 => 16,
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"rootID": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`profiling commitDetails should be collected for each commit: 7: CommitDetails: remove children 1`] = `
|
||||
Object {
|
||||
"actualDurations": Map {
|
||||
3 => 2,
|
||||
2 => 12,
|
||||
1 => 12,
|
||||
},
|
||||
"commitIndex": 2,
|
||||
"interactions": Array [],
|
||||
"rootID": 1,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`profiling profilingSummary should be collected for each commit: 1: mount 1`] = `
|
||||
[root]
|
||||
▾ <Parent key="A">
|
||||
@@ -28,34 +97,22 @@ exports[`profiling profilingSummary should be collected for each commit: 4: prof
|
||||
`;
|
||||
|
||||
exports[`profiling profilingSummary should be collected for each commit: ProfilingSummary 1`] = `
|
||||
{
|
||||
Object {
|
||||
"commitDurations": Array [
|
||||
16,
|
||||
12,
|
||||
],
|
||||
"commitTimes": Array [
|
||||
16,
|
||||
28,
|
||||
],
|
||||
"initialTreeBaseDurations": Map {
|
||||
1 => 14,
|
||||
2 => 14,
|
||||
3 => 2,
|
||||
4 => 2,
|
||||
},
|
||||
"interactionCount": 0,
|
||||
"rootID": 1,
|
||||
"commitDurations": [
|
||||
16,
|
||||
12
|
||||
],
|
||||
"commitTimes": [
|
||||
16,
|
||||
28
|
||||
],
|
||||
"initialTreeBaseDurations": [
|
||||
[
|
||||
1,
|
||||
14
|
||||
],
|
||||
[
|
||||
2,
|
||||
14
|
||||
],
|
||||
[
|
||||
3,
|
||||
2
|
||||
],
|
||||
[
|
||||
4,
|
||||
2
|
||||
]
|
||||
],
|
||||
"interactionCount": 0
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -76,6 +76,93 @@ describe('profiling', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('commitDetails', () => {
|
||||
it('should be collected for each commit', async done => {
|
||||
const Parent = ({ count }) => {
|
||||
Scheduler.advanceTime(10);
|
||||
return new Array(count)
|
||||
.fill(true)
|
||||
.map((_, index) => <Child key={index} />);
|
||||
};
|
||||
const Child = () => {
|
||||
Scheduler.advanceTime(2);
|
||||
return null;
|
||||
};
|
||||
|
||||
const container = document.createElement('div');
|
||||
|
||||
utils.act(() => store.startProfiling());
|
||||
|
||||
utils.act(() => ReactDOM.render(<Parent key="A" count={2} />, container));
|
||||
expect(store).toMatchSnapshot('1: mount');
|
||||
|
||||
utils.act(() => ReactDOM.render(<Parent key="A" count={3} />, container));
|
||||
expect(store).toMatchSnapshot('2: add child');
|
||||
|
||||
utils.act(() => ReactDOM.render(<Parent key="A" count={1} />, container));
|
||||
expect(store).toMatchSnapshot('3: remove children');
|
||||
|
||||
utils.act(() => store.stopProfiling());
|
||||
expect(store).toMatchSnapshot('4: profiling stopped');
|
||||
|
||||
let commitDetails;
|
||||
function Suspender({ commitIndex, rendererID, rootID }) {
|
||||
commitDetails = store.profilingCache.CommitDetails.read({
|
||||
commitIndex,
|
||||
rendererID,
|
||||
rootID,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
const rendererID = utils.getRendererID();
|
||||
const rootID = store.roots[0];
|
||||
|
||||
await utils.actSuspense(() =>
|
||||
TestRenderer.create(
|
||||
<React.Suspense fallback={null}>
|
||||
<Suspender
|
||||
commitIndex={0}
|
||||
rendererID={rendererID}
|
||||
rootID={rootID}
|
||||
/>
|
||||
</React.Suspense>
|
||||
)
|
||||
);
|
||||
expect(commitDetails).toMatchSnapshot('5: CommitDetails: mount');
|
||||
|
||||
await utils.actSuspense(() =>
|
||||
TestRenderer.create(
|
||||
<React.Suspense fallback={null}>
|
||||
<Suspender
|
||||
commitIndex={1}
|
||||
rendererID={rendererID}
|
||||
rootID={rootID}
|
||||
/>
|
||||
</React.Suspense>
|
||||
)
|
||||
);
|
||||
expect(commitDetails).toMatchSnapshot('6: CommitDetails: add child');
|
||||
|
||||
await utils.actSuspense(() =>
|
||||
TestRenderer.create(
|
||||
<React.Suspense fallback={null}>
|
||||
<Suspender
|
||||
commitIndex={2}
|
||||
rendererID={rendererID}
|
||||
rootID={rootID}
|
||||
/>
|
||||
</React.Suspense>
|
||||
)
|
||||
);
|
||||
expect(commitDetails).toMatchSnapshot(
|
||||
'7: CommitDetails: remove children'
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove profiling data when roots are unmounted', async () => {
|
||||
const Parent = ({ count }) =>
|
||||
new Array(count).fill(true).map((_, index) => <Child key={index} />);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// test() is part of Jest's serializer API
|
||||
export function test(maybeProfilingSummary) {
|
||||
return (
|
||||
typeof maybeProfilingSummary === 'object' &&
|
||||
maybeProfilingSummary !== null &&
|
||||
typeof maybeProfilingSummary.rootID === 'number' &&
|
||||
Array.isArray(maybeProfilingSummary.commitDurations) &&
|
||||
Array.isArray(maybeProfilingSummary.commitTimes) &&
|
||||
typeof maybeProfilingSummary.initialTreeBaseDurations === 'object' &&
|
||||
maybeProfilingSummary.initialTreeBaseDurations !== null &&
|
||||
typeof maybeProfilingSummary.interactionCount === 'number'
|
||||
);
|
||||
}
|
||||
|
||||
// print() is part of Jest's serializer API
|
||||
export function print(profilingSummary, serialize, indent) {
|
||||
return JSON.stringify(
|
||||
{
|
||||
...profilingSummary,
|
||||
initialTreeBaseDurations: [...profilingSummary.initialTreeBaseDurations],
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
// @flow
|
||||
|
||||
import Agent from 'src/backend/agent';
|
||||
import { initBackend } from 'src/backend';
|
||||
import Bridge from 'src/bridge';
|
||||
import Store from 'src/devtools/store';
|
||||
import { installHook } from 'src/hook';
|
||||
|
||||
const env = jasmine.getEnv();
|
||||
env.beforeEach(() => {
|
||||
// These files should be required (and re-reuired) before each test,
|
||||
// rather than imported at the head of the module.
|
||||
// That's because we reset modules between tests,
|
||||
// which disconnects the DevTool's cache from the current dispatcher ref.
|
||||
const Agent = require('src/backend/agent').default;
|
||||
const { initBackend } = require('src/backend');
|
||||
const Bridge = require('src/bridge').default;
|
||||
const Store = require('src/devtools/store').default;
|
||||
const { installHook } = require('src/hook');
|
||||
|
||||
// Fake timers let us flush Bridge operations between setup and assertions.
|
||||
jest.useFakeTimers();
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import Store from 'src/devtools/store';
|
||||
|
||||
// test() is part of Jest's serializer API
|
||||
export function test(maybeStore) {
|
||||
return maybeStore instanceof Store;
|
||||
// It's important to lazy-require the Store rather than imported at the head of the module.
|
||||
// Because we reset modules between tests, different Store implementations will be used for each test.
|
||||
// Unfortunately Jest does not reset its own serializer modules.
|
||||
return maybeStore instanceof require('src/devtools/store').default;
|
||||
}
|
||||
|
||||
// print() is part of Jest's serializer API
|
||||
|
||||
@@ -49,6 +49,8 @@ const Pending = 0;
|
||||
const Resolved = 1;
|
||||
const Rejected = 2;
|
||||
|
||||
// TODO This file isn't being re-imported between tests it seems, so it's getting disconnected
|
||||
|
||||
const ReactCurrentDispatcher = (React: any)
|
||||
.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user