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

Support array-like iterable children in v3 #1187

Merged
merged 4 commits into from
Oct 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import flatten from 'lodash/flatten';
import { flatten, isArrayLike } from 'enzyme-adapter-utils';

export function nodeTypeFromType(type) {
if (typeof type === 'string') {
Expand All @@ -21,8 +21,8 @@ export default function elementToTree(el) {
const { type, props, key, ref } = el;
const { children } = props;
let rendered = null;
if (Array.isArray(children)) {
rendered = flatten(children, true).map(elementToTree);
if (isArrayLike(children)) {
rendered = flatten([...children], true).map(elementToTree);
} else if (typeof children !== 'undefined') {
rendered = elementToTree(children);
}
Expand Down
25 changes: 22 additions & 3 deletions packages/enzyme-adapter-utils/src/Utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import flatten from 'lodash/flatten';
import createMountWrapper from './createMountWrapper';
import createRenderWrapper from './createRenderWrapper';

Expand Down Expand Up @@ -95,15 +94,35 @@ export function nodeTypeFromType(type) {
return 'function';
}

function isIterable(obj) {
return (
obj != null &&
typeof Symbol === 'function' &&
typeof Symbol.iterator === 'symbol' &&
typeof obj[Symbol.iterator] === 'function'
);
}

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

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

export function elementToTree(el) {
if (el === null || typeof el !== 'object' || !('type' in el)) {
return el;
}
const { type, props, key, ref } = el;
const { children } = props;
let rendered = null;
if (Array.isArray(children)) {
rendered = flatten(children, true).map(elementToTree);
if (isArrayLike(children)) {
rendered = flatten([...children], true).map(elementToTree);
} else if (typeof children !== 'undefined') {
rendered = elementToTree(children);
}
Expand Down
135 changes: 135 additions & 0 deletions packages/enzyme-test-suite/test/RSTTraversal-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,141 @@ describe('RSTTraversal', () => {
expect(spy.callCount).to.equal(4);
});

it('should handle array children', () => {
const spy = sinon.spy();
const twoDivArray = [
<div key="a" />,
<div key="b" />,
];
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const node = $(
<div>
{twoDivArray}

Choose a reason for hiding this comment

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

Suggest we add tests for sibling children (nested arrays and also nested iterables) e.g.

<div>
  {array1}
  {array2}
</div>
<div>
  {iterable1}
  {iterable2}
</div>

</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]);
});

it('should handle array siblings', () => {
const spy = sinon.spy();
const array1 = [
<div key="a" />,
<div key="b" />,
];
const array2 = [
<div key="c" />,
<div key="d" />,
];
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const divC = $(<div key="c" />);
const divD = $(<div key="d" />);
const node = $(
<div>
{array1}
{array2}
</div>,
);
treeForEach(node, spy);
expect(spy.callCount).to.equal(5);
const nodes = spy.args.map(arg => arg[0]);
expect(nodes).to.deep.equal([node, divA, divB, divC, divD]);
});

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>
{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]);
});

it('should handle Map siblings', () => {
const spy = sinon.spy();
const map1 = new Map([
[<div key="a" />],
[<div key="b" />],
]);
const map2 = new Map([
[<div key="c" />],
[<div key="d" />],
]);
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const divC = $(<div key="c" />);
const divD = $(<div key="d" />);
const node = $(
<div>
{map1}
{map2}
</div>,
);
treeForEach(node, spy);
expect(spy.callCount).to.equal(5);
const nodes = spy.args.map(arg => arg[0]);
expect(nodes).to.deep.equal([node, divA, divB, divC, divD]);
});

it('should handle Set children', () => {
const spy = sinon.spy();
const twoDivSet = new Set([
<div key="a" />,
<div key="b" />,
]);
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const node = $(
<div>
{twoDivSet}
</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]);
});

it('should handle Set siblings', () => {
const spy = sinon.spy();
const set1 = new Set([
<div key="a" />,
<div key="b" />,
]);
const set2 = new Set([
<div key="c" />,
<div key="d" />,
]);
const divA = $(<div key="a" />);
const divB = $(<div key="b" />);
const divC = $(<div key="c" />);
const divD = $(<div key="d" />);
const node = $(
<div>
{set1}
{set2}
</div>,
);
treeForEach(node, spy);
expect(spy.callCount).to.equal(5);
const nodes = spy.args.map(arg => arg[0]);
expect(nodes).to.deep.equal([node, divA, divB, divC, divD]);
});

it('should not get trapped from empty strings', () => {
const spy = sinon.spy();
const node = $(
Expand Down