From 4f03d9ecc53b6c5d588faa353b05f2a6743a1459 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 2 Feb 2016 20:37:39 -0800 Subject: [PATCH 1/2] [Fix] `ShallowWrapper#type()`, `ReactWrapper#type()`, and `ReactWrapper#props()` should work with `null` nodes. Fixes #113. --- src/ReactWrapper.js | 8 +++-- src/ShallowWrapper.js | 2 +- src/__tests__/ReactWrapper-spec.js | 47 ++++++++++++++++++++++++++++ src/__tests__/ShallowWrapper-spec.js | 47 ++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/ReactWrapper.js b/src/ReactWrapper.js index 9843d8456..801861383 100644 --- a/src/ReactWrapper.js +++ b/src/ReactWrapper.js @@ -20,6 +20,7 @@ import { import { mapNativeEventNames, containsChildrenSubArray, + propsOfNode, } from './Utils'; import { debugInsts, @@ -381,7 +382,7 @@ export default class ReactWrapper { * @returns {Object} */ props() { - return this.single(n => getNode(n).props || {}); + return this.single(propsOfNode); } /** @@ -484,7 +485,10 @@ export default class ReactWrapper { * @returns {String|Function} */ type() { - return this.single(n => getNode(n).type); + return this.single((n) => { + const node = getNode(n); + return node ? node.type : null; + }); } /** diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index 9616db946..5abd57a53 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -464,7 +464,7 @@ export default class ShallowWrapper { * @returns {String|Function} */ type() { - return this.single(n => n.type); + return this.single(n => n ? n.type : null); } /** diff --git a/src/__tests__/ReactWrapper-spec.js b/src/__tests__/ReactWrapper-spec.js index e0d41e6a7..827bb4abc 100644 --- a/src/__tests__/ReactWrapper-spec.js +++ b/src/__tests__/ReactWrapper-spec.js @@ -397,6 +397,53 @@ describeWithDOM('mount', () => { expect(spy.args[3][0].hasClass('bux')).to.equal(true); }); + describeIf(!REACT013, 'stateless functional components', () => { + it('finds nodes', () => { + const SFC = function SFC({ selector }) { + return ( +
+ + +
+ ); + }; + + const selector = 'blah'; + const wrapper = mount(); + const foundSpan = wrapper.findWhere(n => ( + n.type() === 'span' && n.props()['data-foo'] === selector + )); + expect(foundSpan.type()).to.equal('span'); + + const foundNotSpan = wrapper.findWhere(n => ( + n.type() !== 'span' && n.props()['data-foo'] === selector + )); + expect(foundNotSpan.type()).to.equal('i'); + }); + + it('finds nodes when conditionally rendered', () => { + const SFC = function SFC({ selector }) { + return ( +
+ + {selector === 'baz' ? : null} +
+ ); + }; + + const selector = 'blah'; + const wrapper = mount(); + const foundSpan = wrapper.findWhere(n => ( + n.type() === 'span' && n.props()['data-foo'] === selector + )); + expect(foundSpan.type()).to.equal('span'); + + const foundNotSpan = wrapper.findWhere(n => ( + n.type() !== 'span' && n.props()['data-foo'] === selector + )); + expect(foundNotSpan).to.have.length(0); + }); + }); }); describe('.setProps(newProps)', () => { diff --git a/src/__tests__/ShallowWrapper-spec.js b/src/__tests__/ShallowWrapper-spec.js index 8b0a2bb08..f2b6bc959 100644 --- a/src/__tests__/ShallowWrapper-spec.js +++ b/src/__tests__/ShallowWrapper-spec.js @@ -484,6 +484,53 @@ describe('shallow', () => { expect(spy.args[3][0].hasClass('bux')).to.equal(true); }); + describeIf(!REACT013, 'stateless functional components', () => { + it('finds nodes', () => { + const SFC = function SFC({ selector }) { + return ( +
+ + +
+ ); + }; + + const selector = 'blah'; + const wrapper = shallow(); + const foundSpan = wrapper.findWhere(n => ( + n.type() === 'span' && n.props()['data-foo'] === selector + )); + expect(foundSpan.type()).to.equal('span'); + + const foundNotSpan = wrapper.findWhere(n => ( + n.type() !== 'span' && n.props()['data-foo'] === selector + )); + expect(foundNotSpan.type()).to.equal('i'); + }); + + it('finds nodes when conditionally rendered', () => { + const SFC = function SFC({ selector }) { + return ( +
+ + {selector === 'baz' ? : null} +
+ ); + }; + + const selector = 'blah'; + const wrapper = shallow(); + const foundSpan = wrapper.findWhere(n => ( + n.type() === 'span' && n.props()['data-foo'] === selector + )); + expect(foundSpan.type()).to.equal('span'); + + const foundNotSpan = wrapper.findWhere(n => ( + n.type() !== 'span' && n.props()['data-foo'] === selector + )); + expect(foundNotSpan).to.have.length(0); + }); + }); }); describe('.setProps(newProps)', () => { From 198db6c3bc67f513b14678c6e1735269d2841cbb Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 2 Feb 2016 21:44:56 -0800 Subject: [PATCH 2/2] Add `typeOfNode` Util. --- src/ReactWrapper.js | 6 ++---- src/ShallowWrapper.js | 3 ++- src/Utils.js | 4 ++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ReactWrapper.js b/src/ReactWrapper.js index 801861383..9bc1ca1d2 100644 --- a/src/ReactWrapper.js +++ b/src/ReactWrapper.js @@ -21,6 +21,7 @@ import { mapNativeEventNames, containsChildrenSubArray, propsOfNode, + typeOfNode, } from './Utils'; import { debugInsts, @@ -485,10 +486,7 @@ export default class ReactWrapper { * @returns {String|Function} */ type() { - return this.single((n) => { - const node = getNode(n); - return node ? node.type : null; - }); + return this.single(n => typeOfNode(getNode(n))); } /** diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js index 5abd57a53..c255fd6b0 100644 --- a/src/ShallowWrapper.js +++ b/src/ShallowWrapper.js @@ -7,6 +7,7 @@ import { propFromEvent, withSetStateAllowed, propsOfNode, + typeOfNode, } from './Utils'; import { debugNodes, @@ -464,7 +465,7 @@ export default class ShallowWrapper { * @returns {String|Function} */ type() { - return this.single(n => n ? n.type : null); + return this.single(typeOfNode); } /** diff --git a/src/Utils.js b/src/Utils.js index 7d123001e..28ed699c4 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -20,6 +20,10 @@ export function propsOfNode(node) { return (node && node.props) || {}; } +export function typeOfNode(node) { + return node ? node.type : null; +} + export function onPrototype(Component, lifecycle, method) { const proto = Component.prototype; Object.getOwnPropertyNames(proto).forEach((name) => {