From ac865b28c5facd4f3814a30f5cf40968d5bc92b1 Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Tue, 20 Feb 2024 17:47:30 -0500 Subject: [PATCH 1/6] Remove RTR from ReactProfiler-test --- .../__tests__/ReactProfiler-test.internal.js | 615 ++++++++++-------- .../ReactProfiler-test.internal.js.snap | 64 +- 2 files changed, 360 insertions(+), 319 deletions(-) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index 0f4155a43209f..5bded9e142adc 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @emails react-core - * @jest-environment node */ 'use strict'; @@ -14,20 +13,21 @@ let React; let ReactFeatureFlags; let ReactNoop; let Scheduler; -let ReactTestRenderer; +let ReactDOMClient; +let ReactDOM; let act; let AdvanceTime; let assertLog; let waitFor; let waitForAll; let waitForThrow; +let container; function loadModules({ enableProfilerTimer = true, enableProfilerCommitHooks = true, enableProfilerNestedUpdatePhase = true, replayFailedUnitOfWorkWithInvokeGuardedCallback = false, - useNoopRenderer = false, } = {}) { ReactFeatureFlags = require('shared/ReactFeatureFlags'); @@ -40,17 +40,9 @@ function loadModules({ React = require('react'); Scheduler = require('scheduler'); - act = require('internal-test-utils').act; - - if (useNoopRenderer) { - ReactNoop = require('react-noop-renderer'); - ReactTestRenderer = null; - } else { - ReactNoop = null; - ReactTestRenderer = require('react-test-renderer'); - } const InternalTestUtils = require('internal-test-utils'); + act = InternalTestUtils.act; assertLog = InternalTestUtils.assertLog; waitFor = InternalTestUtils.waitFor; waitForAll = InternalTestUtils.waitForAll; @@ -72,7 +64,37 @@ function loadModules({ }; } +function loadModulesNoop({ + enableProfilerTimer = true, + enableProfilerCommitHooks = true, + enableProfilerNestedUpdatePhase = true, + enableProfilerNestedUpdateScheduledHook = false, + replayFailedUnitOfWorkWithInvokeGuardedCallback = false, +} = {}) { + loadModules(arguments[0]); + ReactNoop = require('react-noop-renderer'); + ReactDOMClient = null; + ReactDOM = null; +} + +function loadModulesReactDOM({ + enableProfilerTimer = true, + enableProfilerCommitHooks = true, + enableProfilerNestedUpdatePhase = true, + enableProfilerNestedUpdateScheduledHook = false, + replayFailedUnitOfWorkWithInvokeGuardedCallback = false, +} = {}) { + loadModules(arguments[0]); + ReactNoop = null; + ReactDOMClient = require('react-dom/client'); + ReactDOM = require('react-dom'); +} + describe('Profiler', () => { + beforeEach(() => { + container = document.createElement('div'); + }); + describe('works in profiling and non-profiling bundles', () => { [true, false].forEach(enableProfilerTimer => { describe(`enableProfilerTimer:${ @@ -81,15 +103,18 @@ describe('Profiler', () => { beforeEach(() => { jest.resetModules(); - loadModules({enableProfilerTimer}); + loadModulesReactDOM({enableProfilerTimer}); }); // This will throw in production too, // But the test is only interested in verifying the DEV error message. if (__DEV__ && enableProfilerTimer) { - it('should warn if required params are missing', () => { + it('should warn if required params are missing', async () => { + const root = ReactDOMClient.createRoot(container); expect(() => { - ReactTestRenderer.create(); + ReactDOM.flushSync(() => { + root.render(); + }); }).toErrorDev( 'Profiler must specify an "id" of type `string` as a prop. Received the type `undefined` instead.', { @@ -99,55 +124,63 @@ describe('Profiler', () => { }); } - it('should support an empty Profiler (with no children)', () => { + it('should support an empty Profiler (with no children)', async () => { + const root = ReactDOMClient.createRoot(container); // As root - expect( - ReactTestRenderer.create( - , - ).toJSON(), - ).toMatchSnapshot(); + await act(() => { + root.render(); + }); + expect(container.innerHTML).toMatchSnapshot(); // As non-root - expect( - ReactTestRenderer.create( + await act(() => { + root.render(
, - ).toJSON(), - ).toMatchSnapshot(); + ); + }); + expect(container.innerHTML).toMatchSnapshot(); }); - it('should render children', () => { + it('should render children', async () => { const FunctionComponent = ({label}) => {label}; - const renderer = ReactTestRenderer.create( -
- outside span - - inside span - - -
, - ); - expect(renderer.toJSON()).toMatchSnapshot(); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( +
+ outside span + + inside span + + +
, + ); + }); + expect(container.innerHTML).toMatchSnapshot(); }); - it('should support nested Profilers', () => { + it('should support nested Profilers', async () => { const FunctionComponent = ({label}) =>
{label}
; class ClassComponent extends React.Component { render() { - return {this.props.label}; + return {this.props.label}; } } - const renderer = ReactTestRenderer.create( - - - - - inner span - - , - ); - expect(renderer.toJSON()).toMatchSnapshot(); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + inner span + + , + ); + }); + + expect(container.innerHTML).toMatchSnapshot(); }); }); }); @@ -158,10 +191,12 @@ describe(`onRender`, () => { beforeEach(() => { jest.resetModules(); - loadModules(); + loadModulesReactDOM(); + + container = document.createElement('div'); }); - it('should handle errors thrown', () => { + it('should handle errors thrown', async () => { const callback = jest.fn(id => { if (id === 'throw') { throw Error('expected'); @@ -178,18 +213,22 @@ describe(`onRender`, () => { } } + const root = ReactDOMClient.createRoot(container); + // Errors thrown from onRender should not break the commit phase, // Or prevent other lifecycles from being called. expect(() => - ReactTestRenderer.create( - - - -
+ ReactDOM.flushSync(() => { + root.render( + + + +
+ - - , - ), + , + ); + }), ).toThrow('expected'); expect(didMount).toBe(true); expect(callback).toHaveBeenCalledTimes(2); @@ -203,15 +242,14 @@ describe(`onRender`, () => { return null; }; + const root = ReactDOMClient.createRoot(container); + React.startTransition(() => { - ReactTestRenderer.create( + root.render( , - { - isConcurrent: true, - }, ); }); @@ -238,12 +276,12 @@ describe(`onRender`, () => { jest.resetModules(); - loadModules(); + loadModulesReactDOM(); // Clear yields in case the current time is read during initialization. Scheduler.unstable_clearLog(); - ReactTestRenderer.create( + ReactDOM.render(
@@ -251,6 +289,7 @@ describe(`onRender`, () => {
, + container, ); // Restore original mock @@ -259,7 +298,7 @@ describe(`onRender`, () => { // TODO: unstable_now is called by more places than just the profiler. // Rewrite this test so it's less fragile. if (gate(flags => flags.enableDeferRootSchedulingToMicrotask)) { - assertLog(['read current time', 'read current time']); + assertLog(['read current time']); } else { assertLog([ 'read current time', @@ -301,7 +340,10 @@ describe(`onRender`, () => { ); } - const renderer = ReactTestRenderer.create(); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render(); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -319,7 +361,9 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(20); // 10 -> 30 - renderer.update(); + await act(() => { + root.render(); + }); if (gate(flags => flags.enableUseJSStackToTrackPassiveDurations)) { // None of the Profiler's subtree was rendered because App bailed out before the Profiler. @@ -352,16 +396,19 @@ describe(`onRender`, () => { expect(callback).not.toHaveBeenCalled(); }); - it('logs render times for both mount and update', () => { + it('logs render times for both mount and update', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - const renderer = ReactTestRenderer.create( - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -379,11 +426,13 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(20); // 15 -> 35 - renderer.update( - - - , - ); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -401,11 +450,13 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(20); // 45 -> 65 - renderer.update( - - - , - ); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -420,22 +471,25 @@ describe(`onRender`, () => { expect(call[5]).toBe(69); // commit time }); - it('includes render times of nested Profilers in their parent times', () => { + it('includes render times of nested Profilers in their parent times', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactTestRenderer.create( - - - - - - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -455,21 +509,24 @@ describe(`onRender`, () => { expect(parentCall[5]).toBe(35); // commit time }); - it('traces sibling Profilers separately', () => { + it('traces sibling Profilers separately', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactTestRenderer.create( - - - - - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -488,20 +545,23 @@ describe(`onRender`, () => { expect(secondCall[5]).toBe(30); // commit time }); - it('does not include time spent outside of profile root', () => { + it('does not include time spent outside of profile root', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactTestRenderer.create( - - - - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -513,7 +573,7 @@ describe(`onRender`, () => { expect(call[5]).toBe(50); // commit time }); - it('is not called when blocked by sCU false', () => { + it('is not called when blocked by sCU false', async () => { const callback = jest.fn(); let instance; @@ -525,22 +585,24 @@ describe(`onRender`, () => { } } - const renderer = ReactTestRenderer.create( - - - -
- - - , - ); - + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + +
+ + + , + ); + }); // All profile callbacks are called for initial render expect(callback).toHaveBeenCalledTimes(2); callback.mockReset(); - renderer.unstable_flushSync(() => { + ReactDOM.flushSync(() => { instance.setState({ count: 1, }); @@ -553,30 +615,35 @@ describe(`onRender`, () => { expect(callback.mock.calls[0][0]).toBe('outer'); }); - it('decreases actual time but not base time when sCU prevents an update', () => { + it('decreases actual time but not base time when sCU prevents an update', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - const renderer = ReactTestRenderer.create( - - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); Scheduler.unstable_advanceTime(30); // 28 -> 58 - renderer.update( - - - - - , - ); + await act(() => { + root.render( + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -595,7 +662,7 @@ describe(`onRender`, () => { expect(updateCall[5]).toBe(62); // commit time }); - it('includes time spent in render phase lifecycles', () => { + it('includes time spent in render phase lifecycles', async () => { class WithLifecycles extends React.Component { state = {}; static getDerivedStateFromProps() { @@ -616,19 +683,24 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const renderer = ReactTestRenderer.create( - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + , + ); + }); Scheduler.unstable_advanceTime(15); // 13 -> 28 - renderer.update( - - - , - ); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -648,9 +720,8 @@ describe(`onRender`, () => { }); it('should clear nested-update flag when multiple cascading renders are scheduled', async () => { - loadModules({ - useNoopRenderer: true, - }); + jest.resetModules(); + loadModulesNoop(); function Component() { const [didMount, setDidMount] = React.useState(false); @@ -689,9 +760,8 @@ describe(`onRender`, () => { }); it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => { - loadModules({ - useNoopRenderer: true, - }); + jest.resetModules(); + loadModulesNoop(); function Component() { const [didMount, setDidMount] = React.useState(false); @@ -742,14 +812,14 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 + const root = ReactDOMClient.createRoot(container); // Render partially, but run out of time before completing. React.startTransition(() => { - ReactTestRenderer.create( + root.render( , - {isConcurrent: true}, ); }); @@ -779,10 +849,11 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 + const root = ReactDOMClient.createRoot(container); // Render partially, but don't finish. // This partial render should take 5ms of simulated time. React.startTransition(() => { - ReactTestRenderer.create( + root.render( @@ -790,7 +861,6 @@ describe(`onRender`, () => { , - {isConcurrent: true}, ); }); @@ -832,16 +902,15 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 + const root = ReactDOMClient.createRoot(container); // Render a partially update, but don't finish. // This partial render should take 10ms of simulated time. - let renderer; React.startTransition(() => { - renderer = ReactTestRenderer.create( + root.render( , - {isConcurrent: true}, ); }); @@ -853,8 +922,8 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // The interrupted work simulates an additional 5ms of time. - renderer.unstable_flushSync(() => { - renderer.update( + ReactDOM.flushSync(() => { + root.render( , @@ -888,13 +957,12 @@ describe(`onRender`, () => { }; Scheduler.unstable_advanceTime(5); // 0 -> 5 - - const renderer = ReactTestRenderer.create( + const root = ReactDOMClient.createRoot(container); + root.render( , - {isConcurrent: true}, ); // Render everything initially. @@ -914,7 +982,7 @@ describe(`onRender`, () => { // Render a partially update, but don't finish. // This partial render should take 3ms of simulated time. React.startTransition(() => { - renderer.update( + root.render( @@ -938,8 +1006,8 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // The interrupted work simulates an additional 11ms of time. - renderer.unstable_flushSync(() => { - renderer.update( + ReactDOM.flushSync(() => { + root.render( , @@ -994,12 +1062,12 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const renderer = ReactTestRenderer.create( + const root = ReactDOMClient.createRoot(container); + root.render( , - {isConcurrent: true}, ); // Render everything initially. @@ -1036,7 +1104,7 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // This simulates a total of 37ms of actual render time. - renderer.unstable_flushSync(() => second.setState({renderTime: 30})); + ReactDOM.flushSync(() => second.setState({renderTime: 30})); assertLog(['SecondComponent:30', 'Yield:7']); // The actual time should include only the most recent render (37ms), @@ -1077,7 +1145,7 @@ describe(`onRender`, () => { beforeEach(() => { jest.resetModules(); - loadModules({ + loadModulesReactDOM({ replayFailedUnitOfWorkWithInvokeGuardedCallback, }); }); @@ -1107,13 +1175,14 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactTestRenderer.create( + ReactDOM.render( , + container, ); expect(callback).toHaveBeenCalledTimes(2); @@ -1186,13 +1255,14 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactTestRenderer.create( + ReactDOM.render( , + container, ); expect(callback).toHaveBeenCalledTimes(1); @@ -1222,8 +1292,7 @@ describe(`onRender`, () => { it('should reset the fiber stack correct after a "complete" phase error', async () => { jest.resetModules(); - loadModules({ - useNoopRenderer: true, + loadModulesNoop({ replayFailedUnitOfWorkWithInvokeGuardedCallback, }); @@ -1260,26 +1329,31 @@ describe(`onRender`, () => { }); }); - it('reflects the most recently rendered id value', () => { + it('reflects the most recently rendered id value', async () => { const callback = jest.fn(); Scheduler.unstable_advanceTime(5); // 0 -> 5 - const renderer = ReactTestRenderer.create( - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); Scheduler.unstable_advanceTime(20); // 7 -> 27 - renderer.update( - - - , - ); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -1298,7 +1372,7 @@ describe(`onRender`, () => { expect(updateCall[4]).toBe(27); // start time }); - it('should not be called until after mutations', () => { + it('should not be called until after mutations', async () => { let classComponentMounted = false; const callback = jest.fn( (id, phase, actualDuration, baseDuration, startTime, commitTime) => { @@ -1319,12 +1393,14 @@ describe(`onRender`, () => { return null; } } - - ReactTestRenderer.create( - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); }); @@ -1334,10 +1410,10 @@ describe(`onCommit`, () => { beforeEach(() => { jest.resetModules(); - loadModules(); + loadModulesReactDOM(); }); - it('should report time spent in layout effects and commit lifecycles', () => { + it('should report time spent in layout effects and commit lifecycles', async () => { const callback = jest.fn(); const ComponentWithEffects = () => { @@ -1376,13 +1452,15 @@ describe(`onCommit`, () => { } Scheduler.unstable_advanceTime(1); - - const renderer = ReactTestRenderer.create( - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -1396,12 +1474,14 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - renderer.update( - - - - , - ); + await act(() => { + root.render( + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -1415,7 +1495,9 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - renderer.update(); + await act(() => { + root.render(); + }); expect(callback).toHaveBeenCalledTimes(3); @@ -1428,7 +1510,7 @@ describe(`onCommit`, () => { expect(call[3]).toBe(1112030); // commit start time (before mutations or effects) }); - it('should report time spent in layout effects and commit lifecycles with cascading renders', () => { + it('should report time spent in layout effects and commit lifecycles with cascading renders', async () => { const callback = jest.fn(); const ComponentWithEffects = ({shouldCascade}) => { @@ -1466,13 +1548,15 @@ describe(`onCommit`, () => { } Scheduler.unstable_advanceTime(1); - - const renderer = ReactTestRenderer.create( - - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -1494,12 +1578,14 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - renderer.update( - - - - , - ); + await act(() => { + root.render( + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(4); @@ -1520,7 +1606,7 @@ describe(`onCommit`, () => { expect(call[3]).toBe(3300011272); // commit start time (before mutations or effects) }); - it('should include time spent in ref callbacks', () => { + it('should include time spent in ref callbacks', async () => { const callback = jest.fn(); const refSetter = ref => { @@ -1544,11 +1630,14 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - const renderer = ReactTestRenderer.create( - - - , - ); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -1562,7 +1651,9 @@ describe(`onCommit`, () => { callback.mockClear(); - renderer.update(); + await act(() => { + root.render(); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -1595,9 +1686,9 @@ describe(`onCommit`, () => { const setCountRef = React.createRef(null); - let renderer = null; + const root = ReactDOMClient.createRoot(container); await act(() => { - renderer = ReactTestRenderer.create( + root.render( { expect(call[3]).toBe(1013); // commit start time (before mutations or effects) await act(() => { - renderer.update( + root.render( @@ -1694,8 +1785,9 @@ describe(`onCommit`, () => { // Test an error that happens during an effect + const root = ReactDOMClient.createRoot(container); await act(() => { - ReactTestRenderer.create( + root.render( { Scheduler.unstable_advanceTime(1); - let renderer = null; - + const root = ReactDOMClient.createRoot(container); await act(() => { - renderer = ReactTestRenderer.create( + root.render( { // Test an error that happens during an cleanup function await act(() => { - renderer.update( + root.render( { beforeEach(() => { jest.resetModules(); - loadModules(); + loadModulesReactDOM(); }); it('should report time spent in passive effects', async () => { @@ -1906,9 +1997,9 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); - let renderer; + const root = ReactDOMClient.createRoot(container); await act(() => { - renderer = ReactTestRenderer.create( + root.render( , @@ -1929,7 +2020,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); await act(() => { - renderer.update( + root.render( , @@ -1950,9 +2041,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); await act(() => { - renderer.update( - , - ); + root.render(); }); await waitForAll([]); @@ -1991,8 +2080,9 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); + const root = ReactDOMClient.createRoot(container); await act(() => { - ReactTestRenderer.create( + root.render( , @@ -2038,9 +2128,9 @@ describe(`onPostCommit`, () => { const setCountRef = React.createRef(null); - let renderer = null; + const root = ReactDOMClient.createRoot(container); await act(() => { - renderer = ReactTestRenderer.create( + root.render( { expect(call[3]).toBe(1013); // commit start time (before mutations or effects) await act(() => { - renderer.update( + root.render( @@ -2136,9 +2226,9 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); // Test an error that happens during an effect - + const root = ReactDOMClient.createRoot(container); await act(() => { - ReactTestRenderer.create( + root.render( { Scheduler.unstable_advanceTime(1); - let renderer = null; - + const root = ReactDOMClient.createRoot(container); await act(() => { - renderer = ReactTestRenderer.create( + root.render( { // Test an error that happens during an cleanup function await act(() => { - renderer.update( + root.render( - - outside span - - - inside span - - - function component - -
-`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should render children 1`] = `"
outside spaninside spanfunction component
"`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 1`] = `null`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 1`] = `""`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 2`] = `
`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support an empty Profiler (with no children) 2`] = `"
"`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support nested Profilers 1`] = ` -[ -
- outer function component -
, - - inner class component - , - - inner span - , -] -`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:disabled should support nested Profilers 1`] = `"
outer function component
inner class componentinner span"`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should render children 1`] = ` -
- - outside span - - - inside span - - - function component - -
-`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should render children 1`] = `"
outside spaninside spanfunction component
"`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 1`] = `null`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 1`] = `""`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 2`] = `
`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support an empty Profiler (with no children) 2`] = `"
"`; -exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support nested Profilers 1`] = ` -[ -
- outer function component -
, - - inner class component - , - - inner span - , -] -`; +exports[`Profiler works in profiling and non-profiling bundles enableProfilerTimer:enabled should support nested Profilers 1`] = `"
outer function component
inner class componentinner span"`; From e83292e1d9f7f2ed8b92ad618a8b75114f426dad Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Thu, 7 Mar 2024 12:02:09 -0500 Subject: [PATCH 2/6] Fix www test run from ci --- packages/react/src/__tests__/ReactProfiler-test.internal.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index 5bded9e142adc..66a7abf0320c5 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -305,7 +305,6 @@ describe(`onRender`, () => { 'read current time', 'read current time', 'read current time', - 'read current time', ]); } }); From 3a036453ad6575d72d92b078686fa96f81af89a4 Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Thu, 7 Mar 2024 12:54:16 -0500 Subject: [PATCH 3/6] Split DOM based tests --- .../__tests__/ReactProfiler-test.internal.js | 318 ++++++------------ .../ReactProfilerComponent-test.internal.js | 137 ++++++++ ...ctProfilerComponent-test.internal.js.snap} | 0 3 files changed, 235 insertions(+), 220 deletions(-) create mode 100644 packages/react/src/__tests__/ReactProfilerComponent-test.internal.js rename packages/react/src/__tests__/__snapshots__/{ReactProfiler-test.internal.js.snap => ReactProfilerComponent-test.internal.js.snap} (100%) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index 66a7abf0320c5..bf5031224f31c 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -13,15 +13,12 @@ let React; let ReactFeatureFlags; let ReactNoop; let Scheduler; -let ReactDOMClient; -let ReactDOM; let act; let AdvanceTime; let assertLog; let waitFor; let waitForAll; let waitForThrow; -let container; function loadModules({ enableProfilerTimer = true, @@ -40,7 +37,7 @@ function loadModules({ React = require('react'); Scheduler = require('scheduler'); - + ReactNoop = require('react-noop-renderer'); const InternalTestUtils = require('internal-test-utils'); act = InternalTestUtils.act; assertLog = InternalTestUtils.assertLog; @@ -64,136 +61,10 @@ function loadModules({ }; } -function loadModulesNoop({ - enableProfilerTimer = true, - enableProfilerCommitHooks = true, - enableProfilerNestedUpdatePhase = true, - enableProfilerNestedUpdateScheduledHook = false, - replayFailedUnitOfWorkWithInvokeGuardedCallback = false, -} = {}) { - loadModules(arguments[0]); - ReactNoop = require('react-noop-renderer'); - ReactDOMClient = null; - ReactDOM = null; -} - -function loadModulesReactDOM({ - enableProfilerTimer = true, - enableProfilerCommitHooks = true, - enableProfilerNestedUpdatePhase = true, - enableProfilerNestedUpdateScheduledHook = false, - replayFailedUnitOfWorkWithInvokeGuardedCallback = false, -} = {}) { - loadModules(arguments[0]); - ReactNoop = null; - ReactDOMClient = require('react-dom/client'); - ReactDOM = require('react-dom'); -} - -describe('Profiler', () => { - beforeEach(() => { - container = document.createElement('div'); - }); - - describe('works in profiling and non-profiling bundles', () => { - [true, false].forEach(enableProfilerTimer => { - describe(`enableProfilerTimer:${ - enableProfilerTimer ? 'enabled' : 'disabled' - }`, () => { - beforeEach(() => { - jest.resetModules(); - - loadModulesReactDOM({enableProfilerTimer}); - }); - - // This will throw in production too, - // But the test is only interested in verifying the DEV error message. - if (__DEV__ && enableProfilerTimer) { - it('should warn if required params are missing', async () => { - const root = ReactDOMClient.createRoot(container); - expect(() => { - ReactDOM.flushSync(() => { - root.render(); - }); - }).toErrorDev( - 'Profiler must specify an "id" of type `string` as a prop. Received the type `undefined` instead.', - { - withoutStack: true, - }, - ); - }); - } - - it('should support an empty Profiler (with no children)', async () => { - const root = ReactDOMClient.createRoot(container); - // As root - await act(() => { - root.render(); - }); - expect(container.innerHTML).toMatchSnapshot(); - - // As non-root - await act(() => { - root.render( -
- -
, - ); - }); - expect(container.innerHTML).toMatchSnapshot(); - }); - - it('should render children', async () => { - const FunctionComponent = ({label}) => {label}; - const root = ReactDOMClient.createRoot(container); - await act(() => { - root.render( -
- outside span - - inside span - - -
, - ); - }); - expect(container.innerHTML).toMatchSnapshot(); - }); - - it('should support nested Profilers', async () => { - const FunctionComponent = ({label}) =>
{label}
; - class ClassComponent extends React.Component { - render() { - return {this.props.label}; - } - } - const root = ReactDOMClient.createRoot(container); - await act(() => { - root.render( - - - - - inner span - - , - ); - }); - - expect(container.innerHTML).toMatchSnapshot(); - }); - }); - }); - }); -}); - describe(`onRender`, () => { beforeEach(() => { jest.resetModules(); - - loadModulesReactDOM(); - - container = document.createElement('div'); + loadModules(); }); it('should handle errors thrown', async () => { @@ -213,13 +84,11 @@ describe(`onRender`, () => { } } - const root = ReactDOMClient.createRoot(container); - // Errors thrown from onRender should not break the commit phase, // Or prevent other lifecycles from being called. - expect(() => - ReactDOM.flushSync(() => { - root.render( + await expect( + act(() => { + ReactNoop.render( @@ -229,7 +98,7 @@ describe(`onRender`, () => { , ); }), - ).toThrow('expected'); + ).rejects.toThrow('expected'); expect(didMount).toBe(true); expect(callback).toHaveBeenCalledTimes(2); }); @@ -242,10 +111,8 @@ describe(`onRender`, () => { return null; }; - const root = ReactDOMClient.createRoot(container); - React.startTransition(() => { - root.render( + ReactNoop.render( @@ -260,7 +127,7 @@ describe(`onRender`, () => { expect(callback).toHaveBeenCalledTimes(1); }); - it('does not record times for components outside of Profiler tree', () => { + it('does not record times for components outside of Profiler tree', async () => { // Mock the Scheduler module so we can track how many times the current // time is read jest.mock('scheduler', obj => { @@ -276,21 +143,22 @@ describe(`onRender`, () => { jest.resetModules(); - loadModulesReactDOM(); + loadModules(); // Clear yields in case the current time is read during initialization. Scheduler.unstable_clearLog(); - ReactDOM.render( -
- - - - - -
, - container, - ); + await act(() => { + ReactNoop.render( +
+ + + + + +
, + ); + }); // Restore original mock jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock')); @@ -298,14 +166,14 @@ describe(`onRender`, () => { // TODO: unstable_now is called by more places than just the profiler. // Rewrite this test so it's less fragile. if (gate(flags => flags.enableDeferRootSchedulingToMicrotask)) { - assertLog(['read current time']); - } else { assertLog([ 'read current time', 'read current time', 'read current time', 'read current time', ]); + } else { + assertLog(['read current time']); } }); @@ -339,7 +207,7 @@ describe(`onRender`, () => { ); } - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render(); }); @@ -400,7 +268,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -475,7 +343,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -513,7 +381,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -549,7 +417,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -584,7 +452,7 @@ describe(`onRender`, () => { } } - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -601,7 +469,7 @@ describe(`onRender`, () => { callback.mockReset(); - ReactDOM.flushSync(() => { + ReactNoop.flushSync(() => { instance.setState({ count: 1, }); @@ -619,7 +487,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -682,7 +550,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -720,7 +588,7 @@ describe(`onRender`, () => { it('should clear nested-update flag when multiple cascading renders are scheduled', async () => { jest.resetModules(); - loadModulesNoop(); + loadModules(); function Component() { const [didMount, setDidMount] = React.useState(false); @@ -760,7 +628,7 @@ describe(`onRender`, () => { it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => { jest.resetModules(); - loadModulesNoop(); + loadModules(); function Component() { const [didMount, setDidMount] = React.useState(false); @@ -811,7 +679,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); // Render partially, but run out of time before completing. React.startTransition(() => { root.render( @@ -848,7 +716,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); // Render partially, but don't finish. // This partial render should take 5ms of simulated time. React.startTransition(() => { @@ -901,7 +769,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); // Render a partially update, but don't finish. // This partial render should take 10ms of simulated time. React.startTransition(() => { @@ -921,7 +789,7 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // The interrupted work simulates an additional 5ms of time. - ReactDOM.flushSync(() => { + ReactNoop.flushSync(() => { root.render( @@ -956,7 +824,7 @@ describe(`onRender`, () => { }; Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); root.render( @@ -1005,7 +873,7 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // The interrupted work simulates an additional 11ms of time. - ReactDOM.flushSync(() => { + ReactNoop.flushSync(() => { root.render( @@ -1061,7 +929,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); root.render( @@ -1103,7 +971,7 @@ describe(`onRender`, () => { // Interrupt with higher priority work. // This simulates a total of 37ms of actual render time. - ReactDOM.flushSync(() => second.setState({renderTime: 30})); + ReactNoop.flushSync(() => second.setState({renderTime: 30})); assertLog(['SecondComponent:30', 'Yield:7']); // The actual time should include only the most recent render (37ms), @@ -1144,12 +1012,12 @@ describe(`onRender`, () => { beforeEach(() => { jest.resetModules(); - loadModulesReactDOM({ + loadModules({ replayFailedUnitOfWorkWithInvokeGuardedCallback, }); }); - it('should accumulate actual time after an error handled by componentDidCatch()', () => { + it('should accumulate actual time after an error handled by componentDidCatch()', async () => { const callback = jest.fn(); const ThrowsError = ({unused}) => { @@ -1174,15 +1042,16 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactDOM.render( - - - - - - , - container, - ); + await act(() => { + ReactNoop.render( + + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(2); @@ -1199,13 +1068,17 @@ describe(`onRender`, () => { // Since the tree is empty for the initial commit expect(mountCall[3]).toBe(2); // start time - expect(mountCall[4]).toBe(5); + expect(mountCall[4]).toBe( + __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback + ? 22 + : 19, + ); // commit time: 5 initially + 14 of work // Add an additional 3 (ThrowsError) if we replayed the failed work expect(mountCall[5]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback - ? 22 - : 19, + ? 39 + : 33, ); // The update includes the ErrorBoundary and its fallback child @@ -1217,19 +1090,19 @@ describe(`onRender`, () => { // start time expect(updateCall[4]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback - ? 22 - : 19, + ? 39 + : 33, ); // commit time: 19 (startTime) + 2 (ErrorBoundary) + 20 (AdvanceTime) // Add an additional 3 (ThrowsError) if we replayed the failed work expect(updateCall[5]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback - ? 44 - : 41, + ? 61 + : 55, ); }); - it('should accumulate actual time after an error handled by getDerivedStateFromError()', () => { + it('should accumulate actual time after an error handled by getDerivedStateFromError()', async () => { const callback = jest.fn(); const ThrowsError = ({unused}) => { @@ -1254,15 +1127,16 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - ReactDOM.render( - - - - - - , - container, - ); + await act(() => { + ReactNoop.render( + + + + + + , + ); + }); expect(callback).toHaveBeenCalledTimes(1); @@ -1279,19 +1153,23 @@ describe(`onRender`, () => { // base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime) expect(mountCall[3]).toBe(22); // start time - expect(mountCall[4]).toBe(5); - // commit time - expect(mountCall[5]).toBe( + expect(mountCall[4]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback ? 54 : 44, ); + // commit time + expect(mountCall[5]).toBe( + __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback + ? 103 + : 83, + ); }); it('should reset the fiber stack correct after a "complete" phase error', async () => { jest.resetModules(); - loadModulesNoop({ + loadModules({ replayFailedUnitOfWorkWithInvokeGuardedCallback, }); @@ -1333,7 +1211,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1392,7 +1270,7 @@ describe(`onRender`, () => { return null; } } - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1409,7 +1287,7 @@ describe(`onCommit`, () => { beforeEach(() => { jest.resetModules(); - loadModulesReactDOM(); + loadModules(); }); it('should report time spent in layout effects and commit lifecycles', async () => { @@ -1451,7 +1329,7 @@ describe(`onCommit`, () => { } Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1547,7 +1425,7 @@ describe(`onCommit`, () => { } Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1629,7 +1507,7 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1685,7 +1563,7 @@ describe(`onCommit`, () => { const setCountRef = React.createRef(null); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1784,7 +1662,7 @@ describe(`onCommit`, () => { // Test an error that happens during an effect - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1869,7 +1747,7 @@ describe(`onCommit`, () => { Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -1965,7 +1843,7 @@ describe(`onPostCommit`, () => { beforeEach(() => { jest.resetModules(); - loadModulesReactDOM(); + loadModules(); }); it('should report time spent in passive effects', async () => { @@ -1996,7 +1874,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -2079,7 +1957,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -2127,7 +2005,7 @@ describe(`onPostCommit`, () => { const setCountRef = React.createRef(null); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -2225,7 +2103,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); // Test an error that happens during an effect - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( @@ -2311,7 +2189,7 @@ describe(`onPostCommit`, () => { Scheduler.unstable_advanceTime(1); - const root = ReactDOMClient.createRoot(container); + const root = ReactNoop.createRoot(); await act(() => { root.render( diff --git a/packages/react/src/__tests__/ReactProfilerComponent-test.internal.js b/packages/react/src/__tests__/ReactProfilerComponent-test.internal.js new file mode 100644 index 0000000000000..325354b63f364 --- /dev/null +++ b/packages/react/src/__tests__/ReactProfilerComponent-test.internal.js @@ -0,0 +1,137 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react-core + */ + +'use strict'; + +let React; +let ReactDOMClient; +let ReactFeatureFlags; +let act; +let container; + +function loadModules({ + enableProfilerTimer = true, + enableProfilerCommitHooks = true, + enableProfilerNestedUpdatePhase = true, + enableProfilerNestedUpdateScheduledHook = false, + replayFailedUnitOfWorkWithInvokeGuardedCallback = false, +} = {}) { + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + + ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer; + ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks; + ReactFeatureFlags.enableProfilerNestedUpdatePhase = + enableProfilerNestedUpdatePhase; + ReactFeatureFlags.enableProfilerNestedUpdateScheduledHook = + enableProfilerNestedUpdateScheduledHook; + ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = + replayFailedUnitOfWorkWithInvokeGuardedCallback; + + React = require('react'); + ReactDOMClient = require('react-dom/client'); + const InternalTestUtils = require('internal-test-utils'); + act = InternalTestUtils.act; +} + +describe('Profiler', () => { + beforeEach(() => { + container = document.createElement('div'); + }); + + describe('works in profiling and non-profiling bundles', () => { + [true, false].forEach(enableProfilerTimer => { + describe(`enableProfilerTimer:${ + enableProfilerTimer ? 'enabled' : 'disabled' + }`, () => { + beforeEach(() => { + jest.resetModules(); + + loadModules({enableProfilerTimer}); + }); + + // This will throw in production too, + // But the test is only interested in verifying the DEV error message. + if (__DEV__ && enableProfilerTimer) { + it('should warn if required params are missing', async () => { + const root = ReactDOMClient.createRoot(container); + await expect(async () => { + await act(() => { + root.render(); + }); + }).toErrorDev( + 'Profiler must specify an "id" of type `string` as a prop. Received the type `undefined` instead.', + { + withoutStack: true, + }, + ); + }); + } + + it('should support an empty Profiler (with no children)', async () => { + const root = ReactDOMClient.createRoot(container); + // As root + await act(() => { + root.render(); + }); + expect(container.innerHTML).toMatchSnapshot(); + + // As non-root + await act(() => { + root.render( +
+ +
, + ); + }); + expect(container.innerHTML).toMatchSnapshot(); + }); + + it('should render children', async () => { + const FunctionComponent = ({label}) => {label}; + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( +
+ outside span + + inside span + + +
, + ); + }); + expect(container.innerHTML).toMatchSnapshot(); + }); + + it('should support nested Profilers', async () => { + const FunctionComponent = ({label}) =>
{label}
; + class ClassComponent extends React.Component { + render() { + return {this.props.label}; + } + } + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( + + + + + inner span + + , + ); + }); + + expect(container.innerHTML).toMatchSnapshot(); + }); + }); + }); + }); +}); diff --git a/packages/react/src/__tests__/__snapshots__/ReactProfiler-test.internal.js.snap b/packages/react/src/__tests__/__snapshots__/ReactProfilerComponent-test.internal.js.snap similarity index 100% rename from packages/react/src/__tests__/__snapshots__/ReactProfiler-test.internal.js.snap rename to packages/react/src/__tests__/__snapshots__/ReactProfilerComponent-test.internal.js.snap From c502f876bbab06c7488f7da219be221da485cf15 Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Thu, 7 Mar 2024 13:03:31 -0500 Subject: [PATCH 4/6] f --- .../src/__tests__/ReactProfiler-test.internal.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index bf5031224f31c..f026c88635a43 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -173,7 +173,16 @@ describe(`onRender`, () => { 'read current time', ]); } else { - assertLog(['read current time']); + assertLog([ + 'read current time', + 'read current time', + 'read current time', + 'read current time', + 'read current time', + 'read current time', + 'read current time', + 'read current time', + ]); } }); From fa3f924ff19ada27d4f13dc8acf86ab43cb42445 Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Thu, 7 Mar 2024 15:51:07 -0500 Subject: [PATCH 5/6] f --- packages/react/src/__tests__/ReactProfiler-test.internal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index f026c88635a43..2d5351de496fe 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @emails react-core + * @jest-environment node */ 'use strict'; From c00d1048970aeb935b47e7b0f803d575b64388ef Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Mon, 11 Mar 2024 10:56:00 -0400 Subject: [PATCH 6/6] Update comments --- .../src/__tests__/ReactProfiler-test.internal.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index 2d5351de496fe..22c551e0801f2 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -1077,14 +1077,15 @@ describe(`onRender`, () => { // base time includes: 2 (ErrorBoundary) // Since the tree is empty for the initial commit expect(mountCall[3]).toBe(2); - // start time + // start time: 5 initially + 14 of work + // Add an additional 3 (ThrowsError) if we replayed the failed work expect(mountCall[4]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback ? 22 : 19, ); - // commit time: 5 initially + 14 of work - // Add an additional 3 (ThrowsError) if we replayed the failed work + // commit time: 19 initially + 14 of work + // Add an additional 6 (ThrowsError *2) if we replayed the failed work expect(mountCall[5]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback ? 39 @@ -1103,8 +1104,8 @@ describe(`onRender`, () => { ? 39 : 33, ); - // commit time: 19 (startTime) + 2 (ErrorBoundary) + 20 (AdvanceTime) - // Add an additional 3 (ThrowsError) if we replayed the failed work + // commit time: 33 (startTime) + 2 (ErrorBoundary) + 20 (AdvanceTime) + // Add an additional 6 (ThrowsError *2) if we replayed the failed work expect(updateCall[5]).toBe( __DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback ? 61