Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing render props component

Tags:

reactjs

enzyme

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?

like image 647
Mike Rifgin Avatar asked Sep 20 '18 08:09

Mike Rifgin


People also ask

How do you test a component with props?

Testing The ParentComponent is Setting Props Correctlyrender(<ParentComponent open data="some data" />); // Check that the Jest mock function is called with an object. // Use 'expect. objectContaining' to make sure any other default // React props are ignored. expect(mockChildComponent). toHaveBeenCalledWith( expect.

How do I know if a component is rendered?

Using React DevTools to highlight what components rerendered To enable it, go to "Profiler" >> click the "Cog wheel" on the right side of the top bar >> "General" tab >> Check the "Highlight updates when components render." checkbox.

How do I render a component in props?

The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function. In simple words, render props are simply props of a component where you can pass functions. These functions need to return elements, which will be used in rendering the components.


1 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

like image 122
Alex Avatar answered Oct 21 '22 11:10

Alex