React fast, use Enzyme

Erez Carmel
Israeli Tech Radar
Published in
4 min readJan 11, 2022

--

While ReactJS is growing and becoming the lead UI library, we need also an easy utility to test it.
Yes, ReactJS comes with its TestUtils, developed by the React team, but also in their documentation they recommend using AirBnB’s Enzyme for easier testing.

Before we talk about Enzyme, let’s understand what React TestUtils gives us.
Because of ReactJS unique DOM manipulation, testing it with common frameworks like Jasmine for example, is more complicated. Facebook React team has developed their internal testing utility to test the DOM manipulations easier. The drawback of the TestUtils is its over-complexity of methods, and I’ll explain…

Let’s say we want to find a DOM element in our page, an easy and common requirement, right? TestUtils provide us the `scryRenderedComponentsWithTag` method. It’ll so the work... BUT! only if we’re looking for only one element. What happens if we have more than one element of the same type on our page? TestUtils provide us a different method for that: `findRenderedDOMComponentWithTag`.
At that point, the developer asks himself “Why do I need 2 different methods? I used to do it with jQuery’s ‘find’ method!”.

Tada! This is what Enzyme is here for - to simplify the TestUtils methods over complexity.
While being based on React TestUtils, Enzyme provides a jQuery-like APIs to make React DOM manipulation more intuitive & flexible and doesn’t require the developer to use a different method for each DOM action.
If we were using the DOM element search example for TestUtils, with Enzyme the only thing we’ll have to do is to use find().

Let’s see some code.

This is the TestUtils way:

it('should update clicked in component state to true on button click', () => {
const component = TestUtils.renderIntoDocument(<ButtonComponent />);
const buttonComp = TestUtils.findRenderedDOMComponentWithClass(component, 'btn’);
const buttonNode = ReactDOM.findDOMNode(buttonComp);
TestUtils.Simulate.click(buttonNode);
expect(buttonComp.state.clicked).to.equal(true);
});

and this is the Enzyme way:

it('should update clicked in component state to true on button click', () => {
const component = mount(<ButtonComponent />)
component.find('.btn').simulate('click');
expect(component.instance().state.clicked).to.equal(true);
});

ignore the mount, simulate methods, for now, we’ll get into it later. Just notice that what TestUtils does in 5 lines, Enzyme is doing with only 3. It’s only 2 lines in this example, but when it comes to a larger tests scale, it can save you LOTS of code lines and complexity.

Now, let’s explain some basics about Enzyme.
I’m not going to write a full tutorial on how to use Enzyme, they have pretty good documentation for that, but I’ll show some basics so you’ll have a general feeling of how easy & intuitive Enzyme APIs are.

Selectors

As I noted before, Enzyme is mimicking jQuery’s APIs, so if you are familiar with jQuery, this part should be pretty easy. Just use... find().
For example, if we want to find an element with the class .foo, just call:

component.find('.foo’);

Same for elements with a foo property:

component.find(‘[title=“foo”]’);

Easy.

Element properties

Every ReactJS developer knows its famous props. Right? Enzyme knows these props too.
Let’s start with an easy one, just reading the element’s id prop:

component.find('.btn').node.props.id;

But we can also run onClick prop manually:

component.find('.btn').node.props.onClick({target: {value: 'value’}});

This feature is pretty strong when we’re running some flow in our test which requires a button click. We cannot really click on the button, but we can imitate it.

Arrays

Handling arrays with Enzyme is pretty straightforward. We get an array, and ‘asking’ for the item in a specific index:
In this example, we’re running a ‘find’ selector to get all the elements with the .btnclass. It is very common that there will be more than one element with this class on our page, so we will get an array holding all the elements the selector found. Now if we want only the second element found, we will ‘get’ it:

component.find('.btn').get(1);

Quick note: The array is Zero-based. I hope you’re not surprised by that.

Simulating

At the beginning of this post, I was shown the differences between TestUtils & Enzyme, and I used a click simulation to do it.
This is a very powerful feature in ReactJS tests, after all, we’re building user interfaces that require user interactions. Therefore, we need to test those interactions. We can do it easily by simulating those interactions.
For example, if we want to simulate a user click on a button:

component.find(‘button’).simulate('click');

Interactions are not all about clicking. Input fields are also an interaction, and they can be simulated very easily too:

component.find('input').simulate('keyDown', {keyCode: 89});

Here we simulate the keyDown event and provide the input field the keyCode 89, which is the letter ‘z’.
We can simulate every keyboard key, even arrow keyCodes (37, 38, 39, 40), page up/down (33, 34), numlock (144), well... you got the idea.

If we want to just simulate a change, let’s say an input field change, which will cause the onChange to be called, we can use:

component.find('input').simulate('change');

Summary

I was trying to show you why using Enzyme can be much easier than React TestUtils, and how it will make your tests shorter & easier to read.
AirBnB’s Enzyme is well documented, I encourage you to give it a chance.

--

--

Erez Carmel
Israeli Tech Radar

Full stack developer, consultant & lecturer, experienced with developing interfaces on various platforms.