From bd370f6f604a4fdb8fcd1588edc52fec5193e359 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 26 Mar 2019 10:34:49 -0400 Subject: [PATCH] [Fix] `mount`/`shallow`: `renderProp`: improve error messages --- .../test/shared/methods/renderProp.jsx | 27 ++++++++++++++++++- packages/enzyme/src/ReactWrapper.js | 6 ++--- packages/enzyme/src/ShallowWrapper.js | 6 ++--- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx b/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx index 99db157a6..4b6a3eb84 100644 --- a/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx @@ -13,6 +13,7 @@ import { is } from '../../_helpers/version'; export default function describeRenderProp({ Wrap, WrapRendered, + WrapperName, }) { wrap() .withConsoleThrows() @@ -25,7 +26,7 @@ export default function describeRenderProp({ class Bar extends React.Component { render() { const { render: r } = this.props; - return
{r()}
; + return
{typeof r === 'function' && r()}
; } } class RendersBar extends React.Component { @@ -50,6 +51,30 @@ export default function describeRenderProp({ expect(stub.args).to.deep.equal([['one', 'two']]); }); + it('throws on a non-string prop name', () => { + const wrapper = Wrap( {}} />); + expect(() => wrapper.renderProp()).to.throw( + TypeError, + `${WrapperName}::renderProp(): \`propName\` must be a string`, + ); + }); + + it('throws on a missing prop', () => { + const wrapper = Wrap( {}} />); + expect(() => wrapper.renderProp('nope')).to.throw( + Error, + `${WrapperName}::renderProp(): no prop called “nope“ found`, + ); + }); + + it('throws on a non-function render prop value', () => { + const wrapper = Wrap(); + expect(() => wrapper.renderProp('render')).to.throw( + TypeError, + `${WrapperName}::renderProp(): expected prop “render“ to contain a function, but it holds “object“`, + ); + }); + it('throws on host elements', () => { class Div extends React.Component { render() { diff --git a/packages/enzyme/src/ReactWrapper.js b/packages/enzyme/src/ReactWrapper.js index 87c048713..64ed81e16 100644 --- a/packages/enzyme/src/ReactWrapper.js +++ b/packages/enzyme/src/ReactWrapper.js @@ -794,15 +794,15 @@ class ReactWrapper { throw new TypeError('ReactWrapper::renderProp() can only be called on custom components'); } if (typeof propName !== 'string') { - throw new TypeError('`propName` must be a string'); + throw new TypeError('ReactWrapper::renderProp(): `propName` must be a string'); } const props = this.props(); if (!has(props, propName)) { - throw new Error(`no prop called “${propName}“ found`); + throw new Error(`ReactWrapper::renderProp(): no prop called “${propName}“ found`); } const propValue = props[propName]; if (typeof propValue !== 'function') { - throw new TypeError(`expected prop “${propName}“ to contain a function, but it holds “${typeof prop}“`); + throw new TypeError(`ReactWrapper::renderProp(): expected prop “${propName}“ to contain a function, but it holds “${typeof propValue}“`); } return (...args) => { diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index b72b414db..7c2e79f6d 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -1191,15 +1191,15 @@ class ShallowWrapper { throw new TypeError('ShallowWrapper::renderProp() can only be called on custom components'); } if (typeof propName !== 'string') { - throw new TypeError('`propName` must be a string'); + throw new TypeError('ShallowWrapper::renderProp(): `propName` must be a string'); } const props = this.props(); if (!has(props, propName)) { - throw new Error(`no prop called “${propName}“ found`); + throw new Error(`ShallowWrapper::renderProp(): no prop called “${propName}“ found`); } const propValue = props[propName]; if (typeof propValue !== 'function') { - throw new TypeError(`expected prop “${propName}“ to contain a function, but it holds “${typeof prop}“`); + throw new TypeError(`ShallowWrapper::renderProp(): expected prop “${propName}“ to contain a function, but it holds “${typeof propValue}“`); } return (...args) => {