diff --git a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js index d1f5493e95f44..42908a693cce3 100644 --- a/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactLegacyCompositeComponent-test.js @@ -11,16 +11,18 @@ let React; let ReactDOM; -let ReactTestUtils; +let ReactDOMClient; let PropTypes; +let act; describe('ReactLegacyCompositeComponent', () => { beforeEach(() => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); + ReactDOMClient = require('react-dom/client'); PropTypes = require('prop-types'); + act = require('internal-test-utils').act; }); it('should warn about `setState` in render in legacy mode', () => { @@ -70,7 +72,7 @@ describe('ReactLegacyCompositeComponent', () => { }); // @gate !disableLegacyContext - it('should pass context to children when not owner', () => { + it('should pass context to children when not owner', async () => { class Parent extends React.Component { render() { return ( @@ -106,13 +108,17 @@ describe('ReactLegacyCompositeComponent', () => { return
{this.context.foo}
; } } - - const component = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + let component; + await act(() => { + root.render( (component = current)} />); + }); expect(ReactDOM.findDOMNode(component).innerHTML).toBe('bar'); }); // @gate !disableLegacyContext - it('should pass context when re-rendered for static child', () => { + it('should pass context when re-rendered for static child', async () => { let parentInstance = null; let childInstance = null; @@ -156,24 +162,31 @@ describe('ReactLegacyCompositeComponent', () => { } } - parentInstance = ReactTestUtils.renderIntoDocument( - - - - - , - ); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + + await act(() => { + root.render( + (parentInstance = current)}> + + + + , + ); + }); expect(parentInstance.state.flag).toBe(false); expect(childInstance.context).toEqual({foo: 'bar', flag: false}); - parentInstance.setState({flag: true}); + await act(() => { + parentInstance.setState({flag: true}); + }); expect(parentInstance.state.flag).toBe(true); expect(childInstance.context).toEqual({foo: 'bar', flag: true}); }); // @gate !disableLegacyContext - it('should pass context when re-rendered for static child within a composite component', () => { + it('should pass context when re-rendered for static child within a composite component', async () => { class Parent extends React.Component { static childContextTypes = { flag: PropTypes.bool, @@ -217,20 +230,27 @@ describe('ReactLegacyCompositeComponent', () => { } } - const wrapper = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + let wrapper; + await act(() => { + root.render( (wrapper = current)} />); + }); expect(wrapper.parentRef.current.state.flag).toEqual(true); expect(wrapper.childRef.current.context).toEqual({flag: true}); // We update while is still a static prop relative to this update - wrapper.parentRef.current.setState({flag: false}); + await act(() => { + wrapper.parentRef.current.setState({flag: false}); + }); expect(wrapper.parentRef.current.state.flag).toEqual(false); expect(wrapper.childRef.current.context).toEqual({flag: false}); }); // @gate !disableLegacyContext - it('should pass context transitively', () => { + it('should pass context transitively', async () => { let childInstance = null; let grandchildInstance = null; @@ -286,13 +306,18 @@ describe('ReactLegacyCompositeComponent', () => { } } - ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render(); + }); + expect(childInstance.context).toEqual({foo: 'bar', depth: 0}); expect(grandchildInstance.context).toEqual({foo: 'bar', depth: 1}); }); // @gate !disableLegacyContext - it('should pass context when re-rendered', () => { + it('should pass context when re-rendered', async () => { let parentInstance = null; let childInstance = null; @@ -334,11 +359,16 @@ describe('ReactLegacyCompositeComponent', () => { } } - parentInstance = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render( (parentInstance = current)} />); + }); + expect(childInstance).toBeNull(); expect(parentInstance.state.flag).toBe(false); - ReactDOM.unstable_batchedUpdates(function () { + await act(() => { parentInstance.setState({flag: true}); }); expect(parentInstance.state.flag).toBe(true); @@ -699,7 +729,7 @@ describe('ReactLegacyCompositeComponent', () => { ); }); - it('should replace state in legacy mode', () => { + it('should replace state in legacy mode', async () => { class Moo extends React.Component { state = {x: 1}; render() { @@ -707,15 +737,23 @@ describe('ReactLegacyCompositeComponent', () => { } } - const moo = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + let moo; + await act(() => { + root.render( (moo = current)} />); + }); + // No longer a public API, but we can test that it works internally by // reaching into the updater. - moo.updater.enqueueReplaceState(moo, {y: 2}); + await act(() => { + moo.updater.enqueueReplaceState(moo, {y: 2}); + }); expect('x' in moo.state).toBe(false); expect(moo.state.y).toBe(2); }); - it('should support objects with prototypes as state in legacy mode', () => { + it('should support objects with prototypes as state in legacy mode', async () => { const NotActuallyImmutable = function (str) { this.str = str; }; @@ -732,24 +770,34 @@ describe('ReactLegacyCompositeComponent', () => { } } - const moo = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + let moo; + await act(() => { + root.render( (moo = current)} />); + }); + expect(moo.state.str).toBe('first'); expect(moo.state.amIImmutable()).toBe(true); const secondState = new NotActuallyImmutable('second'); - moo._replaceState(secondState); + await act(() => { + moo._replaceState(secondState); + }); expect(moo.state.str).toBe('second'); expect(moo.state.amIImmutable()).toBe(true); expect(moo.state).toBe(secondState); - moo.setState({str: 'third'}); + await act(() => { + moo.setState({str: 'third'}); + }); expect(moo.state.str).toBe('third'); // Here we lose the prototype. expect(moo.state.amIImmutable).toBe(undefined); // When more than one state update is enqueued, we have the same behavior const fifthState = new NotActuallyImmutable('fifth'); - ReactDOM.unstable_batchedUpdates(function () { + await act(() => { moo.setState({str: 'fourth'}); moo._replaceState(fifthState); }); @@ -757,7 +805,7 @@ describe('ReactLegacyCompositeComponent', () => { // When more than one state update is enqueued, we have the same behavior const sixthState = new NotActuallyImmutable('sixth'); - ReactDOM.unstable_batchedUpdates(function () { + await act(() => { moo._replaceState(sixthState); moo.setState({str: 'seventh'}); });