From e90125277d549ce1864541d3ea547c7d132d6fa8 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Fri, 7 Apr 2017 17:29:03 -0600 Subject: [PATCH 01/21] [Compat] support React@15.5 A few deprecation warnings were added in React@15.5. This supports the new APIs that React recommends. Closes #875 --- README.md | 10 +++++++++- package.json | 2 +- src/ReactWrapperComponent.jsx | 3 ++- src/react-compat.js | 25 ++++++++++++++++++++++--- src/version.js | 1 + 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 408e0598a..a3b8ce821 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ npm i --save-dev enzyme Enzyme is currently compatible with `React 15.x`, `React 0.14.x` and `React 0.13.x`. In order to achieve this compatibility, some dependencies cannot be explicitly listed in our `package.json`. -If you are using `React 0.14` or `React 15.x`, in addition to `enzyme`, you will have to ensure that +If you are using `React 0.14` or `React <15.5`, in addition to `enzyme`, you will have to ensure that you also have the following npm modules installed if they were not already: ```bash @@ -68,6 +68,14 @@ npm i --save-dev react-addons-test-utils npm i --save-dev react-dom ``` +If you are using `React >=15.5`, in addition to `enzyme`, you will have to ensure that you also have +the following npm modules installed if they were not already: + +```bash +npm i --save-dev react-dom +npm i --save-dev prop-types +``` + Basic Usage =========== diff --git a/package.json b/package.json index bfa21393f..b5bce1cac 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils", "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", - "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 && npm install", + "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 prop-types@15 create-react-class@15 && npm install", "docs:clean": "rimraf _book", "docs:prepare": "gitbook install", "docs:build": "npm run docs:prepare && gitbook build", diff --git a/src/ReactWrapperComponent.jsx b/src/ReactWrapperComponent.jsx index 4bba0d081..049a4c182 100644 --- a/src/ReactWrapperComponent.jsx +++ b/src/ReactWrapperComponent.jsx @@ -1,5 +1,6 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; import objectAssign from 'object.assign'; +import { PropTypes, createClass } from './react-compat'; /* eslint react/forbid-prop-types: 0 */ diff --git a/src/react-compat.js b/src/react-compat.js index 2d108bd30..85a562152 100644 --- a/src/react-compat.js +++ b/src/react-compat.js @@ -7,7 +7,7 @@ */ import objectAssign from 'object.assign'; -import { REACT013 } from './version'; +import { REACT013, REACT155 } from './version'; let TestUtils; let createShallowRenderer; @@ -18,6 +18,8 @@ let childrenToArray; let renderWithOptions; let unmountComponentAtNode; let batchedUpdates; +let PropTypes; +let createClass; const React = require('react'); @@ -95,8 +97,13 @@ if (REACT013) { // to list this as a dependency in package.json and have 0.13 work properly. // As a result, right now this is basically an implicit dependency. try { - // eslint-disable-next-line import/no-extraneous-dependencies - TestUtils = require('react-addons-test-utils'); + if (REACT155) { + // eslint-disable-next-line import/no-extraneous-dependencies + TestUtils = require('react-dom/test-utils'); + } else { + // eslint-disable-next-line import/no-extraneous-dependencies + TestUtils = require('react-addons-test-utils'); + } } catch (e) { // eslint-disable-next-line no-console console.error( @@ -150,6 +157,16 @@ if (REACT013) { }; } +if (REACT155) { + // eslint-disable-next-line import/no-extraneous-dependencies + PropTypes = require('prop-types'); + // eslint-disable-next-line import/no-extraneous-dependencies + createClass = require('create-react-class'); +} else { + PropTypes = React.PropTypes; + createClass = React.createClass; +} + function isDOMComponentElement(inst) { return React.isValidElement(inst) && typeof inst.type === 'string'; } @@ -185,4 +202,6 @@ export { renderWithOptions, unmountComponentAtNode, batchedUpdates, + PropTypes, + createClass, }; diff --git a/src/version.js b/src/version.js index 8d64d2611..3b889e2d6 100644 --- a/src/version.js +++ b/src/version.js @@ -4,3 +4,4 @@ export const VERSION = React.version; export const REACT013 = VERSION.slice(0, 4) === '0.13'; export const REACT014 = VERSION.slice(0, 4) === '0.14'; export const REACT15 = VERSION.slice(0, 3) === '15.'; +export const REACT155 = VERSION.slice(0, 4) === '15.5'; From a0bb9bf29c44b0c1211cc18cbb96563cbb05da78 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 8 Apr 2017 09:37:17 -0700 Subject: [PATCH 02/21] Pull shallow renderer from react-test-renderer/shallow for React 15.5 --- package.json | 2 +- src/react-compat.js | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b5bce1cac..2c93e9aa4 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils", "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", - "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 prop-types@15 create-react-class@15 && npm install", + "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 prop-types@15 create-react-class@15 react-test-renderer@15 && npm install", "docs:clean": "rimraf _book", "docs:prepare": "gitbook install", "docs:build": "npm run docs:prepare && gitbook build", diff --git a/src/react-compat.js b/src/react-compat.js index 85a562152..afde69bff 100644 --- a/src/react-compat.js +++ b/src/react-compat.js @@ -20,6 +20,7 @@ let unmountComponentAtNode; let batchedUpdates; let PropTypes; let createClass; +let shallowRendererFactory; const React = require('react'); @@ -114,6 +115,26 @@ if (REACT013) { throw e; } + // Shallow renderer is accessible via the react-test-renderer package for React 15.5+. + // This is a separate package though and may not be installed. + try { + if (REACT155) { + // eslint-disable-next-line import/no-extraneous-dependencies + shallowRendererFactory = require('react-test-renderer/shallow').createRenderer; + } else { + // eslint-disable-next-line import/no-extraneous-dependencies + shallowRendererFactory = TestUtils.createRenderer; + } + } catch (e) { + // eslint-disable-next-line no-console + console.error( + 'react-test-renderer is an implicit dependency in order to support react@15.5+. ' + + 'Please add the appropriate version to your devDependencies. ' + + 'See https://github.com/airbnb/enzyme#installation', + ); + throw e; + } + // Shallow rendering changed from 0.13 => 0.14 in such a way that // 0.14 now does not allow shallow rendering of native DOM elements. // This is mainly because the result of such a call should not realistically @@ -122,7 +143,7 @@ if (REACT013) { // is essentially a replacement for `TestUtils.createRenderer` that doesn't use // shallow rendering when it's just a DOM element. createShallowRenderer = function createRendererCompatible() { - const renderer = TestUtils.createRenderer(); + const renderer = shallowRendererFactory(); const originalRender = renderer.render; const originalRenderOutput = renderer.getRenderOutput; let isDOM = false; From 1c932cbaa2daa8ea8eb8862325f266010b286d91 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 8 Apr 2017 14:46:08 -0700 Subject: [PATCH 03/21] Accompanying change to ShallowWrapper to resolve shallowRenderer 15.5 issue --- src/ShallowWrapper.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index 1567c689c..534430a1d 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -110,7 +110,7 @@ class ShallowWrapper { this.unrendered = nodes; this.renderer = createShallowRenderer(); withSetStateAllowed(() => { - batchedUpdates(() => { + this.batchedUpdates(() => { this.renderer.render(nodes, options.context); const instance = this.instance(); if ( @@ -142,6 +142,16 @@ class ShallowWrapper { this.complexSelector = new ComplexSelector(buildPredicate, findWhereUnwrapped, childrenOfNode); } + batchedUpdates(fn) { + const renderer = this.root.renderer; + if (renderer.unstable_batchedUpdates) { + // React 15.5+ exposes batching on shallow renderer itself + return renderer.unstable_batchedUpdates(fn); + } + // React <15.5: Fallback to ReactDOM + return batchedUpdates(fn); + } + /** * Returns the wrapped ReactElement. * @@ -223,7 +233,7 @@ class ShallowWrapper { const prevContext = instance.context; const nextProps = props || prevProps; const nextContext = context || prevContext; - batchedUpdates(() => { + this.batchedUpdates(() => { let shouldRender = true; // dirty hack: // make sure that componentWillReceiveProps is called before shouldComponentUpdate @@ -611,7 +621,7 @@ class ShallowWrapper { withSetStateAllowed(() => { // TODO(lmr): create/use synthetic events // TODO(lmr): emulate React's event propagation - batchedUpdates(() => { + this.batchedUpdates(() => { handler(...args); }); this.root.update(); From 49e0825c45a22052c6a960f55f062282d7cbab0c Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 8 Apr 2017 18:14:39 -0700 Subject: [PATCH 04/21] Add prop-types as a regular dependency --- README.md | 1 - package.json | 3 ++- src/ReactWrapperComponent.jsx | 3 ++- src/react-compat.js | 5 ----- test/ReactWrapper-spec.jsx | 27 +++++++++++++------------ test/ShallowWrapper-spec.jsx | 37 ++++++++++++++++++----------------- test/staticRender-spec.jsx | 7 ++++--- 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index a3b8ce821..43a3f134f 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,6 @@ the following npm modules installed if they were not already: ```bash npm i --save-dev react-dom -npm i --save-dev prop-types ``` diff --git a/package.json b/package.json index 2c93e9aa4..7f77372fc 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils", "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", - "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 prop-types@15 create-react-class@15 react-test-renderer@15 && npm install", + "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 create-react-class@15 react-test-renderer@15 && npm install", "docs:clean": "rimraf _book", "docs:prepare": "gitbook install", "docs:build": "npm run docs:prepare && gitbook build", @@ -60,6 +60,7 @@ "object.assign": "^4.0.4", "object.entries": "^1.0.3", "object.values": "^1.0.3", + "prop-types": "^15.5.4", "uuid": "^2.0.3" }, "devDependencies": { diff --git a/src/ReactWrapperComponent.jsx b/src/ReactWrapperComponent.jsx index 049a4c182..4cbeb00b9 100644 --- a/src/ReactWrapperComponent.jsx +++ b/src/ReactWrapperComponent.jsx @@ -1,6 +1,7 @@ import React from 'react'; +import PropTypes from 'prop-types'; import objectAssign from 'object.assign'; -import { PropTypes, createClass } from './react-compat'; +import { createClass } from './react-compat'; /* eslint react/forbid-prop-types: 0 */ diff --git a/src/react-compat.js b/src/react-compat.js index afde69bff..6ca2e7c57 100644 --- a/src/react-compat.js +++ b/src/react-compat.js @@ -18,7 +18,6 @@ let childrenToArray; let renderWithOptions; let unmountComponentAtNode; let batchedUpdates; -let PropTypes; let createClass; let shallowRendererFactory; @@ -179,12 +178,9 @@ if (REACT013) { } if (REACT155) { - // eslint-disable-next-line import/no-extraneous-dependencies - PropTypes = require('prop-types'); // eslint-disable-next-line import/no-extraneous-dependencies createClass = require('create-react-class'); } else { - PropTypes = React.PropTypes; createClass = React.createClass; } @@ -223,6 +219,5 @@ export { renderWithOptions, unmountComponentAtNode, batchedUpdates, - PropTypes, createClass, }; diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index d80529b6a..ab9370e40 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -1,6 +1,7 @@ /* globals document */ import React from 'react'; +import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; import { batchedUpdates } from '../src/react-compat'; @@ -25,7 +26,7 @@ describeWithDOM('mount', () => { it('can pass in context', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -40,7 +41,7 @@ describeWithDOM('mount', () => { it('can pass context to the child of mounted component', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -53,7 +54,7 @@ describeWithDOM('mount', () => { }); const childContextTypes = { - name: React.PropTypes.string.isRequired, + name: PropTypes.string.isRequired, }; const context = { name: 'foo' }; const wrapper = mount(, { context, childContextTypes }); @@ -74,7 +75,7 @@ describeWithDOM('mount', () => { it('is instrospectable through context API', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -93,7 +94,7 @@ describeWithDOM('mount', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const context = { name: 'foo' }; const wrapper = mount(, { context }); @@ -104,14 +105,14 @@ describeWithDOM('mount', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const ComplexComponent = () => (
); const childContextTypes = { - name: React.PropTypes.string.isRequired, + name: PropTypes.string.isRequired, }; const context = { name: 'foo' }; @@ -132,7 +133,7 @@ describeWithDOM('mount', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const context = { name: 'foo' }; const wrapper = mount(, { context }); @@ -150,7 +151,7 @@ describeWithDOM('mount', () => { ); Foo.contextTypes = { - _: React.PropTypes.string, + _: PropTypes.string, }; const wrapper = mount(, { @@ -1098,7 +1099,7 @@ describeWithDOM('mount', () => { it('should set context for a component multiple times', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -1117,7 +1118,7 @@ describeWithDOM('mount', () => { it('should throw if it is called when shallow didn’t include context', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -1136,7 +1137,7 @@ describeWithDOM('mount', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const context = { name: 'foo' }; const wrapper = mount(, { context }); @@ -1151,7 +1152,7 @@ describeWithDOM('mount', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const wrapper = mount(); expect(() => wrapper.setContext({ name: 'bar' })).to.throw( diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index bf82dc7e6..3afeb3b1b 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; @@ -12,7 +13,7 @@ describe('shallow', () => { it('can pass in context', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -38,7 +39,7 @@ describe('shallow', () => { it('is instrospectable through context API', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -57,7 +58,7 @@ describe('shallow', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const context = { name: 'foo' }; const wrapper = shallow(, { context }); @@ -77,7 +78,7 @@ describe('shallow', () => { const SimpleComponent = (props, context) => (
{context.name}
); - SimpleComponent.contextTypes = { name: React.PropTypes.string }; + SimpleComponent.contextTypes = { name: PropTypes.string }; const wrapper = shallow(, { context }); @@ -892,7 +893,7 @@ describe('shallow', () => { } } - Foo.contextTypes = { x: React.PropTypes.string }; + Foo.contextTypes = { x: PropTypes.string }; const context = { x: 'yolo' }; const wrapper = shallow(, { context }); @@ -938,7 +939,7 @@ describe('shallow', () => { const Foo = (props, context) => (
{context.x}
); - Foo.contextTypes = { x: React.PropTypes.string }; + Foo.contextTypes = { x: PropTypes.string }; const context = { x: 'yolo' }; const wrapper = shallow(, { context }); @@ -953,7 +954,7 @@ describe('shallow', () => { describe('.setContext(newContext)', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -982,7 +983,7 @@ describe('shallow', () => { const SFC = (props, context) => (
{context.name}
); - SFC.contextTypes = { name: React.PropTypes.string }; + SFC.contextTypes = { name: PropTypes.string }; it('should set context for a component multiple times', () => { const context = { name: 'foo' }; @@ -2309,7 +2310,7 @@ describe('shallow', () => { } } Bar.contextTypes = { - name: React.PropTypes.string, + name: PropTypes.string, }; class Foo extends React.Component { render() { @@ -2355,7 +2356,7 @@ describe('shallow', () => { } } Bar.contextTypes = { - name: React.PropTypes.string, + name: PropTypes.string, }; class Foo extends React.Component { render() { @@ -2399,7 +2400,7 @@ describe('shallow', () => { const Bar = (props, context) => (
{context.name}
); - Bar.contextTypes = { name: React.PropTypes.string }; + Bar.contextTypes = { name: PropTypes.string }; const Foo = () => (
@@ -2430,7 +2431,7 @@ describe('shallow', () => { const Bar = (props, context) => (
{context.name}
); - Bar.contextTypes = { name: React.PropTypes.string }; + Bar.contextTypes = { name: PropTypes.string }; const Foo = () => (
@@ -2921,7 +2922,7 @@ describe('shallow', () => { } } Foo.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; const wrapper = shallow( @@ -3145,7 +3146,7 @@ describe('shallow', () => { } } Foo.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; const wrapper = shallow( @@ -3304,7 +3305,7 @@ describe('shallow', () => { } } Foo.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; const wrapper = shallow( , @@ -3363,7 +3364,7 @@ describe('shallow', () => { } } Foo.contextTypes = { - foo: React.PropTypes.string, + foo: PropTypes.string, }; const wrapper = shallow( , @@ -4005,7 +4006,7 @@ describe('shallow', () => { return ; } } - WrapsRendersDOM.contextTypes = { foo: React.PropTypes.string }; + WrapsRendersDOM.contextTypes = { foo: PropTypes.string }; class DoubleWrapsRendersDOM extends React.Component { render() { return ; @@ -4016,7 +4017,7 @@ describe('shallow', () => { return ; } } - ContextWrapsRendersDOM.contextTypes = { foo: React.PropTypes.string }; + ContextWrapsRendersDOM.contextTypes = { foo: PropTypes.string }; it('throws on a DOM node', () => { const wrapper = shallow(); diff --git a/test/staticRender-spec.jsx b/test/staticRender-spec.jsx index 39a1c663d..4fa4f4a64 100644 --- a/test/staticRender-spec.jsx +++ b/test/staticRender-spec.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { expect } from 'chai'; import { describeWithDOM, describeIf } from './_helpers'; import { render } from '../src/'; @@ -9,7 +10,7 @@ describeWithDOM('render', () => { it('can pass in context', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -23,7 +24,7 @@ describeWithDOM('render', () => { it('can pass context to the child of mounted component', () => { const SimpleComponent = React.createClass({ contextTypes: { - name: React.PropTypes.string, + name: PropTypes.string, }, render() { return
{this.context.name}
; @@ -36,7 +37,7 @@ describeWithDOM('render', () => { }); const childContextTypes = { - name: React.PropTypes.string.isRequired, + name: PropTypes.string.isRequired, }; const context = { name: 'foo' }; const wrapper = render(, { context, childContextTypes }); From c3f35197defff670bc3087880d39e8b30d87da1b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 8 Apr 2017 18:17:42 -0700 Subject: [PATCH 05/21] Use createClass from react-compat instead of React.createClass --- README.md | 5 ++--- test/ReactWrapper-spec.jsx | 26 +++++++++++++------------- test/ShallowWrapper-spec.jsx | 23 ++++++++++++----------- test/staticRender-spec.jsx | 9 +++++---- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 43a3f134f..c333aee36 100644 --- a/README.md +++ b/README.md @@ -64,15 +64,14 @@ If you are using `React 0.14` or `React <15.5`, in addition to `enzyme`, you wil you also have the following npm modules installed if they were not already: ```bash -npm i --save-dev react-addons-test-utils -npm i --save-dev react-dom +npm i --save-dev react-addons-test-utils react-dom ``` If you are using `React >=15.5`, in addition to `enzyme`, you will have to ensure that you also have the following npm modules installed if they were not already: ```bash -npm i --save-dev react-dom +npm i --save-dev react-dom create-react-class ``` diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index ab9370e40..53bdecb4d 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -4,7 +4,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; -import { batchedUpdates } from '../src/react-compat'; +import { batchedUpdates, createClass } from '../src/react-compat'; import { describeWithDOM, @@ -24,7 +24,7 @@ import { REACT013, REACT014, REACT15 } from '../src/version'; describeWithDOM('mount', () => { describe('context', () => { it('can pass in context', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -39,7 +39,7 @@ describeWithDOM('mount', () => { }); it('can pass context to the child of mounted component', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -47,7 +47,7 @@ describeWithDOM('mount', () => { return
{this.context.name}
; }, }); - const ComplexComponent = React.createClass({ + const ComplexComponent = createClass({ render() { return
; }, @@ -62,7 +62,7 @@ describeWithDOM('mount', () => { }); it('should not throw if context is passed in but contextTypes is missing', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ render() { return
{this.context.name}
; }, @@ -73,7 +73,7 @@ describeWithDOM('mount', () => { }); it('is instrospectable through context API', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -1097,7 +1097,7 @@ describeWithDOM('mount', () => { describe('.setContext(newContext)', () => { it('should set context for a component multiple times', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -1116,7 +1116,7 @@ describeWithDOM('mount', () => { }); it('should throw if it is called when shallow didn’t include context', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -1467,7 +1467,7 @@ describeWithDOM('mount', () => { const emptyRenderValues = generateEmptyRenderData(); itWithData(emptyRenderValues, 'when a React class component returns: ', (data) => { - const Foo = React.createClass({ + const Foo = createClass({ render() { return data.value; }, @@ -3268,9 +3268,9 @@ describeWithDOM('mount', () => { }); }); - describe('React.createClass', () => { + describe('createClass', () => { it('should return the name of the node', () => { - const Foo = React.createClass({ + const Foo = createClass({ displayName: 'CustomWrapper', render() { return
; @@ -3304,9 +3304,9 @@ describeWithDOM('mount', () => { }); }); - describe('React.createClass', () => { + describe('createClass', () => { it('should return the name of the node', () => { - const Foo = React.createClass({ + const Foo = createClass({ render() { return
; }, diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index 3afeb3b1b..f474ad1c2 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; +import { createClass } from '../src/react-compat'; import { shallow, render, ShallowWrapper } from '../src/'; import { describeIf, itIf, itWithData, generateEmptyRenderData } from './_helpers'; import { ITERATOR_SYMBOL, withSetStateAllowed } from '../src/Utils'; @@ -11,7 +12,7 @@ import { REACT013, REACT014, REACT15 } from '../src/version'; describe('shallow', () => { describe('context', () => { it('can pass in context', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -26,7 +27,7 @@ describe('shallow', () => { }); it('should not throw if context is passed in but contextTypes is missing', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ render() { return
{this.context.name}
; }, @@ -37,7 +38,7 @@ describe('shallow', () => { }); it('is instrospectable through context API', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -952,7 +953,7 @@ describe('shallow', () => { }); describe('.setContext(newContext)', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -1272,7 +1273,7 @@ describe('shallow', () => { const emptyRenderValues = generateEmptyRenderData(); itWithData(emptyRenderValues, 'when a React class component returns: ', (data) => { - const Foo = React.createClass({ + const Foo = createClass({ render() { return data.value; }, @@ -3907,15 +3908,15 @@ describe('shallow', () => { }); }); - describe('React.createClass', () => { + describe('createClass', () => { it('should return the name of the node', () => { - const Foo = React.createClass({ + const Foo = createClass({ displayName: 'CustomWrapper', render() { return
; }, }); - const Wrapper = React.createClass({ + const Wrapper = createClass({ render() { return ; }, @@ -3953,14 +3954,14 @@ describe('shallow', () => { }); }); - describe('React.createClass', () => { + describe('createClass', () => { it('should return the name of the node', () => { - const Foo = React.createClass({ + const Foo = createClass({ render() { return
; }, }); - const Wrapper = React.createClass({ + const Wrapper = createClass({ render() { return ; }, diff --git a/test/staticRender-spec.jsx b/test/staticRender-spec.jsx index 4fa4f4a64..4ebe74c4f 100644 --- a/test/staticRender-spec.jsx +++ b/test/staticRender-spec.jsx @@ -4,11 +4,12 @@ import { expect } from 'chai'; import { describeWithDOM, describeIf } from './_helpers'; import { render } from '../src/'; import { REACT013 } from '../src/version'; +import { createClass } from '../src/react-compat'; describeWithDOM('render', () => { describeIf(!REACT013, 'context', () => { it('can pass in context', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -22,7 +23,7 @@ describeWithDOM('render', () => { expect(wrapper.text()).to.equal('foo'); }); it('can pass context to the child of mounted component', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ contextTypes: { name: PropTypes.string, }, @@ -30,7 +31,7 @@ describeWithDOM('render', () => { return
{this.context.name}
; }, }); - const ComplexComponent = React.createClass({ + const ComplexComponent = createClass({ render() { return
; }, @@ -45,7 +46,7 @@ describeWithDOM('render', () => { expect(wrapper.children().first().text()).to.equal('foo'); }); it('should not throw if context is passed in but contextTypes is missing', () => { - const SimpleComponent = React.createClass({ + const SimpleComponent = createClass({ render() { return
{this.context.name}
; }, From 252040d56bfd4995be8b000a3c9d1989cfdead73 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Sun, 9 Apr 2017 08:40:21 +0200 Subject: [PATCH 06/21] test both react 15.4 and react 15 --- .travis.yml | 2 ++ install-relevant-react.sh | 4 ++++ package.json | 7 ++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 87cc3f0cd..c3eaa0f44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,8 @@ matrix: env: KARMA=true REACT=0.13 - node_js: "6" env: KARMA=true REACT=0.14 + - node_js: "6" + env: KARMA=true REACT=15.4 - node_js: "6" env: KARMA=true REACT=15 allow_failures: diff --git a/install-relevant-react.sh b/install-relevant-react.sh index 6619dda6b..6303d0ffe 100644 --- a/install-relevant-react.sh +++ b/install-relevant-react.sh @@ -12,6 +12,10 @@ if [ "$REACT" = "0.14" ]; then npm run react:14 fi +if [ "$REACT" = "15.4" ]; then + npm run react:15.4 +fi + if [ "$REACT" = "15" ]; then npm run react:15 fi diff --git a/package.json b/package.json index 7f77372fc..37fcca523 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,12 @@ "test:watch": "mocha --recursive --watch test", "test:karma": "karma start", "test:env": "sh ./example-test.sh", - "test:all": "npm run react:13 && npm run test:only && npm run react:14 && npm run test:only && npm run react:15 && npm run test:only", - "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils", + "test:all": "npm run react:13 && npm run test:only && npm run react:14 && npm run test:only && npm run react:15.4 && npm run test:only && npm run react:15 && npm run test:only", + "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils node_modules/create-react-class node_modules/react-test-renderer", "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", - "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 react-addons-test-utils@15 create-react-class@15 react-test-renderer@15 && npm install", + "react:15.4": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15.4 react-dom@15.4 react-addons-test-utils@15.4 && npm install", + "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 create-react-class@15 react-test-renderer@15 && npm install", "docs:clean": "rimraf _book", "docs:prepare": "gitbook install", "docs:build": "npm run docs:prepare && gitbook build", From b7522b0daf1fa6a475eaf8275f881f202ef0d0b7 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Sun, 9 Apr 2017 08:43:55 +0200 Subject: [PATCH 07/21] add missing env entry --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c3eaa0f44..356457cad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,4 +45,5 @@ matrix: env: - REACT=0.13 - REACT=0.14 + - REACT=15.4 - REACT=15 From 5db207f56d2bf3127a4e8702bcccd4470a688e3e Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 8 Apr 2017 23:13:43 -0700 Subject: [PATCH 08/21] `react-test-renderer` needs to be v15.5.4 or later. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 37fcca523..0d72a75fb 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,13 @@ "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", "react:15.4": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15.4 react-dom@15.4 react-addons-test-utils@15.4 && npm install", - "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 create-react-class@15 react-test-renderer@15 && npm install", + "react:15": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15 react-dom@15 create-react-class@15 react-test-renderer@^15.5.4 && npm install", "docs:clean": "rimraf _book", "docs:prepare": "gitbook install", "docs:build": "npm run docs:prepare && gitbook build", "docs:watch": "npm run docs:prepare && gitbook serve", "docs:publish": "npm run docs:clean && npm run docs:build && cd _book && git init && git commit --allow-empty -m 'update book' && git fetch git@github.com:airbnb/enzyme.git gh-pages && git checkout -b gh-pages && git add . && git commit -am 'update book' && git push git@github.com:airbnb/enzyme.git gh-pages --force", - "travis": "babel-node ./node_modules/.bin/istanbul cover --report html _mocha -- test --recursive" + "travis": "babel-node \"$(which istanbul)\" cover --report html _mocha -- test --recursive" }, "repository": { "type": "git", From b0e2fac8c9a8140182d48c03c168bbcdaac02f8d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Sun, 9 Apr 2017 12:14:46 +0100 Subject: [PATCH 09/21] Extract batchedUpdates to a function --- src/ShallowWrapper.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index 534430a1d..c96e3d325 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -98,6 +98,17 @@ function validateOptions(options) { } } + +function performBatchedUpdates(wrapper, fn) { + const renderer = wrapper.root.renderer; + if (renderer.unstable_batchedUpdates) { + // React 15.5+ exposes batching on shallow renderer itself + return renderer.unstable_batchedUpdates(fn); + } + // React <15.5: Fallback to ReactDOM + return batchedUpdates(fn); +} + /** * @class ShallowWrapper */ @@ -110,7 +121,7 @@ class ShallowWrapper { this.unrendered = nodes; this.renderer = createShallowRenderer(); withSetStateAllowed(() => { - this.batchedUpdates(() => { + performBatchedUpdates(this, () => { this.renderer.render(nodes, options.context); const instance = this.instance(); if ( @@ -143,13 +154,7 @@ class ShallowWrapper { } batchedUpdates(fn) { - const renderer = this.root.renderer; - if (renderer.unstable_batchedUpdates) { - // React 15.5+ exposes batching on shallow renderer itself - return renderer.unstable_batchedUpdates(fn); - } - // React <15.5: Fallback to ReactDOM - return batchedUpdates(fn); + } /** @@ -233,7 +238,7 @@ class ShallowWrapper { const prevContext = instance.context; const nextProps = props || prevProps; const nextContext = context || prevContext; - this.batchedUpdates(() => { + performBatchedUpdates(this, () => { let shouldRender = true; // dirty hack: // make sure that componentWillReceiveProps is called before shouldComponentUpdate @@ -621,7 +626,7 @@ class ShallowWrapper { withSetStateAllowed(() => { // TODO(lmr): create/use synthetic events // TODO(lmr): emulate React's event propagation - this.batchedUpdates(() => { + performBatchedUpdates(this, () => { handler(...args); }); this.root.update(); From edeb99c21cbcbc86e70a4d627192dc975d955544 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 10 Apr 2017 09:00:37 +0200 Subject: [PATCH 10/21] Remove dependency on create-react-class - remove createClass export from src/react-compat - add test/react-compat with createClass export - change spec files to import createClass from test/react-compat - undo changes to src/ReactWrapperComponent.jsx (use of createClass there removed in #877 - update README with correct dependencies for react@15.5 --- README.md | 2 +- src/ReactWrapperComponent.jsx | 4 +--- src/react-compat.js | 9 --------- test/ReactWrapper-spec.jsx | 3 ++- test/ShallowWrapper-spec.jsx | 2 +- test/react-compat.js | 14 ++++++++++++++ test/staticRender-spec.jsx | 2 +- 7 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 test/react-compat.js diff --git a/README.md b/README.md index c333aee36..135392a77 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ If you are using `React >=15.5`, in addition to `enzyme`, you will have to ensur the following npm modules installed if they were not already: ```bash -npm i --save-dev react-dom create-react-class +npm i --save-dev react-test-renderer react-dom ``` diff --git a/src/ReactWrapperComponent.jsx b/src/ReactWrapperComponent.jsx index 4cbeb00b9..4bba0d081 100644 --- a/src/ReactWrapperComponent.jsx +++ b/src/ReactWrapperComponent.jsx @@ -1,7 +1,5 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { PropTypes } from 'react'; import objectAssign from 'object.assign'; -import { createClass } from './react-compat'; /* eslint react/forbid-prop-types: 0 */ diff --git a/src/react-compat.js b/src/react-compat.js index 6ca2e7c57..88820512c 100644 --- a/src/react-compat.js +++ b/src/react-compat.js @@ -18,7 +18,6 @@ let childrenToArray; let renderWithOptions; let unmountComponentAtNode; let batchedUpdates; -let createClass; let shallowRendererFactory; const React = require('react'); @@ -177,13 +176,6 @@ if (REACT013) { }; } -if (REACT155) { - // eslint-disable-next-line import/no-extraneous-dependencies - createClass = require('create-react-class'); -} else { - createClass = React.createClass; -} - function isDOMComponentElement(inst) { return React.isValidElement(inst) && typeof inst.type === 'string'; } @@ -219,5 +211,4 @@ export { renderWithOptions, unmountComponentAtNode, batchedUpdates, - createClass, }; diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 53bdecb4d..9af9b89ed 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -4,7 +4,8 @@ import React from 'react'; import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; -import { batchedUpdates, createClass } from '../src/react-compat'; +import { batchedUpdates } from '../src/react-compat'; +import { createClass } from './react-compat' import { describeWithDOM, diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index f474ad1c2..4736bb483 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; -import { createClass } from '../src/react-compat'; +import { createClass } from './react-compat'; import { shallow, render, ShallowWrapper } from '../src/'; import { describeIf, itIf, itWithData, generateEmptyRenderData } from './_helpers'; import { ITERATOR_SYMBOL, withSetStateAllowed } from '../src/Utils'; diff --git a/test/react-compat.js b/test/react-compat.js new file mode 100644 index 000000000..7ae2fde21 --- /dev/null +++ b/test/react-compat.js @@ -0,0 +1,14 @@ +import { REACT155 } from './version'; + +let createClass; + +if (REACT155) { + // eslint-disable-next-line import/no-extraneous-dependencies + createClass = require('create-react-class'); +} else { + createClass = require('react').createClass; +} + +export { + createClass, +}; diff --git a/test/staticRender-spec.jsx b/test/staticRender-spec.jsx index 4ebe74c4f..05b895f2e 100644 --- a/test/staticRender-spec.jsx +++ b/test/staticRender-spec.jsx @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { describeWithDOM, describeIf } from './_helpers'; import { render } from '../src/'; import { REACT013 } from '../src/version'; -import { createClass } from '../src/react-compat'; +import { createClass } from './react-compat' describeWithDOM('render', () => { describeIf(!REACT013, 'context', () => { From d6baddafe5c80f444cc65749ca13eb43961526d9 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 10 Apr 2017 09:31:41 +0200 Subject: [PATCH 11/21] Fix import --- test/react-compat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/react-compat.js b/test/react-compat.js index 7ae2fde21..951a0ad72 100644 --- a/test/react-compat.js +++ b/test/react-compat.js @@ -1,4 +1,4 @@ -import { REACT155 } from './version'; +import { REACT155 } from '../src/version'; let createClass; From 270ee7fd83b819e9ed6ba2908dcf1103b68ad14e Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 10 Apr 2017 09:45:09 +0200 Subject: [PATCH 12/21] Remove unnecessary tests see PR #878 for explanation --- test/ReactWrapper-spec.jsx | 13 ------------- test/ShallowWrapper-spec.jsx | 18 ------------------ 2 files changed, 31 deletions(-) diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 9af9b89ed..65478e20a 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -3304,19 +3304,6 @@ describeWithDOM('mount', () => { expect(wrapper.name()).to.equal('SFC'); }); }); - - describe('createClass', () => { - it('should return the name of the node', () => { - const Foo = createClass({ - render() { - return
; - }, - }); - - const wrapper = mount(); - expect(wrapper.name()).to.equal('Foo'); - }); - }); }); describe('DOM node', () => { diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index 4736bb483..e12227343 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -3953,24 +3953,6 @@ describe('shallow', () => { expect(wrapper.name()).to.equal('SFC'); }); }); - - describe('createClass', () => { - it('should return the name of the node', () => { - const Foo = createClass({ - render() { - return
; - }, - }); - const Wrapper = createClass({ - render() { - return ; - }, - }); - - const wrapper = shallow(); - expect(wrapper.name()).to.equal('Foo'); - }); - }); }); describe('DOM node', () => { From ec7bbc5690073a1fdc373a3041ca5a05efaa46fd Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 10 Apr 2017 10:24:02 +0200 Subject: [PATCH 13/21] Lint --- src/ShallowWrapper.js | 4 ---- test/ReactWrapper-spec.jsx | 2 +- test/react-compat.js | 6 ++++++ test/staticRender-spec.jsx | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index c96e3d325..2d4af03c6 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -153,10 +153,6 @@ class ShallowWrapper { this.complexSelector = new ComplexSelector(buildPredicate, findWhereUnwrapped, childrenOfNode); } - batchedUpdates(fn) { - - } - /** * Returns the wrapped ReactElement. * diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 65478e20a..27457c750 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; import { batchedUpdates } from '../src/react-compat'; -import { createClass } from './react-compat' +import { createClass } from './react-compat'; import { describeWithDOM, diff --git a/test/react-compat.js b/test/react-compat.js index 951a0ad72..6d1bb2a47 100644 --- a/test/react-compat.js +++ b/test/react-compat.js @@ -1,3 +1,9 @@ +/* eslint + global-require: 0, + import/no-mutable-exports: 0, + import/prefer-default-export: 0, +*/ + import { REACT155 } from '../src/version'; let createClass; diff --git a/test/staticRender-spec.jsx b/test/staticRender-spec.jsx index 05b895f2e..54ce78fb2 100644 --- a/test/staticRender-spec.jsx +++ b/test/staticRender-spec.jsx @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { describeWithDOM, describeIf } from './_helpers'; import { render } from '../src/'; import { REACT013 } from '../src/version'; -import { createClass } from './react-compat' +import { createClass } from './react-compat'; describeWithDOM('render', () => { describeIf(!REACT013, 'context', () => { From 3ff9832b33c21f9b166890d6945406f96001ca59 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 10 Apr 2017 10:44:10 +0200 Subject: [PATCH 14/21] Update karma cofig to be compatible with react@15.5 --- karma.conf.js | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index 8bbdc4da0..30ac506e5 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -4,6 +4,36 @@ require('babel-register'); var IgnorePlugin = require('webpack').IgnorePlugin; var REACT013 = require('./src/version').REACT013; +var REACT155 = require('./src/version').REACT155; + +function getPlugins() { + var plugins = []; + + /* + this list of conditional IgnorePlugins mirrors the conditional + requires in src/react-compat.js and exists to avoid error + output from the webpack compilation + */ + + if (!REACT013) { + plugins.push(new IgnorePlugin(/react\/lib\/ExecutionEnvironment/)); + plugins.push(new IgnorePlugin(/react\/lib\/ReactContext/)); + plugins.push(new IgnorePlugin(/react\/addons/)); + } + if (REACT013) { + plugins.push(new IgnorePlugin(/react-dom/)); + } + if (REACT013 || REACT155) { + plugins.push(new IgnorePlugin(/react-addons-test-utils/)); + } + if (!REACT155) { + plugins.push(new IgnorePlugin(/react-test-renderer/)); + plugins.push(new IgnorePlugin(/react-dom\/test-utils/)); + plugins.push(new IgnorePlugin(/create-react-class/)); + } + + return plugins +} module.exports = function karma(config) { config.set({ @@ -29,11 +59,7 @@ module.exports = function karma(config) { reporters: ['dots'], files: [ - 'test/*.{jsx,js}', - ], - - exclude: [ - 'test/_*.{jsx,js}', + 'test/*-spec.{jsx,js}', ], browsers: [ @@ -71,18 +97,7 @@ module.exports = function karma(config) { }, ], }, - plugins: [ - /* - this list of conditional IgnorePlugins mirrors the conditional - requires in src/react-compat.js and exists to avoid error - output from the webpack compilation - */ - !REACT013 && new IgnorePlugin(/react\/lib\/ExecutionEnvironment/), - !REACT013 && new IgnorePlugin(/react\/lib\/ReactContext/), - !REACT013 && new IgnorePlugin(/react\/addons/), - REACT013 && new IgnorePlugin(/react-dom/), - REACT013 && new IgnorePlugin(/react-addons-test-utils/), - ].filter(function filterPlugins(plugin) { return plugin !== false; }), + plugins: getPlugins(), }, webpackServer: { From f5f6001ca0eb7b13ccbaee3a8ae4bf4889648b57 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 12 Apr 2017 01:07:36 +0200 Subject: [PATCH 15/21] Update ReactWrapperComponent to use prop-types package --- src/ReactWrapperComponent.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ReactWrapperComponent.jsx b/src/ReactWrapperComponent.jsx index 4bba0d081..19a187d52 100644 --- a/src/ReactWrapperComponent.jsx +++ b/src/ReactWrapperComponent.jsx @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import objectAssign from 'object.assign'; /* eslint react/forbid-prop-types: 0 */ From 2f957afe00417794026a82266d1777d8ad1fe7b9 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 12 Apr 2017 01:20:41 +0200 Subject: [PATCH 16/21] REACT155 constant is now true for react 15.5 or above --- src/version.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/version.js b/src/version.js index 3b889e2d6..3a691d7ce 100644 --- a/src/version.js +++ b/src/version.js @@ -1,7 +1,10 @@ import React from 'react'; export const VERSION = React.version; + +const [major, minor] = VERSION.split('.'); + export const REACT013 = VERSION.slice(0, 4) === '0.13'; export const REACT014 = VERSION.slice(0, 4) === '0.14'; -export const REACT15 = VERSION.slice(0, 3) === '15.'; -export const REACT155 = VERSION.slice(0, 4) === '15.5'; +export const REACT15 = major === '15'; +export const REACT155 = REACT15 && +minor >= 5; From b48e551900bd7239568f3d65820ab069a5c26bda Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 12 Apr 2017 01:23:44 +0200 Subject: [PATCH 17/21] Change condition in `performBatchedUpdates` to a version check --- src/ShallowWrapper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index 2d4af03c6..9d7b74ba9 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -37,6 +37,7 @@ import { batchedUpdates, isDOMComponentElement, } from './react-compat'; +import { REACT155 } from './version'; /** * Finds all nodes in the current wrapper nodes' render trees that match the provided predicate @@ -101,7 +102,7 @@ function validateOptions(options) { function performBatchedUpdates(wrapper, fn) { const renderer = wrapper.root.renderer; - if (renderer.unstable_batchedUpdates) { + if (REACT155) { // React 15.5+ exposes batching on shallow renderer itself return renderer.unstable_batchedUpdates(fn); } From cc78489bc1a72050ffa768ab2f59883b1ded140d Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 12 Apr 2017 01:32:00 +0200 Subject: [PATCH 18/21] Update error message in react-compat --- src/react-compat.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/react-compat.js b/src/react-compat.js index 88820512c..204deab53 100644 --- a/src/react-compat.js +++ b/src/react-compat.js @@ -104,12 +104,19 @@ if (REACT013) { TestUtils = require('react-addons-test-utils'); } } catch (e) { - // eslint-disable-next-line no-console - console.error( - 'react-addons-test-utils is an implicit dependency in order to support react@0.13-14. ' + - 'Please add the appropriate version to your devDependencies. ' + - 'See https://github.com/airbnb/enzyme#installation', - ); + if (REACT155) { + console.error( // eslint-disable-line no-console + 'react-dom@15.5+ is an implicit dependency when using react@15.5+ with enzyme. ' + + 'Please add the appropriate version to your devDependencies. ' + + 'See https://github.com/airbnb/enzyme#installation', + ); + } else { + console.error( // eslint-disable-line no-console + 'react-addons-test-utils is an implicit dependency in order to support react@0.13-14. ' + + 'Please add the appropriate version to your devDependencies. ' + + 'See https://github.com/airbnb/enzyme#installation', + ); + } throw e; } From 22f368f21934d41f98acf8b70d952571b531df96 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 11 Apr 2017 22:05:00 -0600 Subject: [PATCH 19/21] address final comments --- karma.conf.js | 8 ++++++-- src/version.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/karma.conf.js b/karma.conf.js index 30ac506e5..a4e83f693 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -32,7 +32,7 @@ function getPlugins() { plugins.push(new IgnorePlugin(/create-react-class/)); } - return plugins + return plugins; } module.exports = function karma(config) { @@ -59,7 +59,11 @@ module.exports = function karma(config) { reporters: ['dots'], files: [ - 'test/*-spec.{jsx,js}', + 'test/*.{jsx,js}', + ], + + exclude: [ + 'test/_*.{jsx,js}', ], browsers: [ diff --git a/src/version.js b/src/version.js index 3a691d7ce..d55f7f3df 100644 --- a/src/version.js +++ b/src/version.js @@ -7,4 +7,4 @@ const [major, minor] = VERSION.split('.'); export const REACT013 = VERSION.slice(0, 4) === '0.13'; export const REACT014 = VERSION.slice(0, 4) === '0.14'; export const REACT15 = major === '15'; -export const REACT155 = REACT15 && +minor >= 5; +export const REACT155 = REACT15 && minor >= 5; From 4464a17d40c674a0284d42782037147b1f4416f7 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 11 Apr 2017 22:04:19 -0700 Subject: [PATCH 20/21] [Tests] move helpers in to `test/_helpers` dir --- karma.conf.js | 2 +- test/ReactWrapper-spec.jsx | 2 +- test/ShallowWrapper-spec.jsx | 2 +- test/{_helpers.jsx => _helpers/index.jsx} | 0 test/{ => _helpers}/react-compat.js | 2 +- test/staticRender-spec.jsx | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename test/{_helpers.jsx => _helpers/index.jsx} (100%) rename test/{ => _helpers}/react-compat.js (87%) diff --git a/karma.conf.js b/karma.conf.js index a4e83f693..c2387224b 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -63,7 +63,7 @@ module.exports = function karma(config) { ], exclude: [ - 'test/_*.{jsx,js}', + 'test/_helpers/index.jsx', ], browsers: [ diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 27457c750..0233beff7 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; import { batchedUpdates } from '../src/react-compat'; -import { createClass } from './react-compat'; +import { createClass } from './_helpers/react-compat'; import { describeWithDOM, diff --git a/test/ShallowWrapper-spec.jsx b/test/ShallowWrapper-spec.jsx index e12227343..e084718bb 100644 --- a/test/ShallowWrapper-spec.jsx +++ b/test/ShallowWrapper-spec.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { expect } from 'chai'; import sinon from 'sinon'; -import { createClass } from './react-compat'; +import { createClass } from './_helpers/react-compat'; import { shallow, render, ShallowWrapper } from '../src/'; import { describeIf, itIf, itWithData, generateEmptyRenderData } from './_helpers'; import { ITERATOR_SYMBOL, withSetStateAllowed } from '../src/Utils'; diff --git a/test/_helpers.jsx b/test/_helpers/index.jsx similarity index 100% rename from test/_helpers.jsx rename to test/_helpers/index.jsx diff --git a/test/react-compat.js b/test/_helpers/react-compat.js similarity index 87% rename from test/react-compat.js rename to test/_helpers/react-compat.js index 6d1bb2a47..261ba2a8d 100644 --- a/test/react-compat.js +++ b/test/_helpers/react-compat.js @@ -4,7 +4,7 @@ import/prefer-default-export: 0, */ -import { REACT155 } from '../src/version'; +import { REACT155 } from '../../src/version'; let createClass; diff --git a/test/staticRender-spec.jsx b/test/staticRender-spec.jsx index 54ce78fb2..85566a6f5 100644 --- a/test/staticRender-spec.jsx +++ b/test/staticRender-spec.jsx @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { describeWithDOM, describeIf } from './_helpers'; import { render } from '../src/'; import { REACT013 } from '../src/version'; -import { createClass } from './react-compat'; +import { createClass } from './_helpers/react-compat'; describeWithDOM('render', () => { describeIf(!REACT013, 'context', () => { From 21f6e7a8f43db309146399a2bc9fd8bd509e6336 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 11 Apr 2017 22:07:18 -0700 Subject: [PATCH 21/21] [Tests] `create-react-class` should be a static dev dependency. --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d72a75fb..04bb62646 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:karma": "karma start", "test:env": "sh ./example-test.sh", "test:all": "npm run react:13 && npm run test:only && npm run react:14 && npm run test:only && npm run react:15.4 && npm run test:only && npm run react:15 && npm run test:only", - "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils node_modules/create-react-class node_modules/react-test-renderer", + "react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils node_modules/react-test-renderer", "react:13": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.13 && npm install", "react:14": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14 && npm install", "react:15.4": "rimraf node_modules/.bin/npm && npm run react:clean && npm i react@15.4 react-dom@15.4 react-addons-test-utils@15.4 && npm install", @@ -73,6 +73,7 @@ "babel-register": "^6.24.1", "chai": "^3.5.0", "coveralls": "^2.13.0", + "create-react-class": "^15.5.2", "enzyme-example-jest": "^0.1.0", "enzyme-example-karma": "^0.1.1", "enzyme-example-karma-webpack": "^0.1.4",