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

Sentiment analysis of Shopee layoffs using Reddit commentsSentiment analysis of Shopee layoffs using Reddit comments
Do Dollar Cost Average really work?Do Dollar Cost Average really work?
Using DataRobot to predict the price of million-dollar HDB resale flatsUsing DataRobot to predict the price of million-dollar HDB resale flats

Copyright © Terence Lucas Yap

Powered by Gatsby JS