
Idiomatic React Testing Patterns - jfdk
https://gist.github.com/joshdover/235714771d94509a83609b16d232014a
======
jitl
See also Enzyme, a testing library specifically for React, that allows you to
easy assert on both deep and shallow renders of the React DOM.

[https://github.com/airbnb/enzyme#basic-
usage](https://github.com/airbnb/enzyme#basic-usage)

~~~
jfdk
We haven't tried Enzyme, but we tend to prefer not adding more JS tools when
we don't need to. JS is already a land of wayyyy too many tools and minimizing
when possible can be a huge advantage when onboarding new devs onto a project.

Also the DOM api is actually pretty simple to use when it comes to traversing
the DOM. No need for "jQuery mimicking." Keep it simple.

~~~
Klathmon
This is a bit off topic, but why such aversion to purpose built tools in JS
land?

In my experience it's much harder to onboard devs to a custom-ish process than
it is to hand them a purpose built tool with proper documentation and lots of
examples of real-world usage to learn from.

I tend to try to use already made tools over doing it myself* as it makes
onboarding easier, lightens my cognitive load, reduces my testing surface, and
is generally quicker than coming up with my own solution.

* A bit of a disclaimer... I mean well made, well tested, and well supported tools taking into account the time cost of doing it myself, the complexity of the tool, how important/ingrained it will be in my application, the number of contributors in the project, the test coverage of the project, the speed/ease it can be switched out, how well it actually solves my problem at hand, and a ton of other things. I do not mean that you should blindly use every tools you can whenever possible, or that you should use it because Facebook/Google/Other-Company uses it.

~~~
jfdk
What I should have said is "minimize tools when it makes sense" rather than
"when possible." There are some tools that are more trouble than they're worth
(for example, I feel this strongly about Jest).

Enzyme isn't necessarily one of those, like I said I haven't used it, but I
also haven't found a need to. Some abstractions over TestUtils' event
simulation would certainly be valuable.

What I am trying to present here are patterns of different testing scenarios
in a format that should be useful regardless of the testing tools you may be
using.

------
cjcenizal
I've found the best testing pattern is to test the interface of the component,
not the implementation.

This means treating the component as an opaque function with inputs (props)
and outputs (the rendered result). Your tests just need to that verify that
different prop values result in the DOM changes or callbacks that you expect.

~~~
shepmaster
Do you use any tools to make the assertions on the resulting DOM simpler?

What about any components that maintain internal state; do you just step them
through the states and assert the DOM state as well?

~~~
cjcenizal
I built this testing tool at a previous employer:
[https://github.com/smaato/react-test-kit](https://github.com/smaato/react-
test-kit). It's very very simple, it just exposes jQuery-like methods for
querying the DOM (and internally uses Sizzle).

Here's an example of how we used react-test-kit to test a SearchBox component:
[https://github.com/smaato/ui-
framework/blob/develop/src/fram...](https://github.com/smaato/ui-
framework/blob/develop/src/framework/searchBox/SearchBox.spec.jsx)

Here's the interactive component example: [http://smaato.github.io/ui-
framework/#/searchbox](http://smaato.github.io/ui-framework/#/searchbox)

------
pietro
From what Dan Abramov has been posting on Twitter recently, findDOMNode() is
in the process of being deprecated, so rather than writing

    
    
        const component = ReactDOM.findDOMNode(TestUtils.renderIntoDocument(
            <MyComponent {...props} />
        ));
    

we should be writing

    
    
        let node;
        const component = TestUtils.renderIntoDocument(
            <MyComponent {...props} ref={n => node = n}/>
        );
    

[https://gist.github.com/gaearon/7f0e03d3028016bfabfad641720d...](https://gist.github.com/gaearon/7f0e03d3028016bfabfad641720d3de1)

~~~
jfdk
Good to know, will update the examples when I have time. Not sure I'm a big
fan of it though, doesn't seem as clear to a React noob what is going on with
ref?

------
djacobs
I looked through the patterns and I wonder what makes them 'idiomatic'?

I've found it useful to use wrapper libraries like Enzyme [0] and Teaspoon [1]
when testing React components and interactions.

[0] [https://github.com/airbnb/enzyme](https://github.com/airbnb/enzyme)

[1] [https://github.com/jquense/teaspoon](https://github.com/jquense/teaspoon)

------
sotojuan
Cool post but I'll play devil's advocate and ask what's so idiomatic about
this. Can someone comment if this is what most the community is going? Not
blaming the author at all, but skeptical of anything called "idiomatic"
nowadays.

------
haukur
It can be very helpful to define all the different states (as props) for the
set of components you're building. The data can be static or the result of
dynamic calls to API endpoints (both approaches have benefits and trade-offs).
For instance, if you're building a page with a list of items and at most 10
should be shown at a time, you could define the empty state (0 items), the
half-full (1-10 items) and the overloaded state (11+ items, requiring
pagination). Then you can implement the actual UI.

When this is done (and you're happy with the way it looks), you can make your
test suite iterate over each of the different states and capture a screenshot
of the UI. When something changes, you will know (the test suite should diff
it). This approach is obviously mostly for presentation rather than
functionality.

The benefits are not limited to testing, this is also very helpful in
development, since you could switch between different states very quickly
without having to constantly change URLs (for different API results). One
method is using a dropdown overlay (only present in the development build).
It's also very helpful during code review.

------
tengbretson
In my experience, as long as you have a well tested data model and use
proptypes/Flow/TypeScript, testing the components themselves becomes almost
entirely irrelevant.

However, I can see the utility of component testing if I were wrapping
something like Ace editor or a jQuery plugin or something of that nature.

~~~
shepmaster
Do you use anything like Redux? When writing Redux state reducers and actions,
it all seems so... simple. There's a lot of code like `return {
...currentState, newProp }` which seems too silly to test.

~~~
tengbretson
I often leave off tests for strictly "synchronous" actions like `return {
...currentState, newProp }`. Most of my tests are for confirming that the
right paths are taken for actions that trigger one or more async operations to
ensure correct failure case handling.

------
lhnz
Do others agree with the `getComponent` pattern described there?

I do like it but I'm wary of moving away from the `beforeEach` pattern. The
`beforeEach` pattern is much more common and is a consistent interface that
engineers can easily pickup and won't need to recreate in every single test
file.

~~~
jfdk
I've found beforeEach breaks down super quickly as soon as you need to change
the input props. Keeping things as purely functional as possible also helps
manage complexity when writing tests in a large suite. You don't have to trace
through all the beforeEach of each describe/context block. That said we use a
healthy combination of both, as with everything know when to use the right
tool.

