A dive into testing Styled Components and React HOCs
Tags: styledcomponents, react
Published: 2017-08-24 03:40:02

---
title: A dive into testing Styled Components and React HOCs
published: true
description: My experience on snapshot testing with styled-components
tags: styled-components, react
---

For my latest project, it made sense to use the very nice CSS in JS solution called [styled-components](https://github.com/styled-components/jest-styled-components), along with [snapshot testing](https://facebook.github.io/jest/docs/snapshot-testing.html), which is a way to save and compare snapshots of your component's rendering (HTML and CSS) in order to prevent unintended changes. One of this tests can replace several others checking for particular attributes of the rendering.

Be noted that, in order to have nice snapshots using Jest and Styled Components, you have to install this [additional package](https://github.com/styled-components/jest-styled-components). Just read the docs and be sure to do the configuration required in case you use Enzyme, like me.

Finally, when I went ahead using ``shallow()`` by the book to test my button component, I wrote this:

```javascript
it("renders correctly", () => {
  const renderedComponent = shallow(<Button {...props}>Click me!</Button>);
  expect(renderedComponent).toMatchSnapshot();
});
```

The output of the snapshot didn't look like the HTML or CSS I expected:

```text
<Styled(styled.button)
  theme={
    Object {
      "bg": "white",
      "fg": "black",
    }
  }
>
  Click me!
</Styled(styled.button)>
```

This initially puzzled me but then I realized that our ``Button`` component is a stateless functional higher order component (HOC) that works like this:

```javascript
export const Button = props => {
  // assemble some props
  // decide which button to create
  return props.primary
    ? <PrimaryButton {...ourProps}>
        {props.children}
      </PrimaryButton>
    : <RegularButton {...ourProps}>
        {props.children}
      </RegularButton>;
};
``` 

Since we are using ``shallow()`` rendering, we won't get to the second level of components! So, this is where [``dive()``](https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/dive.md) comes in. This function:

> "Shallow render the one non-DOM child of the current wrapper, and return a wrapper around the result."

Turns out that we have two layers under our Button component, one for primary, icon buttons and so, and a "base class" for all of them. This means that we ended up having to do a double dive, so we called it a ``deepDive()``:

```javascript
const deepDive = c => shallow(c).dive().dive();

it("renders correctly", () => {
  const renderedComponent = deepDive(<Button {...props}>Click me!</Button>);
  expect(renderedComponent).toMatchSnapshot();
});
```

In fact, if you don't know how many layers your component will wrap, you can generalize the idea using recursion:

```javascript
const dd = w => (typeof w.type() === "function" ? dd(w.dive()) : w); // recursive diving
const deepDive = c => dd(shallow(c));
```

Look at how the ``type()``function on the ``ShallowWrapper``tells us if we have reached the DOM level or we can still ``dive()``again.

After deep diving, snapshots came out containing only CSS and basic HTML. We now have the liberty to work at ease with the component or any of its subcomponents knowing that no visual alteration will pass unnoticed by our tests.

Interaction tests work (we're only doing basic ones, clicks and disabled and so) and we got 100% coverage because every component layer goes exercised.