Skip to content

Commit

Permalink
Fix ShallowWrapper for array-rendering components
Browse files Browse the repository at this point in the history
  • Loading branch information
vsiao authored and ljharb committed Jan 30, 2018
1 parent f9cec19 commit 2385783
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 39 deletions.
4 changes: 3 additions & 1 deletion packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ class ReactSixteenAdapter extends EnzymeAdapter {
key: cachedNode.key || undefined,
ref: cachedNode.ref,
instance: renderer._instance,
rendered: elementToTree(output),
rendered: Array.isArray(output)
? flatten(output).map(elementToTree)
: elementToTree(output),
};
},
simulateEvent(node, event, ...args) {
Expand Down
2 changes: 1 addition & 1 deletion packages/enzyme-test-suite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.5.1"
}
}
}
13 changes: 13 additions & 0 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3117,6 +3117,19 @@ describeWithDOM('mount', () => {
expect(rendered.html()).to.equal(null);
});

itIf(REACT16, 'works with class components that return arrays', () => {
class Foo extends React.Component {
render() {
return [<div />, <div />];
}
}
const wrapper = mount(<Foo />);
expect(wrapper).to.have.lengthOf(1);
expect(wrapper.type()).to.equal(Foo);
expect(wrapper.children()).to.have.lengthOf(2);
expect(wrapper.find('div')).to.have.lengthOf(2);
});

itIf(is('>=15 || ^16.0.0-alpha'), 'works with SFCs that return null', () => {
const Foo = () => null;

Expand Down
11 changes: 11 additions & 0 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3964,6 +3964,17 @@ describe('shallow', () => {
expect(rendered.html()).to.equal(null);
});

itIf(REACT16, 'works with class components that return arrays', () => {
class Foo extends React.Component {
render() {
return [<div />, <div />];
}
}
const wrapper = shallow(<Foo />);
expect(wrapper).to.have.lengthOf(2);
expect(wrapper.find('div')).to.have.lengthOf(2);
});

itIf(is('>=15 || ^16.0.0-alpha'), 'works with SFCs that return null', () => {
const Foo = () => null;

Expand Down
41 changes: 18 additions & 23 deletions packages/enzyme/src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ function filterWhereUnwrapped(wrapper, predicate) {
return wrapper.wrap(compact(wrapper.getNodesInternal().filter(predicate)));
}

function privateSetNodes(wrapper, nodes) {
if (!nodes) {
privateSet(wrapper, NODE, null);
privateSet(wrapper, NODES, []);
} else if (!Array.isArray(nodes)) {
privateSet(wrapper, NODE, nodes);
privateSet(wrapper, NODES, [nodes]);
} else {
privateSet(wrapper, NODE, nodes[0]);
privateSet(wrapper, NODES, nodes);
}
privateSet(wrapper, 'length', wrapper[NODES].length);
}

/**
* @class ReactWrapper
*/
Expand All @@ -79,25 +93,12 @@ class ReactWrapper {
privateSet(this, RENDERER, renderer);
renderer.render(nodes, options.context);
privateSet(this, ROOT, this);
const node = this[RENDERER].getNode();
privateSet(this, NODE, node);
privateSet(this, NODES, [node]);
this.length = 1;
privateSetNodes(this, this[RENDERER].getNode());
} else {
privateSet(this, UNRENDERED, null);
privateSet(this, RENDERER, root[RENDERER]);
privateSet(this, ROOT, root);
if (!nodes) {
privateSet(this, NODE, null);
privateSet(this, NODES, []);
} else if (!Array.isArray(nodes)) {
privateSet(this, NODE, nodes);
privateSet(this, NODES, [nodes]);
} else {
privateSet(this, NODE, nodes[0]);
privateSet(this, NODES, nodes);
}
this.length = this[NODES].length;
privateSetNodes(this, nodes);
}
privateSet(this, OPTIONS, root ? root[OPTIONS] : options);
}
Expand Down Expand Up @@ -223,11 +224,7 @@ class ReactWrapper {
if (this[ROOT] !== this) {
throw new Error('ReactWrapper::update() can only be called on the root');
}
this.single('update', () => {
const node = this[RENDERER].getNode();
this[NODE] = node;
this[NODES] = [node];
});
privateSetNodes(this, this[RENDERER].getNode());
return this;
}

Expand Down Expand Up @@ -258,9 +255,7 @@ class ReactWrapper {
if (this[ROOT] !== this) {
throw new Error('ReactWrapper::mount() can only be called on the root');
}
this.single('mount', () => {
this[RENDERER].render(this[UNRENDERED], this[OPTIONS].context, () => this.update());
});
this[RENDERER].render(this[UNRENDERED], this[OPTIONS].context, () => this.update());
return this;
}

Expand Down
28 changes: 14 additions & 14 deletions packages/enzyme/src/ShallowWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ function getRootNode(node) {
return node.rendered;
}

function privateSetNodes(wrapper, nodes) {
if (!Array.isArray(nodes)) {
privateSet(wrapper, NODE, nodes);
privateSet(wrapper, NODES, [nodes]);
} else {
privateSet(wrapper, NODE, nodes[0]);
privateSet(wrapper, NODES, nodes);
}
privateSet(wrapper, 'length', wrapper[NODES].length);
}

/**
* @class ShallowWrapper
*/
Expand All @@ -122,26 +133,16 @@ class ShallowWrapper {
instance.componentDidMount();
});
}
privateSet(this, NODE, getRootNode(this[RENDERER].getNode()));
privateSet(this, NODES, [this[NODE]]);
this.length = 1;
privateSetNodes(this, getRootNode(this[RENDERER].getNode()));
} else {
privateSet(this, ROOT, root);
privateSet(this, UNRENDERED, null);
privateSet(this, RENDERER, root[RENDERER]);
if (!Array.isArray(nodes)) {
privateSet(this, NODE, nodes);
privateSet(this, NODES, [nodes]);
} else {
privateSet(this, NODE, nodes[0]);
privateSet(this, NODES, nodes);
}
this.length = this[NODES].length;
privateSetNodes(this, nodes);
}
privateSet(this, OPTIONS, root ? root[OPTIONS] : options);
}


/**
* Returns the root wrapper
*
Expand Down Expand Up @@ -227,8 +228,7 @@ class ShallowWrapper {
throw new Error('ShallowWrapper::update() can only be called on the root');
}
this.single('update', () => {
this[NODE] = getRootNode(this[RENDERER].getNode());
this[NODES] = [this[NODE]];
privateSetNodes(this, getRootNode(this[RENDERER].getNode()));
});
return this;
}
Expand Down

0 comments on commit 2385783

Please sign in to comment.