Skip to content

Commit efb3913

Browse files
authored
Merge pull request #662 from vadimdemedes/skip-null-or-undefined-props
[Breaking] Skip undefined props when comparing nodes
2 parents b355eed + 9bb8a91 commit efb3913

File tree

14 files changed

+82
-21
lines changed

14 files changed

+82
-21
lines changed

docs/api/ShallowWrapper/equals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ expect(wrapper.equals(<div className="foo bar" />)).to.equal(true);
3232
when you are calling it you are calling it with a ReactElement or a JSX expression.
3333
- Keep in mind that this method determines equality based on the equality of the node's children as
3434
well.
35-
35+
- Following React's behavior, `.equals()` ignores properties whose values are `undefined`.

docs/api/selector.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ a string can be used to find it:
8585
function MyComponent() {
8686
return <div />;
8787
}
88-
MyComponent.displayName = 'MyComponent!';
88+
MyComponent.displayName = 'My Component';
8989

9090
// find instances of MyComponent
91-
const myComponents = wrapper.find('MyComponent!');
91+
const myComponents = wrapper.find('My Component');
9292
```
9393

9494
NOTE: This will *only* work if the selector (and thus the component's `displayName`) is a string
@@ -113,3 +113,14 @@ wrapper.find({ foo: 3 });
113113
wrapper.find({ bar: false });
114114
wrapper.find({ title: 'baz' });
115115
```
116+
117+
**Note - undefined properties**
118+
are not allowed in the object property selector and will cause an error:
119+
120+
121+
```jsx
122+
wrapper.find({ foo: 3, bar: undefined });
123+
// => TypeError: Enzyme::Props can't have 'undefined' values. Try using 'findWhere()' instead.
124+
```
125+
126+
If you have to search by `undefined` property value, use [.findWhere()](ShallowWrapper/findWhere.md).

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,6 @@
104104
"sinon": "^2.4.1",
105105
"webpack": "^1.13.3"
106106
},
107-
"dependencies": {}
107+
"dependencies": {
108+
}
108109
}

