Skip to content

Commit

Permalink
Merge pull request #240 from iancmyers/icm/react-15-compat
Browse files Browse the repository at this point in the history
Add compatibility for React 15 RC1
  • Loading branch information
lelandrichardson committed Mar 9, 2016
2 parents 89e7744 + d991353 commit 3ed3632
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 25 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ after_script:
env:
- REACT=0.13
- REACT=0.14
- REACT=15
- EXAMPLE=mocha
- EXAMPLE=karma
- EXAMPLE=react-native
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ To get started with enzyme, you can simply install it with npm:
npm i --save-dev enzyme
```

Enzyme is currently compatible with both `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`.
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`, in addition to `enzyme`, you will have to ensure that you also
have the following npm modules installed if they were not already:
If you are using React 0.14` or `React 15.x`, 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-addons-test-utils
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* [Installation](/docs/installation/README.md)
* [Working with React 0.13.x](/docs/installation/react-013.md)
* [Working with React 0.14.x](/docs/installation/react-014.md)
* [Working with React 15.x](/docs/installation/react-15.md)
* [API Reference](/docs/api/README.md)
* [Shallow Rendering](/docs/api/shallow.md)
* [at(index)](/docs/api/ShallowWrapper/at.md)
Expand Down
4 changes: 3 additions & 1 deletion docs/installation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ npm i --save-dev enzyme
```

