From a00ed0bd36bc13933dfde9cb82c6ee7d760e0fd2 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 5 Mar 2019 00:20:10 -0800 Subject: [PATCH] [enzyme-adapter-utils] [fix] allow `node`, not just `element` Fixes #2030. --- .../src/wrapWithSimpleWrapper.jsx | 2 +- .../test/ReactWrapper-spec.jsx | 146 ++++++++++++------ .../test/ShallowWrapper-spec.jsx | 146 ++++++++++++------ 3 files changed, 199 insertions(+), 95 deletions(-) diff --git a/packages/enzyme-adapter-utils/src/wrapWithSimpleWrapper.jsx b/packages/enzyme-adapter-utils/src/wrapWithSimpleWrapper.jsx index 153d03c0f..c0fc2c57d 100644 --- a/packages/enzyme-adapter-utils/src/wrapWithSimpleWrapper.jsx +++ b/packages/enzyme-adapter-utils/src/wrapWithSimpleWrapper.jsx @@ -3,7 +3,7 @@ import { intersects } from 'semver'; import PropTypes from 'prop-types'; const propTypes = { - children: PropTypes.element.isRequired, + children: PropTypes.node.isRequired, }; const Wrapper = (intersects('>= 0.14', React.version) diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index 8cf154832..e39eaa063 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -5408,67 +5408,119 @@ describeWithDOM('mount', () => { }); }); - describe('.renderProp()', () => { - it('returns a wrapper around the node returned from the render prop', () => { - class Foo extends React.Component { - render() { - return
; + wrap() + .withConsoleThrows() + .describe('.renderProp()', () => { + it('returns a wrapper around the node returned from the render prop', () => { + class Foo extends React.Component { + render() { + return
; + } } - } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; + class Bar extends React.Component { + render() { + const { render: r } = this.props; + return
{r()}
; + } } - } - const wrapperA = mount(
} />
); - const renderPropWrapperA = wrapperA.find(Bar).renderProp('render')(); - expect(renderPropWrapperA.find(Foo)).to.have.lengthOf(1); + const wrapperA = mount(
} />
); + const renderPropWrapperA = wrapperA.find(Bar).renderProp('render')(); + expect(renderPropWrapperA.find(Foo)).to.have.lengthOf(1); - const wrapperB = mount(
} />
); - const renderPropWrapperB = wrapperB.find(Bar).renderProp('render')(); - expect(renderPropWrapperB.find(Foo)).to.have.lengthOf(1); + const wrapperB = mount(
} />
); + const renderPropWrapperB = wrapperB.find(Bar).renderProp('render')(); + expect(renderPropWrapperB.find(Foo)).to.have.lengthOf(1); - const stub = sinon.stub().returns(
); - const wrapperC = mount(
); - stub.resetHistory(); - wrapperC.find(Bar).renderProp('render')('one', 'two'); - expect(stub.args).to.deep.equal([['one', 'two']]); - }); + const stub = sinon.stub().returns(
); + const wrapperC = mount(
); + stub.resetHistory(); + wrapperC.find(Bar).renderProp('render')('one', 'two'); + expect(stub.args).to.deep.equal([['one', 'two']]); + }); - it('throws on host elements', () => { - class Div extends React.Component { - render() { - const { children } = this.props; - return
{children}
; + it('throws on host elements', () => { + class Div extends React.Component { + render() { + const { children } = this.props; + return
{children}
; + } } - } - const wrapper = mount(
).childAt(0); - expect(wrapper.is('div')).to.equal(true); - expect(() => wrapper.renderProp('foo')).to.throw(); - }); + const wrapper = mount(
).childAt(0); + expect(wrapper.is('div')).to.equal(true); + expect(() => wrapper.renderProp('foo')).to.throw(); + }); - wrap() - .withOverride(() => getAdapter(), 'wrap', () => undefined) - .it('throws with a react adapter that lacks a `.wrap`', () => { - class Foo extends React.Component { - render() { - return
; + wrap() + .withOverride(() => getAdapter(), 'wrap', () => undefined) + .it('throws with a react adapter that lacks a `.wrap`', () => { + class Foo extends React.Component { + render() { + return
; + } } - } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; + class Bar extends React.Component { + render() { + const { render: r } = this.props; + return
{r()}
; + } } + + const wrapper = mount(
} />
); + expect(() => wrapper.find(Bar).renderProp('render')).to.throw(RangeError); + }); + + describeIf(is('>= 16'), 'allows non-nodes', () => { + function MyComponent({ val }) { + return x} />; + } + + function ComponentWithRenderProp({ val, r }) { + return r(val); } - const wrapper = mount(
} />
); - expect(() => wrapper.find(Bar).renderProp('render')).to.throw(RangeError); + it('works with strings', () => { + const wrapper = mount(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')('foo'); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(''); + }); + + it('works with numbers', () => { + const wrapper = mount(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(42); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(0); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(NaN); + }); + + it('works with arrays', () => { + const wrapper = mount(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')([]); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(['a']); + + wrapper.find(ComponentWithRenderProp).renderProp('r')([Infinity]); + }); + + it('works with false', () => { + const wrapper = mount(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(false); + }); + + it('throws with true', () => { + const wrapper = mount(); + + expect(() => wrapper.find(ComponentWithRenderProp).renderProp('r')(true)).to.throw(); + }); }); - }); + }); describe('lifecycle methods', () => { describeIf(is('>= 16.3'), 'getDerivedStateFromProps', () => { diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index bda4036c9..422ee07f4 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -5489,67 +5489,119 @@ describe('shallow', () => { }); }); - describe('.renderProp()', () => { - it('returns a wrapper around the node returned from the render prop', () => { - class Foo extends React.Component { - render() { - return
; + wrap() + .withConsoleThrows() + .describe('.renderProp()', () => { + it('returns a wrapper around the node returned from the render prop', () => { + class Foo extends React.Component { + render() { + return
; + } } - } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; + class Bar extends React.Component { + render() { + const { render: r } = this.props; + return
{r()}
; + } } - } - const wrapperA = shallow(
} />
); - const renderPropWrapperA = wrapperA.find(Bar).renderProp('render')(); - expect(renderPropWrapperA.find(Foo)).to.have.lengthOf(1); + const wrapperA = shallow(
} />
); + const renderPropWrapperA = wrapperA.find(Bar).renderProp('render')(); + expect(renderPropWrapperA.find(Foo)).to.have.lengthOf(1); - const wrapperB = shallow(
} />
); - const renderPropWrapperB = wrapperB.find(Bar).renderProp('render')(); - expect(renderPropWrapperB.find(Foo)).to.have.lengthOf(1); + const wrapperB = shallow(
} />
); + const renderPropWrapperB = wrapperB.find(Bar).renderProp('render')(); + expect(renderPropWrapperB.find(Foo)).to.have.lengthOf(1); - const stub = sinon.stub().returns(
); - const wrapperC = shallow(
); - stub.resetHistory(); - wrapperC.find(Bar).renderProp('render')('one', 'two'); - expect(stub.args).to.deep.equal([['one', 'two']]); - }); + const stub = sinon.stub().returns(
); + const wrapperC = shallow(
); + stub.resetHistory(); + wrapperC.find(Bar).renderProp('render')('one', 'two'); + expect(stub.args).to.deep.equal([['one', 'two']]); + }); - it('throws on host elements', () => { - class Div extends React.Component { - render() { - const { children } = this.props; - return
{children}
; + it('throws on host elements', () => { + class Div extends React.Component { + render() { + const { children } = this.props; + return
{children}
; + } } - } - const wrapper = shallow(
); - expect(wrapper.is('div')).to.equal(true); - expect(() => wrapper.renderProp('foo')).to.throw(); - }); + const wrapper = shallow(
); + expect(wrapper.is('div')).to.equal(true); + expect(() => wrapper.renderProp('foo')).to.throw(); + }); - wrap() - .withOverride(() => getAdapter(), 'wrap', () => undefined) - .it('throws with a react adapter that lacks a `.wrap`', () => { - class Foo extends React.Component { - render() { - return
; + wrap() + .withOverride(() => getAdapter(), 'wrap', () => undefined) + .it('throws with a react adapter that lacks a `.wrap`', () => { + class Foo extends React.Component { + render() { + return
; + } } - } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; + class Bar extends React.Component { + render() { + const { render: r } = this.props; + return
{r()}
; + } } + + const wrapper = shallow(
} />
); + expect(() => wrapper.find(Bar).renderProp('render')).to.throw(RangeError); + }); + + describeIf(is('>= 16'), 'allows non-nodes', () => { + function MyComponent({ val }) { + return x} />; + } + + function ComponentWithRenderProp({ val, r }) { + return r(val); } - const wrapper = shallow(
} />
); - expect(() => wrapper.find(Bar).renderProp('render')).to.throw(RangeError); + it('works with strings', () => { + const wrapper = shallow(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')('foo'); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(''); + }); + + it('works with numbers', () => { + const wrapper = shallow(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(42); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(0); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(NaN); + }); + + it('works with arrays', () => { + const wrapper = shallow(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')([]); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(['a']); + + wrapper.find(ComponentWithRenderProp).renderProp('r')([Infinity]); + }); + + it('works with false', () => { + const wrapper = shallow(); + + wrapper.find(ComponentWithRenderProp).renderProp('r')(false); + }); + + it('throws with true', () => { + const wrapper = shallow(); + + expect(() => wrapper.find(ComponentWithRenderProp).renderProp('r')(true).shallow()).to.throw(); + }); }); - }); + }); describe('lifecycle methods', () => { describe('disableLifecycleMethods option', () => {