Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add disableLifecycleMethods for shallow #789

Merged
merged 5 commits into from
Mar 17, 2017

Conversation

jwbay
Copy link
Contributor

@jwbay jwbay commented Jan 28, 2017

As part of the plan to switch on all lifecycle methods for shallow in the next major, introduce a no-op flag ahead of time that turns that off.

Ref: #678 (comment)

Since there's no options validation, I'm not sure any code changes are necessary. (added) It may be confusing if someone sets this flag to explicitly false and expects their lifecycle methods to be called. Should we set lifecycleExperimental to true in that case?

I didn't prefix the option with deprecated because it seemed this flag is going to be sticking around as the official, inverted version of lifecycleExperimental. I may have misunderstood something though.

The name feels a bit off since it's not disabling all the lifecycle methods, just two of them. Should it be something like disableFullLifecycle?

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should still have some code to ensure that users aren't passing flags both to enable and disable the methods, and throws in that case.

@jwbay
Copy link
Contributor Author

jwbay commented Jan 28, 2017

Added some validation.

function validateOptions(options) {
if (
options.lifecycleExperimental != null &&
options.lifecycleExperimental === options.disableLifecycleMethods
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this comparison should probably just both options, and throw if they're the same, as long as both of them aren't == null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, done

expect(() => shallow(<div />, {
lifecycleExperimental: false,
disableLifecycleMethods: false,
})).to.throw(/same value/);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's also add tests where both are omitted, and where either aren't a boolean (ie, it should throw if a non-boolean non-undefined value is provided)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

['componentWillReceiveProps'],
['shouldComponentUpdate'],
['componentWillUpdate'],
['render'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether componentDidUpdate is supposed to be called here, but it's not currently. If this behavior is correct it's going to make this flag + documentation pretty confusing since, per next test down, setState does trigger componentDidUpdate for shallow rendered components (even without enzyme in the picture).

The flag is looking more like it should be disableDidMountAllTheTimeAndDidUpdateSomeOfTheTime. 😅

cc @koba04 any thoughts on correctness here? Note this is all without lifecycleExperimental set to true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwbay
Currently, lifecycleExperimental does complement lifecycle methods that ShallowRenderer is missing, which are componentDidMount and componentDidUpdate in setProps and setContext #318 (comment).

In setState, componentDidUpdate is always called because ShallowWrapper calls instance.setState() directly. 😅

To be clear, if disableLifecycleMethods set to true, componentDidMount and componentDidUpdate(in setProps and setContext) are not called on the component.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is looking great, but let's get more reviewers to take a look before merging.

const { lifecycleExperimental, disableLifecycleMethods } = options;
if (
typeof lifecycleExperimental !== 'undefined' &&
lifecycleExperimental !== !!lifecycleExperimental
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeof lifecycleExperimental !== 'boolean' is more explicitly?

});
});

describeIf(REACT014, 'setContext', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad we're testing this on all React versions - could you elaborate on why componentWillReceiveProps fires in 13 and 15, but not 14?

Copy link
Contributor Author

@jwbay jwbay Feb 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In React 13 and 14, the check for whether willReceiveProps is called is just a strict equality check in ReactCompositeComponent between the previous and next elements. In React 15, they added an additional equality check between previous and next context.

willReceiveProps is called in 13 because Enzyme clones the element on each render in react-compat's createRendererCompatible, failing the equality check.

It's not called in 14 because the elements are equal. createRendererCompatible is only used for React 13.

It's called in 15 because of the new check for context.

Copy link
Collaborator

@aweary aweary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the advantage of adding a no-op flag in a minor release, @ljharb can you clarify why we'd want that? It feels like it will just be ignored anyway if it's a no-op.

But otherwise this implementation LGTM if we want this.

@ljharb
Copy link
Member

ljharb commented Feb 16, 2017

@aweary because then people who depend on the false behavior have a way to explicitly preserve it when they upgrade (which will flip the default, making true the noop instead of false), without having to change their code.

@aweary
Copy link
Collaborator

aweary commented Feb 16, 2017

It just sounds unlikely that anyone is going enable a no-op flag from a minor release when their tests are all working as they would expect. What's more likely is that they upgrade to the next major release, have breakage, and then enable the flag.

But either way, it's not like this change will hurt anyone so 👍

@ljharb
Copy link
Member

ljharb commented Feb 16, 2017

I envision "upgrade, breakage, downgrade, gradually migrate their tests to use an explicit flag, upgrade smoothly later" :-)

@blainekasten
Copy link
Contributor

Sooo. Sounds like this is good to merge then? @jwbay mind rebasing?

@jwbay
Copy link
Contributor Author

jwbay commented Mar 15, 2017

@blainekasten rebased

@blainekasten
Copy link
Contributor

cc @ljharb do you want these all rebased down to 1 commit or is this fine?

@ljharb
Copy link
Member

ljharb commented Mar 17, 2017

This is fine, as long as there's no merge commits :-)

@blainekasten blainekasten merged commit 595d15f into enzymejs:master Mar 17, 2017
@blainekasten
Copy link
Contributor

Thanks for the work on this @jwbay ! This is big!

@jwbay jwbay deleted the disableLifecycleMethods branch March 17, 2017 19:08
@jwbay jwbay restored the disableLifecycleMethods branch August 13, 2017 16:35
@jwbay jwbay deleted the disableLifecycleMethods branch August 13, 2017 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants