Testing Child Component Props With React-Redux And Enzyme

Testing Child Component Props With React-Redux And Enzyme

Documenting An Undocumented Enzyme Feature

Introduction

So, I encountered a pretty silly mistake recently that was causing my unit tests to keep failing. I had to modify a component which contains a user's ID as its prop. The application's state is managed by React-Redux.

The user's ID is passed down to a <ChildComponent /> together with other prop values.

class ParentComponent extends Component {
    // SuperAgent to retrieve the user's ID and manage the state via Redux
}
...
render() {
    return (
        <ChildComponent
            userID={userID}
            val={props.val}
        />
    )
}

Small Change, Huge Impact

Due to this small change, my previous tests kept failing. You might think that a simple setProps() method on <ParentComponent /> would resolve the issue.

// Mocking function for userID
const store = configureStore()({
    user: {
        id: 'userId'
    }
});
component = mount(
    <Provider store={store}>
        <ParentComponent {...props} />
    <Provider />
);

let ChildComponent = component.find('ChildComponent');
component.setProps({userID: 'foo', val: 'bar'});
expect(ChildComponent.prop('val').toBe('bar'));

Unfortunately, it was a spectacular failure.

$ Comparing two different types of values. Expected string but received undefined.

Apparently the <ChildComponent /> was returning undefined for its 'val' props.

What's The Difference between Shallow and Full DOM Rendering?

Shallow rendering (shallow()) is used to test a component in isolation. Full DOM rendering (mount()) on the other hand, allows testing of the component lifecycle and child component behaviors.

Shallow Rendering
Full DOM Rendering

Silly me!

I just need to call setProps() on <ChildComponent /> instead of on <ParentComponent /> right?

let ChildComponent = component.find('ChildComponent');
ChildComponent.setProps({userID: 'foo', val: 'bar'});
expect(ChildComponent.prop('bal').toBe('bar'));

Wrong!

$ReactWrapper::setProps() can only be called on the root

Turns out, Enzyme has an undocumented feature, "children:", which when used on setProps(), allows us to set the props on child components.

However, in the above scenario, the root component was <Provider /> instead of <ParentComponent />. Due to this misapplication, I was calling setProps() on <Provider /> instead of <ParentComponent />.

By adding the children syntax on setProps(), the props are properly passed down from <ParentComponent /> to <ChildComponent />.

component.setProps({children: <ParentComponent {userID: 'foo', val: 'bar'}});
PASS  src/components/header/ParentComponent.test.js

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.193s

Latest Posts

Testing Child Component Props With React-Redux And EnzymeTesting Child Component Props With React-Redux And Enzyme
Higher-Order ComponentsHigher-Order Components
A neat JavaScript trickA neat JavaScript trick