Enzyme can be used with your test runner of choice. All examples in the documentation will be
provided using [mocha](https://mochajs.org/) and [BDD style chai](http://chaijs.com/api/bdd/),
provided using [mocha](https://mochajs.org/) and [BDD style chai](http://chaijs.com/api/bdd/),
although neither library is a dependency of enzyme.

{% include "./react-013.md" %}

{% include "./react-014.md" %}

{% include "./react-15.md" %}
34 changes: 34 additions & 0 deletions docs/installation/react-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Working with React 15

If you are wanting to use Enzyme with React 0.14, but don't already have React 15 and react-dom
installed, you should do so:

```bash
npm i --save [email protected] [email protected]
```

Further, enzyme requires the test utilities addon be installed:

```bash
npm i --save-dev [email protected]
```

Next, to get started with enzyme, you can simply install it with npm:

```bash
npm i --save-dev enzyme
```

And then you're ready to go! In your test files you can simply `require` or `import` enzyme:

ES6:
```js
import { shallow, mount, render } from 'enzyme';
const wrapper = shallow(<Foo />);
```

ES5:
```js
var enzyme = require('enzyme');
var wrapper = enzyme.shallow(<Foo />);
```
4 changes: 4 additions & 0 deletions install-relevant-react.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ fi
if [ "$REACT" = "0.14" ]; then
npm run react:14
fi

if [ "$REACT" = "15" ]; then
npm run react:15
fi
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
"check": "npm run lint && npm run test:all",
"build": "babel src --out-dir build",
"test": "npm run lint && npm run test:only",
"test:only": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js",
"test:single": "mocha --require withDom.js --compilers js:babel-core/register --watch",
"test:watch": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js --watch",
"test:only": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js --reporter dot",
"test:single": "mocha --require withDom.js --compilers js:babel-core/register --watch --reporter dot",
"test:watch": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js --watch --reporter dot",
"test:env": "sh ./example-test.sh",
"test:all": "npm run react:13 && npm test && npm run react:14 && npm test",
"test:all": "npm run react:13 && npm test && npm run react:14 && npm test && npm run react:15 && npm test",
"react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils",
"react:13": "npm run react:clean && npm i [email protected]",
"react:14": "npm run react:clean && npm i [email protected] [email protected] [email protected]",
"react:15": "npm run react:clean && npm i [email protected] [email protected] [email protected]",
"docs:clean": "rimraf _book",
"docs:prepare": "gitbook install",
"docs:build": "npm run docs:prepare && gitbook build",
Expand Down Expand Up @@ -79,6 +80,6 @@
"sinon": "^1.15.4"
},
"peerDependencies": {
"react": "0.13.x || 0.14.x"
"react": "0.13.x || 0.14.x || 15.* || 15.0.0-rc.1"
}
}
7 changes: 3 additions & 4 deletions src/Debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
childrenOfNode,
} from './ShallowTraversal';
import {
internalInstance,
renderedChildrenOfInst,
} from './MountedTraversal';
import {
Expand All @@ -11,12 +10,13 @@ import {
isElement,
} from './react-compat';
import {
internalInstance,
propsOfNode,
} from './Utils';
import without from 'lodash/without';
import escape from 'lodash/escape';
import compact from 'lodash/compact';
import { REACT013, REACT014 } from './version';
import { REACT013 } from './version';
import objectValues from 'object.values';

export function typeName(node) {
Expand Down Expand Up @@ -85,7 +85,6 @@ export function debugInst(inst, indentLength = 2) {
const internal = internalInstance(inst);
return debugInst(internal, indentLength);
}

const publicInst = inst.getPublicInstance();

if (typeof publicInst === 'string' || typeof publicInst === 'number') return escape(publicInst);
Expand All @@ -104,7 +103,7 @@ export function debugInst(inst, indentLength = 2) {
children.push(...objectValues(renderedChildren));
}
} else if (
REACT014 &&
!REACT013 &&
isElement(currentElement) &&
typeof currentElement.type === 'function'
) {
Expand Down
19 changes: 12 additions & 7 deletions src/MountedTraversal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import isEmpty from 'lodash/isEmpty';
import isSubset from 'is-subset';
import {
internalInstance,
coercePropValue,
nodeEqual,
propsOfNode,
Expand All @@ -20,11 +21,7 @@ import {
isElement,
findDOMNode,
} from './react-compat';
import { REACT013, REACT014 } from './version';

export function internalInstance(inst) {
return inst._reactInternalInstance;
}
import { REACT013 } from './version';

export function getNode(inst) {
if (!inst || inst._store || typeof inst === 'string') {
Expand All @@ -36,6 +33,9 @@ export function getNode(inst) {
if (internalInstance(inst)) {
return internalInstance(inst)._currentElement;
}
if (inst._reactInternalInstance) {
return inst._reactInternalInstance._currentElement;
}
if (inst._reactInternalComponent) {
return inst._reactInternalComponent._currentElement;
}
Expand Down Expand Up @@ -75,6 +75,10 @@ export function instHasProperty(inst, propKey, stringifiedPropValue) {
if (!isDOMComponent(inst)) return false;
const node = getNode(inst);
const nodeProps = propsOfNode(node);
const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey);
if (descriptor && descriptor.get) {
return false;
}
const nodePropValue = nodeProps[propKey];

const propValue = coercePropValue(propKey, stringifiedPropValue);
Expand Down Expand Up @@ -107,6 +111,7 @@ export function childrenOfInstInternal(inst) {
const internal = internalInstance(inst);
return childrenOfInstInternal(internal);
}

const publicInst = inst.getPublicInstance();
const currentElement = inst._currentElement;
if (isDOMComponent(publicInst)) {
Expand All @@ -124,7 +129,7 @@ export function childrenOfInstInternal(inst) {
}
return children;
} else if (
REACT014 &&
!REACT013 &&
isElement(currentElement) &&
typeof currentElement.type === 'function'
) {
Expand Down Expand Up @@ -259,7 +264,7 @@ function findAllInRenderedTreeInternal(inst, test) {
);
}
} else if (
REACT014 &&
!REACT013 &&
isElement(currentElement) &&
typeof currentElement.type === 'function'
) {
Expand Down
4 changes: 2 additions & 2 deletions src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ export default class ReactWrapper {
const predicate = Array.isArray(nodeOrNodes)
? other => containsChildrenSubArray(instEqual, other, nodeOrNodes)
: other => instEqual(nodeOrNodes, other);

return findWhereUnwrapped(this, predicate).length > 0;
}

Expand Down Expand Up @@ -343,7 +342,8 @@ export default class ReactWrapper {
html() {
return this.single(n => {
const node = findDOMNode(n);
return node === null ? null : node.outerHTML.replace(/\sdata-reactid+="[^"]+"/g, '');
return node === null ? null :
node.outerHTML.replace(/\sdata-(reactid|reactroot)+="([^"]*)+"/g, '');
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/ShallowTraversal.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export function nodeHasId(node, id) {
export function nodeHasProperty(node, propKey, stringifiedPropValue) {
const nodeProps = propsOfNode(node);
const propValue = coercePropValue(propKey, stringifiedPropValue);
const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey);
if (descriptor && descriptor.get) {
return false;
}
const nodePropValue = nodeProps[propKey];

if (nodePropValue === undefined) {
Expand Down
19 changes: 17 additions & 2 deletions src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,31 @@ import {
} from './react-compat';
import {
REACT013,
REACT014,
REACT15,
} from './version';

function internalInstanceKey(node) {
return Object.keys(Object(node)).filter(key => key.match(/^__reactInternalInstance\$/))[0];
}

export function internalInstance(inst) {
return inst._reactInternalInstance ||
inst[internalInstanceKey(inst)];
}

export function propsOfNode(node) {
if (REACT013 && node && node._store) {
return (node._store.props) || {};
}
if (node && node._reactInternalComponent && node._reactInternalComponent._currentElement) {
return (node._reactInternalComponent._currentElement.props) || {};
}
if (REACT15 && node) {
if (internalInstance(node) && internalInstance(node)._currentElement) {
return (internalInstance(node)._currentElement.props) || {};
}
}

return (node && node.props) || {};
}

Expand Down Expand Up @@ -232,7 +247,7 @@ export function mapNativeEventNames(event) {
volumechange: 'volumeChange',
};

if (REACT014) {
if (!REACT013) {
// these could not be simulated in React 0.13:
// https://github.com/facebook/react/issues/1297
nativeToReactEventMap.mouseenter = 'mouseEnter';
Expand Down
1 change: 1 addition & 0 deletions src/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ import React from 'react';
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.';

0 comments on commit 3ed3632

Please sign in to comment.