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

Better support for iterable children #1334

Merged
merged 3 commits into from
Nov 18, 2017

Conversation

Inucoder
Copy link

@Inucoder Inucoder commented Nov 7, 2017

…e Object.

Update isIterable function to leverage getIteratorFn.
Rewrite flatten function to leverage getIteratorFn.
Add unit test for flatten function.
Add unit tests for arbitrary iterable children.
Support for Symbol.iterator and @@iterator iterables.

@Inucoder
Copy link
Author

Inucoder commented Nov 7, 2017

Fixes #1328 by implementing similar-to-React support for iterable children. @ljharb

}

function isIterable(obj) {
return Boolean(getIteratorFn(obj));
Copy link
Member

Choose a reason for hiding this comment

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

this should use !! rather than Boolean().

}

function isIterable(obj) {
return Boolean(getIteratorFn(obj));
}

export function isArrayLike(obj) {
return Array.isArray(obj) || (isIterable(obj) && typeof obj !== 'string');
Copy link
Member

Choose a reason for hiding this comment

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

(predates your PR, but still) let's flip the typeof check here; isIterable shouldn't be called at all in the string case.

@@ -316,6 +316,115 @@ describe('RSTTraversal', () => {
expect(nodes).to.deep.equal([node, divA, divB, divC, divD]);
});

describe('support for arbitrary iterable children', () => {
const makeDivIterator = (lowerBound, upperBound) => {
let counter = lowerBound;
Copy link
Member

Choose a reason for hiding this comment

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

let counter = lowerBound + 'a'.charCodeAt(0); would avoid needing to look up "a"'s charCode every time

@Inucoder
Copy link
Author

Inucoder commented Nov 8, 2017

@ljharb, working on the feedback from your review. Thanks so much.

@Inucoder
Copy link
Author

Inucoder commented Nov 8, 2017

It's ready for review again @ljharb.

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.

Seems legit.

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.

The additional tests are nice, but I'm not sure I see the value in the getIteratorFn approach. Internally we're almost always dealing with actual arrays, while iterable children aren't a super common pattern.

step = iterator.next();
}

return flatArrs;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This feels like a lot of added complexity when flatten should almost always be called with arrays. It just seems like we're doing the same work that [...iterable] is doing, except that this approach won't benefit from any internal optimizations that the spread operator may have.

Copy link
Author

@Inucoder Inucoder Nov 8, 2017

Choose a reason for hiding this comment

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

Our use case is running our unit test suite on PhantomJS, where some of our components return Immutable List instance of React elements. As described in #1328, that feature was recently added but was not working on PhantomJS due the lack of support for Symbol.iterator. I agree the increased complexity is evident, and that's why I aimed for good test coverage. The main reason to make this change is to catch up with React, which is very flexible with the children it's able to handle, and switching from v2 to v3 may break tests of some middle to large projects using a pattern like us and results in additional effort to make the bump. Really appreciate your comments.

Copy link
Author

Choose a reason for hiding this comment

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

@aweary, what if I add below code at the beginning of flatten function?

if (Array.isArray(arrs)) {
  return arrs.reduce(
    (flattened, item) => flattened.concat(isArrayLike(item) ? flatten(item) : item),
    [],
  );
}

That way flatten will be as performant as it used to before my change, for the most common case where arrs is a regular JS Array. But gracefully fallbacks to support any kind of iterable children React can also handle.

Let me know your thoughts. cc @ljharb

Copy link
Member

Choose a reason for hiding this comment

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

Seems reasonable to me.

Copy link
Author

Choose a reason for hiding this comment

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

Cool, I'm going to make that change and push.

@Inucoder
Copy link
Author

Made the optimization for the most common case and pushed @ljharb cc @aweary. Thanks for your feedback.

@ljharb
Copy link
Member

ljharb commented Nov 16, 2017

@Inucoder would you please rebase this on the command line, so as to remove all merge commits?

@Inucoder Inucoder force-pushed the better_support_for_iterable_children branch from ec131ad to d96e780 Compare November 17, 2017 01:16
@Inucoder
Copy link
Author

It's done @ljharb, a coworker gave me a helping hand to do the rebase.

@ljharb
Copy link
Member

ljharb commented Nov 17, 2017

@Inucoder thanks! it looks like it's still out of date with master tho; you may need to fetch and redo the rebase? (if this gets onerous, I'm happy to take care of it for you)

Oswaldo Ceballos Zavala added 3 commits November 17, 2017 12:48
…e Object.

Update isIterable function to leverage getIteratorFn.
Rewrite flatten function to leverage getIteratorFn.
Add unit test for flatten function.
Add unit tests for arbitrary iterable children.
Support for Symbol.iterator and @@iterator iterables.
@Inucoder Inucoder force-pushed the better_support_for_iterable_children branch from d96e780 to 308578a Compare November 17, 2017 17:50
@Inucoder
Copy link
Author

Should be good now @ljharb, not a big deal.

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.

LGTM; this still should have a couple more collabs stamp it first.

@lelandrichardson
Copy link
Collaborator

Seems good to me. Thanks for working on this.

@ljharb ljharb merged commit ea73ec1 into enzymejs:master Nov 18, 2017
ljharb added a commit to ljharb/enzyme that referenced this pull request Nov 22, 2017
 - [New] Better support for iterable children (enzymejs#1334)
jquense pushed a commit to jquense/enzyme that referenced this pull request Feb 23, 2018
 - [New] Better support for iterable children (enzymejs#1334)
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.

4 participants