Testing React components with Huxley

React components are pure functions which map a state to React virtual DOM. This purity makes it very easy to automate tests, in particular when used together with Huxley. In the following article I'll explain how I managed to automate React component tests such that they can be described in a fully declarative way.

The idea behind Huxley is simple: You give it a HTML page and Huxley takes a screenshot. If you later change your HTML or stylesheets in a way that alters the looks of the page, you'll notice it because the image changes. When used in conjuction with the image diff view that GitHub provides, it makes it very easy to spot if a pull request changes anything in the UI.

Remember that React components are pure functions which take a state as input. All you need to render a HTML page with a single component is the components constructor and the input state. Everything else is boilerplate and can be generated.

Implementation

I have one JavaScript file for each React component that is tested. Multiple input states can be provided, to make it easier to compare them. Here is a test spec for a WardrobePlayer component. The player can be in one of three states and I'm interested how the component looks in each of those.

var undecidedPlayer = { ... };
var playerWithRole  = { ... };
var readyPlayer     = { ... };

window.spec = {
    title: 'wardrobe-player',

    // The components constructor.
    createComponent: rmx.Components.WardrobePlayer,

    // The input states to test.
    testCases:
        [ undecidedPlayer
        , playerWithRole
        , readyPlayer
        ]
}

The corresponding HTML file loads this script and uses a huxley spec driver to render the component. The driver renders a button for each input state so that you can easily switch between them.

image

All JavaScript files which describe the Huxley tests live in a single directory. A Makefile automatically generates a HTML page for each JavaScript file that there is, as well as the Huxleyfile.

Conclusion

The tests have served me well. Though there is potential for improvement.

I generate a single Huxleyfile for all tests, but Huxley doesn't have good support for running only specific test cases. One workaround is to create a separate Huxleyfile for each component.

Related to that, it would be great to have support for running multiple browsers in parallel and storing their screenshots separately.

I'm reluctant to force Selenium (and thus Java) on my coworkers. Having an automated build bot which checks pull request and runs the tests would be useful here. I have a spare MacBook lying around which I can use for just that.