diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index 5ba368da6..ea5e255c8 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -933,6 +933,18 @@ class ReactSixteenAdapter extends EnzymeAdapter { return isElement(element); } + shouldComponentUpdate(prevProps, root) { + const instance = root.instance(); + if (instance !== null) { + const { updater, props } = instance; + return ( + updater._renderer._newState !== null || !shallowEqual(prevProps, props) + ); + } + + return true; + } + isValidElementType(object) { return !!object && isValidElementType(object); } diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 9411f1d56..942f08684 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -2237,9 +2237,12 @@ describe('shallow', () => { } } const wrapper = shallow(, { disableLifecycleMethods: true }); - expect(wrapper.find(Table).length).to.equal(0); + expect(wrapper.find(Table)).to.have.lengthOf(0); + wrapper.instance().componentDidMount(); - expect(wrapper.find(Table).length).to.equal(1); + // wrapper.update(); // TODO: uncomment or delete + + expect(wrapper.find(Table)).to.have.lengthOf(1); }); it('calls shouldComponentUpdate when disableLifecycleMethods flag is true', () => { diff --git a/packages/enzyme-test-suite/test/shared/methods/find.jsx b/packages/enzyme-test-suite/test/shared/methods/find.jsx index 4fd9223af..ad147a921 100644 --- a/packages/enzyme-test-suite/test/shared/methods/find.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/find.jsx @@ -308,6 +308,50 @@ export default function describeFind({ expect(wrapper.find('.b').find('.c')).to.have.lengthOf(6); }); + it('can call find on the same wrapper more than once', () => { + class TestComponent extends React.Component { + render() { + return ( +
+

Title

+ 1 + 2 +
+ ); + } + } + const component = Wrap(); + + const cards = component.find('span'); + + const title = component.find('h1'); // for side effects + expect(title.is('h1')).to.equal(true); + + expect(cards.at(0).parent().is('div')).to.equal(true); + }); + + describeIf(is('> 0.13'), 'stateless function components (SFCs)', () => { + it('can call find on the same wrapper more than once', () => { + function TestComponentSFC() { + return ( +
+

Title

+ 1 + 2 +
+ ); + } + const component = Wrap(); + + const cards = component.find('span'); + + const title = component.find('h1'); // for side effects + expect(title.is('h1')).to.equal(true); + + expect(cards.at(0).parent().debug()).to.equal('
'); + }); + }); + it('works with an adjacent sibling selector', () => { const a = 'some'; const b = 'text'; diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index 28f34fbe0..0e3da3c61 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -473,8 +473,13 @@ class ShallowWrapper { */ getNodesInternal() { if (this[ROOT] === this && this.length === 1) { - this.update(); + const adapter = getAdapter(this[OPTIONS]); + const prevProps = (this[UNRENDERED] && this[UNRENDERED].props) || {}; + if (!adapter.shouldComponentUpdate || adapter.shouldComponentUpdate(prevProps, this[ROOT])) { + this.update(); + } } + return this[NODES]; } @@ -569,8 +574,10 @@ class ShallowWrapper { */ unmount() { this[RENDERER].unmount(); + this.update(); if (this[ROOT][WRAPPING_COMPONENT]) { this[ROOT][WRAPPING_COMPONENT].unmount(); + this[ROOT][WRAPPING_COMPONENT].update(); } return this; }