mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Rewrite ReactTreeTraversal-test.js using public APIs (#11664)
* rewrite two phase traversal tests with public APIs
* rewrite enter/leave tests
* lift render into beforeEach, organise variables
* move getLowestCommonAncestor test
* remove internal tree traversal test
* fix linter errors
* move creation of outer nodes into {before,after}Each
* explain why getLowestCommonAncestor test was moved
* remove unnessecary ARG and ARG2 token
these were used for testing the internal API to simulate synthetic
events passed to traverseEnterLeave. since we're now dealing with
actual synthetic events we can remove them.
* run prettier
This commit is contained in:
@@ -1360,4 +1360,90 @@ describe('ResponderEventPlugin', () => {
|
||||
run(config, three, nativeEvent);
|
||||
expect(ResponderEventPlugin._getResponder()).toBe(null);
|
||||
});
|
||||
|
||||
it('should determine the first common ancestor correctly', () => {
|
||||
// This test was moved here from the ReactTreeTraversal test since only the
|
||||
// ResponderEventPlugin uses `getLowestCommonAncestor`
|
||||
var React = require('react');
|
||||
var ReactTestUtils = require('react-dom/test-utils');
|
||||
var ReactTreeTraversal = require('shared/ReactTreeTraversal');
|
||||
var ReactDOMComponentTree = require('../../react-dom/src/client/ReactDOMComponentTree');
|
||||
|
||||
class ChildComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div ref="DIV" id={this.props.id + '__DIV'}>
|
||||
<div ref="DIV_1" id={this.props.id + '__DIV_1'} />
|
||||
<div ref="DIV_2" id={this.props.id + '__DIV_2'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ParentComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div ref="P" id="P">
|
||||
<div ref="P_P1" id="P_P1">
|
||||
<ChildComponent ref="P_P1_C1" id="P_P1_C1" />
|
||||
<ChildComponent ref="P_P1_C2" id="P_P1_C2" />
|
||||
</div>
|
||||
<div ref="P_OneOff" id="P_OneOff" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var parent = ReactTestUtils.renderIntoDocument(<ParentComponent />);
|
||||
|
||||
var ancestors = [
|
||||
// Common ancestor with self is self.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
com: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
},
|
||||
// Common ancestor with self is self - even if topmost DOM.
|
||||
{one: parent.refs.P, two: parent.refs.P, com: parent.refs.P},
|
||||
// Siblings
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV_2,
|
||||
com: parent.refs.P_P1_C1.refs.DIV,
|
||||
},
|
||||
// Common ancestor with parent is the parent.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV,
|
||||
com: parent.refs.P_P1_C1.refs.DIV,
|
||||
},
|
||||
// Common ancestor with grandparent is the grandparent.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1,
|
||||
com: parent.refs.P_P1,
|
||||
},
|
||||
// Grandparent across subcomponent boundaries.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C2.refs.DIV_1,
|
||||
com: parent.refs.P_P1,
|
||||
},
|
||||
// Something deep with something one-off.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_OneOff,
|
||||
com: parent.refs.P,
|
||||
},
|
||||
];
|
||||
var i;
|
||||
for (i = 0; i < ancestors.length; i++) {
|
||||
var plan = ancestors[i];
|
||||
var firstCommon = ReactTreeTraversal.getLowestCommonAncestor(
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.one),
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.two),
|
||||
);
|
||||
expect(firstCommon).toBe(ReactDOMComponentTree.getInstanceFromNode(plan.com));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* 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';
|
||||
|
||||
var React = require('react');
|
||||
// TODO: can we express this test with only public API?
|
||||
var ReactDOMComponentTree = require('../client/ReactDOMComponentTree');
|
||||
var ReactTestUtils = require('react-dom/test-utils');
|
||||
|
||||
/**
|
||||
* Ensure that all callbacks are invoked, passing this unique argument.
|
||||
*/
|
||||
var ARG = {arg: true};
|
||||
var ARG2 = {arg2: true};
|
||||
|
||||
class ChildComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div ref="DIV" id={this.props.id + '__DIV'}>
|
||||
<div ref="DIV_1" id={this.props.id + '__DIV_1'} />
|
||||
<div ref="DIV_2" id={this.props.id + '__DIV_2'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ParentComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div ref="P" id="P">
|
||||
<div ref="P_P1" id="P_P1">
|
||||
<ChildComponent ref="P_P1_C1" id="P_P1_C1" />
|
||||
<ChildComponent ref="P_P1_C2" id="P_P1_C2" />
|
||||
</div>
|
||||
<div ref="P_OneOff" id="P_OneOff" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function renderParentIntoDocument() {
|
||||
return ReactTestUtils.renderIntoDocument(<ParentComponent />);
|
||||
}
|
||||
|
||||
describe('ReactTreeTraversal', () => {
|
||||
var ReactTreeTraversal;
|
||||
var mockFn = jest.fn();
|
||||
|
||||
function callback(inst, phase, arg) {
|
||||
mockFn(ReactDOMComponentTree.getNodeFromInstance(inst).id, phase, arg);
|
||||
}
|
||||
|
||||
function getInst(node) {
|
||||
return ReactDOMComponentTree.getInstanceFromNode(node);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
ReactTreeTraversal = require('shared/ReactTreeTraversal');
|
||||
mockFn.mockReset();
|
||||
});
|
||||
|
||||
describe('traverseTwoPhase', () => {
|
||||
it('should not traverse when traversing outside DOM', () => {
|
||||
ReactTreeTraversal.traverseTwoPhase(null, callback, ARG);
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should traverse two phase across component boundary', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var target = getInst(parent.refs.P_P1_C1.refs.DIV_1);
|
||||
var expectedCalls = [
|
||||
['P', 'captured', ARG],
|
||||
['P_P1', 'captured', ARG],
|
||||
['P_P1_C1__DIV', 'captured', ARG],
|
||||
['P_P1_C1__DIV_1', 'captured', ARG],
|
||||
|
||||
['P_P1_C1__DIV_1', 'bubbled', ARG],
|
||||
['P_P1_C1__DIV', 'bubbled', ARG],
|
||||
['P_P1', 'bubbled', ARG],
|
||||
['P', 'bubbled', ARG],
|
||||
];
|
||||
ReactTreeTraversal.traverseTwoPhase(target, callback, ARG);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should traverse two phase at shallowest node', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var target = getInst(parent.refs.P);
|
||||
var expectedCalls = [['P', 'captured', ARG], ['P', 'bubbled', ARG]];
|
||||
ReactTreeTraversal.traverseTwoPhase(target, callback, ARG);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
});
|
||||
|
||||
describe('traverseEnterLeave', () => {
|
||||
it('should not traverse when enter/leaving outside DOM', () => {
|
||||
ReactTreeTraversal.traverseEnterLeave(null, null, callback, ARG, ARG2);
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not traverse if enter/leave the same node', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var leave = getInst(parent.refs.P_P1_C1.refs.DIV_1);
|
||||
var enter = getInst(parent.refs.P_P1_C1.refs.DIV_1);
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should traverse enter/leave to sibling - avoids parent', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var leave = getInst(parent.refs.P_P1_C1.refs.DIV_1);
|
||||
var enter = getInst(parent.refs.P_P1_C1.refs.DIV_2);
|
||||
var expectedCalls = [
|
||||
['P_P1_C1__DIV_1', 'bubbled', ARG],
|
||||
// enter/leave shouldn't fire anything on the parent
|
||||
['P_P1_C1__DIV_2', 'captured', ARG2],
|
||||
];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should traverse enter/leave to parent - avoids parent', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var leave = getInst(parent.refs.P_P1_C1.refs.DIV_1);
|
||||
var enter = getInst(parent.refs.P_P1_C1.refs.DIV);
|
||||
var expectedCalls = [['P_P1_C1__DIV_1', 'bubbled', ARG]];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should enter from the window', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var leave = null; // From the window or outside of the React sandbox.
|
||||
var enter = getInst(parent.refs.P_P1_C1.refs.DIV);
|
||||
var expectedCalls = [
|
||||
['P', 'captured', ARG2],
|
||||
['P_P1', 'captured', ARG2],
|
||||
['P_P1_C1__DIV', 'captured', ARG2],
|
||||
];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should enter from the window to the shallowest', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var leave = null; // From the window or outside of the React sandbox.
|
||||
var enter = getInst(parent.refs.P);
|
||||
var expectedCalls = [['P', 'captured', ARG2]];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should leave to the window', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var enter = null; // From the window or outside of the React sandbox.
|
||||
var leave = getInst(parent.refs.P_P1_C1.refs.DIV);
|
||||
var expectedCalls = [
|
||||
['P_P1_C1__DIV', 'bubbled', ARG],
|
||||
['P_P1', 'bubbled', ARG],
|
||||
['P', 'bubbled', ARG],
|
||||
];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should leave to the window from the shallowest', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var enter = null; // From the window or outside of the React sandbox.
|
||||
var leave = getInst(parent.refs.P_P1_C1.refs.DIV);
|
||||
var expectedCalls = [
|
||||
['P_P1_C1__DIV', 'bubbled', ARG],
|
||||
['P_P1', 'bubbled', ARG],
|
||||
['P', 'bubbled', ARG],
|
||||
];
|
||||
ReactTreeTraversal.traverseEnterLeave(leave, enter, callback, ARG, ARG2);
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFirstCommonAncestor', () => {
|
||||
it('should determine the first common ancestor correctly', () => {
|
||||
var parent = renderParentIntoDocument();
|
||||
var ancestors = [
|
||||
// Common ancestor with self is self.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
com: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
},
|
||||
// Common ancestor with self is self - even if topmost DOM.
|
||||
{one: parent.refs.P, two: parent.refs.P, com: parent.refs.P},
|
||||
// Siblings
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV_2,
|
||||
com: parent.refs.P_P1_C1.refs.DIV,
|
||||
},
|
||||
// Common ancestor with parent is the parent.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C1.refs.DIV,
|
||||
com: parent.refs.P_P1_C1.refs.DIV,
|
||||
},
|
||||
// Common ancestor with grandparent is the grandparent.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1,
|
||||
com: parent.refs.P_P1,
|
||||
},
|
||||
// Grandparent across subcomponent boundaries.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_P1_C2.refs.DIV_1,
|
||||
com: parent.refs.P_P1,
|
||||
},
|
||||
// Something deep with something one-off.
|
||||
{
|
||||
one: parent.refs.P_P1_C1.refs.DIV_1,
|
||||
two: parent.refs.P_OneOff,
|
||||
com: parent.refs.P,
|
||||
},
|
||||
];
|
||||
var i;
|
||||
for (i = 0; i < ancestors.length; i++) {
|
||||
var plan = ancestors[i];
|
||||
var firstCommon = ReactTreeTraversal.getLowestCommonAncestor(
|
||||
getInst(plan.one),
|
||||
getInst(plan.two),
|
||||
);
|
||||
expect(firstCommon).toBe(getInst(plan.com));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* 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';
|
||||
|
||||
var React;
|
||||
var ReactDOM;
|
||||
|
||||
const ChildComponent = ({id, eventHandler}) => (
|
||||
<div
|
||||
id={id + '__DIV'}
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>
|
||||
<div
|
||||
id={id + '__DIV_1'}
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
/>
|
||||
<div
|
||||
id={id + '__DIV_2'}
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ParentComponent = ({eventHandler}) => (
|
||||
<div
|
||||
id="P"
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>
|
||||
<div
|
||||
id="P_P1"
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}>
|
||||
<ChildComponent id="P_P1_C1" eventHandler={eventHandler} />
|
||||
<ChildComponent id="P_P1_C2" eventHandler={eventHandler} />
|
||||
</div>
|
||||
<div
|
||||
id="P_OneOff"
|
||||
onClickCapture={e => eventHandler(e.currentTarget.id, 'captured', e.type)}
|
||||
onClick={e => eventHandler(e.currentTarget.id, 'bubbled', e.type)}
|
||||
onMouseEnter={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
onMouseLeave={e => eventHandler(e.currentTarget.id, e.type)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
describe('ReactTreeTraversal', () => {
|
||||
var mockFn = jest.fn();
|
||||
var container;
|
||||
var outerNode1;
|
||||
var outerNode2;
|
||||
|
||||
beforeEach(() => {
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
|
||||
mockFn.mockReset();
|
||||
|
||||
container = document.createElement('div');
|
||||
outerNode1 = document.createElement('div');
|
||||
outerNode2 = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
document.body.appendChild(outerNode1);
|
||||
document.body.appendChild(outerNode2);
|
||||
|
||||
ReactDOM.render(<ParentComponent eventHandler={mockFn} />, container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(container);
|
||||
document.body.removeChild(outerNode1);
|
||||
document.body.removeChild(outerNode2);
|
||||
container = null;
|
||||
outerNode1 = null;
|
||||
outerNode2 = null;
|
||||
});
|
||||
|
||||
describe('Two phase traversal', () => {
|
||||
it('should not traverse when target is outside component boundary', () => {
|
||||
outerNode1.dispatchEvent(
|
||||
new MouseEvent('click', {bubbles: true, cancelable: true}),
|
||||
);
|
||||
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should traverse two phase across component boundary', () => {
|
||||
var expectedCalls = [
|
||||
['P', 'captured', 'click'],
|
||||
['P_P1', 'captured', 'click'],
|
||||
['P_P1_C1__DIV', 'captured', 'click'],
|
||||
['P_P1_C1__DIV_1', 'captured', 'click'],
|
||||
|
||||
['P_P1_C1__DIV_1', 'bubbled', 'click'],
|
||||
['P_P1_C1__DIV', 'bubbled', 'click'],
|
||||
['P_P1', 'bubbled', 'click'],
|
||||
['P', 'bubbled', 'click'],
|
||||
];
|
||||
|
||||
var node = document.getElementById('P_P1_C1__DIV_1');
|
||||
node.dispatchEvent(
|
||||
new MouseEvent('click', {bubbles: true, cancelable: true}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should traverse two phase at shallowest node', () => {
|
||||
var node = document.getElementById('P');
|
||||
node.dispatchEvent(
|
||||
new MouseEvent('click', {bubbles: true, cancelable: true}),
|
||||
);
|
||||
|
||||
var expectedCalls = [
|
||||
['P', 'captured', 'click'],
|
||||
['P', 'bubbled', 'click'],
|
||||
];
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Enter leave traversal', () => {
|
||||
it('should not traverse when enter/leaving outside DOM', () => {
|
||||
outerNode1.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: outerNode2,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not traverse if enter/leave the same node', () => {
|
||||
var leaveNode = document.getElementById('P_P1_C1__DIV_1');
|
||||
var enterNode = document.getElementById('P_P1_C1__DIV_1');
|
||||
|
||||
leaveNode.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: enterNode,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should traverse enter/leave to sibling - avoids parent', () => {
|
||||
var leaveNode = document.getElementById('P_P1_C1__DIV_1');
|
||||
var enterNode = document.getElementById('P_P1_C1__DIV_2');
|
||||
|
||||
var expectedCalls = [
|
||||
['P_P1_C1__DIV_1', 'mouseleave'],
|
||||
// enter/leave shouldn't fire anything on the parent
|
||||
['P_P1_C1__DIV_2', 'mouseenter'],
|
||||
];
|
||||
|
||||
leaveNode.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: enterNode,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should traverse enter/leave to parent - avoids parent', () => {
|
||||
var leaveNode = document.getElementById('P_P1_C1__DIV_1');
|
||||
var enterNode = document.getElementById('P_P1_C1__DIV');
|
||||
|
||||
var expectedCalls = [['P_P1_C1__DIV_1', 'mouseleave']];
|
||||
|
||||
leaveNode.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: enterNode,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should enter from the window', () => {
|
||||
var enterNode = document.getElementById('P_P1_C1__DIV');
|
||||
|
||||
var expectedCalls = [
|
||||
['P', 'mouseenter'],
|
||||
['P_P1', 'mouseenter'],
|
||||
['P_P1_C1__DIV', 'mouseenter'],
|
||||
];
|
||||
|
||||
outerNode1.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: enterNode,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should enter from the window to the shallowest', () => {
|
||||
var enterNode = document.getElementById('P');
|
||||
|
||||
var expectedCalls = [['P', 'mouseenter']];
|
||||
|
||||
outerNode1.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: enterNode,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should leave to the window', () => {
|
||||
var leaveNode = document.getElementById('P_P1_C1__DIV');
|
||||
|
||||
var expectedCalls = [
|
||||
['P_P1_C1__DIV', 'mouseleave'],
|
||||
['P_P1', 'mouseleave'],
|
||||
['P', 'mouseleave'],
|
||||
];
|
||||
|
||||
leaveNode.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: outerNode1,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
|
||||
it('should leave to the window from the shallowest', () => {
|
||||
var leaveNode = document.getElementById('P');
|
||||
|
||||
var expectedCalls = [['P', 'mouseleave']];
|
||||
|
||||
leaveNode.dispatchEvent(
|
||||
new MouseEvent('mouseout', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: outerNode1,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(expectedCalls);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user