diff --git a/packages/react-dom/src/events/plugins/__tests__/EnterLeaveEventPlugin-test.js b/packages/react-dom/src/events/plugins/__tests__/EnterLeaveEventPlugin-test.js index f6a9232e87c62..569a29a22a5b8 100644 --- a/packages/react-dom/src/events/plugins/__tests__/EnterLeaveEventPlugin-test.js +++ b/packages/react-dom/src/events/plugins/__tests__/EnterLeaveEventPlugin-test.js @@ -11,6 +11,8 @@ let React; let ReactDOM; +let ReactDOMClient; +let act; describe('EnterLeaveEventPlugin', () => { let container; @@ -20,6 +22,8 @@ describe('EnterLeaveEventPlugin', () => { React = require('react'); ReactDOM = require('react-dom'); + ReactDOMClient = require('react-dom/client'); + act = require('internal-test-utils').act; // The container has to be attached for events to fire. container = document.createElement('div'); @@ -31,7 +35,7 @@ describe('EnterLeaveEventPlugin', () => { container = null; }); - it('should set onMouseLeave relatedTarget properly in iframe', () => { + it('should set onMouseLeave relatedTarget properly in iframe', async () => { const iframe = document.createElement('iframe'); container.appendChild(iframe); const iframeDocument = iframe.contentDocument; @@ -41,30 +45,36 @@ describe('EnterLeaveEventPlugin', () => { iframeDocument.close(); const leaveEvents = []; - const node = ReactDOM.render( -
{ - e.persist(); - leaveEvents.push(e); - }} - />, + const root = ReactDOMClient.createRoot( iframeDocument.body.getElementsByTagName('div')[0], ); - - node.dispatchEvent( - new MouseEvent('mouseout', { - bubbles: true, - cancelable: true, - relatedTarget: iframe.contentWindow, - }), - ); + await act(() => { + root.render( +
{ + e.persist(); + leaveEvents.push(e); + }} + />, + ); + }); + const node = iframeDocument.body.getElementsByTagName('div')[0].firstChild; + await act(() => { + node.dispatchEvent( + new MouseEvent('mouseout', { + bubbles: true, + cancelable: true, + relatedTarget: iframe.contentWindow, + }), + ); + }); expect(leaveEvents.length).toBe(1); expect(leaveEvents[0].target).toBe(node); expect(leaveEvents[0].relatedTarget).toBe(iframe.contentWindow); }); - it('should set onMouseEnter relatedTarget properly in iframe', () => { + it('should set onMouseEnter relatedTarget properly in iframe', async () => { const iframe = document.createElement('iframe'); container.appendChild(iframe); const iframeDocument = iframe.contentDocument; @@ -74,23 +84,29 @@ describe('EnterLeaveEventPlugin', () => { iframeDocument.close(); const enterEvents = []; - const node = ReactDOM.render( -
{ - e.persist(); - enterEvents.push(e); - }} - />, + const root = ReactDOMClient.createRoot( iframeDocument.body.getElementsByTagName('div')[0], ); - - node.dispatchEvent( - new MouseEvent('mouseover', { - bubbles: true, - cancelable: true, - relatedTarget: null, - }), - ); + await act(() => { + root.render( +
{ + e.persist(); + enterEvents.push(e); + }} + />, + ); + }); + const node = iframeDocument.body.getElementsByTagName('div')[0].firstChild; + await act(() => { + node.dispatchEvent( + new MouseEvent('mouseover', { + bubbles: true, + cancelable: true, + relatedTarget: null, + }), + ); + }); expect(enterEvents.length).toBe(1); expect(enterEvents[0].target).toBe(node); @@ -98,7 +114,7 @@ describe('EnterLeaveEventPlugin', () => { }); // Regression test for https://github.com/facebook/react/issues/10906. - it('should find the common parent after updates', () => { + it('should find the common parent after updates', async () => { let parentEnterCalls = 0; let childEnterCalls = 0; let parent = null; @@ -117,18 +133,24 @@ describe('EnterLeaveEventPlugin', () => { } } - ReactDOM.render(, container); - // The issue only reproduced on insertion during the first update. - ReactDOM.render(, container); + const root = ReactDOMClient.createRoot(container); + await act(() => { + root.render(); + }); + await act(() => { + root.render(); + }); // Enter from parent into the child. - parent.dispatchEvent( - new MouseEvent('mouseout', { - bubbles: true, - cancelable: true, - relatedTarget: parent.firstChild, - }), - ); + await act(() => { + parent.dispatchEvent( + new MouseEvent('mouseout', { + bubbles: true, + cancelable: true, + relatedTarget: parent.firstChild, + }), + ); + }); // Entering a child should fire on the child, not on the parent. expect(childEnterCalls).toBe(1); @@ -136,7 +158,7 @@ describe('EnterLeaveEventPlugin', () => { }); // Test for https://github.com/facebook/react/issues/16763. - it('should call mouseEnter once from sibling rendered inside a rendered component', done => { + it('should call mouseEnter once from sibling rendered inside a rendered component in legacy roots', done => { const mockFn = jest.fn(); class Parent extends React.Component { @@ -186,7 +208,7 @@ describe('EnterLeaveEventPlugin', () => { ReactDOM.render(, container); }); - it('should call mouseEnter when pressing a non tracked React node', done => { + it('should call mouseEnter when pressing a non tracked React node in legacy root', done => { const mockFn = jest.fn(); class Parent extends React.Component { @@ -237,7 +259,7 @@ describe('EnterLeaveEventPlugin', () => { ReactDOM.render(, container); }); - it('should work with portals outside of the root that has onMouseLeave', () => { + it('should work with portals outside of the root that has onMouseLeave', async () => { const divRef = React.createRef(); const onMouseLeave = jest.fn(); @@ -249,21 +271,27 @@ describe('EnterLeaveEventPlugin', () => { ); } - ReactDOM.render(, container); + const root = ReactDOMClient.createRoot(container); + + await act(() => { + root.render(); + }); // Leave from the portal div - divRef.current.dispatchEvent( - new MouseEvent('mouseout', { - bubbles: true, - cancelable: true, - relatedTarget: document.body, - }), - ); + await act(() => { + divRef.current.dispatchEvent( + new MouseEvent('mouseout', { + bubbles: true, + cancelable: true, + relatedTarget: document.body, + }), + ); + }); expect(onMouseLeave).toHaveBeenCalledTimes(1); }); - it('should work with portals that have onMouseEnter outside of the root ', () => { + it('should work with portals that have onMouseEnter outside of the root ', async () => { const divRef = React.createRef(); const otherDivRef = React.createRef(); const onMouseEnter = jest.fn(); @@ -279,7 +307,11 @@ describe('EnterLeaveEventPlugin', () => { ); } - ReactDOM.render(, container); + const root = ReactDOMClient.createRoot(container); + + await act(() => { + root.render(); + }); // Leave from the portal div divRef.current.dispatchEvent(