diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
index d902bd494..12af2e7d0 100644
--- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
+++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
@@ -1353,7 +1353,7 @@ describeWithDOM('mount', () => {
]);
});
- itIf(!REACT16, 'should throw if an exception occurs during render', () => {
+ it('should throw if an exception occurs during render', () => {
class Trainwreck extends React.Component {
render() {
const { user } = this.props;
@@ -1413,6 +1413,62 @@ describeWithDOM('mount', () => {
});
});
+ it('should call componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, and componentDidUpdate 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);
+ }
+
+ componentDidUpdate(prevProps) {
+ spy('componentDidUpdate', prevProps, this.props);
+ }
+
+ render() {
+ return (
+
{user.name.givenName}
diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
index 1894b18ce..ca1c3647a 100644
--- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
+++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
@@ -1240,6 +1240,66 @@ describe('shallow', () => {
]);
});
+ it('should throw if an exception occurs during render', () => {
+ class Trainwreck extends React.Component {
+ render() {
+ const { user } = this.props;
+ return (
+
+ {user.name.givenName}
+
+ );
+ }
+ }
+
+ const similarException = ((() => {
+ const user = {};
+ try {
+ return user.name.givenName;
+ } catch (e) {
+ return e;
+ }
+ })());
+
+ const validUser = {
+ name: {
+ givenName: 'Brian',
+ },
+ };
+
+ const wrapper = shallow(
);
+
+ const setInvalidProps = () => {
+ wrapper.setProps({
+ user: {},
+ });
+ };
+
+ expect(setInvalidProps).to.throw(TypeError, similarException.message);
+ });
+
+ it('should call the callback when setProps has completed', () => {
+ class Foo extends React.Component {
+ render() {
+ const { id } = this.props;
+ return (
+
+ {id}
+
+ );
+ }
+ }
+ const wrapper = shallow(
);
+ expect(wrapper.find('.foo')).to.have.lengthOf(1);
+
+ wrapper[sym('__renderer__')].batchedUpdates(() => {
+ wrapper.setProps({ id: 'bar', foo: 'bla' }, () => {
+ expect(wrapper.find('.bar')).to.have.lengthOf(1);
+ });
+ });
+ expect(wrapper.find('.foo')).to.have.lengthOf(0);
+ });
+
it('should call componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, and componentDidUpdate with merged newProps', () => {
const spy = sinon.spy();
@@ -1341,6 +1401,42 @@ describe('shallow', () => {
wrapper.setProps({ x: 5 }); // Just force a re-render
expect(wrapper.first('div').text()).to.equal('yolo');
});
+
+ it('should throw if an exception occurs during render', () => {
+ const Trainwreck = ({ user }) => (
+
+ {user.name.givenName}
+
+ );
+
+ const validUser = {
+ name: {
+ givenName: 'Brian',
+ },
+ };
+
+ const similarException = ((() => {
+ const user = {};
+ try {
+ return user.name.givenName;
+ } catch (e) {
+ return e;
+ }
+ })());
+
+ const wrapper = shallow(
);
+
+ const setInvalidProps = () => {
+ wrapper.setProps({
+ user: {},
+ });
+ };
+
+ expect(setInvalidProps).to.throw(
+ TypeError,
+ similarException.message,
+ );
+ });
});
});
diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js
index c6602a514..edba7dcd1 100644
--- a/packages/enzyme/src/ShallowWrapper.js
+++ b/packages/enzyme/src/ShallowWrapper.js
@@ -30,6 +30,8 @@ import {
} from './RSTTraversal';
import { buildPredicate, reduceTreesBySelector } from './selectors';
+const noop = () => {};
+
const NODE = sym('__node__');
const NODES = sym('__nodes__');
const RENDERER = sym('__renderer__');
@@ -376,13 +378,19 @@ class ShallowWrapper {
* NOTE: can only be called on a wrapper instance that is also the root instance.
*
* @param {Object} props object
+ * @param {Function} cb - callback function
* @returns {ShallowWrapper}
*/
- setProps(props) {
+ setProps(props, callback = noop) {
if (this[ROOT] !== this) {
throw new Error('ShallowWrapper::setProps() can only be called on the root');
}
- return this.rerender(props);
+ if (typeof callback !== 'function') {
+ throw new TypeError('ShallowWrapper::setProps() expects a function as its second argument');
+ }
+ this.rerender(props);
+ callback();
+ return this;
}
/**