enzyme vs unexpected-react
This was a tweet storm (actually more of a light-wind) comparing tests and output from enzyme and unexpected-react.
If you’re reviewing what to use for testing your react components, take a quick look through these examples and see which you find more useful. (TL;DR: There’s a clear winner 😊)
The simplest test
Here’s the first super simple test (these tests are 100% equivalent)
… and the outputs if they fail
Let’s trigger an event
Still in the shallow renderer, let’s trigger an event (it works just the same in all renderers)
and the outputs if the render is wrong (we’ll see this test again!)
Now with the same test, but this time with a different problem. Note you can’t actually tell what the problem is from the enzyme test output
Great question, I’m glad you asked…
(we’re working on typings)
Now we’ll render two buttons, and try and trigger the event on the one with the class “second”
But the className isn’t set, so it can’t find the button to trigger the event on:
As the className wasn’t set, we can use indexes to identify the button. It was pointed out on the twitters that using indexes is a bad idea generally, and it is, hopefully in the real world there’d be something identifying the button you want to click on (you can match on anything, contents, wrapper components, props etc).
The eventTarget prop is optional, and tells unexpected-react which component we want to be the target for the event if we’re targeting a sub-component.
Jest snapshot tests work out of the box, and with all renderers (shallow, full DOM and the react-test-renderer). The difference with unexpected-react is that the snapshots are objects not strings, so you get smart diffs
Because the snapshots are smart, it picks up on things that would otherwise be missed. For example, if you forget to bind your function, a standard jest snapshot test will still pass, with unexpected-react you get a failure with a helpful error message
It works the other way too. If the order of the classes in className changes, a jest snapshot will fail because it’s only comparing strings, unexpected-react will pass because it knows the order doesn’t matter.
Full DOM rendering
When using the full DOM renderer (you can use the built in helpers, or the standard ReactDOM.render() method), you get to validate the full virtual DOM as shown in the React devtools.
Notice how the custom components are greyed out as they’re not included in the assertion. But they could be, so you can test to any level you like. It’s like having a shallow renderer that renders 2 or 3 or however many levels you like.
Let’s use ‘to contain’ to try and keep our tests as less brittle as possible.
and the output when they fail (here’s another case where you only see the actual problem with unexpected-react):
With the unexpected-react output, you can go and fix either the test or the component straight away, no starting your app, switching to the browser, digging around trying to find out what’s gone wrong.
Snapshot tests work out of the box with the full DOM renderer, and you get the full tree there too, so you can see exactly whether the changes are in your components or the rendered HTML.
You can search for a subtree using ‘queried for’ (this also works on all three renderers). Once you’ve searched, you can continue to assert on that part of the subtree, or just take a snapshot.
If the query fails to find the results, here’s the output from the two tests:
Thanks for reading, I hope you’ll give unexpected-react a try, I’ve found it means I switch to the browser less (especially when coupled with wallaby.js), and many problems can be fixed directly from the output of the tests.