What is Enzyme?

It’s a testing utility to assert, manipulate and read rendered React components.

Why use it?

  • Keeps the code base clean and reduced boiler code
  • Stable rendering of components
  • Easy to use API to assert on rendered components e.g dom.find('.element')

What our code looked like before Enzyme

Below is one test asserting the user name exists in the ProfileBox component.

In the before function a component is rendered to the dom (using jsdom). The setTimeout is used to wait 20ms, allowing extra time for the component to mount. (this is a hack.)

In the after the component is removed for clean up and a setTimeout is used for similar reasons as mentioned previously.

findDOMNode method is used to get the rendered component from the DOM, allowing access to stand DOM API which can be used to assert on as shown in the it.

describe('User profile', () => {
  let component, dom;

  before((done) => {
    let person = { FirstName:'Richard', LastName:'Kotze' };
    component = React.render(
      <ProfileBox hint={person} />,
      document.body,
      () => {
        setTimeout(done);
      }
    );
  });

  after((done) => {
    React.unmountComponentAtNode(document.body);
    setTimeout(done);
  });

  it('should contain name', () => {
    dom = React.findDOMNode(component);
    dom.textContent.should.containEql('Richard Kotze');
  });
});

Using Enzyme

The same example as above but using Enzyme.

import { mount } from 'enzyme';
describe('User profile', () => {
  const person = { FirstName:'Richard', LastName:'Kotze' };

  it('should contain name', () => {
    const profileDom = mount(<ProfileBox hint={person} />);
    profileDom.text().should.containEql('Richard Kotze');
  });
});

Clearly, there are far less lines of code written, making it more focused and readable. Also, the Enzyme test is more reliable because in the first example, the hack creates flaky tests.

There is no need for the before so we render the component in the it, but the component can be rendered in the before if needed.

Enzyme API

Enzyme Guide

Enzyme provides three ways to render your components.

Shallow: shallow(<component />)

Testing the component as a unit and not asserting on child components. (jsdom or browser not needed)

Full: mount(<component />)

Full DOM rendering when interacting with DOM APIs or components that use lifecycle methods. (Needs jsdom or browser envrionment)

Static: render(<component />)

Render React components to static HTML and analyse the HTML stucture using the Cheerio library. (jsdom or browser not needed)

Common Enzyme examples

In the examples below are commonly used Enzyme methods to help get started. The assert library used is shouldJS, the Chai can also be used. I find “should” helps make the asserts more readable and focused. If you are using shouldJS then you can try should enzyme to help with Enzyme assertions.

The find method will probably be used in every test and is used to traverse through the DOM using css selectors to get elements. This returns a ReactWrapper. There other Enzyme selectors to find elements.

The following example renders a component containing a list and the find method is used to get the list items to assert the total.

const dom = shallow(<ExampleComponent />);

const exampleList = dom.find('.exampleList li');

exampleList.length.should.equal(3);

get(index) returns a node (ReactElement) giving access to React and DOM methods.

at(index) returns a wrapper to access Enzyme methods.

While the difference is subtle the get method is useful to check the rendered markup.

In the following example, the first list item is found and checks for a css class.

const dom = shallow(<ExampleComponent />);

const exampleList = dom.find('.exampleList li');

exampleList.get(0).getAttribute('class').should.equal('special');

To access the state and prop objects in a React component, Enzyme exposes state([key]), prop([key]) and props().

In the following example, the component takes a profileId to get a user profile. Assert the profileId is correct on the props and the expected user name assigned in the state.

const dom = mount(<ExampleComponent profileId="123" />);

const exampleList = dom.find('.exampleProfile');

dom.state('name').should.equal('Richard');
dom.prop('profileId').should.equal(123);

To simulate an event like onChange, use the simulate(event[, mockData]) method.

In the following example, that event onChange is fired with a mock value, and the test asserts that the value has changed.

const dom = mount(<ExampleComponent />);

const exampleInput = dom.find('.exampleForm .userName');

dom.state('userName').should.equal('typo.doe');

exampleInput.simulate('change', { target: { value: 'john.doe'}});

dom.state('userName').should.equal('john.doe');

Enzyme JS is a useful tool for testing React components enabling developers to build tests efficiently. I would encourage all React app development to use this library.