Skip to content

Commit b400025

Browse files
committed
[enzyme-adapter-react-*, shallow] [refactor]: add “lifecycles” adapter option
1 parent 0d446f4 commit b400025

File tree

6 files changed

+110
-13
lines changed

6 files changed

+110
-13
lines changed

packages/enzyme-adapter-react-13/src/ReactThirteenAdapter.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,17 @@ function instanceToTree(inst) {
9999
class ReactThirteenAdapter extends EnzymeAdapter {
100100
constructor() {
101101
super();
102+
103+
const { lifecycles } = this.options;
102104
this.options = {
103105
...this.options,
104-
supportPrevContextArgumentOfComponentDidUpdate: true,
106+
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
107+
lifecycles: {
108+
...lifecycles,
109+
componentDidUpdate: {
110+
prevContext: true,
111+
},
112+
},
105113
};
106114
}
107115
createMountRenderer(options) {

packages/enzyme-adapter-react-14/src/ReactFourteenAdapter.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,17 @@ function instanceToTree(inst) {
7272
class ReactFifteenAdapter extends EnzymeAdapter {
7373
constructor() {
7474
super();
75+
76+
const { lifecycles } = this.options;
7577
this.options = {
7678
...this.options,
77-
supportPrevContextArgumentOfComponentDidUpdate: true,
79+
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
80+
lifecycles: {
81+
...lifecycles,
82+
componentDidUpdate: {
83+
prevContext: true,
84+
},
85+
},
7886
};
7987
}
8088
createMountRenderer(options) {

packages/enzyme-adapter-react-15.4/src/ReactFifteenFourAdapter.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,17 @@ function instanceToTree(inst) {
103103
class ReactFifteenFourAdapter extends EnzymeAdapter {
104104
constructor() {
105105
super();
106+
107+
const { lifecycles } = this.options;
106108
this.options = {
107109
...this.options,
108-
supportPrevContextArgumentOfComponentDidUpdate: true,
110+
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
111+
lifecycles: {
112+
...lifecycles,
113+
componentDidUpdate: {
114+
prevContext: true,
115+
},
116+
},
109117
};
110118
}
111119
createMountRenderer(options) {

packages/enzyme-adapter-react-15/src/ReactFifteenAdapter.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,17 @@ function instanceToTree(inst) {
103103
class ReactFifteenAdapter extends EnzymeAdapter {
104104
constructor() {
105105
super();
106+
107+
const { lifecycles } = this.options;
106108
this.options = {
107109
...this.options,
108-
supportPrevContextArgumentOfComponentDidUpdate: true,
110+
supportPrevContextArgumentOfComponentDidUpdate: true, // TODO: remove, semver-major
111+
lifecycles: {
112+
...lifecycles,
113+
componentDidUpdate: {
114+
prevContext: true,
115+
},
116+
},
109117
};
110118
}
111119
createMountRenderer(options) {

packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,17 @@ function nodeToHostNode(_node) {
160160
class ReactSixteenAdapter extends EnzymeAdapter {
161161
constructor() {
162162
super();
163+
const { lifecycles } = this.options;
163164
this.options = {
164165
...this.options,
165-
enableComponentDidUpdateOnSetState: true,
166-
supportGetSnapshotBeforeUpdate: true,
166+
enableComponentDidUpdateOnSetState: true, // TODO: remove, semver-major
167+
lifecycles: {
168+
...lifecycles,
169+
componentDidUpdate: {
170+
onSetState: true,
171+
},
172+
getSnapshotBeforeUpdate: true,
173+
},
167174
};
168175
}
169176
createMountRenderer(options) {

packages/enzyme/src/ShallowWrapper.js

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,13 @@ function filterWhereUnwrapped(wrapper, predicate) {
6666
* @param {Object} options
6767
*/
6868
function validateOptions(options) {
69-
const { lifecycleExperimental, disableLifecycleMethods } = options;
69+
const {
70+
lifecycleExperimental,
71+
disableLifecycleMethods,
72+
enableComponentDidUpdateOnSetState,
73+
supportPrevContextArgumentOfComponentDidUpdate,
74+
lifecycles,
75+
} = options;
7076
if (
7177
typeof lifecycleExperimental !== 'undefined' &&
7278
typeof lifecycleExperimental !== 'boolean'
@@ -88,6 +94,48 @@ function validateOptions(options) {
8894
) {
8995
throw new Error('lifecycleExperimental and disableLifecycleMethods cannot be set to the same value');
9096
}
97+
98+
if (
99+
typeof enableComponentDidUpdateOnSetState !== 'undefined' &&
100+
lifecycles.componentDidUpdate &&
101+
lifecycles.componentDidUpdate.onSetState !== enableComponentDidUpdateOnSetState
102+
) {
103+
throw new TypeError('the legacy enableComponentDidUpdateOnSetState option should be replaced by `lifecycles: { componentDidUpdate: { onSetState: true } }`');
104+
}
105+
106+
if (
107+
typeof supportPrevContextArgumentOfComponentDidUpdate !== 'undefined' &&
108+
lifecycles.componentDidUpdate &&
109+
lifecycles.componentDidUpdate.prevContext !== supportPrevContextArgumentOfComponentDidUpdate
110+
) {
111+
throw new TypeError('the legacy supportPrevContextArgumentOfComponentDidUpdate option should be replaced by `lifecycles: { componentDidUpdate: { prevContext: true } }`');
112+
}
113+
}
114+
115+
function getAdapterLifecycles({ options }) {
116+
const {
117+
lifecycles = {},
118+
enableComponentDidUpdateOnSetState,
119+
supportPrevContextArgumentOfComponentDidUpdate,
120+
} = options;
121+
122+
const hasLegacySetStateArg = typeof enableComponentDidUpdateOnSetState !== 'undefined';
123+
const hasLegacyPrevContextArg = typeof supportPrevContextArgumentOfComponentDidUpdate !== 'undefined';
124+
const componentDidUpdate = hasLegacySetStateArg || hasLegacyPrevContextArg
125+
? {
126+
...(hasLegacySetStateArg && {
127+
onSetState: !!enableComponentDidUpdateOnSetState,
128+
}),
129+
...(hasLegacyPrevContextArg && {
130+
prevContext: !!supportPrevContextArgumentOfComponentDidUpdate,
131+
}),
132+
}
133+
: null;
134+
135+
return {
136+
...lifecycles,
137+
...(componentDidUpdate && { componentDidUpdate }),
138+
};
91139
}
92140

93141
function getRootNode(node) {
@@ -302,20 +350,24 @@ class ShallowWrapper {
302350
if (originalShouldComponentUpdate) {
303351
instance.shouldComponentUpdate = originalShouldComponentUpdate;
304352
}
353+
const lifecycles = getAdapterLifecycles(adapter);
305354
if (
306355
!this[OPTIONS].disableLifecycleMethods &&
307356
instance
308357
) {
309358
if (
310-
adapter.options.supportGetSnapshotBeforeUpdate
359+
lifecycles.getSnapshotBeforeUpdate
311360
&& typeof instance.getSnapshotBeforeUpdate === 'function'
312361
) {
313362
const snapshot = instance.getSnapshotBeforeUpdate(prevProps, state);
314363
if (typeof instance.componentDidUpdate === 'function') {
315364
instance.componentDidUpdate(prevProps, state, snapshot);
316365
}
317366
} else if (typeof instance.componentDidUpdate === 'function') {
318-
if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) {
367+
if (
368+
lifecycles.componentDidUpdate &&
369+
lifecycles.componentDidUpdate.prevContext
370+
) {
319371
instance.componentDidUpdate(prevProps, state, prevContext);
320372
} else {
321373
instance.componentDidUpdate(prevProps, state);
@@ -379,6 +431,9 @@ class ShallowWrapper {
379431
this.single('setState', () => {
380432
withSetStateAllowed(() => {
381433
const adapter = getAdapter(this[OPTIONS]);
434+
435+
const lifecycles = getAdapterLifecycles(adapter);
436+
382437
const instance = this.instance();
383438
const prevProps = instance.props;
384439
const prevState = instance.state;
@@ -391,7 +446,8 @@ class ShallowWrapper {
391446
let originalShouldComponentUpdate;
392447
if (
393448
!this[OPTIONS].disableLifecycleMethods &&
394-
adapter.options.enableComponentDidUpdateOnSetState &&
449+
lifecycles.componentDidUpdate &&
450+
lifecycles.componentDidUpdate.onSetState &&
395451
instance &&
396452
typeof instance.shouldComponentUpdate === 'function'
397453
) {
@@ -405,22 +461,24 @@ class ShallowWrapper {
405461
// We don't pass the setState callback here
406462
// to guarantee to call the callback after finishing the render
407463
instance.setState(state);
464+
408465
if (
409466
shouldRender &&
410467
!this[OPTIONS].disableLifecycleMethods &&
411-
adapter.options.enableComponentDidUpdateOnSetState &&
468+
lifecycles.componentDidUpdate &&
469+
lifecycles.componentDidUpdate.onSetState &&
412470
instance
413471
) {
414472
if (
415-
adapter.options.supportGetSnapshotBeforeUpdate &&
473+
lifecycles.getSnapshotBeforeUpdate &&
416474
typeof instance.getSnapshotBeforeUpdate === 'function'
417475
) {
418476
const snapshot = instance.getSnapshotBeforeUpdate(prevProps, prevState);
419477
if (typeof instance.componentDidUpdate === 'function') {
420478
instance.componentDidUpdate(prevProps, prevState, snapshot);
421479
}
422480
} else if (typeof instance.componentDidUpdate === 'function') {
423-
if (adapter.options.supportPrevContextArgumentOfComponentDidUpdate) {
481+
if (lifecycles.componentDidUpdate.prevContext) {
424482
instance.componentDidUpdate(prevProps, prevState, prevContext);
425483
} else {
426484
instance.componentDidUpdate(prevProps, prevState);

0 commit comments

Comments
 (0)