-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Support array-like iterable children in v3 #1187
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
Conversation
| @@ -0,0 +1,65 @@ | |||
| const ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; | |||
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 saw that enzyme has this elsewhere, but in a different package. If there's a good way to share this across lerna packages, please let me know. I haven't used lerna before 😄
| } | ||
| } | ||
|
|
||
| export function nodeTypeFromType(type) { |
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.
Moved this to its own file so that elementToTree could still use it
05f921f to
2e1b7b8
Compare
|
After searching around the codebase some more, I see that the I'm going to pause on this for now to see if any maintainers have ideas about how best to tackle this. |
|
Interesting! I didn't know React had this capability. |
|
fyi I plan on coming back to this next week! |
|
@lelandrichardson I have changed this to now be about adding Immutable.js support. Please see the updated description and code and let me know if you have any questions! |
ad838e4 to
8f952c4
Compare
ljharb
left a comment
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.
Generic iterables makes sense to me; that's in the language.
A .toArray function is arbitrary and non-standard; unless React supports this explicitly, I do not think we should support it in enzyme.
8f952c4 to
4475fbe
Compare
|
Hi @ljharb thanks for the review. I have made this more generic -- I did some more research and found out that all iterables support |
ljharb
left a comment
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.
Thanks, this looks much better!
| if (Array.isArray(children)) { | ||
| rendered = flatten(children, true).map(elementToTree); | ||
| } else if (isIterable(children) && typeof children !== 'string') { | ||
| rendered = flatten(Array.from(children), true).map(elementToTree); |
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.
since we use babel, this could also be flatten([...children], true)
| return ( | ||
| typeof Symbol === 'function' && | ||
| typeof Symbol.iterator === 'symbol' && | ||
| obj != null && |
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'd probably move the obj check higher, since that's faster then checking Symbols
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.
Awesome, I wasn't aware of that! Thanks!
| if (Array.isArray(children)) { | ||
| rendered = flatten(children, true).map(elementToTree); | ||
| } else if (isIterable(children) && typeof children !== 'string') { | ||
| rendered = flatten(Array.from(children), true).map(elementToTree); |
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.
similarly, flatten([...children], true)
| </div>, | ||
| ); | ||
| treeForEach(node, spy); | ||
| expect(spy.callCount).to.equal(3); |
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.
Could we also use expect(spy.calls).to.deep.equal in both places, and assert that it's called with the right items?
It'd also be great to test with a Map as well as a Set
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.
Yes for sure, I like that. The tree objects are pretty complex, how do you feel about just checking part of it, say keys? Like this:
it('should handle Map children', () => {
const spy = sinon.spy();
const twoDivMap = new Map([
[<div key="a" />],
[<div key="b" />],
]);
const node = $(
<div key="root">
{twoDivMap}
</div>,
);
treeForEach(node, spy);
expect(spy.callCount).to.equal(3);
const keys = spy.args.map(arg => arg[0].key);
expect(keys).to.deep.equal(['root', 'a', 'b']);
});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.
ah nevermind, even better I can just use $ and check the whole thing:
it('should handle Map children', () => {
const spy = sinon.spy();
const twoDivMap = new Map([
[<div key="a" />],
[<div key="b" />],
]);
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const node = $(
<div key="root">
{twoDivMap}
</div>,
);
treeForEach(node, spy);
expect(spy.callCount).to.equal(3);
const nodes = spy.args.map(arg => arg[0]);
expect(nodes).to.deep.equal([node, divA, divB]);
});I'll get this committed soon!
2c90486 to
2d43e65
Compare
|
Alrighty! @ljharb travis is happy and I think I answered your comments. Can you please review again? |
ljharb
left a comment
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.
Looks great! Although it does seem like you've only added iterable support in the react 13 adapter - the 14, 15, 15.4, and 16 adapters would need it as well.
|
Thanks! Actually the v13 adapter is special-cased. The others all use the |
ljharb
left a comment
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.
Awesome, thanks for clarifying :-)
|
Any idea when this might be released? |
|
@stevenmusumeche when a few more collaborators have reviewed it. |
|
would it be helpful if I periodically rebase this? otherwise I can just do it once we're ready |
|
I hate to be a pest, but is there a way to move the review up in priority for the other collaborators? The code and tests look great to me, but I am not intimately familiar with the codebase. It is something that worked before in v2 and doesn't in v3 and is preventing quite a few companies from upgrading to React 16. |
aweary
left a comment
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.
Sorry it took so long! I'm taking some time away from OSS right now. This looks good though 👍
|
@kmcq please do rebase it, yes :-) |
703eb0a to
3ad399c
Compare
|
rebased! |
|
Thank you all so much for what you do. |
|
Thanks @ljharb! I appreciate everyone's reviews. This was my first time contributing to a library like this and you all made it fun and I learned some things too. Cheers! |
|
Thanks @kmcq! Any ETA on when a new version will be cut? This was the only thing blocking us from upgrading to react 16. Thanks! |
|
Looking forward for this to be released! Great work guys! |
|
@kamui no ETA yet. I'm shooting for this week, ASAP. |
|
All adapters, as well as enzyme-adapter-utils, have been bumped. |
|
Hey @ljharb, sorry to bug you but it looks like the React 15 adapter's release didn't make it to NPM: https://www.npmjs.com/package/enzyme-adapter-react-15. I checked and the rest look good 👍 Is that something that you need to handle or is that one just lagging behind? Thanks! Edit: I should point out that this is not a big issue, nor should it block anyone, since the change was in Edit2: It's there now! Thanks so much! |
|
Hey guys, I'm running enzyme Above unit test doesn't pass, since I could add Immutable as a dependency of enzyme-adapter-utils to extend I think having support for Immutable children makes sense because:
I'm looking forward to collaborate, keep the great work! |
|
@ljharb, the test I shared was with Immutable |
|
@ljharb, I found that the issue was because we are running our unit tests on PhantomJS, and ES6 Symbol API is missing there, and might be the case for old browsers. Tried to run the test on recent Chrome version and works just fine. We could change in the enzyme-adapter-utils, to that's exactly what React does. |
|
Hmm - Can you confirm whether React supported this behavior down to 0.13? Also, can you file a separate issue about this? |
|
For sure @ljharb, I'll take a look into that. |
|
Linking to #1334 as well. |
What this is
Fixes #1181.
This adds support for non-Array, but still iterable, children, such as Immutable-js Lists, Sets, etc., which is supported by React:
The React PR that originally added this functionality is here: facebook/react#2376.
The code
childrenis iterable, and if so, useArray.fromto convert it to an array.I like this approach because it compartmentalizes the knowledge that children are sometimes things other than arrays.