diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index 7bcf387cf..3fe9b07f6 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -163,6 +163,7 @@ class ReactSixteenAdapter extends EnzymeAdapter { this.options = { ...this.options, enableComponentDidUpdateOnSetState: true, + supportGetSnapshotBeforeUpdate: true, }; } createMountRenderer(options) { diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 503035084..c822119d7 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -3932,6 +3932,46 @@ describe('shallow', () => { }); }); + describeIf(REACT16, 'support getSnapshotBeforeUpdate', () => { + it('should call getSnapshotBeforeUpdate and pass snapshot to componentDidUpdate', () => { + const spy = sinon.spy(); + class Foo extends React.Component { + constructor(props) { + super(props); + this.state = { + foo: 'bar', + }; + } + componentDidUpdate(prevProps, prevState, snapshot) { + spy('componentDidUpdate', prevProps, this.props, prevState, this.state, snapshot); + } + getSnapshotBeforeUpdate(prevProps, prevState) { + spy('getSnapshotBeforeUpdate', prevProps, this.props, prevState, this.state); + return { snapshot: 'ok' }; + } + render() { + spy('render'); + return
foo
; + } + } + const wrapper = shallow(); + spy.reset(); + wrapper.setProps({ name: 'bar' }); + expect(spy.args).to.deep.equal([ + ['render'], + ['getSnapshotBeforeUpdate', { name: 'foo' }, { name: 'bar' }, { foo: 'bar' }, { foo: 'bar' }], + ['componentDidUpdate', { name: 'foo' }, { name: 'bar' }, { foo: 'bar' }, { foo: 'bar' }, { snapshot: 'ok' }], + ]); + spy.reset(); + wrapper.setState({ foo: 'baz' }); + expect(spy.args).to.deep.equal([ + ['render'], + ['getSnapshotBeforeUpdate', { name: 'bar' }, { name: 'bar' }, { foo: 'bar' }, { foo: 'baz' }], + ['componentDidUpdate', { name: 'bar' }, { name: 'bar' }, { foo: 'bar' }, { foo: 'baz' }, { snapshot: 'ok' }], + ]); + }); + }); + it('should not call when disableLifecycleMethods flag is true', () => { const spy = sinon.spy(); class Foo extends React.Component { diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index ab6152d91..0c1f07263 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -304,13 +304,22 @@ class ShallowWrapper { } if ( !this[OPTIONS].disableLifecycleMethods && - instance && - typeof instance.componentDidUpdate === 'function' + instance ) { - if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) { - instance.componentDidUpdate(prevProps, state, prevContext); - } else { - instance.componentDidUpdate(prevProps, state); + if ( + adapter.options.supportGetSnapshotBeforeUpdate + && typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + const snapshot = instance.getSnapshotBeforeUpdate(prevProps, state); + if (typeof instance.componentDidUpdate === 'function') { + instance.componentDidUpdate(prevProps, state, snapshot); + } + } else if (typeof instance.componentDidUpdate === 'function') { + if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) { + instance.componentDidUpdate(prevProps, state, prevContext); + } else { + instance.componentDidUpdate(prevProps, state); + } } } this.update(); @@ -400,13 +409,22 @@ class ShallowWrapper { shouldRender && !this[OPTIONS].disableLifecycleMethods && adapter.options.enableComponentDidUpdateOnSetState && - instance && - typeof instance.componentDidUpdate === 'function' + instance ) { - if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) { - instance.componentDidUpdate(prevProps, prevState, prevContext); - } else { - instance.componentDidUpdate(prevProps, prevState); + if ( + adapter.options.supportGetSnapshotBeforeUpdate && + typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + const snapshot = instance.getSnapshotBeforeUpdate(prevProps, prevState); + if (typeof instance.componentDidUpdate === 'function') { + instance.componentDidUpdate(prevProps, prevState, snapshot); + } + } else if (typeof instance.componentDidUpdate === 'function') { + if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) { + instance.componentDidUpdate(prevProps, prevState, prevContext); + } else { + instance.componentDidUpdate(prevProps, prevState); + } } } this.update();