diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js index 7dd8423f5..cd15a12dd 100644 --- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js +++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js @@ -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) { diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index 648b64cfd..7fd6a0224 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -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 [
,
]; + } + } + const wrapper = mount(); + 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; diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 3f88565f5..fc5da81d0 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -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 [
,
]; + } + } + const wrapper = shallow(); + 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; diff --git a/packages/enzyme/src/ReactWrapper.js b/packages/enzyme/src/ReactWrapper.js index 430af63e8..a039b6edd 100644 --- a/packages/enzyme/src/ReactWrapper.js +++ b/packages/enzyme/src/ReactWrapper.js @@ -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 */ @@ -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); } @@ -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; } @@ -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; } diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index f8f4ca792..f28a8c30b 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -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 */ @@ -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 * @@ -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; }