Unit testing higher order components using enzyme

03.11.2017

Not all the components you write for your react application can be divided into Stateful and Stateless (dumb) categories. There is a 3rd yet advanced type of components in React that are called Higher order components. If you don’t know about them yet, you can always refer to the documentation and to see them in real world action, I’ve already wrote about them here.

Get to the point

The point of this piece of writing is to demonstrate how to unit test these Higher Order Components. For the purpose of this article, I suggest using Enzyme and Jest, but feel free to use whatever library that suits you.

One of the common HOCs I write for every project of mine is called withConditional. It’s simply supposed to render a component if and only if the condition passes, otherwise just return a null object.

import React from 'react';
const withConditional = Component =>
  function withConditionalComponent({ condition, ...props }) {
    if (condition) {
      return <Component {...props} />;
    }
    return null;
};
export default withConditional;

As you can see, when the condition passed to the HOC, fulfills, it returns the component, otherwise just returns null.

So how to unit test the HOC? There are surprisingly less than a few articles talking about unit testing them, and I had a hard time figuring out the proper way. Recently the solution just clicked!

Solution

To properly test these badass components, you just need to know that they are simple stupid functions and that’s all! So we can treat them as plain functions that wrap our components and decorate them. The way we use them is like:

const ConditionalComponent = withConditional(<MyComponent />);
class HelloWorld extends React.Component {
  render() {
    return (<ConditionalComponent condition={3 > 4} />);
  }
}

So we should use the exact same way to unit test them as well.

The important thing to take into account here is that always test them for all states. For instance, if our HOC can handle two different states, depending on the condition passed to it, then we MUST test for both states.

When condition passes:

it(
  'should render the component only when the condition passes'
  , () => {
  const ConditionalComponent = withConditional(Component);
  const wrapper = shallow(
    <ConditionalComponent condition={true} />
  );
  expect(wrapper.html()).not.toBe(null);
});

When condition fails:

it(
  'should return null when the condition fails'
  , () => {
const ConditionalComponent = withConditional(Component);
const wrapper = shallow(
    <ConditionalComponent condition={false} />
  );
expect(wrapper.html()).toBe(null);
});

Wrap Up

I hope this article helps you as well, since it was very usefull for me to look at the way I need to actually implement my unit tests on these components.

Have fun and test it up.