-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
ensure ShallowWrapper render output can't get stale #490
Conversation
this.node = this.renderer.getRenderOutput(); | ||
this.nodes = [this.node]; | ||
Object.defineProperty(this, 'node', { | ||
get() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh :-/ getters are incredibly slow and deoptimize all code they touch. I'd rather do a breaking change to make this a method, than use a getter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also be down for using functions. I've always felt nervous about using .node
/ .nodes
as I felt like it was reaching into enzyme internals that could be changed without notice.. Functions feel more like a public API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, node
and nodes
aren't technically public API are they? We don't document them as far as I can see. I agree that using a function would be an improvement, so maybe we can make that change for the next breaking release and then add node()
and nodes()
to the API documentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything accessible - not just everything documented - is public API, even if it has a magical underscore in the front of the property name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So any change to any object property would be considered a breaking change? If someone is using ReactWrapper.complexSelector.find
and we rename/move that, would that require a major release? Maybe we're not talking about the same thing. I usually define public API as the API that we document for the public and that we support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getters and setters are horrifically bad for readability and maintainability. imo they should never be used, in any project. A property should be a property, not a function.
Since this is not a bug fix, there's no urgency to add this change, and I'd prefer to convert .node
to a function if we want more behavior than "data property".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I agree that getters don't improve readability, this is definitely a bug. Ask anyone with passing familiarity with Enzyme about what this should do and compare it with what actually happens:
let wrapper = Enzyme.shallow(<MyInput debounce={ 500 } />)
wrapper.simulate("keypress", {char: "b"})
wrapper.simulate("keypress", {char: "a"})
wrapper.simulate("keypress", {char: "r"})
expect(wrapper.find(".result").text()).toBe("")
jasmine.clock().tick(1000)
expect(wrapper.find(".result").text()).toBe("bar")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The requirement to manually update()
is intentional. I agree it's a UX improvement to do it automatically, but it's not a bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ljharb I can convert these to functions. Would that be acceptable? Want to make sure because it's a more involved change. 😄 I understand it would have to wait for a 3.x release.
Are there any concerns about ReactWrapper having properties for these and ShallowWrapper having functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should convert both to functions at the same time, for consistency.
67699b6
to
d27d5e4
Compare
This is ready for a second look. The first commit was only updated to get tests passing on older versions of React/Node. I didn't switch everything in ReactWrapper to use the new functions because the only benefit would've been for internal uniformity at the cost of function calls where they weren't needed. Can switch if desired. Outstanding questions:
|
@@ -169,9 +169,6 @@ Manually sets context of the root component. | |||
#### [`.instance() => ReactComponent`](ShallowWrapper/instance.md) | |||
Returns the instance of the root component. | |||
|
|||
#### [`.update() => ShallowWrapper`](ShallowWrapper/update.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method still seems useful in case someone mutates state/props without calling the appropriate methods and wants to force an update.
fwiw I think internal uniformity is much more important than avoiding function calls, which are pretty cheap anyways. |
Does anyone have further thoughts on this? |
The more I think about this, the more I'm confused why there's both "getNode" and "getNodes"? |
Don't think there's a reason besides avoiding lots of |
If it's just a convenience, perhaps |
Good points, updated! |
@jwbay this is a great and very welcome change! Although I agree w/ @ljharb that with a Thoughts? |
@lelandrichardson Thanks! I agree this is a breaking change. |
I'd also be fine keeping the internal .node updated for now, but removing it in the next major version bump. |
So restore the old .update functionality? Should it still call .forceUpdate on the instance as well? It didn't before this PR. |
@jwbay ah, if the PR can't be easily made to be semver-minor, then we may as well go full semver-major :-) |
Oh I don't mind making the change, especially if it can get this shipped sooner :) I just wasn't sure whether adding .forceUpdate calls where there weren't any before would be a breaking change as well. Seems like it would actually. I'll take a look at what's involved for back-compat. |
@ljharb @lelandrichardson we should be semver-minor now 👍 |
LGTM |
fb76502
to
20408fd
Compare
Resolved conflicts. |
Is there any chance of this branch getting merged? This would reduce a lot of boilerplate code for our team. |
…tput is always fresh. removes need for .update
hi! any timeline on releasing this? |
I'll cut a few releases after #670 gets in. |
Seems to work under |
2.5.0 supports passing callbacks to `setState`, which we require for `client/auth/test/login`. Furthermore, there's a fix in 2.6.0 that's required for this to actually work (enzymejs/enzyme#490) Not updating to >=3.0.0 yet since chai-expect isn't compatible (yet). Changelog: https://github.com/airbnb/enzyme/blob/master/CHANGELOG.md#252-november-9-2016
2.5.0 supports passing callbacks to `setState`, which we require for `client/auth/test/login`. Furthermore, there's a fix in 2.6.0 that's required for this to actually work (enzymejs/enzyme#490) Not updating to >=3.0.0 yet since chai-expect isn't compatible (yet). Changelog: https://github.com/airbnb/enzyme/blob/master/CHANGELOG.md#252-november-9-2016
…8472) * Auth: Prettify login.jsx * Auth: Run i18n codemod on login.jsx * Auth: Run react-create-class codemod on login.jsx * Auth: Prettify login.jsx * Auth: Simplify login.jsx * Auth: Named export for un-localized Login component * Framework: Upgrade enzyme to 2.9.1 2.5.0 supports passing callbacks to `setState`, which we require for `client/auth/test/login`. Furthermore, there's a fix in 2.6.0 that's required for this to actually work (enzymejs/enzyme#490) Not updating to >=3.0.0 yet since chai-expect isn't compatible (yet). Changelog: https://github.com/airbnb/enzyme/blob/master/CHANGELOG.md#252-november-9-2016 * Auth: Simplify FormTextInput ref (focus) * Auth: Use enzyme to test login.jsx * Auth: Remove obsolete refs from login.jsx (These were only used by tests.) * Auth: Move SelfHostedInstructions and LostPassword to separate files
…8472) * Auth: Prettify login.jsx * Auth: Run i18n codemod on login.jsx * Auth: Run react-create-class codemod on login.jsx * Auth: Prettify login.jsx * Auth: Simplify login.jsx * Auth: Named export for un-localized Login component * Framework: Upgrade enzyme to 2.9.1 2.5.0 supports passing callbacks to `setState`, which we require for `client/auth/test/login`. Furthermore, there's a fix in 2.6.0 that's required for this to actually work (enzymejs/enzyme#490) Not updating to >=3.0.0 yet since chai-expect isn't compatible (yet). Changelog: https://github.com/airbnb/enzyme/blob/master/CHANGELOG.md#252-november-9-2016 * Auth: Simplify FormTextInput ref (focus) * Auth: Use enzyme to test login.jsx * Auth: Remove obsolete refs from login.jsx (These were only used by tests.) * Auth: Move SelfHostedInstructions and LostPassword to separate files
Replace .node and .nodes with 'get' functions in ShallowWrapper to ensure render output is always fresh. Add equivalent functions in ReactWrapper. Removes need for ShallowWrapper's .update, fixes #360
Many thanks to @guncha for the idea in #360.