diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 0a5e20d08..10a0a3c11 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -958,6 +958,50 @@ describe('shallow', () => { expect(wrapper.first('div').text()).to.equal('yolo'); }); + it('should call componentWillReceiveProps, shouldComponentUpdate and componentWillUpdate with merged newProps', () => { + const spy = sinon.spy(); + + class Foo extends React.Component { + componentWillReceiveProps(nextProps) { + spy('componentWillReceiveProps', this.props, nextProps); + } + shouldComponentUpdate(nextProps) { + spy('shouldComponentUpdate', this.props, nextProps); + return true; + } + componentWillUpdate(nextProps) { + spy('componentWillUpdate', this.props, nextProps); + } + render() { + return ( +
+ ); + } + } + + const wrapper = shallow(); + + wrapper.setProps({ b: 'c', d: 'e' }); + + expect(spy.args).to.deep.equal([ + [ + 'componentWillReceiveProps', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + [ + 'shouldComponentUpdate', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + [ + 'componentWillUpdate', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + ]); + }); + describeIf(!REACT013, 'stateless function components', () => { it('should set props for a component multiple times', () => { const Foo = props => ( @@ -3094,6 +3138,58 @@ describe('shallow', () => { ); }); + it('should componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate and componentDidUpdate with merged props', () => { + const spy = sinon.spy(); + + class Foo extends React.Component { + componentWillReceiveProps(nextProps) { + spy('componentWillReceiveProps', this.props, nextProps); + } + shouldComponentUpdate(nextProps) { + spy('shouldComponentUpdate', this.props, nextProps); + return true; + } + componentWillUpdate(nextProps) { + spy('componentWillUpdate', this.props, nextProps); + } + componentDidUpdate(prevProps) { + spy('componentDidUpdate', prevProps, this.props); + } + render() { + return ( +
+ ); + } + } + + const wrapper = shallow(, { lifecycleExperimental: true }); + + wrapper.setProps({ b: 'c', d: 'e' }); + + expect(spy.args).to.deep.equal([ + [ + 'componentWillReceiveProps', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + [ + 'shouldComponentUpdate', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + [ + 'componentWillUpdate', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + [ + 'componentDidUpdate', + { a: 'a', b: 'b' }, + { a: 'a', b: 'c', d: 'e' }, + ], + ]); + }); + it('should cancel rendering when Component returns false in shouldComponentUpdate', () => { const spy = sinon.spy(); diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index c4defa1bc..5bab2813e 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -262,7 +262,7 @@ class ShallowWrapper { const state = instance.state; const prevProps = instance.props || this[UNRENDERED].props; const prevContext = instance.context || this[OPTIONS].context; - const nextProps = props || prevProps; + const nextProps = { ...prevProps, ...props }; const nextContext = context || prevContext; if (context) { this[OPTIONS] = { ...this[OPTIONS], context: nextContext };