From dfe5d83a7756d6615ee5902452ee6dabe9bf1a49 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Tue, 12 Jun 2018 02:47:52 +0200 Subject: [PATCH 1/3] Use native event dispatching instead of Simulate or SimulateNative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In #12629 @gaearon suggested that it would be better to drop usage of `ReactTestUtils.Simulate` and `ReactTestUtils.SimulateNative`. In this PR I’m attempting at removing it from a lot of places with only a few leftovers. Those leftovers can be categorized into three groups: 1. Anything that tests that `SimulateNative` throws. This is a property that native event dispatching doesn’t have so I can’t convert that easily. Affected test suites: `EventPluginHub-test`, `ReactBrowserEventEmitter-test`. 2. Anything that tests `ReactTestUtils` directly. Affected test suites: `ReactBrowserEventEmitter-test` (this file has one test that reads "should have mouse enter simulated by test utils"), `ReactTestUtils-test`. 3. Anything that dispatches a `change` event. The reason here goes a bit deeper and is rooted in the way we shim onChange. Usually when using native event dispatching, you would set the node’s `.value` and then dispatch the event. However inside [`inputValueTracking.js`][] we install a setter on the node’s `.value` that will ignore the next `change` event (I found [this][near-perfect-oninput-shim] article from Sophie that explains that this is to avoid onChange when updating the value via JavaScript). All remaining usages of `Simulate` or `SimulateNative` can be avoided by mounting the containers inside the `document` and dispatching native events. Here some remarks: 1. I’m using `Element#click()` instead of `dispatchEvent`. In the jsdom changelog I read that `click()` now properly sets the correct values (you can also verify it does the same thing by looking at the [source][jsdom-source]). 2. I had to update jsdom in order to get `TouchEvent` constructors working (and while doing so also updated jest). There was one unexpected surprise: `ReactScheduler-test` was relying on not having `window.performance` available. I’ve recreated the previous environment by deleting this property from the global object. 3. I was a bit confused that `ReactTestUtils.renderIntoDocument()` does not render into the document 🤷‍ [`inputValueTracking.js`]: https://github.com/facebook/react/blob/392530104c00c25074ce38e1f7e1dd363018c7ce/packages/react-dom/src/client/inputValueTracking.js#L79 [near-perfect-oninput-shim]: https://sophiebits.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html [jsdom-source]: https://github.com/jsdom/jsdom/blob/45b77f5d21cef74cad278d089937d8462c29acce/lib/jsdom/living/nodes/HTMLElement-impl.js#L43-L76 --- package.json | 2 +- .../ReactBrowserEventEmitter-test.internal.js | 36 +- .../__tests__/ReactComponentLifeCycle-test.js | 8 +- .../__tests__/ReactCompositeComponent-test.js | 8 +- ...ReactCompositeComponentNestedState-test.js | 4 +- .../react-dom/src/__tests__/ReactDOM-test.js | 13 +- .../src/__tests__/ReactDOMFiber-test.js | 48 +- .../__tests__/ReactEventIndependence-test.js | 19 +- .../ReactServerRenderingHydration.js | 17 +- packages/react-dom/src/__tests__/refs-test.js | 57 +- .../SimpleEventPlugin-test.internal.js | 60 +- .../events/__tests__/SyntheticEvent-test.js | 12 +- .../__tests__/TapEventPlugin-test.internal.js | 69 +- .../src/__tests__/ReactScheduler-test.js | 2 + yarn.lock | 609 ++++++++++-------- 15 files changed, 560 insertions(+), 404 deletions(-) diff --git a/package.json b/package.json index 73c007dfa3f22..23692fd8d4ca4 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "gzip-js": "~0.3.2", "gzip-size": "^3.0.0", "jasmine-check": "^1.0.0-rc.0", - "jest": "^23.0.1", + "jest": "^23.1.0", "jest-diff": "^23.0.1", "merge-stream": "^1.0.0", "minimatch": "^3.0.4", diff --git a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js index 85d6e22dfbc07..86a668a4bbc17 100644 --- a/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactBrowserEventEmitter-test.internal.js @@ -42,6 +42,8 @@ let getListener; let putListener; let deleteAllListeners; +let container; + function registerSimpleTestHandler() { putListener(CHILD, ON_CLICK_KEY, LISTENER); const listener = getListener(CHILD, ON_CLICK_KEY); @@ -63,7 +65,8 @@ describe('ReactBrowserEventEmitter', () => { ReactBrowserEventEmitter = require('../events/ReactBrowserEventEmitter'); ReactTestUtils = require('react-dom/test-utils'); - const container = document.createElement('div'); + container = document.createElement('div'); + document.body.appendChild(container); let GRANDPARENT_PROPS = {}; let PARENT_PROPS = {}; @@ -129,6 +132,11 @@ describe('ReactBrowserEventEmitter', () => { idCallOrder = []; }); + afterEach(() => { + document.body.removeChild(container); + container = null; + }); + it('should store a listener correctly', () => { registerSimpleTestHandler(); const listener = getListener(CHILD, ON_CLICK_KEY); @@ -150,17 +158,17 @@ describe('ReactBrowserEventEmitter', () => { it('should invoke a simple handler registered on a node', () => { registerSimpleTestHandler(); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(LISTENER).toHaveBeenCalledTimes(1); }); it('should not invoke handlers if ReactBrowserEventEmitter is disabled', () => { registerSimpleTestHandler(); ReactBrowserEventEmitter.setEnabled(false); - ReactTestUtils.SimulateNative.click(CHILD); + CHILD.click(); expect(LISTENER).toHaveBeenCalledTimes(0); ReactBrowserEventEmitter.setEnabled(true); - ReactTestUtils.SimulateNative.click(CHILD); + CHILD.click(); expect(LISTENER).toHaveBeenCalledTimes(1); }); @@ -168,7 +176,7 @@ describe('ReactBrowserEventEmitter', () => { putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, CHILD)); putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT)); putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT)); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(3); expect(idCallOrder[0]).toBe(CHILD); expect(idCallOrder[1]).toBe(PARENT); @@ -179,7 +187,7 @@ describe('ReactBrowserEventEmitter', () => { putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, 'GRANDPARENT')); putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, 'PARENT')); putListener(CHILD, ON_CLICK_KEY, recordID.bind(null, 'CHILD')); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder).toEqual(['CHILD', 'PARENT', 'GRANDPARENT']); idCallOrder = []; @@ -191,7 +199,7 @@ describe('ReactBrowserEventEmitter', () => { recordID.bind(null, 'UPDATED_GRANDPARENT'), ); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder).toEqual(['CHILD', 'PARENT', 'UPDATED_GRANDPARENT']); }); @@ -224,7 +232,7 @@ describe('ReactBrowserEventEmitter', () => { recordID(GRANDPARENT); expect(event.currentTarget).toBe(GRANDPARENT); }); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(3); expect(idCallOrder[0]).toBe(CHILD); expect(idCallOrder[1]).toBe(PARENT); @@ -239,7 +247,7 @@ describe('ReactBrowserEventEmitter', () => { recordIDAndStopPropagation.bind(null, PARENT), ); putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT)); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(2); expect(idCallOrder[0]).toBe(CHILD); expect(idCallOrder[1]).toBe(PARENT); @@ -254,7 +262,7 @@ describe('ReactBrowserEventEmitter', () => { e.isPropagationStopped = () => true; }); putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT)); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(2); expect(idCallOrder[0]).toBe(CHILD); expect(idCallOrder[1]).toBe(PARENT); @@ -268,7 +276,7 @@ describe('ReactBrowserEventEmitter', () => { ); putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT)); putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT)); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(1); expect(idCallOrder[0]).toBe(CHILD); }); @@ -277,7 +285,7 @@ describe('ReactBrowserEventEmitter', () => { putListener(CHILD, ON_CLICK_KEY, recordIDAndReturnFalse.bind(null, CHILD)); putListener(PARENT, ON_CLICK_KEY, recordID.bind(null, PARENT)); putListener(GRANDPARENT, ON_CLICK_KEY, recordID.bind(null, GRANDPARENT)); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(idCallOrder.length).toBe(3); expect(idCallOrder[0]).toBe(CHILD); expect(idCallOrder[1]).toBe(PARENT); @@ -300,7 +308,7 @@ describe('ReactBrowserEventEmitter', () => { }; putListener(CHILD, ON_CLICK_KEY, handleChildClick); putListener(PARENT, ON_CLICK_KEY, handleParentClick); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(handleParentClick).toHaveBeenCalledTimes(1); }); @@ -310,7 +318,7 @@ describe('ReactBrowserEventEmitter', () => { putListener(PARENT, ON_CLICK_KEY, handleParentClick); }; putListener(CHILD, ON_CLICK_KEY, handleChildClick); - ReactTestUtils.Simulate.click(CHILD); + CHILD.click(); expect(handleParentClick).toHaveBeenCalledTimes(0); }); diff --git a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js index 965b04f30aaa9..7be40ebbaee1f 100644 --- a/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js +++ b/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js @@ -1065,7 +1065,9 @@ describe('ReactComponentLifeCycle', () => { } } - ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + document.body.appendChild(container); + ReactDOM.render(, container); expect(divRef.current.textContent).toBe('remote:0, local:0'); // Trigger setState() calls @@ -1073,8 +1075,10 @@ describe('ReactComponentLifeCycle', () => { expect(divRef.current.textContent).toBe('remote:1, local:1'); // Trigger batched setState() calls - ReactTestUtils.Simulate.click(divRef.current); + divRef.current.click(); expect(divRef.current.textContent).toBe('remote:2, local:2'); + + document.body.removeChild(container); }); it('should pass the return value from getSnapshotBeforeUpdate to componentDidUpdate', () => { diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 216afa8550d3e..4b4e4b338b820 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -140,13 +140,15 @@ describe('ReactCompositeComponent', () => { }); it('should react to state changes from callbacks', () => { - const instance = ReactTestUtils.renderIntoDocument(); + const container = document.createElement('div'); + document.body.appendChild(container); + const instance = ReactDOM.render(, container); let el = ReactDOM.findDOMNode(instance); expect(el.tagName).toBe('A'); - - ReactTestUtils.Simulate.click(el); + el.click(); el = ReactDOM.findDOMNode(instance); expect(el.tagName).toBe('B'); + document.body.removeChild(container); }); it('should rewire refs when rendering to different child types', () => { diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponentNestedState-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponentNestedState-test.js index 94a33a457a3f0..e233e78b72082 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponentNestedState-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponentNestedState-test.js @@ -11,13 +11,11 @@ let React; let ReactDOM; -let ReactTestUtils; describe('ReactCompositeComponentNestedState-state', () => { beforeEach(() => { React = require('react'); ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); }); it('should provide up to date values for props', () => { @@ -102,7 +100,7 @@ describe('ReactCompositeComponentNestedState-state', () => { void ReactDOM.render(, container); // click "light green" - ReactTestUtils.Simulate.click(container.childNodes[0].childNodes[3]); + container.childNodes[0].childNodes[3].click(); expect(logger.mock.calls).toEqual([ ['parent-render', 'blue'], diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js index cca40165fd458..639915189a23d 100644 --- a/packages/react-dom/src/__tests__/ReactDOM-test.js +++ b/packages/react-dom/src/__tests__/ReactDOM-test.js @@ -308,15 +308,9 @@ describe('ReactDOM', () => { it("shouldn't fire duplicate event handler while handling other nested dispatch", () => { const actual = []; - function click(node) { - ReactTestUtils.Simulate.click(node, { - path: [node, container], - }); - } - class Wrapper extends React.Component { componentDidMount() { - click(this.ref1); + this.ref1.click(); } render() { @@ -325,7 +319,7 @@ describe('ReactDOM', () => {
{ actual.push('1st node clicked'); - click(this.ref2); + this.ref2.click(); }} ref={ref => (this.ref1 = ref)} /> @@ -341,6 +335,7 @@ describe('ReactDOM', () => { } const container = document.createElement('div'); + document.body.appendChild(container); ReactDOM.render(, container); const expected = [ @@ -348,6 +343,8 @@ describe('ReactDOM', () => { "2nd node clicked imperatively from 1st's handler", ]; expect(actual).toEqual(expected); + + document.body.removeChild(container); }); it('should not crash with devtools installed', () => { diff --git a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js index 911f161b0e660..0eb37f00d0d9d 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js @@ -11,7 +11,6 @@ const React = require('react'); const ReactDOM = require('react-dom'); -const ReactTestUtils = require('react-dom/test-utils'); const PropTypes = require('prop-types'); describe('ReactDOMFiber', () => { @@ -843,6 +842,7 @@ describe('ReactDOMFiber', () => { it('should bubble events from the portal to the parent', () => { const portalContainer = document.createElement('div'); + document.body.appendChild(portalContainer); const ops = []; let portal = null; @@ -863,13 +863,17 @@ describe('ReactDOMFiber', () => { expect(portal.tagName).toBe('DIV'); - ReactTestUtils.Simulate.click(portal); + portal.click(); expect(ops).toEqual(['portal clicked', 'parent clicked']); + + document.body.removeChild(portalContainer); }); it('should not onMouseLeave when staying in the portal', () => { const portalContainer = document.createElement('div'); + document.body.appendChild(container); + document.body.appendChild(portalContainer); let ops = []; let firstTarget = null; @@ -878,14 +882,22 @@ describe('ReactDOMFiber', () => { function simulateMouseMove(from, to) { if (from) { - ReactTestUtils.SimulateNative.mouseOut(from, { - relatedTarget: to, - }); + from.dispatchEvent( + new MouseEvent('mouseout', { + bubbles: true, + cancelable: true, + relatedTarget: to, + }), + ); } if (to) { - ReactTestUtils.SimulateNative.mouseOver(to, { - relatedTarget: from, - }); + to.dispatchEvent( + new MouseEvent('mouseover', { + bubbles: true, + cancelable: true, + relatedTarget: from, + }), + ); } } @@ -928,6 +940,9 @@ describe('ReactDOMFiber', () => { 'leave portal', 'leave parent', // Only when we leave the portal does onMouseLeave fire. ]); + + document.body.removeChild(container); + document.body.removeChild(portalContainer); }); it('should throw on bad createPortal argument', () => { @@ -967,6 +982,7 @@ describe('ReactDOMFiber', () => { }); it('should not update event handlers until commit', () => { + document.body.appendChild(container); let ops = []; const handlerA = () => ops.push('A'); const handlerB = () => ops.push('B'); @@ -988,7 +1004,7 @@ describe('ReactDOMFiber', () => { class Click extends React.Component { constructor() { super(); - click(node); + node.click(); } render() { return null; @@ -1000,11 +1016,7 @@ describe('ReactDOMFiber', () => { const node = container.firstChild; expect(node.tagName).toEqual('DIV'); - function click(target) { - ReactTestUtils.Simulate.click(target); - } - - click(node); + node.click(); expect(ops).toEqual(['A']); ops = []; @@ -1012,7 +1024,7 @@ describe('ReactDOMFiber', () => { // Render with the other event handler. inst.flip(); - click(node); + node.click(); expect(ops).toEqual(['B']); ops = []; @@ -1020,7 +1032,7 @@ describe('ReactDOMFiber', () => { // Rerender without changing any props. inst.tick(); - click(node); + node.click(); expect(ops).toEqual(['B']); ops = []; @@ -1040,8 +1052,10 @@ describe('ReactDOMFiber', () => { ops = []; // Any click that happens after commit, should invoke A. - click(node); + node.click(); expect(ops).toEqual(['A']); + + document.body.removeChild(container); }); it('should not crash encountering low-priority tree', () => { diff --git a/packages/react-dom/src/__tests__/ReactEventIndependence-test.js b/packages/react-dom/src/__tests__/ReactEventIndependence-test.js index 5133c3d8181b1..588833c688aed 100644 --- a/packages/react-dom/src/__tests__/ReactEventIndependence-test.js +++ b/packages/react-dom/src/__tests__/ReactEventIndependence-test.js @@ -11,7 +11,6 @@ let React; let ReactDOM; -let ReactTestUtils; describe('ReactEventIndependence', () => { beforeEach(() => { @@ -19,38 +18,45 @@ describe('ReactEventIndependence', () => { React = require('react'); ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); }); it('does not crash with other react inside', () => { let clicks = 0; - const div = ReactTestUtils.renderIntoDocument( + const container = document.createElement('div'); + document.body.appendChild(container); + const div = ReactDOM.render(
clicks++} dangerouslySetInnerHTML={{ __html: '
', }} />, + container, ); - ReactTestUtils.SimulateNative.click(div.firstChild); + + div.firstChild.click(); expect(clicks).toBe(1); + document.body.removeChild(container); }); it('does not crash with other react outside', () => { let clicks = 0; const outer = document.createElement('div'); + document.body.appendChild(outer); outer.setAttribute('data-reactid', '.z'); const inner = ReactDOM.render( , outer, ); - ReactTestUtils.SimulateNative.click(inner); + inner.click(); expect(clicks).toBe(1); + document.body.removeChild(outer); }); it('does not when event fired on unmounted tree', () => { let clicks = 0; const container = document.createElement('div'); + document.body.appendChild(container); const button = ReactDOM.render( , container, @@ -59,9 +65,10 @@ describe('ReactEventIndependence', () => { // Now we unmount the component, as if caused by a non-React event handler // for the same click we're about to simulate, like closing a layer: ReactDOM.unmountComponentAtNode(container); - ReactTestUtils.SimulateNative.click(button); + button.click(); // Since the tree is unmounted, we don't dispatch the click event. expect(clicks).toBe(0); + document.body.removeChild(container); }); }); diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js index 3fa9a18eaa437..afa6de92337b4 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js @@ -12,7 +12,6 @@ let React; let ReactDOM; let ReactDOMServer; -let ReactTestUtils; // These tests rely both on ReactDOMServer and ReactDOM. // If a test only needs ReactDOMServer, put it in ReactServerRendering-test instead. @@ -21,7 +20,6 @@ describe('ReactDOMServerHydration', () => { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); ReactDOMServer = require('react-dom/server'); }); @@ -48,6 +46,7 @@ describe('ReactDOMServerHydration', () => { } const element = document.createElement('div'); + document.body.appendChild(element); ReactDOM.render(, element); let lastMarkup = element.innerHTML; @@ -89,7 +88,8 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after mount into server markup expect(numClicks).toEqual(0); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance.refs.span)); + + ReactDOM.findDOMNode(instance.refs.span).click(); expect(numClicks).toEqual(1); ReactDOM.unmountComponentAtNode(element); @@ -107,8 +107,10 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after markup mismatch. expect(numClicks).toEqual(1); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance.refs.span)); + ReactDOM.findDOMNode(instance.refs.span).click(); expect(numClicks).toEqual(2); + + document.body.removeChild(element); }); it('should have the correct mounting behavior (new hydrate API)', () => { @@ -134,6 +136,7 @@ describe('ReactDOMServerHydration', () => { } const element = document.createElement('div'); + document.body.appendChild(element); ReactDOM.render(, element); let lastMarkup = element.innerHTML; @@ -167,7 +170,7 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after mount into server markup expect(numClicks).toEqual(0); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance.refs.span)); + ReactDOM.findDOMNode(instance.refs.span).click(); expect(numClicks).toEqual(1); ReactDOM.unmountComponentAtNode(element); @@ -185,8 +188,10 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after markup mismatch. expect(numClicks).toEqual(1); - ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance.refs.span)); + ReactDOM.findDOMNode(instance.refs.span).click(); expect(numClicks).toEqual(2); + + document.body.removeChild(element); }); // We have a polyfill for autoFocus on the client, but we intentionally don't diff --git a/packages/react-dom/src/__tests__/refs-test.js b/packages/react-dom/src/__tests__/refs-test.js index f439118cd75ec..6ca2c981f6ad4 100644 --- a/packages/react-dom/src/__tests__/refs-test.js +++ b/packages/react-dom/src/__tests__/refs-test.js @@ -10,6 +10,7 @@ 'use strict'; let React = require('react'); +let ReactDOM = require('react-dom'); let ReactTestUtils = require('react-dom/test-utils'); /** @@ -81,24 +82,6 @@ class TestRefsComponent extends React.Component { } } -/** - * Render a TestRefsComponent and ensure that the main refs are wired up. - */ -const renderTestRefsComponent = function() { - const testRefsComponent = ReactTestUtils.renderIntoDocument( - , - ); - expect(testRefsComponent instanceof TestRefsComponent).toBe(true); - - const generalContainer = testRefsComponent.refs.myContainer; - expect(generalContainer instanceof GeneralContainerComponent).toBe(true); - - const counter = testRefsComponent.refs.myCounter; - expect(counter instanceof ClickCounter).toBe(true); - - return testRefsComponent; -}; - const expectClickLogsLengthToBe = function(instance, length) { const clickLogs = ReactTestUtils.scryRenderedDOMComponentsWithClass( instance, @@ -109,12 +92,40 @@ const expectClickLogsLengthToBe = function(instance, length) { }; describe('reactiverefs', () => { + let container; + beforeEach(() => { jest.resetModules(); React = require('react'); + ReactDOM = require('react-dom'); ReactTestUtils = require('react-dom/test-utils'); }); + afterEach(() => { + if (container) { + document.body.removeChild(container); + container = null; + } + }); + + /** + * Render a TestRefsComponent and ensure that the main refs are wired up. + */ + const renderTestRefsComponent = function() { + container = document.createElement('div'); + document.body.appendChild(container); + const testRefsComponent = ReactDOM.render(, container); + expect(testRefsComponent instanceof TestRefsComponent).toBe(true); + + const generalContainer = testRefsComponent.refs.myContainer; + expect(generalContainer instanceof GeneralContainerComponent).toBe(true); + + const counter = testRefsComponent.refs.myCounter; + expect(counter instanceof ClickCounter).toBe(true); + + return testRefsComponent; + }; + /** * Ensure that for every click log there is a corresponding ref (from the * perspective of the injected ClickCounter component. @@ -129,18 +140,18 @@ describe('reactiverefs', () => { expectClickLogsLengthToBe(testRefsComponent, 1); // After clicking the reset, there should still only be one click log ref. - ReactTestUtils.Simulate.click(testRefsComponent.refs.resetDiv); + testRefsComponent.refs.resetDiv.click(); expectClickLogsLengthToBe(testRefsComponent, 1); // Begin incrementing clicks (and therefore refs). - ReactTestUtils.Simulate.click(clickIncrementer); + clickIncrementer.click(); expectClickLogsLengthToBe(testRefsComponent, 2); - ReactTestUtils.Simulate.click(clickIncrementer); + clickIncrementer.click(); expectClickLogsLengthToBe(testRefsComponent, 3); // Now reset again - ReactTestUtils.Simulate.click(testRefsComponent.refs.resetDiv); + testRefsComponent.refs.resetDiv.click(); expectClickLogsLengthToBe(testRefsComponent, 1); }); }); @@ -168,6 +179,7 @@ describe('ref swapping', () => { beforeEach(() => { jest.resetModules(); React = require('react'); + ReactDOM = require('react-dom'); ReactTestUtils = require('react-dom/test-utils'); RefHopsAround = class extends React.Component { @@ -293,7 +305,6 @@ describe('ref swapping', () => { describe('root level refs', () => { it('attaches and detaches root refs', () => { - const ReactDOM = require('react-dom'); let inst = null; // host node diff --git a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js index 4020e69fd0cae..3525f2d09aca2 100644 --- a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js @@ -12,23 +12,25 @@ describe('SimpleEventPlugin', function() { let React; let ReactDOM; - let ReactTestUtils; let ReactFeatureFlags; let onClick; + let container; function expectClickThru(element) { - ReactTestUtils.SimulateNative.click(ReactDOM.findDOMNode(element)); + ReactDOM.findDOMNode(element).click(); expect(onClick).toHaveBeenCalledTimes(1); } function expectNoClickThru(element) { - ReactTestUtils.SimulateNative.click(ReactDOM.findDOMNode(element)); + ReactDOM.findDOMNode(element).click(); expect(onClick).toHaveBeenCalledTimes(0); } function mounted(element) { - element = ReactTestUtils.renderIntoDocument(element); + container = document.createElement('div'); + document.body.appendChild(container); + element = ReactDOM.render(element, container); return element; } @@ -60,54 +62,59 @@ describe('SimpleEventPlugin', function() { jest.resetModules(); React = require('react'); ReactDOM = require('react-dom'); - ReactTestUtils = require('react-dom/test-utils'); onClick = jest.fn(); }); + afterEach(() => { + if (container && document.body.contains(container)) { + document.body.removeChild(container); + container = null; + } + }); + it('A non-interactive tags click when disabled', function() { const element =
; expectClickThru(mounted(element)); }); it('A non-interactive tags clicks bubble when disabled', function() { - const element = ReactTestUtils.renderIntoDocument( + const element = mounted(
, ); const child = ReactDOM.findDOMNode(element).firstChild; - - ReactTestUtils.SimulateNative.click(child); + child.click(); expect(onClick).toHaveBeenCalledTimes(1); }); it('does not register a click when clicking a child of a disabled element', function() { - const element = ReactTestUtils.renderIntoDocument( + const element = mounted( , ); const child = ReactDOM.findDOMNode(element).querySelector('span'); - ReactTestUtils.SimulateNative.click(child); + child.click(); expect(onClick).toHaveBeenCalledTimes(0); }); it('triggers click events for children of disabled elements', function() { - const element = ReactTestUtils.renderIntoDocument( + const element = mounted( , ); const child = ReactDOM.findDOMNode(element).querySelector('span'); - ReactTestUtils.SimulateNative.click(child); + child.click(); expect(onClick).toHaveBeenCalledTimes(1); }); it('triggers parent captured click events when target is a child of a disabled elements', function() { - const element = ReactTestUtils.renderIntoDocument( + const element = mounted(
, ); const child = ReactDOM.findDOMNode(element).querySelector('span'); - ReactTestUtils.SimulateNative.click(child); + child.click(); expect(onClick).toHaveBeenCalledTimes(1); }); @@ -152,7 +159,8 @@ describe('SimpleEventPlugin', function() { }); it('should forward clicks when it becomes not disabled', () => { - const container = document.createElement('div'); + container = document.createElement('div'); + document.body.appendChild(container); let element = ReactDOM.render( React.createElement(tagName, {onClick: onClick, disabled: true}), container, @@ -165,7 +173,8 @@ describe('SimpleEventPlugin', function() { }); it('should not forward clicks when it becomes disabled', () => { - const container = document.createElement('div'); + container = document.createElement('div'); + document.body.appendChild(container); let element = ReactDOM.render( React.createElement(tagName, {onClick: onClick}), container, @@ -178,7 +187,8 @@ describe('SimpleEventPlugin', function() { }); it('should work correctly if the listener is changed', () => { - const container = document.createElement('div'); + container = document.createElement('div'); + document.body.appendChild(container); let element = ReactDOM.render( React.createElement(tagName, {onClick: onClick, disabled: true}), container, @@ -193,7 +203,7 @@ describe('SimpleEventPlugin', function() { }); it('batches updates that occur as a result of a nested event dispatch', () => { - const container = document.createElement('div'); + container = document.createElement('div'); document.body.appendChild(container); let ops = []; @@ -251,7 +261,7 @@ describe('SimpleEventPlugin', function() { }); it('flushes pending interactive work before extracting event handler', () => { - const container = document.createElement('div'); + container = document.createElement('div'); const root = ReactDOM.unstable_createRoot(container); document.body.appendChild(container); @@ -331,7 +341,7 @@ describe('SimpleEventPlugin', function() { }); it('end result of many interactive updates is deterministic', () => { - const container = document.createElement('div'); + container = document.createElement('div'); const root = ReactDOM.unstable_createRoot(container); document.body.appendChild(container); @@ -386,7 +396,7 @@ describe('SimpleEventPlugin', function() { }); it('flushes lowest pending interactive priority', () => { - const container = document.createElement('div'); + container = document.createElement('div'); document.body.appendChild(container); let button; @@ -459,7 +469,7 @@ describe('SimpleEventPlugin', function() { // See http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html it('does not add a local click to interactive elements', function() { - const container = document.createElement('div'); + container = document.createElement('div'); ReactDOM.render(
', - }} - />, - container, - ); + try { + const div = ReactDOM.render( +
clicks++} + dangerouslySetInnerHTML={{ + __html: '
', + }} + />, + container, + ); - div.firstChild.click(); - expect(clicks).toBe(1); - document.body.removeChild(container); + div.firstChild.click(); + expect(clicks).toBe(1); + } finally { + document.body.removeChild(container); + } }); it('does not crash with other react outside', () => { let clicks = 0; const outer = document.createElement('div'); document.body.appendChild(outer); - outer.setAttribute('data-reactid', '.z'); - const inner = ReactDOM.render( - , - outer, - ); - inner.click(); - expect(clicks).toBe(1); - document.body.removeChild(outer); + try { + outer.setAttribute('data-reactid', '.z'); + const inner = ReactDOM.render( + , + outer, + ); + inner.click(); + expect(clicks).toBe(1); + } finally { + document.body.removeChild(outer); + } }); it('does not when event fired on unmounted tree', () => { let clicks = 0; const container = document.createElement('div'); document.body.appendChild(container); - const button = ReactDOM.render( - , - container, - ); + try { + const button = ReactDOM.render( + , + container, + ); - // Now we unmount the component, as if caused by a non-React event handler - // for the same click we're about to simulate, like closing a layer: - ReactDOM.unmountComponentAtNode(container); - button.click(); + // Now we unmount the component, as if caused by a non-React event handler + // for the same click we're about to simulate, like closing a layer: + ReactDOM.unmountComponentAtNode(container); + button.click(); - // Since the tree is unmounted, we don't dispatch the click event. - expect(clicks).toBe(0); - document.body.removeChild(container); + // Since the tree is unmounted, we don't dispatch the click event. + expect(clicks).toBe(0); + } finally { + document.body.removeChild(container); + } }); }); diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js index afa6de92337b4..065f9409fbd8e 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js @@ -47,70 +47,72 @@ describe('ReactDOMServerHydration', () => { const element = document.createElement('div'); document.body.appendChild(element); - ReactDOM.render(, element); - - let lastMarkup = element.innerHTML; - - // Exercise the update path. Markup should not change, - // but some lifecycle methods should be run again. - ReactDOM.render(, element); - expect(mountCount).toEqual(1); - - // Unmount and remount. We should get another mount event and - // we should get different markup, as the IDs are unique each time. - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - ReactDOM.render(, element); - expect(mountCount).toEqual(2); - expect(element.innerHTML).not.toEqual(lastMarkup); - - // Now kill the node and render it on top of server-rendered markup, as if - // we used server rendering. We should mount again, but the markup should - // be unchanged. We will append a sentinel at the end of innerHTML to be - // sure that innerHTML was not changed. - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - - lastMarkup = ReactDOMServer.renderToString(); - element.innerHTML = lastMarkup; - - let instance; - - expect(() => { - instance = ReactDOM.render(, element); - }).toLowPriorityWarnDev( - 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + - 'will stop working in React v17. Replace the ReactDOM.render() call ' + - 'with ReactDOM.hydrate() if you want React to attach to the server HTML.', - ); - expect(mountCount).toEqual(3); - expect(element.innerHTML).toBe(lastMarkup); - - // Ensure the events system works after mount into server markup - expect(numClicks).toEqual(0); - - ReactDOM.findDOMNode(instance.refs.span).click(); - expect(numClicks).toEqual(1); - - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - - // Now simulate a situation where the app is not idempotent. React should - // warn but do the right thing. - element.innerHTML = lastMarkup; - expect(() => { - instance = ReactDOM.render(, element); - }).toWarnDev('Text content did not match. Server: "x" Client: "y"'); - expect(mountCount).toEqual(4); - expect(element.innerHTML.length > 0).toBe(true); - expect(element.innerHTML).not.toEqual(lastMarkup); - - // Ensure the events system works after markup mismatch. - expect(numClicks).toEqual(1); - ReactDOM.findDOMNode(instance.refs.span).click(); - expect(numClicks).toEqual(2); - - document.body.removeChild(element); + try { + ReactDOM.render(, element); + + let lastMarkup = element.innerHTML; + + // Exercise the update path. Markup should not change, + // but some lifecycle methods should be run again. + ReactDOM.render(, element); + expect(mountCount).toEqual(1); + + // Unmount and remount. We should get another mount event and + // we should get different markup, as the IDs are unique each time. + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + ReactDOM.render(, element); + expect(mountCount).toEqual(2); + expect(element.innerHTML).not.toEqual(lastMarkup); + + // Now kill the node and render it on top of server-rendered markup, as if + // we used server rendering. We should mount again, but the markup should + // be unchanged. We will append a sentinel at the end of innerHTML to be + // sure that innerHTML was not changed. + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + + lastMarkup = ReactDOMServer.renderToString(); + element.innerHTML = lastMarkup; + + let instance; + + expect(() => { + instance = ReactDOM.render(, element); + }).toLowPriorityWarnDev( + 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + + 'will stop working in React v17. Replace the ReactDOM.render() call ' + + 'with ReactDOM.hydrate() if you want React to attach to the server HTML.', + ); + expect(mountCount).toEqual(3); + expect(element.innerHTML).toBe(lastMarkup); + + // Ensure the events system works after mount into server markup + expect(numClicks).toEqual(0); + + ReactDOM.findDOMNode(instance.refs.span).click(); + expect(numClicks).toEqual(1); + + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + + // Now simulate a situation where the app is not idempotent. React should + // warn but do the right thing. + element.innerHTML = lastMarkup; + expect(() => { + instance = ReactDOM.render(, element); + }).toWarnDev('Text content did not match. Server: "x" Client: "y"'); + expect(mountCount).toEqual(4); + expect(element.innerHTML.length > 0).toBe(true); + expect(element.innerHTML).not.toEqual(lastMarkup); + + // Ensure the events system works after markup mismatch. + expect(numClicks).toEqual(1); + ReactDOM.findDOMNode(instance.refs.span).click(); + expect(numClicks).toEqual(2); + } finally { + document.body.removeChild(element); + } }); it('should have the correct mounting behavior (new hydrate API)', () => { @@ -137,61 +139,63 @@ describe('ReactDOMServerHydration', () => { const element = document.createElement('div'); document.body.appendChild(element); - ReactDOM.render(, element); - - let lastMarkup = element.innerHTML; - - // Exercise the update path. Markup should not change, - // but some lifecycle methods should be run again. - ReactDOM.render(, element); - expect(mountCount).toEqual(1); - - // Unmount and remount. We should get another mount event and - // we should get different markup, as the IDs are unique each time. - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - ReactDOM.render(, element); - expect(mountCount).toEqual(2); - expect(element.innerHTML).not.toEqual(lastMarkup); - - // Now kill the node and render it on top of server-rendered markup, as if - // we used server rendering. We should mount again, but the markup should - // be unchanged. We will append a sentinel at the end of innerHTML to be - // sure that innerHTML was not changed. - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - - lastMarkup = ReactDOMServer.renderToString(); - element.innerHTML = lastMarkup; - - let instance = ReactDOM.hydrate(, element); - expect(mountCount).toEqual(3); - expect(element.innerHTML).toBe(lastMarkup); - - // Ensure the events system works after mount into server markup - expect(numClicks).toEqual(0); - ReactDOM.findDOMNode(instance.refs.span).click(); - expect(numClicks).toEqual(1); - - ReactDOM.unmountComponentAtNode(element); - expect(element.innerHTML).toEqual(''); - - // Now simulate a situation where the app is not idempotent. React should - // warn but do the right thing. - element.innerHTML = lastMarkup; - expect(() => { - instance = ReactDOM.hydrate(, element); - }).toWarnDev('Text content did not match. Server: "x" Client: "y"'); - expect(mountCount).toEqual(4); - expect(element.innerHTML.length > 0).toBe(true); - expect(element.innerHTML).not.toEqual(lastMarkup); - - // Ensure the events system works after markup mismatch. - expect(numClicks).toEqual(1); - ReactDOM.findDOMNode(instance.refs.span).click(); - expect(numClicks).toEqual(2); - - document.body.removeChild(element); + try { + ReactDOM.render(, element); + + let lastMarkup = element.innerHTML; + + // Exercise the update path. Markup should not change, + // but some lifecycle methods should be run again. + ReactDOM.render(, element); + expect(mountCount).toEqual(1); + + // Unmount and remount. We should get another mount event and + // we should get different markup, as the IDs are unique each time. + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + ReactDOM.render(, element); + expect(mountCount).toEqual(2); + expect(element.innerHTML).not.toEqual(lastMarkup); + + // Now kill the node and render it on top of server-rendered markup, as if + // we used server rendering. We should mount again, but the markup should + // be unchanged. We will append a sentinel at the end of innerHTML to be + // sure that innerHTML was not changed. + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + + lastMarkup = ReactDOMServer.renderToString(); + element.innerHTML = lastMarkup; + + let instance = ReactDOM.hydrate(, element); + expect(mountCount).toEqual(3); + expect(element.innerHTML).toBe(lastMarkup); + + // Ensure the events system works after mount into server markup + expect(numClicks).toEqual(0); + ReactDOM.findDOMNode(instance.refs.span).click(); + expect(numClicks).toEqual(1); + + ReactDOM.unmountComponentAtNode(element); + expect(element.innerHTML).toEqual(''); + + // Now simulate a situation where the app is not idempotent. React should + // warn but do the right thing. + element.innerHTML = lastMarkup; + expect(() => { + instance = ReactDOM.hydrate(, element); + }).toWarnDev('Text content did not match. Server: "x" Client: "y"'); + expect(mountCount).toEqual(4); + expect(element.innerHTML.length > 0).toBe(true); + expect(element.innerHTML).not.toEqual(lastMarkup); + + // Ensure the events system works after markup mismatch. + expect(numClicks).toEqual(1); + ReactDOM.findDOMNode(instance.refs.span).click(); + expect(numClicks).toEqual(2); + } finally { + document.body.removeChild(element); + } }); // We have a polyfill for autoFocus on the client, but we intentionally don't diff --git a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js index 2c3d78a5eca2f..c2e968afd952c 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js @@ -245,12 +245,10 @@ describe('SyntheticEvent', () => { it('should properly log warnings when events simulated with rendered components', () => { let event; - const element = document.createElement('div'); - document.body.appendChild(element); function assignEvent(e) { event = e; } - const node = ReactDOM.render(
, element); + const node = ReactDOM.render(
, container); ReactDOM.findDOMNode(node).click(); // access a property to cause the warning @@ -263,8 +261,6 @@ describe('SyntheticEvent', () => { 'keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', ); - - document.body.removeChild(element); }); it('should warn if Proxy is supported and the synthetic event is added a property', () => { From 36ec14d72970d617320629280df3b0dee3b90e47 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Wed, 13 Jun 2018 00:38:34 +0200 Subject: [PATCH 3/3] Remove unnecessary findDOMNode calls --- .../src/__tests__/ReactComponent-test.js | 2 +- .../__tests__/ReactCompositeComponent-test.js | 6 +- .../react-dom/src/__tests__/ReactDOM-test.js | 13 ++- .../src/__tests__/ReactDOMIframe-test.js | 4 +- .../src/__tests__/ReactDOMInput-test.js | 81 ++++++++----------- .../src/__tests__/ReactDOMOption-test.js | 12 +-- .../src/__tests__/ReactDOMSelect-test.js | 55 +++++-------- .../__tests__/ReactDOMTextComponent-test.js | 47 +++++------ .../src/__tests__/ReactIdentity-test.js | 2 +- .../ReactServerRenderingHydration.js | 8 +- .../src/__tests__/ReactTestUtils-test.js | 5 +- .../SimpleEventPlugin-test.internal.js | 14 ++-- .../events/__tests__/SyntheticEvent-test.js | 2 +- 13 files changed, 99 insertions(+), 152 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactComponent-test.js b/packages/react-dom/src/__tests__/ReactComponent-test.js index 37f3fc226a3b8..06bfa68baa193 100644 --- a/packages/react-dom/src/__tests__/ReactComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactComponent-test.js @@ -278,7 +278,7 @@ describe('ReactComponent', () => { componentDidMount() { // Check .props.title to make sure we got the right elements back expect(this.wrapperRef.getTitle()).toBe('wrapper'); - expect(ReactDOM.findDOMNode(this.innerRef).className).toBe('inner'); + expect(this.innerRef.className).toBe('inner'); mounted = true; } } diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 0d63351f8c547..d614d27dd3585 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -157,11 +157,11 @@ describe('ReactCompositeComponent', () => { it('should rewire refs when rendering to different child types', () => { const instance = ReactTestUtils.renderIntoDocument(); - expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('A'); + expect(instance.refs.x.tagName).toBe('A'); instance._toggleActivatedState(); - expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('B'); + expect(instance.refs.x.tagName).toBe('B'); instance._toggleActivatedState(); - expect(ReactDOM.findDOMNode(instance.refs.x).tagName).toBe('A'); + expect(instance.refs.x.tagName).toBe('A'); }); it('should not cache old DOM nodes when switching constructors', () => { diff --git a/packages/react-dom/src/__tests__/ReactDOM-test.js b/packages/react-dom/src/__tests__/ReactDOM-test.js index 4d54389a4f930..48609a2c253dd 100644 --- a/packages/react-dom/src/__tests__/ReactDOM-test.js +++ b/packages/react-dom/src/__tests__/ReactDOM-test.js @@ -45,23 +45,21 @@ describe('ReactDOM', () => { it('allows a DOM element to be used with a string', () => { const element = React.createElement('div', {className: 'foo'}); - const instance = ReactTestUtils.renderIntoDocument(element); - expect(ReactDOM.findDOMNode(instance).tagName).toBe('DIV'); + const node = ReactTestUtils.renderIntoDocument(element); + expect(node.tagName).toBe('DIV'); }); it('should allow children to be passed as an argument', () => { - const argDiv = ReactTestUtils.renderIntoDocument( + const argNode = ReactTestUtils.renderIntoDocument( React.createElement('div', null, 'child'), ); - const argNode = ReactDOM.findDOMNode(argDiv); expect(argNode.innerHTML).toBe('child'); }); it('should overwrite props.children with children argument', () => { - const conflictDiv = ReactTestUtils.renderIntoDocument( + const conflictNode = ReactTestUtils.renderIntoDocument( React.createElement('div', {children: 'fakechild'}, 'child'), ); - const conflictNode = ReactDOM.findDOMNode(conflictDiv); expect(conflictNode.innerHTML).toBe('child'); }); @@ -103,8 +101,7 @@ describe('ReactDOM', () => {
,
, ); - const root = ReactDOM.findDOMNode(myDiv); - const dog = root.childNodes[0]; + const dog = myDiv.childNodes[0]; expect(dog.className).toBe('bigdog'); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMIframe-test.js b/packages/react-dom/src/__tests__/ReactDOMIframe-test.js index 97b07bb0b7722..8c3a01b78f0af 100644 --- a/packages/react-dom/src/__tests__/ReactDOMIframe-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMIframe-test.js @@ -11,12 +11,10 @@ describe('ReactDOMIframe', () => { let React; - let ReactDOM; let ReactTestUtils; beforeEach(() => { React = require('react'); - ReactDOM = require('react-dom'); ReactTestUtils = require('react-dom/test-utils'); }); @@ -28,7 +26,7 @@ describe('ReactDOMIframe', () => { const loadEvent = document.createEvent('Event'); loadEvent.initEvent('load', false, false); - ReactDOM.findDOMNode(iframe).dispatchEvent(loadEvent); + iframe.dispatchEvent(loadEvent); expect(onLoadSpy).toHaveBeenCalled(); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMInput-test.js b/packages/react-dom/src/__tests__/ReactDOMInput-test.js index 4a3066a073f72..ca4b999f5f239 100644 --- a/packages/react-dom/src/__tests__/ReactDOMInput-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMInput-test.js @@ -38,27 +38,27 @@ describe('ReactDOMInput', () => { it('should properly control a value even if no event listener exists', () => { const container = document.createElement('div'); - let stub; + let node; expect(() => { - stub = ReactDOM.render(, container); + node = ReactDOM.render(, container); }).toWarnDev( 'Failed prop type: You provided a `value` prop to a form field without an `onChange` handler.', ); document.body.appendChild(container); - const node = ReactDOM.findDOMNode(stub); - - setUntrackedValue.call(node, 'giraffe'); - - // This must use the native event dispatching. If we simulate, we will - // bypass the lazy event attachment system so we won't actually test this. - dispatchEventOnNode(node, 'change'); + try { + setUntrackedValue.call(node, 'giraffe'); - expect(node.value).toBe('lion'); + // This must use the native event dispatching. If we simulate, we will + // bypass the lazy event attachment system so we won't actually test this. + dispatchEventOnNode(node, 'change'); - document.body.removeChild(container); + expect(node.value).toBe('lion'); + } finally { + document.body.removeChild(container); + } }); it('should control a value in reentrant events', () => { @@ -169,26 +169,24 @@ describe('ReactDOMInput', () => { describe('switching text inputs between numeric and string numbers', () => { it('does change the number 2 to "2.0" with no change handler', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); node.value = '2.0'; - ReactTestUtils.Simulate.change(stub); + ReactTestUtils.Simulate.change(node); expect(node.getAttribute('value')).toBe('2'); expect(node.value).toBe('2'); }); it('does change the string "2" to "2.0" with no change handler', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); node.value = '2.0'; - ReactTestUtils.Simulate.change(stub); + ReactTestUtils.Simulate.change(node); expect(node.getAttribute('value')).toBe('2'); expect(node.value).toBe('2'); @@ -315,8 +313,7 @@ describe('ReactDOMInput', () => { it('should display `defaultValue` of number 0', () => { let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.getAttribute('value')).toBe('0'); expect(node.value).toBe('0'); @@ -348,16 +345,14 @@ describe('ReactDOMInput', () => { it('should display "true" for `defaultValue` of `true`', () => { let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.value).toBe('true'); }); it('should display "false" for `defaultValue` of `false`', () => { let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.value).toBe('false'); }); @@ -467,17 +462,15 @@ describe('ReactDOMInput', () => { }, }; - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.value).toBe('foobar'); }); it('should display `value` of number 0', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.value).toBe('0'); }); @@ -593,9 +586,8 @@ describe('ReactDOMInput', () => { }); it('should properly control a value of number `0`', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); node.value = 'giraffe'; ReactTestUtils.Simulate.change(node); @@ -603,9 +595,8 @@ describe('ReactDOMInput', () => { }); it('should properly control 0.0 for a text input', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); node.value = '0.0'; ReactTestUtils.Simulate.change(node, {target: {value: '0.0'}}); @@ -613,9 +604,8 @@ describe('ReactDOMInput', () => { }); it('should properly control 0.0 for a number input', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); node.value = '0.0'; ReactTestUtils.Simulate.change(node, {target: {value: '0.0'}}); @@ -702,9 +692,8 @@ describe('ReactDOMInput', () => { }); it('should not set a value for submit buttons unnecessarily', () => { - let stub = ; - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const stub = ; + const node = ReactTestUtils.renderIntoDocument(stub); // The value shouldn't be '', or else the button will have no text; it // should have the default "Submit" or "Submit Query" label. Most browsers @@ -1460,10 +1449,9 @@ describe('ReactDOMInput', () => { }); it('an uncontrolled number input will not update the value attribute on blur', () => { - const stub = ReactTestUtils.renderIntoDocument( + const node = ReactTestUtils.renderIntoDocument( , ); - const node = ReactDOM.findDOMNode(stub); node.value = 4; @@ -1473,10 +1461,9 @@ describe('ReactDOMInput', () => { }); it('an uncontrolled text input will not update the value attribute on blur', () => { - const stub = ReactTestUtils.renderIntoDocument( + const node = ReactTestUtils.renderIntoDocument( , ); - const node = ReactDOM.findDOMNode(stub); node.value = 4; diff --git a/packages/react-dom/src/__tests__/ReactDOMOption-test.js b/packages/react-dom/src/__tests__/ReactDOMOption-test.js index 02e1f662c062f..8cbd0118d2ce7 100644 --- a/packages/react-dom/src/__tests__/ReactDOMOption-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMOption-test.js @@ -26,8 +26,7 @@ describe('ReactDOMOption', () => { {1} {'foo'} ); - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.innerHTML).toBe('1 foo'); }); @@ -59,17 +58,15 @@ describe('ReactDOMOption', () => { {undefined} {2} ); - stub = ReactTestUtils.renderIntoDocument(stub); + const node = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); expect(node.innerHTML).toBe('1 2'); }); it('should be able to use dangerouslySetInnerHTML on option', () => { let stub = ); - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); expect(node.options[0].selected).toBe(false); // one expect(node.options[1].selected).toBe(false); // two @@ -259,7 +250,7 @@ describe('ReactDOMSelect', () => { it('should reset child options selected when they are changed and `value` is set', () => { let stub = @@ -270,8 +261,6 @@ describe('ReactDOMSelect', () => { container, ); - const node = ReactDOM.findDOMNode(stub); - expect(node.options[0].selected).toBe(true); // a expect(node.options[1].selected).toBe(true); // b expect(node.options[2].selected).toBe(false); // c @@ -293,8 +282,7 @@ describe('ReactDOMSelect', () => { ); const container = document.createElement('div'); - const stub = ReactDOM.render(el, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(el, container); expect(node.options[0].selected).toBe(false); // monkey expect(node.options[1].selected).toBe(true); // giraffe @@ -327,8 +315,7 @@ describe('ReactDOMSelect', () => { ); const options = stub.props.children; const container = document.createElement('div'); - stub = ReactDOM.render(stub, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(stub, container); expect(node.options[0].selected).toBe(false); // monkey expect(node.options[1].selected).toBe(true); // giraffe @@ -357,8 +344,7 @@ describe('ReactDOMSelect', () => { ); const options = stub.props.children; const container = document.createElement('div'); - stub = ReactDOM.render(stub, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(stub, container); expect(node.options[0].selected).toBe(false); // monkey expect(node.options[1].selected).toBe(true); // giraffe @@ -386,8 +372,7 @@ describe('ReactDOMSelect', () => { ); const options = stub.props.children; const container = document.createElement('div'); - stub = ReactDOM.render(stub, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(stub, container); expect(node.options[0].selected).toBe(false); // monkey expect(node.options[1].selected).toBe(true); // giraffe @@ -410,8 +395,7 @@ describe('ReactDOMSelect', () => { ); const options = stub.props.children; const container = document.createElement('div'); - stub = ReactDOM.render(stub, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(stub, container); ReactDOM.render( ); - stub = ReactTestUtils.renderIntoDocument(stub); - const node = ReactDOM.findDOMNode(stub); + const node = ReactTestUtils.renderIntoDocument(stub); ReactTestUtils.Simulate.change(node); @@ -648,8 +630,7 @@ describe('ReactDOMSelect', () => { ); - stub = ReactDOM.render(stub, container); - const node = ReactDOM.findDOMNode(stub); + const node = ReactDOM.render(stub, container); expect(() => ReactTestUtils.Simulate.change(node)).not.toThrow(); }); diff --git a/packages/react-dom/src/__tests__/ReactDOMTextComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMTextComponent-test.js index f3f9dc5485b35..2adb55d69b45e 100644 --- a/packages/react-dom/src/__tests__/ReactDOMTextComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMTextComponent-test.js @@ -39,7 +39,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - let nodes = filterOutComments(ReactDOM.findDOMNode(inst).childNodes); + let nodes = filterOutComments(inst.childNodes); let foo = nodes[1]; let bar = nodes[2]; @@ -56,7 +56,7 @@ describe('ReactDOMTextComponent', () => { ); // After the update, the text nodes should have stayed in place (as opposed // to getting unmounted and remounted) - nodes = filterOutComments(ReactDOM.findDOMNode(inst).childNodes); + nodes = filterOutComments(inst.childNodes); expect(nodes[1]).toBe(foo); expect(nodes[2]).toBe(bar); expect(foo.data).toBe('baz'); @@ -74,8 +74,7 @@ describe('ReactDOMTextComponent', () => { el, ); - let container = ReactDOM.findDOMNode(inst); - let childNodes = filterOutComments(container.childNodes); + let childNodes = filterOutComments(inst.childNodes); let childDiv = childNodes[1]; inst = ReactDOM.render( @@ -86,8 +85,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - childNodes = filterOutComments(container.childNodes); + childNodes = filterOutComments(inst.childNodes); expect(childNodes.length).toBe(1); expect(childNodes[0]).toBe(childDiv); @@ -99,8 +97,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - childNodes = filterOutComments(container.childNodes); + childNodes = filterOutComments(inst.childNodes); expect(childNodes.length).toBe(3); expect(childNodes[0].data).toBe('foo'); expect(childNodes[1]).toBe(childDiv); @@ -125,8 +122,7 @@ describe('ReactDOMTextComponent', () => { el, ); - let container = ReactDOM.findDOMNode(inst); - container.normalize(); + inst.normalize(); inst = ReactDOM.render(
@@ -138,8 +134,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - expect(container.textContent).toBe('barbazquxfoo'); + expect(inst.textContent).toBe('barbazquxfoo'); }); xit('can reconcile text merged by Node.normalize()', () => { @@ -153,8 +148,7 @@ describe('ReactDOMTextComponent', () => { el, ); - let container = ReactDOM.findDOMNode(inst); - container.normalize(); + inst.normalize(); inst = ReactDOM.render(
@@ -164,8 +158,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - expect(container.textContent).toBe('barbazqux'); + expect(inst.textContent).toBe('barbazqux'); }); it('can reconcile text from pre-rendered markup', () => { @@ -207,15 +200,14 @@ describe('ReactDOMTextComponent', () => { el, ); - let container = ReactDOM.findDOMNode(inst); - let childNodes = filterOutComments(ReactDOM.findDOMNode(inst).childNodes); + let childNodes = filterOutComments(inst.childNodes); let textNode = childNodes[1]; textNode.textContent = 'foo'; - container.insertBefore( + inst.insertBefore( document.createTextNode('bar'), childNodes[1].nextSibling, ); - container.insertBefore( + inst.insertBefore( document.createTextNode('baz'), childNodes[1].nextSibling, ); @@ -227,8 +219,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - expect(container.textContent).toBe('barbazqux'); + expect(inst.textContent).toBe('barbazqux'); }); xit('can reconcile text arbitrarily split into multiple nodes on some substitutions only', () => { @@ -246,21 +237,20 @@ describe('ReactDOMTextComponent', () => { el, ); - let container = ReactDOM.findDOMNode(inst); - let childNodes = filterOutComments(ReactDOM.findDOMNode(inst).childNodes); + let childNodes = filterOutComments(inst.childNodes); let textNode = childNodes[3]; textNode.textContent = 'foo'; - container.insertBefore( + inst.insertBefore( document.createTextNode('bar'), childNodes[3].nextSibling, ); - container.insertBefore( + inst.insertBefore( document.createTextNode('baz'), childNodes[3].nextSibling, ); let secondTextNode = childNodes[5]; secondTextNode.textContent = 'bar'; - container.insertBefore( + inst.insertBefore( document.createTextNode('foo'), childNodes[5].nextSibling, ); @@ -277,8 +267,7 @@ describe('ReactDOMTextComponent', () => {
, el, ); - container = ReactDOM.findDOMNode(inst); - expect(container.textContent).toBe('bazbarbazquxbarbazbar'); + expect(inst.textContent).toBe('bazbarbazquxbarbazbar'); }); xit('can unmount normalized text nodes', () => { diff --git a/packages/react-dom/src/__tests__/ReactIdentity-test.js b/packages/react-dom/src/__tests__/ReactIdentity-test.js index 7849d7d3b7523..880266c87d761 100644 --- a/packages/react-dom/src/__tests__/ReactIdentity-test.js +++ b/packages/react-dom/src/__tests__/ReactIdentity-test.js @@ -78,7 +78,7 @@ describe('ReactIdentity', () => { const instance = ReactDOM.render(, container); const span = instance.refs.span; - expect(ReactDOM.findDOMNode(span)).not.toBe(null); + expect(span).not.toBe(null); } it('should allow any character as a key, in a detached parent', () => { diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js index 065f9409fbd8e..1faf45872b87c 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js @@ -90,7 +90,7 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after mount into server markup expect(numClicks).toEqual(0); - ReactDOM.findDOMNode(instance.refs.span).click(); + instance.refs.span.click(); expect(numClicks).toEqual(1); ReactDOM.unmountComponentAtNode(element); @@ -108,7 +108,7 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after markup mismatch. expect(numClicks).toEqual(1); - ReactDOM.findDOMNode(instance.refs.span).click(); + instance.refs.span.click(); expect(numClicks).toEqual(2); } finally { document.body.removeChild(element); @@ -173,7 +173,7 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after mount into server markup expect(numClicks).toEqual(0); - ReactDOM.findDOMNode(instance.refs.span).click(); + instance.refs.span.click(); expect(numClicks).toEqual(1); ReactDOM.unmountComponentAtNode(element); @@ -191,7 +191,7 @@ describe('ReactDOMServerHydration', () => { // Ensure the events system works after markup mismatch. expect(numClicks).toEqual(1); - ReactDOM.findDOMNode(instance.refs.span).click(); + instance.refs.span.click(); expect(numClicks).toEqual(2); } finally { document.body.removeChild(element); diff --git a/packages/react-dom/src/__tests__/ReactTestUtils-test.js b/packages/react-dom/src/__tests__/ReactTestUtils-test.js index 328eefe0b2dc4..83437133b6a6f 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtils-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtils-test.js @@ -280,12 +280,11 @@ describe('ReactTestUtils', () => { }; spyOnDevAndProd(obj, 'handler').and.callThrough(); const container = document.createElement('div'); - const instance = ReactDOM.render( + const node = ReactDOM.render( , container, ); - const node = ReactDOM.findDOMNode(instance); node.value = 'giraffe'; ReactTestUtils.Simulate.change(node); @@ -321,7 +320,7 @@ describe('ReactTestUtils', () => { container, ); - const node = ReactDOM.findDOMNode(instance.refs.input); + const node = instance.refs.input; node.value = 'zebra'; ReactTestUtils.Simulate.change(node); diff --git a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js index 3525f2d09aca2..2d264fc4ea000 100644 --- a/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js +++ b/packages/react-dom/src/events/__tests__/SimpleEventPlugin-test.internal.js @@ -18,12 +18,12 @@ describe('SimpleEventPlugin', function() { let container; function expectClickThru(element) { - ReactDOM.findDOMNode(element).click(); + element.click(); expect(onClick).toHaveBeenCalledTimes(1); } function expectNoClickThru(element) { - ReactDOM.findDOMNode(element).click(); + element.click(); expect(onClick).toHaveBeenCalledTimes(0); } @@ -84,7 +84,7 @@ describe('SimpleEventPlugin', function() {
, ); - const child = ReactDOM.findDOMNode(element).firstChild; + const child = element.firstChild; child.click(); expect(onClick).toHaveBeenCalledTimes(1); }); @@ -95,7 +95,7 @@ describe('SimpleEventPlugin', function() { , ); - const child = ReactDOM.findDOMNode(element).querySelector('span'); + const child = element.querySelector('span'); child.click(); expect(onClick).toHaveBeenCalledTimes(0); @@ -107,7 +107,7 @@ describe('SimpleEventPlugin', function() { , ); - const child = ReactDOM.findDOMNode(element).querySelector('span'); + const child = element.querySelector('span'); child.click(); expect(onClick).toHaveBeenCalledTimes(1); @@ -121,7 +121,7 @@ describe('SimpleEventPlugin', function() { , ); - const child = ReactDOM.findDOMNode(element).querySelector('span'); + const child = element.querySelector('span'); child.click(); expect(onClick).toHaveBeenCalledTimes(1); @@ -133,7 +133,7 @@ describe('SimpleEventPlugin', function() { , ); - const child = ReactDOM.findDOMNode(element).querySelector('span'); + const child = element.querySelector('span'); child.click(); expect(onClick).toHaveBeenCalledTimes(1); diff --git a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js index c2e968afd952c..6ba906593cba6 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js @@ -249,7 +249,7 @@ describe('SyntheticEvent', () => { event = e; } const node = ReactDOM.render(
, container); - ReactDOM.findDOMNode(node).click(); + node.click(); // access a property to cause the warning expect(() => {