Testing render props component

Viewed 3443

If I have a render prop component like so:

export class ParentComponent extends React.Component {
    render() {
        <Loader loading={false}>
                {() =>
                    <SomeChildComponent />
               }
    }
}

How can I unit test it?

test('should output child component',  => {
    const wrapper = shallow(<ParentComponent />);
    expect(wrapper.find(SomeChildComponent).length).to.be(1);
}

Fails - If I test for the Loader component instead - the test passes:

  expect(wrapper.find(Loader).length).to.be(1);

How can I test that SomeChildComponent is output?

2 Answers

Your inner function () =><SomeChildComponent /> never executed, so your test says the truth that SomeChildComponent does not exists. You just need to call it (notice extra brackets):

export class ParentComponent extends React.Component {
    render() {
        return (<Loader loading={false}>
            { (() =><SomeChildComponent />)()}
        </Loader>);
    }
}

We can refactor it into more render-props way:

export class ParentComponent extends React.Component {
    render() {
        return (<Loader loading={false}>
            { this.props.render()}
        </Loader>);
    }
}

And then change the test accordingly:

const render = () => <SomeChildComponent />;
const wrapper = shallow(
    <ParentComponent render={render} />
);

However, this test becomes not really a unit test, as it tests more then one component at once. To get rid of this dependency we can just check if render() is called:

const renderMock = jest.fn();
const wrapper = shallow(<ParentComponent render={ renderMock } />);
expect(wrapper.find('Loader').exists()).toBeTruthy();
expect(renderMock).toHaveBeenCalled();

If your render() accepts some arguments you can consider using .toHaveBeenCalledWith

If you are using Enzyme 3.8.0 or higher you can follow this guide:

https://medium.com/@fran.villar.rosa/how-to-test-renderprops-with-enzyme-3-8-0-c079622f68ca

On your example:

export class ParentComponent extends React.Component {
    render() {
        <Loader loading={false}>
                {() =>
                    <SomeChildComponent />
               }
    }
}


const wrapper = shallow(<ParentComponent />)
  .find(Loader)
  .renderProp('children')({yourPropsHere: 'example'});

expect(wrapper).toMatchSnapshot()

You have to import your Loader component in your test file.

Related