diff --git a/src/Utils.js b/src/Utils.js index 001c37ad6..04ab9bd24 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -80,11 +80,11 @@ export function nodeEqual(a, b) { const right = propsOfNode(b); for (let i = 0; i < leftKeys.length; i++) { const prop = leftKeys[i]; - if (!(prop in right)) return false; + // we will check children later if (prop === 'children') { - if (!childrenEqual(childrenToArray(left.children), childrenToArray(right.children))) { - return false; - } + // continue; + } else if (!(prop in right)) { + return false; } else if (right[prop] === left[prop]) { // continue; } else if (typeof right[prop] === typeof left[prop] && typeof left[prop] === 'object') { @@ -94,8 +94,17 @@ export function nodeEqual(a, b) { } } + const leftHasChildren = 'children' in left; + const rightHasChildren = 'children' in right; + if (leftHasChildren || rightHasChildren) { + if (!childrenEqual(childrenToArray(left.children), childrenToArray(right.children))) { + return false; + } + } + if (typeof a !== 'string' && typeof a !== 'number') { - return leftKeys.length === Object.keys(right).length; + const rightKeys = Object.keys(right); + return leftKeys.length - leftHasChildren === rightKeys.length - rightHasChildren; } return false; diff --git a/test/Utils-spec.js b/test/Utils-spec.js index c4b8c95e3..9ca1dfcf4 100644 --- a/test/Utils-spec.js +++ b/test/Utils-spec.js @@ -123,6 +123,103 @@ describe('Utils', () => { }); + describe('children props', () => { + it('should match equal nodes', () => { + expect(nodeEqual( +
child
, +
child
+ )).to.equal(true); + }); + + it('should not match not equal nodes', () => { + expect(nodeEqual( +
child
, +
+ )).to.equal(false); + + expect(nodeEqual( +
, +
child
+ )).to.equal(false); + }); + + it('should skip null children', () => { + expect(nodeEqual( +
{null}
, +
+ )).to.equal(true); + }); + + it('should skip undefined children', () => { + expect(nodeEqual( +
{undefined}
, +
+ )).to.equal(true); + }); + + it('should skip empty children', () => { + expect(nodeEqual( +
{[]}
, +
+ )).to.equal(true); + }); + + it('should skip array of null children', () => { + expect(nodeEqual( +
{[null, null, null]}
, +
+ )).to.equal(true); + }); + + }); + + describe('basic props and children mixed', () => { + + it('should match equal nodes', () => { + expect(nodeEqual( +
child
, +
child
+ )).to.equal(true); + }); + + it('should not match when basic props are not equal', () => { + expect(nodeEqual( +
child
, +
child
+ )).to.equal(false); + + expect(nodeEqual( +
, +
+ )).to.equal(false); + }); + + it('should not match when children are not equal', () => { + expect(nodeEqual( +
child
, +
other child
+ )).to.equal(false); + + expect(nodeEqual( +
, +
+ )).to.equal(false); + }); + + it('should match nodes when children are different but falsy', () => { + expect(nodeEqual( +
{null}
, +
+ )).to.equal(true); + + expect(nodeEqual( +
, +
+ )).to.equal(true); + }); + + }); + }); describe('propFromEvent', () => {