diff --git a/packages/react-dom/server.browser.js b/packages/react-dom/server.browser.js index df45b9fa9fd63..c57063649a9f0 100644 --- a/packages/react-dom/server.browser.js +++ b/packages/react-dom/server.browser.js @@ -7,10 +7,10 @@ * @flow */ -'use strict'; - -const ReactDOMServer = require('./src/server/ReactDOMServerBrowser'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest -module.exports = ReactDOMServer.default || ReactDOMServer; +export { + renderToString, + renderToStaticMarkup, + renderToNodeStream, + renderToStaticNodeStream, + version, +} from './src/server/ReactDOMServerBrowser'; diff --git a/packages/react-dom/server.js b/packages/react-dom/server.js index 03006336ba4fe..6010f4e3d5b22 100644 --- a/packages/react-dom/server.js +++ b/packages/react-dom/server.js @@ -7,6 +7,4 @@ * @flow */ -'use strict'; - -module.exports = require('./server.node'); +export * from './server.node'; diff --git a/packages/react-dom/server.node.js b/packages/react-dom/server.node.js index 66e1ea1f0f9ad..e610a8818f961 100644 --- a/packages/react-dom/server.node.js +++ b/packages/react-dom/server.node.js @@ -7,10 +7,11 @@ * @flow */ -'use strict'; - -const ReactDOMServer = require('./src/server/ReactDOMServerNode'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest -module.exports = ReactDOMServer.default || ReactDOMServer; +// For some reason Flow doesn't like export * in this file. I don't know why. +export { + renderToString, + renderToStaticMarkup, + renderToNodeStream, + renderToStaticNodeStream, + version, +} from './src/server/ReactDOMServerNode'; diff --git a/packages/react-dom/src/__tests__/ReactTestUtils-test.js b/packages/react-dom/src/__tests__/ReactTestUtils-test.js index 540f23edd17c0..b0ac326e9573e 100644 --- a/packages/react-dom/src/__tests__/ReactTestUtils-test.js +++ b/packages/react-dom/src/__tests__/ReactTestUtils-test.js @@ -9,11 +9,11 @@ 'use strict'; -let createRenderer; -let React; -let ReactDOM; -let ReactDOMServer; -let ReactTestUtils; +import ReactShallowRenderer from 'react-test-renderer/shallow'; +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as ReactDOMServer from 'react-dom/server'; +import * as ReactTestUtils from 'react-dom/test-utils'; function getTestDocument(markup) { const doc = document.implementation.createHTMLDocument(''); @@ -27,14 +27,6 @@ function getTestDocument(markup) { } describe('ReactTestUtils', () => { - beforeEach(() => { - createRenderer = require('react-test-renderer/shallow').createRenderer; - React = require('react'); - ReactDOM = require('react-dom'); - ReactDOMServer = require('react-dom/server'); - ReactTestUtils = require('react-dom/test-utils'); - }); - it('Simulate should have locally attached media events', () => { expect(Object.keys(ReactTestUtils.Simulate).sort()).toMatchSnapshot(); }); @@ -403,7 +395,7 @@ describe('ReactTestUtils', () => { } const handler = jest.fn().mockName('spy'); - const shallowRenderer = createRenderer(); + const shallowRenderer = ReactShallowRenderer.createRenderer(); const result = shallowRenderer.render( , ); diff --git a/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js b/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js index 93419fa27194b..cbf83b1b71aed 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerBrowser.js @@ -29,6 +29,4 @@ function renderToReadableStream(children: ReactNodeList): ReadableStream { }); } -export default { - renderToReadableStream, -}; +export {renderToReadableStream}; diff --git a/packages/react-dom/src/server/ReactDOMFizzServerNode.js b/packages/react-dom/src/server/ReactDOMFizzServerNode.js index 3815e1f958ef8..154b4fff204a6 100644 --- a/packages/react-dom/src/server/ReactDOMFizzServerNode.js +++ b/packages/react-dom/src/server/ReactDOMFizzServerNode.js @@ -25,6 +25,4 @@ function pipeToNodeWritable( startWork(request); } -export default { - pipeToNodeWritable, -}; +export {pipeToNodeWritable}; diff --git a/packages/react-dom/src/server/ReactDOMServerBrowser.js b/packages/react-dom/src/server/ReactDOMServerBrowser.js index 58f04b4960b31..4424040496b99 100644 --- a/packages/react-dom/src/server/ReactDOMServerBrowser.js +++ b/packages/react-dom/src/server/ReactDOMServerBrowser.js @@ -26,11 +26,10 @@ function renderToStaticNodeStream() { ); } -// Note: when changing this, also consider https://github.com/facebook/react/issues/11526 -export default { +export { renderToString, renderToStaticMarkup, renderToNodeStream, renderToStaticNodeStream, - version: ReactVersion, + ReactVersion as version, }; diff --git a/packages/react-dom/src/server/ReactDOMServerNode.js b/packages/react-dom/src/server/ReactDOMServerNode.js index b1f955eef53d7..1347434b6900c 100644 --- a/packages/react-dom/src/server/ReactDOMServerNode.js +++ b/packages/react-dom/src/server/ReactDOMServerNode.js @@ -13,11 +13,10 @@ import { renderToStaticNodeStream, } from './ReactDOMNodeStreamRenderer'; -// Note: when changing this, also consider https://github.com/facebook/react/issues/11526 -export default { +export { renderToString, renderToStaticMarkup, renderToNodeStream, renderToStaticNodeStream, - version: ReactVersion, + ReactVersion as version, }; diff --git a/packages/react-dom/src/test-utils/ReactTestUtils.js b/packages/react-dom/src/test-utils/ReactTestUtils.js index 5ac2948c1c36b..9449880c83ed4 100644 --- a/packages/react-dom/src/test-utils/ReactTestUtils.js +++ b/packages/react-dom/src/test-utils/ReactTestUtils.js @@ -159,243 +159,233 @@ function validateClassInstance(inst, methodName) { * utilities will suffice for testing purposes. * @lends ReactTestUtils */ -const ReactTestUtils = { - renderIntoDocument: function(element) { - const div = document.createElement('div'); - // None of our tests actually require attaching the container to the - // DOM, and doing so creates a mess that we rely on test isolation to - // clean up, so we're going to stop honoring the name of this method - // (and probably rename it eventually) if no problems arise. - // document.documentElement.appendChild(div); - return ReactDOM.render(element, div); - }, - - isElement: function(element) { - return React.isValidElement(element); - }, - - isElementOfType: function(inst, convenienceConstructor) { - return React.isValidElement(inst) && inst.type === convenienceConstructor; - }, - - isDOMComponent: function(inst) { - return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName); - }, - - isDOMComponentElement: function(inst) { - return !!(inst && React.isValidElement(inst) && !!inst.tagName); - }, - - isCompositeComponent: function(inst) { - if (ReactTestUtils.isDOMComponent(inst)) { - // Accessing inst.setState warns; just return false as that'll be what - // this returns when we have DOM nodes as refs directly - return false; - } - return ( - inst != null && - typeof inst.render === 'function' && - typeof inst.setState === 'function' - ); - }, +function renderIntoDocument(element) { + const div = document.createElement('div'); + // None of our tests actually require attaching the container to the + // DOM, and doing so creates a mess that we rely on test isolation to + // clean up, so we're going to stop honoring the name of this method + // (and probably rename it eventually) if no problems arise. + // document.documentElement.appendChild(div); + return ReactDOM.render(element, div); +} - isCompositeComponentWithType: function(inst, type) { - if (!ReactTestUtils.isCompositeComponent(inst)) { - return false; - } - const internalInstance = getInstance(inst); - const constructor = internalInstance.type; - return constructor === type; - }, - - findAllInRenderedTree: function(inst, test) { - validateClassInstance(inst, 'findAllInRenderedTree'); - if (!inst) { - return []; - } - const internalInstance = getInstance(inst); - return findAllInRenderedFiberTreeInternal(internalInstance, test); - }, +function isElement(element) { + return React.isValidElement(element); +} - /** - * Finds all instance of components in the rendered tree that are DOM - * components with the class name matching `className`. - * @return {array} an array of all the matches. - */ - scryRenderedDOMComponentsWithClass: function(root, classNames) { - validateClassInstance(root, 'scryRenderedDOMComponentsWithClass'); - return ReactTestUtils.findAllInRenderedTree(root, function(inst) { - if (ReactTestUtils.isDOMComponent(inst)) { - let className = inst.className; - if (typeof className !== 'string') { - // SVG, probably. - className = inst.getAttribute('class') || ''; - } - const classList = className.split(/\s+/); - - if (!Array.isArray(classNames)) { - invariant( - classNames !== undefined, - 'TestUtils.scryRenderedDOMComponentsWithClass expects a ' + - 'className as a second argument.', - ); - classNames = classNames.split(/\s+/); - } - return classNames.every(function(name) { - return classList.indexOf(name) !== -1; - }); - } - return false; - }); - }, +function isElementOfType(inst, convenienceConstructor) { + return React.isValidElement(inst) && inst.type === convenienceConstructor; +} - /** - * Like scryRenderedDOMComponentsWithClass but expects there to be one result, - * and returns that one result, or throws exception if there is any other - * number of matches besides one. - * @return {!ReactDOMComponent} The one match. - */ - findRenderedDOMComponentWithClass: function(root, className) { - validateClassInstance(root, 'findRenderedDOMComponentWithClass'); - const all = ReactTestUtils.scryRenderedDOMComponentsWithClass( - root, - className, - ); - if (all.length !== 1) { - throw new Error( - 'Did not find exactly one match (found: ' + - all.length + - ') ' + - 'for class:' + - className, - ); - } - return all[0]; - }, +function isDOMComponent(inst) { + return !!(inst && inst.nodeType === ELEMENT_NODE && inst.tagName); +} - /** - * Finds all instance of components in the rendered tree that are DOM - * components with the tag name matching `tagName`. - * @return {array} an array of all the matches. - */ - scryRenderedDOMComponentsWithTag: function(root, tagName) { - validateClassInstance(root, 'scryRenderedDOMComponentsWithTag'); - return ReactTestUtils.findAllInRenderedTree(root, function(inst) { - return ( - ReactTestUtils.isDOMComponent(inst) && - inst.tagName.toUpperCase() === tagName.toUpperCase() - ); - }); - }, +function isDOMComponentElement(inst) { + return !!(inst && React.isValidElement(inst) && !!inst.tagName); +} - /** - * Like scryRenderedDOMComponentsWithTag but expects there to be one result, - * and returns that one result, or throws exception if there is any other - * number of matches besides one. - * @return {!ReactDOMComponent} The one match. - */ - findRenderedDOMComponentWithTag: function(root, tagName) { - validateClassInstance(root, 'findRenderedDOMComponentWithTag'); - const all = ReactTestUtils.scryRenderedDOMComponentsWithTag(root, tagName); - if (all.length !== 1) { - throw new Error( - 'Did not find exactly one match (found: ' + - all.length + - ') ' + - 'for tag:' + - tagName, - ); - } - return all[0]; - }, +function isCompositeComponent(inst) { + if (isDOMComponent(inst)) { + // Accessing inst.setState warns; just return false as that'll be what + // this returns when we have DOM nodes as refs directly + return false; + } + return ( + inst != null && + typeof inst.render === 'function' && + typeof inst.setState === 'function' + ); +} - /** - * Finds all instances of components with type equal to `componentType`. - * @return {array} an array of all the matches. - */ - scryRenderedComponentsWithType: function(root, componentType) { - validateClassInstance(root, 'scryRenderedComponentsWithType'); - return ReactTestUtils.findAllInRenderedTree(root, function(inst) { - return ReactTestUtils.isCompositeComponentWithType(inst, componentType); - }); - }, +function isCompositeComponentWithType(inst, type) { + if (!isCompositeComponent(inst)) { + return false; + } + const internalInstance = getInstance(inst); + const constructor = internalInstance.type; + return constructor === type; +} - /** - * Same as `scryRenderedComponentsWithType` but expects there to be one result - * and returns that one result, or throws exception if there is any other - * number of matches besides one. - * @return {!ReactComponent} The one match. - */ - findRenderedComponentWithType: function(root, componentType) { - validateClassInstance(root, 'findRenderedComponentWithType'); - const all = ReactTestUtils.scryRenderedComponentsWithType( - root, - componentType, - ); - if (all.length !== 1) { - throw new Error( - 'Did not find exactly one match (found: ' + - all.length + - ') ' + - 'for componentType:' + - componentType, - ); - } - return all[0]; - }, +function findAllInRenderedTree(inst, test) { + validateClassInstance(inst, 'findAllInRenderedTree'); + if (!inst) { + return []; + } + const internalInstance = getInstance(inst); + return findAllInRenderedFiberTreeInternal(internalInstance, test); +} - /** - * Pass a mocked component module to this method to augment it with - * useful methods that allow it to be used as a dummy React component. - * Instead of rendering as usual, the component will become a simple - *
containing any provided children. - * - * @param {object} module the mock function object exported from a - * module that defines the component to be mocked - * @param {?string} mockTagName optional dummy root tag name to return - * from render method (overrides - * module.mockTagName if provided) - * @return {object} the ReactTestUtils object (for chaining) - */ - mockComponent: function(module, mockTagName) { - if (__DEV__) { - if (!hasWarnedAboutDeprecatedMockComponent) { - hasWarnedAboutDeprecatedMockComponent = true; - console.warn( - 'ReactTestUtils.mockComponent() is deprecated. ' + - 'Use shallow rendering or jest.mock() instead.\n\n' + - 'See https://fb.me/test-utils-mock-component for more information.', +/** + * Finds all instance of components in the rendered tree that are DOM + * components with the class name matching `className`. + * @return {array} an array of all the matches. + */ +function scryRenderedDOMComponentsWithClass(root, classNames) { + validateClassInstance(root, 'scryRenderedDOMComponentsWithClass'); + return findAllInRenderedTree(root, function(inst) { + if (isDOMComponent(inst)) { + let className = inst.className; + if (typeof className !== 'string') { + // SVG, probably. + className = inst.getAttribute('class') || ''; + } + const classList = className.split(/\s+/); + + if (!Array.isArray(classNames)) { + invariant( + classNames !== undefined, + 'TestUtils.scryRenderedDOMComponentsWithClass expects a ' + + 'className as a second argument.', ); + classNames = classNames.split(/\s+/); } + return classNames.every(function(name) { + return classList.indexOf(name) !== -1; + }); } + return false; + }); +} - mockTagName = mockTagName || module.mockTagName || 'div'; +/** + * Like scryRenderedDOMComponentsWithClass but expects there to be one result, + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + * @return {!ReactDOMComponent} The one match. + */ +function findRenderedDOMComponentWithClass(root, className) { + validateClassInstance(root, 'findRenderedDOMComponentWithClass'); + const all = scryRenderedDOMComponentsWithClass(root, className); + if (all.length !== 1) { + throw new Error( + 'Did not find exactly one match (found: ' + + all.length + + ') ' + + 'for class:' + + className, + ); + } + return all[0]; +} - module.prototype.render.mockImplementation(function() { - return React.createElement(mockTagName, null, this.props.children); - }); +/** + * Finds all instance of components in the rendered tree that are DOM + * components with the tag name matching `tagName`. + * @return {array} an array of all the matches. + */ +function scryRenderedDOMComponentsWithTag(root, tagName) { + validateClassInstance(root, 'scryRenderedDOMComponentsWithTag'); + return findAllInRenderedTree(root, function(inst) { + return ( + isDOMComponent(inst) && + inst.tagName.toUpperCase() === tagName.toUpperCase() + ); + }); +} - return this; - }, +/** + * Like scryRenderedDOMComponentsWithTag but expects there to be one result, + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + * @return {!ReactDOMComponent} The one match. + */ +function findRenderedDOMComponentWithTag(root, tagName) { + validateClassInstance(root, 'findRenderedDOMComponentWithTag'); + const all = scryRenderedDOMComponentsWithTag(root, tagName); + if (all.length !== 1) { + throw new Error( + 'Did not find exactly one match (found: ' + + all.length + + ') ' + + 'for tag:' + + tagName, + ); + } + return all[0]; +} - nativeTouchData: function(x, y) { - return { - touches: [{pageX: x, pageY: y}], - }; - }, +/** + * Finds all instances of components with type equal to `componentType`. + * @return {array} an array of all the matches. + */ +function scryRenderedComponentsWithType(root, componentType) { + validateClassInstance(root, 'scryRenderedComponentsWithType'); + return findAllInRenderedTree(root, function(inst) { + return isCompositeComponentWithType(inst, componentType); + }); +} - Simulate: null, - SimulateNative: {}, +/** + * Same as `scryRenderedComponentsWithType` but expects there to be one result + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + * @return {!ReactComponent} The one match. + */ +function findRenderedComponentWithType(root, componentType) { + validateClassInstance(root, 'findRenderedComponentWithType'); + const all = scryRenderedComponentsWithType(root, componentType); + if (all.length !== 1) { + throw new Error( + 'Did not find exactly one match (found: ' + + all.length + + ') ' + + 'for componentType:' + + componentType, + ); + } + return all[0]; +} - act, -}; +/** + * Pass a mocked component module to this method to augment it with + * useful methods that allow it to be used as a dummy React component. + * Instead of rendering as usual, the component will become a simple + *
containing any provided children. + * + * @param {object} module the mock function object exported from a + * module that defines the component to be mocked + * @param {?string} mockTagName optional dummy root tag name to return + * from render method (overrides + * module.mockTagName if provided) + * @return {object} the ReactTestUtils object (for chaining) + */ +function mockComponent(module, mockTagName) { + if (__DEV__) { + if (!hasWarnedAboutDeprecatedMockComponent) { + hasWarnedAboutDeprecatedMockComponent = true; + console.warn( + 'ReactTestUtils.mockComponent() is deprecated. ' + + 'Use shallow rendering or jest.mock() instead.\n\n' + + 'See https://fb.me/test-utils-mock-component for more information.', + ); + } + } + + mockTagName = mockTagName || module.mockTagName || 'div'; + + module.prototype.render.mockImplementation(function() { + return React.createElement(mockTagName, null, this.props.children); + }); + + return this; +} + +function nativeTouchData(x, y) { + return { + touches: [{pageX: x, pageY: y}], + }; +} + +const Simulate = {}; +const SimulateNative = {}; /** * Exports: * - * - `ReactTestUtils.Simulate.click(Element)` - * - `ReactTestUtils.Simulate.mouseMove(Element)` - * - `ReactTestUtils.Simulate.change(Element)` + * - `Simulate.click(Element)` + * - `Simulate.mouseMove(Element)` + * - `Simulate.change(Element)` * - ... (All keys from event plugin `eventTypes` objects) */ function makeSimulator(eventType) { @@ -407,7 +397,7 @@ function makeSimulator(eventType) { 'Note that TestUtils.Simulate will not work if you are using shallow rendering.', ); invariant( - !ReactTestUtils.isCompositeComponent(domNode), + !isCompositeComponent(domNode), 'TestUtils.Simulate expected a DOM node as the first argument but received ' + 'a component instance. Pass the DOM node you wish to simulate the event on instead.', ); @@ -450,15 +440,13 @@ function makeSimulator(eventType) { } function buildSimulators() { - ReactTestUtils.Simulate = {}; - let eventType; for (eventType in eventNameDispatchConfigs) { /** * @param {!Element|ReactDOMComponent} domComponentOrNode * @param {?object} eventData Fake event data to use in SyntheticEvent. */ - ReactTestUtils.Simulate[eventType] = makeSimulator(eventType); + Simulate[eventType] = makeSimulator(eventType); } } @@ -467,16 +455,16 @@ buildSimulators(); /** * Exports: * - * - `ReactTestUtils.SimulateNative.click(Element/ReactDOMComponent)` - * - `ReactTestUtils.SimulateNative.mouseMove(Element/ReactDOMComponent)` - * - `ReactTestUtils.SimulateNative.mouseIn/ReactDOMComponent)` - * - `ReactTestUtils.SimulateNative.mouseOut(Element/ReactDOMComponent)` + * - `SimulateNative.click(Element/ReactDOMComponent)` + * - `SimulateNative.mouseMove(Element/ReactDOMComponent)` + * - `SimulateNative.mouseIn/ReactDOMComponent)` + * - `SimulateNative.mouseOut(Element/ReactDOMComponent)` * - ... (All keys from `BrowserEventConstants.topLevelTypes`) * * Note: Top level event types are a subset of the entire set of handler types * (which include a broader set of "synthetic" events). For example, onDragDone * is a synthetic event. Except when testing an event plugin or React's event - * handling code specifically, you probably want to use ReactTestUtils.Simulate + * handling code specifically, you probably want to use Simulate * to dispatch synthetic events. */ @@ -484,7 +472,7 @@ function makeNativeSimulator(eventType, topLevelType) { return function(domComponentOrNode, nativeEventData) { const fakeNativeEvent = new Event(eventType); Object.assign(fakeNativeEvent, nativeEventData); - if (ReactTestUtils.isDOMComponent(domComponentOrNode)) { + if (isDOMComponent(domComponentOrNode)) { simulateNativeEventOnDOMComponent( topLevelType, domComponentOrNode, @@ -576,10 +564,27 @@ function makeNativeSimulator(eventType, topLevelType) { * @param {!Element|ReactDOMComponent} domComponentOrNode * @param {?Event} nativeEventData Fake native event to use in SyntheticEvent. */ - ReactTestUtils.SimulateNative[eventType] = makeNativeSimulator( - eventType, - topLevelType, - ); + SimulateNative[eventType] = makeNativeSimulator(eventType, topLevelType); }); -export default ReactTestUtils; +export { + renderIntoDocument, + isElement, + isElementOfType, + isDOMComponent, + isDOMComponentElement, + isCompositeComponent, + isCompositeComponentWithType, + findAllInRenderedTree, + scryRenderedDOMComponentsWithClass, + findRenderedDOMComponentWithClass, + scryRenderedDOMComponentsWithTag, + findRenderedDOMComponentWithTag, + scryRenderedComponentsWithType, + findRenderedComponentWithType, + mockComponent, + nativeTouchData, + Simulate, + SimulateNative, + act, +}; diff --git a/packages/react-dom/test-utils.js b/packages/react-dom/test-utils.js index 1d4f69189e026..3eaa6b7b8c5d1 100644 --- a/packages/react-dom/test-utils.js +++ b/packages/react-dom/test-utils.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactTestUtils = require('./src/test-utils/ReactTestUtils'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactTestUtils.default || ReactTestUtils; +export * from './src/test-utils/ReactTestUtils'; diff --git a/packages/react-dom/unstable-fizz.browser.js b/packages/react-dom/unstable-fizz.browser.js index 4fb175ec6825e..322d4e364e1ae 100644 --- a/packages/react-dom/unstable-fizz.browser.js +++ b/packages/react-dom/unstable-fizz.browser.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactDOMFizzServerBrowser = require('./src/server/ReactDOMFizzServerBrowser'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest -module.exports = ReactDOMFizzServerBrowser.default || ReactDOMFizzServerBrowser; +export * from './src/server/ReactDOMFizzServerBrowser'; diff --git a/packages/react-dom/unstable-fizz.js b/packages/react-dom/unstable-fizz.js index 81d1ccee698d1..835fb25dca4a3 100644 --- a/packages/react-dom/unstable-fizz.js +++ b/packages/react-dom/unstable-fizz.js @@ -7,6 +7,4 @@ * @flow */ -'use strict'; - -module.exports = require('./unstable-fizz.node'); +export * from './unstable-fizz.node'; diff --git a/packages/react-dom/unstable-fizz.node.js b/packages/react-dom/unstable-fizz.node.js index ef943c74eccf5..ae7462ed70713 100644 --- a/packages/react-dom/unstable-fizz.node.js +++ b/packages/react-dom/unstable-fizz.node.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactDOMFizzServerNode = require('./src/server/ReactDOMFizzServerNode'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest -module.exports = ReactDOMFizzServerNode.default || ReactDOMFizzServerNode; +export * from './src/server/ReactDOMFizzServerNode'; diff --git a/packages/react-dom/unstable-native-dependencies.js b/packages/react-dom/unstable-native-dependencies.js index d44d492b8f198..ec502fb890690 100644 --- a/packages/react-dom/unstable-native-dependencies.js +++ b/packages/react-dom/unstable-native-dependencies.js @@ -7,6 +7,4 @@ * @flow */ -'use strict'; - -module.exports = require('./src/unstable-native-dependencies/ReactDOMUnstableNativeDependencies'); +export * from './src/unstable-native-dependencies/ReactDOMUnstableNativeDependencies'; diff --git a/packages/react-server/src/ReactDOMServerFormatConfig.js b/packages/react-server/src/ReactDOMServerFormatConfig.js index ece3e63890582..fa94102a98c9a 100644 --- a/packages/react-server/src/ReactDOMServerFormatConfig.js +++ b/packages/react-server/src/ReactDOMServerFormatConfig.js @@ -9,7 +9,7 @@ import {convertStringToBuffer} from 'react-server/src/ReactServerHostConfig'; -import ReactDOMServer from 'react-dom/server'; +import {renderToStaticMarkup} from 'react-dom/server'; export function formatChunkAsString(type: string, props: Object): string { let str = '<' + type + '>'; @@ -31,5 +31,5 @@ export function renderHostChildrenToString( // so we can't actually reference the renderer here. Instead, we // should replace this method with a reference to Fizz which // then uses this file to implement the server renderer. - return ReactDOMServer.renderToStaticMarkup(children); + return renderToStaticMarkup(children); } diff --git a/packages/react-test-renderer/index.js b/packages/react-test-renderer/index.js index 8d1c90e8855ac..61da6c01c1d5e 100644 --- a/packages/react-test-renderer/index.js +++ b/packages/react-test-renderer/index.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactTestRenderer = require('./src/ReactTestRenderer'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactTestRenderer.default || ReactTestRenderer; +export * from './src/ReactTestRenderer'; diff --git a/packages/react-test-renderer/shallow.js b/packages/react-test-renderer/shallow.js index 05df5d498fd91..fa548b35732db 100644 --- a/packages/react-test-renderer/shallow.js +++ b/packages/react-test-renderer/shallow.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactShallowRenderer = require('./src/ReactShallowRenderer'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactShallowRenderer.default || ReactShallowRenderer; +export {default} from './src/ReactShallowRenderer'; diff --git a/packages/react-test-renderer/src/ReactShallowRenderer.js b/packages/react-test-renderer/src/ReactShallowRenderer.js index abdd493704888..20751094fd28a 100644 --- a/packages/react-test-renderer/src/ReactShallowRenderer.js +++ b/packages/react-test-renderer/src/ReactShallowRenderer.js @@ -856,4 +856,8 @@ function getMaskedContext(contextTypes, unmaskedContext) { return context; } +// This should probably be a default export and a named export. +// However, this not how any of other APIs are designed so doesn't line up +// with our build configs and makes it hard to properly support ES modules +// and CommonJS. export default ReactShallowRenderer; diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js index 0bd57d4702645..18a69c4202111 100644 --- a/packages/react-test-renderer/src/ReactTestRenderer.js +++ b/packages/react-test-renderer/src/ReactTestRenderer.js @@ -433,138 +433,129 @@ function propsMatch(props: Object, filter: Object): boolean { return true; } -const ReactTestRendererFiber = { - _Scheduler: Scheduler, - - create(element: React$Element, options: TestRendererOptions) { - let createNodeMock = defaultTestOptions.createNodeMock; - let isConcurrent = false; - if (typeof options === 'object' && options !== null) { - if (typeof options.createNodeMock === 'function') { - createNodeMock = options.createNodeMock; +function create(element: React$Element, options: TestRendererOptions) { + let createNodeMock = defaultTestOptions.createNodeMock; + let isConcurrent = false; + if (typeof options === 'object' && options !== null) { + if (typeof options.createNodeMock === 'function') { + createNodeMock = options.createNodeMock; + } + if (options.unstable_isConcurrent === true) { + isConcurrent = true; + } + } + let container = { + children: [], + createNodeMock, + tag: 'CONTAINER', + }; + let root: FiberRoot | null = createContainer( + container, + isConcurrent ? ConcurrentRoot : LegacyRoot, + false, + null, + ); + invariant(root != null, 'something went wrong'); + updateContainer(element, root, null, null); + + const entry = { + _Scheduler: Scheduler, + + root: undefined, // makes flow happy + // we define a 'getter' for 'root' below using 'Object.defineProperty' + toJSON(): Array | ReactTestRendererNode | null { + if (root == null || root.current == null || container == null) { + return null; } - if (options.unstable_isConcurrent === true) { - isConcurrent = true; + if (container.children.length === 0) { + return null; } - } - let container = { - children: [], - createNodeMock, - tag: 'CONTAINER', - }; - let root: FiberRoot | null = createContainer( - container, - isConcurrent ? ConcurrentRoot : LegacyRoot, - false, - null, - ); - invariant(root != null, 'something went wrong'); - updateContainer(element, root, null, null); - - const entry = { - _Scheduler: Scheduler, - - root: undefined, // makes flow happy - // we define a 'getter' for 'root' below using 'Object.defineProperty' - toJSON(): Array | ReactTestRendererNode | null { - if (root == null || root.current == null || container == null) { - return null; - } - if (container.children.length === 0) { - return null; - } - if (container.children.length === 1) { - return toJSON(container.children[0]); - } - if ( - container.children.length === 2 && - container.children[0].isHidden === true && - container.children[1].isHidden === false - ) { - // Omit timed out children from output entirely, including the fact that we - // temporarily wrap fallback and timed out children in an array. - return toJSON(container.children[1]); - } - let renderedChildren = null; - if (container.children && container.children.length) { - for (let i = 0; i < container.children.length; i++) { - const renderedChild = toJSON(container.children[i]); - if (renderedChild !== null) { - if (renderedChildren === null) { - renderedChildren = [renderedChild]; - } else { - renderedChildren.push(renderedChild); - } + if (container.children.length === 1) { + return toJSON(container.children[0]); + } + if ( + container.children.length === 2 && + container.children[0].isHidden === true && + container.children[1].isHidden === false + ) { + // Omit timed out children from output entirely, including the fact that we + // temporarily wrap fallback and timed out children in an array. + return toJSON(container.children[1]); + } + let renderedChildren = null; + if (container.children && container.children.length) { + for (let i = 0; i < container.children.length; i++) { + const renderedChild = toJSON(container.children[i]); + if (renderedChild !== null) { + if (renderedChildren === null) { + renderedChildren = [renderedChild]; + } else { + renderedChildren.push(renderedChild); } } } - return renderedChildren; - }, - toTree() { - if (root == null || root.current == null) { - return null; - } - return toTree(root.current); - }, - update(newElement: React$Element) { - if (root == null || root.current == null) { - return; - } - updateContainer(newElement, root, null, null); - }, - unmount() { - if (root == null || root.current == null) { - return; + } + return renderedChildren; + }, + toTree() { + if (root == null || root.current == null) { + return null; + } + return toTree(root.current); + }, + update(newElement: React$Element) { + if (root == null || root.current == null) { + return; + } + updateContainer(newElement, root, null, null); + }, + unmount() { + if (root == null || root.current == null) { + return; + } + updateContainer(null, root, null, null); + container = null; + root = null; + }, + getInstance() { + if (root == null || root.current == null) { + return null; + } + return getPublicRootInstance(root); + }, + + unstable_flushSync(fn: () => T): T { + return flushSync(fn); + }, + }; + + Object.defineProperty( + entry, + 'root', + ({ + configurable: true, + enumerable: true, + get: function() { + if (root === null) { + throw new Error("Can't access .root on unmounted test renderer"); } - updateContainer(null, root, null, null); - container = null; - root = null; - }, - getInstance() { - if (root == null || root.current == null) { - return null; + const children = getChildren(root.current); + if (children.length === 0) { + throw new Error("Can't access .root on unmounted test renderer"); + } else if (children.length === 1) { + // Normally, we skip the root and just give you the child. + return children[0]; + } else { + // However, we give you the root if there's more than one root child. + // We could make this the behavior for all cases but it would be a breaking change. + return wrapFiber(root.current); } - return getPublicRootInstance(root); - }, - - unstable_flushSync(fn: () => T): T { - return flushSync(fn); }, - }; - - Object.defineProperty( - entry, - 'root', - ({ - configurable: true, - enumerable: true, - get: function() { - if (root === null) { - throw new Error("Can't access .root on unmounted test renderer"); - } - const children = getChildren(root.current); - if (children.length === 0) { - throw new Error("Can't access .root on unmounted test renderer"); - } else if (children.length === 1) { - // Normally, we skip the root and just give you the child. - return children[0]; - } else { - // However, we give you the root if there's more than one root child. - // We could make this the behavior for all cases but it would be a breaking change. - return wrapFiber(root.current); - } - }, - }: Object), - ); - - return entry; - }, + }: Object), + ); - /* eslint-disable-next-line camelcase */ - unstable_batchedUpdates: batchedUpdates, - - act, -}; + return entry; +} const fiberToWrapper = new WeakMap(); function wrapFiber(fiber: Fiber): ReactTestInstance { @@ -589,4 +580,10 @@ injectIntoDevTools({ rendererPackageName: 'react-test-renderer', }); -export default ReactTestRendererFiber; +export { + Scheduler as _Scheduler, + create, + /* eslint-disable-next-line camelcase */ + batchedUpdates as unstable_batchedUpdates, + act, +}; diff --git a/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js b/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js index 68c8299cfe963..13aa7682aff2c 100644 --- a/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js @@ -10,19 +10,13 @@ 'use strict'; -let createRenderer; -let PropTypes; -let React; +import * as PropTypes from 'prop-types'; +import * as React from 'react'; +import ReactShallowRenderer from 'react-test-renderer/shallow'; -describe('ReactShallowRenderer', () => { - beforeEach(() => { - jest.resetModules(); - - createRenderer = require('react-test-renderer/shallow').createRenderer; - PropTypes = require('prop-types'); - React = require('react'); - }); +const createRenderer = ReactShallowRenderer.createRenderer; +describe('ReactShallowRenderer', () => { it('should call all of the legacy lifecycle hooks', () => { const logs = []; const logger = message => () => logs.push(message) || true; diff --git a/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js b/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js index 6b8a962ad5b14..87bbdade2507c 100644 --- a/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js @@ -10,16 +10,12 @@ 'use strict'; -let createRenderer; -let React; +import * as React from 'react'; +import ReactShallowRenderer from 'react-test-renderer/shallow'; -describe('ReactShallowRenderer with hooks', () => { - beforeEach(() => { - jest.resetModules(); - createRenderer = require('react-test-renderer/shallow').createRenderer; - React = require('react'); - }); +const createRenderer = ReactShallowRenderer.createRenderer; +describe('ReactShallowRenderer with hooks', () => { it('should work with useState', () => { function SomeComponent({defaultName}) { const [name] = React.useState(defaultName); diff --git a/packages/react-test-renderer/src/__tests__/ReactShallowRendererMemo-test.js b/packages/react-test-renderer/src/__tests__/ReactShallowRendererMemo-test.js index 9ed3bc681593b..5da98d8a7420a 100644 --- a/packages/react-test-renderer/src/__tests__/ReactShallowRendererMemo-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactShallowRendererMemo-test.js @@ -10,19 +10,13 @@ 'use strict'; -let createRenderer; -let PropTypes; -let React; +import * as PropTypes from 'prop-types'; +import * as React from 'react'; +import ReactShallowRenderer from 'react-test-renderer/shallow'; -describe('ReactShallowRendererMemo', () => { - beforeEach(() => { - jest.resetModules(); - - createRenderer = require('react-test-renderer/shallow').createRenderer; - PropTypes = require('prop-types'); - React = require('react'); - }); +const createRenderer = ReactShallowRenderer.createRenderer; +describe('ReactShallowRendererMemo', () => { it('should call all of the legacy lifecycle hooks', () => { const logs = []; const logger = message => () => logs.push(message) || true;