Skip to content

Commit

Permalink
[enzyme-adapter-react-*, shallow] [refactor]: add “lifecycles” adapte…
Browse files Browse the repository at this point in the history
…r option
  • Loading branch information
ljharb committed Jun 29, 2018
1 parent 6cd6fa2 commit 99d1e63
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 13 deletions.
10 changes: 9 additions & 1 deletion packages/enzyme-adapter-react-13/src/ReactThirteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,17 @@ function instanceToTree(inst) {
class ReactThirteenAdapter extends EnzymeAdapter {
constructor() {
super();

const { lifecycles } = this.options;
this.options = {
...this.options,
supportPrevContextArgumentOfComponentDidUpdate: true,
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
lifecycles: {
...lifecycles,
componentDidUpdate: {
prevContext: true,
},
},
};
}
createMountRenderer(options) {
Expand Down
10 changes: 9 additions & 1 deletion packages/enzyme-adapter-react-14/src/ReactFourteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,17 @@ function instanceToTree(inst) {
class ReactFourteenAdapter extends EnzymeAdapter {
constructor() {
super();

const { lifecycles } = this.options;
this.options = {
...this.options,
supportPrevContextArgumentOfComponentDidUpdate: true,
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
lifecycles: {
...lifecycles,
componentDidUpdate: {
prevContext: true,
},
},
};
}
createMountRenderer(options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,17 @@ function instanceToTree(inst) {
class ReactFifteenFourAdapter extends EnzymeAdapter {
constructor() {
super();

const { lifecycles } = this.options;
this.options = {
...this.options,
supportPrevContextArgumentOfComponentDidUpdate: true,
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
lifecycles: {
...lifecycles,
componentDidUpdate: {
prevContext: true,
},
},
};
}
createMountRenderer(options) {
Expand Down
10 changes: 9 additions & 1 deletion packages/enzyme-adapter-react-15/src/ReactFifteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,17 @@ function instanceToTree(inst) {
class ReactFifteenAdapter extends EnzymeAdapter {
constructor() {
super();

const { lifecycles } = this.options;
this.options = {
...this.options,
supportPrevContextArgumentOfComponentDidUpdate: true,
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
lifecycles: {
...lifecycles,
componentDidUpdate: {
prevContext: true,
},
},
};
}
createMountRenderer(options) {
Expand Down
11 changes: 9 additions & 2 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,17 @@ function nodeToHostNode(_node) {
class ReactSixteenAdapter extends EnzymeAdapter {
constructor() {
super();
const { lifecycles } = this.options;
this.options = {
...this.options,
enableComponentDidUpdateOnSetState: true,
supportGetSnapshotBeforeUpdate: true,
enableComponentDidUpdateOnSetState: true, // TODO: remove, semver-major
lifecycles: {
...lifecycles,
componentDidUpdate: {
onSetState: true,
},
getSnapshotBeforeUpdate: true,
},
};
}
createMountRenderer(options) {
Expand Down
72 changes: 65 additions & 7 deletions packages/enzyme/src/ShallowWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ function filterWhereUnwrapped(wrapper, predicate) {
* @param {Object} options
*/
function validateOptions(options) {
const { lifecycleExperimental, disableLifecycleMethods } = options;
const {
lifecycleExperimental,
disableLifecycleMethods,
enableComponentDidUpdateOnSetState,
supportPrevContextArgumentOfComponentDidUpdate,
lifecycles,
} = options;
if (
typeof lifecycleExperimental !== 'undefined' &&
typeof lifecycleExperimental !== 'boolean'
Expand All @@ -88,6 +94,48 @@ function validateOptions(options) {
) {
throw new Error('lifecycleExperimental and disableLifecycleMethods cannot be set to the same value');
}

if (
typeof enableComponentDidUpdateOnSetState !== 'undefined' &&
lifecycles.componentDidUpdate &&
lifecycles.componentDidUpdate.onSetState !== enableComponentDidUpdateOnSetState
) {
throw new TypeError('the legacy enableComponentDidUpdateOnSetState option should be matched by `lifecycles: { componentDidUpdate: { onSetState: true } }`, for compatibility');
}

if (
typeof supportPrevContextArgumentOfComponentDidUpdate !== 'undefined' &&
lifecycles.componentDidUpdate &&
lifecycles.componentDidUpdate.prevContext !== supportPrevContextArgumentOfComponentDidUpdate
) {
throw new TypeError('the legacy supportPrevContextArgumentOfComponentDidUpdate option should be matched by `lifecycles: { componentDidUpdate: { prevContext: true } }`, for compatibility');
}
}

function getAdapterLifecycles({ options }) {
const {
lifecycles = {},
enableComponentDidUpdateOnSetState,
supportPrevContextArgumentOfComponentDidUpdate,
} = options;

const hasLegacySetStateArg = typeof enableComponentDidUpdateOnSetState !== 'undefined';
const hasLegacyPrevContextArg = typeof supportPrevContextArgumentOfComponentDidUpdate !== 'undefined';
const componentDidUpdate = hasLegacySetStateArg || hasLegacyPrevContextArg
? {
...(hasLegacySetStateArg && {
onSetState: !!enableComponentDidUpdateOnSetState,
}),
...(hasLegacyPrevContextArg && {
prevContext: !!supportPrevContextArgumentOfComponentDidUpdate,
}),
}
: null;

return {
...lifecycles,
...(componentDidUpdate && { componentDidUpdate }),
};
}

function getRootNode(node) {
Expand Down Expand Up @@ -302,20 +350,24 @@ class ShallowWrapper {
if (originalShouldComponentUpdate) {
instance.shouldComponentUpdate = originalShouldComponentUpdate;
}
const lifecycles = getAdapterLifecycles(adapter);
if (
!this[OPTIONS].disableLifecycleMethods &&
instance
) {
if (
adapter.options.supportGetSnapshotBeforeUpdate
lifecycles.getSnapshotBeforeUpdate
&& 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) {
if (
lifecycles.componentDidUpdate &&
lifecycles.componentDidUpdate.prevContext
) {
instance.componentDidUpdate(prevProps, state, prevContext);
} else {
instance.componentDidUpdate(prevProps, state);
Expand Down Expand Up @@ -379,6 +431,9 @@ class ShallowWrapper {
this.single('setState', () => {
withSetStateAllowed(() => {
const adapter = getAdapter(this[OPTIONS]);

const lifecycles = getAdapterLifecycles(adapter);

const instance = this.instance();
const prevProps = instance.props;
const prevState = instance.state;
Expand All @@ -391,7 +446,8 @@ class ShallowWrapper {
let originalShouldComponentUpdate;
if (
!this[OPTIONS].disableLifecycleMethods &&
adapter.options.enableComponentDidUpdateOnSetState &&
lifecycles.componentDidUpdate &&
lifecycles.componentDidUpdate.onSetState &&
instance &&
typeof instance.shouldComponentUpdate === 'function'
) {
Expand All @@ -405,22 +461,24 @@ class ShallowWrapper {
// We don't pass the setState callback here
// to guarantee to call the callback after finishing the render
instance.setState(state);

if (
shouldRender &&
!this[OPTIONS].disableLifecycleMethods &&
adapter.options.enableComponentDidUpdateOnSetState &&
lifecycles.componentDidUpdate &&
lifecycles.componentDidUpdate.onSetState &&
instance
) {
if (
adapter.options.supportGetSnapshotBeforeUpdate &&
lifecycles.getSnapshotBeforeUpdate &&
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) {
if (lifecycles.componentDidUpdate.prevContext) {
instance.componentDidUpdate(prevProps, prevState, prevContext);
} else {
instance.componentDidUpdate(prevProps, prevState);
Expand Down

0 comments on commit 99d1e63

Please sign in to comment.