packages/enzyme-adapter-react-13/src/ReactThirteenElementToTree.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default function elementToTree(el) {
2323
let rendered = null;
2424
if (Array.isArray(children)) {
2525
rendered = flatten(children, true).map(elementToTree);
26-
} else if (children !== undefined) {
26+
} else if (typeof children !== 'undefined') {
2727
rendered = elementToTree(children);
2828
}
2929
return {

packages/enzyme-adapter-utils/src/Utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function elementToTree(el) {
104104
let rendered = null;
105105
if (Array.isArray(children)) {
106106
rendered = flatten(children, true).map(elementToTree);
107-
} else if (children !== undefined) {
107+
} else if (typeof children !== 'undefined') {
108108
rendered = elementToTree(children);
109109
}
110110
return {

packages/enzyme-test-suite/test/ReactWrapper-spec.jsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,19 @@ describeWithDOM('mount', () => {
469469
expect(wrapper.find('[htmlFor]')).to.have.length(2);
470470
});
471471

472+
it('should error sensibly if any of the search props are undefined', () => {
473+
const wrapper = mount((
474+
<div>
475+
<input type={undefined} />
476+
</div>
477+
));
478+
479+
expect(() => wrapper.find({ type: undefined })).to.throw(
480+
TypeError,
481+
'Enzyme::Props can’t have `undefined` values. Try using ‘findWhere()’ instead.',
482+
);
483+
});
484+
472485
it('should compound tag and prop selector', () => {
473486
const wrapper = mount(
474487
<div>
@@ -655,7 +668,6 @@ describeWithDOM('mount', () => {
655668
expect(wrapper.find({ a: 1 })).to.have.length(0);
656669
expect(wrapper.find({ 'data-test': 'ref' })).to.have.length(7);
657670
expect(wrapper.find({ className: 'foo' })).to.have.length(1);
658-
expect(wrapper.find({ 'data-prop': undefined })).to.have.length(1);
659671
expect(wrapper.find({ 'data-prop': null })).to.have.length(1);
660672
expect(wrapper.find({ 'data-prop': 123 })).to.have.length(1);
661673
expect(wrapper.find({ 'data-prop': false })).to.have.length(1);

packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,19 @@ describe('shallow', () => {
603603
);
604604
});
605605

606+
it('should error sensibly if any of the search props are undefined', () => {
607+
const wrapper = shallow(
608+
<div>
609+
<input type={undefined} />
610+
</div>,
611+
);
612+
613+
expect(() => wrapper.find({ type: undefined })).to.throw(
614+
TypeError,
615+
'Enzyme::Props can’t have `undefined` values. Try using ‘findWhere()’ instead.',
616+
);
617+
});
618+
606619
it('should compound tag and prop selector', () => {
607620
const wrapper = shallow(
608621
<div>
@@ -695,7 +708,6 @@ describe('shallow', () => {
695708
expect(wrapper.find({ a: 1 })).to.have.length(0);
696709
expect(wrapper.find({ 'data-test': 'ref' })).to.have.length(7);
697710
expect(wrapper.find({ className: 'foo' })).to.have.length(1);
698-
expect(wrapper.find({ prop: undefined })).to.have.length(1);
699711
expect(wrapper.find({ prop: null })).to.have.length(1);
700712
expect(wrapper.find({ prop: 123 })).to.have.length(1);
701713
expect(wrapper.find({ prop: false })).to.have.length(1);

packages/enzyme-test-suite/test/Utils-spec.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ describe('Utils', () => {
4848
)).to.equal(false);
4949
});
5050

51+
it('should skip undefined props', () => {
52+
expect(nodeEqual(
53+
<div id="foo" className={undefined} />,
54+
<div id="foo" />,
55+
)).to.equal(true);
56+
});
57+
5158
it('should check children as well', () => {
5259
expect(nodeEqual(
5360
<div>

packages/enzyme/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"object-is": "^1.0.1",
3939
"object.assign": "^4.0.4",
4040
"object.entries": "^1.0.4",
41+
"object.values": "^1.0.4",
4142
"raf": "^3.3.2",
4243
"rst-selector-parser": "^2.2.1"
4344
},

packages/enzyme/src/RSTTraversal.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import flatten from 'lodash/flatten';
2+
import entries from 'object.entries';
23
import isSubset from 'is-subset';
34
import functionName from 'function.prototype.name';
45
import { nodeHasProperty } from './Utils';
@@ -39,11 +40,11 @@ export function treeFilter(tree, fn) {
3940
* To support sibling selectors we need to be able to find
4041
* the siblings of a node. The easiest way to do that is find
4142
* the parent of the node and access its children.
42-
*
43+
*
4344
* This would be unneeded if the RST spec included sibling pointers
4445
* such as node.nextSibling and node.prevSibling
45-
* @param {*} root
46-
* @param {*} targetNode
46+
* @param {*} root
47+
* @param {*} targetNode
4748
*/
4849
export function findParentNode(root, targetNode) {
4950
const results = treeFilter(
@@ -98,12 +99,21 @@ export function nodeHasId(node, id) {
9899

99100
export { nodeHasProperty };
100101

102+
const CAN_NEVER_MATCH = {};
103+
function replaceUndefined(v) {
104+
return typeof v !== 'undefined' ? v : CAN_NEVER_MATCH;
105+
}
106+
function replaceUndefinedValues(obj) {
107+
return entries(obj)
108+
.reduce((acc, [k, v]) => ({ ...acc, [k]: replaceUndefined(v) }), {});
109+
}
110+
101111
export function nodeMatchesObjectProps(node, props) {
102-
return isSubset(propsOfNode(node), props);
112+
return isSubset(propsOfNode(node), replaceUndefinedValues(props));
103113
}
104114

105115
export function getTextFromNode(node) {
106-
if (node === null || node === undefined) {
116+
if (node == null) {
107117
return '';
108118
}
109119

0 commit comments

Comments
 (0)