/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import typeof TestRendererType from 'react-test-renderer'; import type Store from 'react-devtools-shared/src/devtools/store'; describe('commit tree', () => { let React; let ReactDOM; let Scheduler; let TestRenderer: TestRendererType; let legacyRender; let store: Store; let utils; beforeEach(() => { utils = require('./utils'); utils.beforeEachProfiling(); legacyRender = utils.legacyRender; store = global.store; store.collapseNodesByDefault = false; store.recordChangeDescriptions = true; React = require('react'); ReactDOM = require('react-dom'); Scheduler = require('scheduler'); TestRenderer = utils.requireTestRenderer(); }); it('should be able to rebuild the store tree for each commit', () => { const Parent = ({count}) => { Scheduler.unstable_advanceTime(10); return new Array(count) .fill(true) .map((_, index) => ); }; const Child = React.memo(function Child() { Scheduler.unstable_advanceTime(2); return null; }); const container = document.createElement('div'); utils.act(() => store.profilerStore.startProfiling()); utils.act(() => legacyRender(, container)); utils.act(() => legacyRender(, container)); utils.act(() => legacyRender(, container)); utils.act(() => legacyRender(, container)); utils.act(() => store.profilerStore.stopProfiling()); let renderFinished = false; function Validator({commitIndex, rootID}) { const commitTree = store.profilerStore.profilingCache.getCommitTree({ commitIndex, rootID, }); expect(commitTree).toMatchSnapshot(`${commitIndex}: CommitTree`); renderFinished = true; return null; } const rootID = store.roots[0]; for (let commitIndex = 0; commitIndex < 4; commitIndex++) { renderFinished = false; utils.act(() => { TestRenderer.create( , ); }); expect(renderFinished).toBe(true); } }); describe('Lazy', () => { async function fakeImport(result) { return {default: result}; } const LazyInnerComponent = () => null; const App = ({renderChildren}) => { if (renderChildren) { return ( ); } else { return null; } }; let LazyComponent; beforeEach(() => { LazyComponent = React.lazy(() => fakeImport(LazyInnerComponent)); }); it('should support Lazy components (legacy render)', async () => { const container = document.createElement('div'); utils.act(() => store.profilerStore.startProfiling()); utils.act(() => legacyRender(, container)); await Promise.resolve(); utils.act(() => legacyRender(, container)); utils.act(() => legacyRender(, container)); utils.act(() => store.profilerStore.stopProfiling()); let renderFinished = false; function Validator({commitIndex, rootID}) { const commitTree = store.profilerStore.profilingCache.getCommitTree({ commitIndex, rootID, }); expect(commitTree).toMatchSnapshot(`${commitIndex}: CommitTree`); renderFinished = true; return null; } const rootID = store.roots[0]; for (let commitIndex = 0; commitIndex < 2; commitIndex++) { renderFinished = false; utils.act(() => { TestRenderer.create( , ); }); expect(renderFinished).toBe(true); } }); it('should support Lazy components (createRoot)', async () => { const container = document.createElement('div'); const root = ReactDOM.createRoot(container); utils.act(() => store.profilerStore.startProfiling()); utils.act(() => root.render()); await Promise.resolve(); utils.act(() => root.render()); utils.act(() => root.render()); utils.act(() => store.profilerStore.stopProfiling()); let renderFinished = false; function Validator({commitIndex, rootID}) { const commitTree = store.profilerStore.profilingCache.getCommitTree({ commitIndex, rootID, }); expect(commitTree).toMatchSnapshot(`${commitIndex}: CommitTree`); renderFinished = true; return null; } const rootID = store.roots[0]; for (let commitIndex = 0; commitIndex < 2; commitIndex++) { renderFinished = false; utils.act(() => { TestRenderer.create( , ); }); expect(renderFinished).toBe(true); } }); it('should support Lazy components that are unmounted before resolving (legacy render)', async () => { const container = document.createElement('div'); utils.act(() => store.profilerStore.startProfiling()); utils.act(() => legacyRender(, container)); utils.act(() => legacyRender(, container)); utils.act(() => store.profilerStore.stopProfiling()); let renderFinished = false; function Validator({commitIndex, rootID}) { const commitTree = store.profilerStore.profilingCache.getCommitTree({ commitIndex, rootID, }); expect(commitTree).toMatchSnapshot(`${commitIndex}: CommitTree`); renderFinished = true; return null; } const rootID = store.roots[0]; for (let commitIndex = 0; commitIndex < 2; commitIndex++) { renderFinished = false; utils.act(() => { TestRenderer.create( , ); }); expect(renderFinished).toBe(true); } }); it('should support Lazy components that are unmounted before resolving (createRoot)', async () => { const container = document.createElement('div'); const root = ReactDOM.createRoot(container); utils.act(() => store.profilerStore.startProfiling()); utils.act(() => root.render()); utils.act(() => root.render()); utils.act(() => store.profilerStore.stopProfiling()); let renderFinished = false; function Validator({commitIndex, rootID}) { const commitTree = store.profilerStore.profilingCache.getCommitTree({ commitIndex, rootID, }); expect(commitTree).toMatchSnapshot(`${commitIndex}: CommitTree`); renderFinished = true; return null; } const rootID = store.roots[0]; for (let commitIndex = 0; commitIndex < 2; commitIndex++) { renderFinished = false; utils.act(() => { TestRenderer.create( , ); }); expect(renderFinished).toBe(true); } }); }); });