Setting up
We'll use create-react-app for this project to quickly set up a React application and get it running. So, to make our application, type the following command into your command prompt:
cd your-project-directory
npx create-react-app logrocket-react-enzyme-app
This will create and initialize the project with a set of pre-configured Node modules for React development. This is the generated file and directories structure:
logrocket-react-enzyme-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js
Installation
Once we've decided to use React 16 (the most recent version at the time of writing) for our project development, we can run the following command to properly install Enzyme:
npm i — save-dev enzyme enzyme-adapter-react-16
Creating our First Test
We need to tell our React app that Enzyme is installed and available before we can use its features. However, keep in mind that we need to refer to the adapter package we installed earlier and set up the adapter properly for Enzyme to use. So, create a new file called enzyme.js in the src folder:
import Enzyme, { configure, shallow, mount, render } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
export { shallow, mount, render };
export default Enzyme;
This will be sufficient to export all of the Enzyme render types. Then, in the src/components directory, make a new folder called tests to save our test files.
Consider the following simple example: an HTML ordered list. It will be made up of two parts:
- OrderedList: This will store the function to construct an <ol> of OrderedListOption elements, checking whether the list is empty or not for various display dispositions.
- OrderedListOption: this option deals with each <li> item separately, with its CSS class and value.
Given its list nature, this component could easily be adapted to a <select>, for example. Let's look at the source code for a moment:
import React from 'react';
import PropTypes from 'prop-types';
import OrderedListOption from './OrderedListOption';
function OrderedList(props) {
const { options } = props;
if (!options.length) {
return <span className="empty">No options added.</span>;
}
return (
<ol className="options">
{options.map(option => <OrderedListOption key={option} value={option} />)}
</ol>
);
}
OrderedList.propTypes = {
options: PropTypes.array,
};
OrderedList.defaultProps = {
options: [],
};
export default OrderedList;
The code is extremely simple: at the top of the file, we import React and the OrderedListOption component, then check for emptiness in the items array to display the proper HTML content. We'll iterate over the array to create list options if it's not empty.
Take a look at the code for OrderedListOption:
import React from 'react';
import PropTypes from 'prop-types';
function OrderedListOption(props) {
const { value } = props;
return <li className="value">{value}</li>;
}
OrderedListOption.propTypes = {
value: PropTypes.string,
};
export default OrderedListOption;
It simply takes the element's value and places it in the <li> element.
Render Types Enzyme Supports
Before we start writing our tests, let's go over the three different render types that Enzyme supports.
shallow
This essentially renders only one component at a time. To put it another way, Enzyme won't test the child elements. Consider situations where you'd like to test the component separately from or within the rest of the system. When unit testing is preferred over a full integrated test, this render type comes in handy.
mount
Working with the full DOM rendering, which includes all child elements, is the polar opposite of shallow. The DOM API is ideal for situations where each component interacts heavily with the others.
render
It outputs static HTML. All of the child elements are included in this. At the same time, it prevents access to React lifecycle methods, resulting in less flexibility and functionalities for testing — aside from the fact that it's much faster. It's based on Cheerio, a server-side DOM manipulation and traversal API based on jQuery Core. As a result, you'll have complete control over jQuery.
Now it's time to put some tests to the test. Add the following code to a new file called OrderedList.test.js in our /tests folder:
import React from 'react';
import { shallow, mount, render } from '../../enzyme';
import OrderedList from '../OrderedList';
describe('Our test suite', () => {
it('renders all the mocked animal options', () => {
const animals = ['duck', 'bear', 'whale'];
const wrapper = render(<OrderedList options={animals} />);
expect(wrapper.find('.options')).toBeDefined();
expect(wrapper.find('.value')).toHaveLength(animals.length);
});
it('renders no animal options', () => {
const animals = [];
const wrapper = shallow(<OrderedList options={animals} />);
expect(wrapper.find('.empty').exists()).toBe(true);
});
it('renders a single animal option', () => {
const animals = ['duck'];
const wrapper = mount(<OrderedList options={animals} />);
expect(wrapper.contains(<li key='duck' className="value">duck</li >)).toBeTruthy();
});
it('renders correct text in animal option', () => {
const animals = ['duck', 'bear', 'whale'];
const wrapper = mount(<OrderedList options={animals} />);
expect(wrapper.find('.value').get(0).props.children).toEqual('duck');
});
});
First, we'll import the three render types from the enzyme.js file we created earlier into the file. For each type of rendering, we're considering four test scenarios.
The first is for the render type; we're basically asking Enzyme to render an OrderedList with the given array of animals param, and we're asserting the test conditions with the expect() function.
The render() result is represented by the wrapper object, and we can use it to get the CSS classes options (of our items' children) and value for each of the inner list elements' classes. In addition, we're experimenting with the number of child elements.
Testing Form Components
You can even test forms, form elements, events, and other things. Consider the following example, which is a login form component (Login.js):
import React from 'react';
class Login extends React.Component {
constructor() {
super()
this.state = {
username: '',
password: ''
}
}
handleInputChange = (event) => {
this.setState({
[event.target.name]: event.target.value
})
}
render() {
return (
<form className='login'>
<label>Username</label>
<input id='email' onBlur={this.handleInputChange} name='email' type='text' />
<label>Password</label>
<input id='password' onBlur={this.handleInputChange} name='password' type='password' />
<button>Submit</button>
</form>
)
}
}
export default Login
Except that the state we're keeping here must be updated every time a blur event occurs in one of the inputs, which is a common form structure component.
Let's look at the Login.test.js file in more detail:
import React from 'react';
import { shallow, mount, render } from '../../enzyme';
import Login from '../Login'
describe('Login Test Suite', () => {
it('should render the form', () => {
const wrapper = shallow(<Login />);
expect(wrapper.find('form.login').exists()).toBe(true);
expect(wrapper.find('#email').length).toEqual(1);
expect(wrapper.find('#password').length).toEqual(1);
})
})
describe('Email Test Suite', () => {
it('should change the state of the Login component', () => {
const wrapper = shallow(<Login />);
wrapper.find('#email').simulate('blur',
{
target: { name: 'email', value: 'logrocket@mail.com' }
});
expect(wrapper.state('email')).toEqual('logrocket@mail.com');
})
})
describe('Password Test Suite', () => {
it('should change the state of the Login component', () => {
const wrapper = mount(<Login />);
wrapper.find('#password').simulate('blur',
{
target: { name: 'password', value: 'my log is rocket' }
});
expect(wrapper.state('password')).toEqual('my log is rocket');
})
})
The first test suite is nothing new; we’re just checking if the form elements exist. The second and third tests are making use of the simulate() function to, as the name suggests, simulate an event in the field — in this case, onBlur.
Once we’ve set that the onBlur will trigger the state update of each input field, we can then check if the same state was stored. That’s a great example of a behavior test, wherein we’re testing what happens after Enzyme forces the simulation of an event in the component.
This would be the final output in your IDE (here, Visual Studio Code):
Test results in the terminal:

Source
FAQs
-
If you want to use enzyme with React 16, but don't already have React 16 and react-dom installed, what command should you run?
Command:
npm i --save react@16 react-dom@16
-
What is Cheerio?
Cheerio is a Node. js tool for parsing HTML and XML.
-
What are the react lifecycle methods?
Mounting, updating, and unmounting are the three types of lifecycle methods.
-
How do we run the React application?
Simply type the “npm start” command into the application root folder to open the index page in your browser at http://localhost:3000/ to check out the running application.
-
What is package.json?
Any Node project's heart is the package.json file. It keeps track of critical project metadata that is required before it can be published to NPM, as well as functional attributes that npm uses to install dependencies, run scripts, and identify the package's entry point.
Key Takeaways
In this article, we have extensively discussed the installation of Enzyme and how to get started with it.
We hope that this blog has helped you enhance your knowledge regarding the installation of Enzyme and if you would like to learn more, check out our articles on Coding Ninjas Studio. Do upvote our blog to help other ninjas grow. Happy Coding!