diff --git a/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.internal.js b/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.internal.js deleted file mode 100644 index 51795d9b48fd4..0000000000000 --- a/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.internal.js +++ /dev/null @@ -1,91 +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; -var ReactDOM; -var ReactDOMComponentTree; -var ReactTestUtils; -var SelectEventPlugin; - -describe('SelectEventPlugin', () => { - function extract(node, topLevelEvent) { - return SelectEventPlugin.extractEvents( - topLevelEvent, - ReactDOMComponentTree.getInstanceFromNode(node), - {target: node}, - node, - ); - } - - beforeEach(() => { - React = require('react'); - ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); - // TODO: can we express this test with only public API? - ReactDOMComponentTree = require('../../client/ReactDOMComponentTree'); - SelectEventPlugin = require('../SelectEventPlugin').default; - }); - - it('should skip extraction if no listeners are present', () => { - class WithoutSelect extends React.Component { - render() { - return ; - } - } - - var rendered = ReactTestUtils.renderIntoDocument(); - var node = ReactDOM.findDOMNode(rendered); - node.focus(); - - // It seems that .focus() isn't triggering this event in our test - // environment so we need to ensure it gets set for this test to be valid. - var fakeNativeEvent = function() {}; - fakeNativeEvent.target = node; - ReactTestUtils.simulateNativeEventOnNode('topFocus', node, fakeNativeEvent); - - var mousedown = extract(node, 'topMouseDown'); - expect(mousedown).toBe(null); - - var mouseup = extract(node, 'topMouseUp'); - expect(mouseup).toBe(null); - }); - - it('should extract if an `onSelect` listener is present', () => { - class WithSelect extends React.Component { - render() { - return ; - } - } - - var cb = jest.fn(); - - var rendered = ReactTestUtils.renderIntoDocument( - , - ); - var node = ReactDOM.findDOMNode(rendered); - - node.selectionStart = 0; - node.selectionEnd = 0; - node.focus(); - - var focus = extract(node, 'topFocus'); - expect(focus).toBe(null); - - var mousedown = extract(node, 'topMouseDown'); - expect(mousedown).toBe(null); - - var mouseup = extract(node, 'topMouseUp'); - expect(mouseup).not.toBe(null); - expect(typeof mouseup).toBe('object'); - expect(mouseup.type).toBe('select'); - expect(mouseup.target).toBe(node); - }); -}); diff --git a/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.js b/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.js new file mode 100644 index 0000000000000..f01a406d409f7 --- /dev/null +++ b/packages/react-dom/src/events/__tests__/SelectEventPlugin-test.js @@ -0,0 +1,111 @@ +/** + * 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; + +describe('SelectEventPlugin', () => { + var container; + + beforeEach(() => { + React = require('react'); + ReactDOM = require('react-dom'); + + container = document.createElement('div'); + document.body.appendChild(container); + }); + + afterEach(() => { + document.body.removeChild(container); + container = null; + }); + + // See https://github.com/facebook/react/pull/3639 for details. + it('does not get confused when dependent events are registered independently', () => { + var select = jest.fn(); + var onSelect = event => { + expect(typeof event).toBe('object'); + expect(event.type).toBe('select'); + expect(event.target).toBe(node); + select(event.currentTarget); + }; + + // Pass `onMouseDown` so React registers a top-level listener. + var node = ReactDOM.render( + , + container, + ); + node.focus(); + + // Trigger `mousedown` and `mouseup`. Note that + // React is not currently listening to `mouseup`. + node.dispatchEvent( + new MouseEvent('mousedown', { + bubbles: true, + cancelable: true, + }), + ); + node.dispatchEvent( + new MouseEvent('mouseup', { + bubbles: true, + cancelable: true, + }), + ); + + // Now subscribe to `onSelect`. + ReactDOM.render(, container); + node.focus(); + + // This triggers a `select` event in our polyfill. + node.dispatchEvent( + new KeyboardEvent('keydown', {bubbles: true, cancelable: true}), + ); + + // Verify that it doesn't get "stuck" waiting for + // a `mouseup` event that it has "missed" because + // a top-level listener didn't exist yet. + expect(select.mock.calls.length).toBe(1); + }); + + it('should fire `onSelect` when a listener is present', () => { + var select = jest.fn(); + var onSelect = event => { + expect(typeof event).toBe('object'); + expect(event.type).toBe('select'); + expect(event.target).toBe(node); + select(event.currentTarget); + }; + + var node = ReactDOM.render( + , + container, + ); + node.focus(); + + var nativeEvent = new MouseEvent('focus', { + bubbles: true, + cancelable: true, + }); + node.dispatchEvent(nativeEvent); + expect(select.mock.calls.length).toBe(0); + + nativeEvent = new MouseEvent('mousedown', { + bubbles: true, + cancelable: true, + }); + node.dispatchEvent(nativeEvent); + expect(select.mock.calls.length).toBe(0); + + nativeEvent = new MouseEvent('mouseup', {bubbles: true, cancelable: true}); + node.dispatchEvent(nativeEvent); + expect(select.mock.calls.length).toBe(1); + }); +});