Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert EnterLeaveEventPlugin to createRoot #28182

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

let React;
let ReactDOM;
let ReactDOMClient;
let act;

describe('EnterLeaveEventPlugin', () => {
let container;
Expand All @@ -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');
Expand All @@ -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;
Expand All @@ -41,30 +45,36 @@ describe('EnterLeaveEventPlugin', () => {
iframeDocument.close();

const leaveEvents = [];
const node = ReactDOM.render(
<div
onMouseLeave={e => {
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(
<div
onMouseLeave={e => {
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;
Expand All @@ -74,31 +84,37 @@ describe('EnterLeaveEventPlugin', () => {
iframeDocument.close();

const enterEvents = [];
const node = ReactDOM.render(
<div
onMouseEnter={e => {
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(
<div
onMouseEnter={e => {
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);
expect(enterEvents[0].relatedTarget).toBe(iframe.contentWindow);
});

// 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;
Expand All @@ -117,26 +133,32 @@ describe('EnterLeaveEventPlugin', () => {
}
}

ReactDOM.render(<Parent />, container);
// The issue only reproduced on insertion during the first update.
ReactDOM.render(<Parent showChild={true} />, container);
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Parent />);
});
await act(() => {
root.render(<Parent showChild={true} />);
});

// 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);
expect(parentEnterCalls).toBe(0);
});

// 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 {
Expand Down Expand Up @@ -186,7 +208,7 @@ describe('EnterLeaveEventPlugin', () => {
ReactDOM.render(<Parent />, 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 {
Expand Down Expand Up @@ -237,7 +259,7 @@ describe('EnterLeaveEventPlugin', () => {
ReactDOM.render(<Parent />, 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();

Expand All @@ -249,21 +271,27 @@ describe('EnterLeaveEventPlugin', () => {
);
}

ReactDOM.render(<Component />, container);
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<Component />);
});

// 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();
Expand All @@ -279,7 +307,11 @@ describe('EnterLeaveEventPlugin', () => {
);
}

ReactDOM.render(<Component />, container);
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<Component />);
});

// Leave from the portal div
divRef.current.dispatchEvent(
Expand Down