@wojtekmaj/enzyme-adapter-react-17 and enzyme-adapter-react-16 are version-specific adapters that enable the Enzyme testing utility to work with React 17 and React 16, respectively. Enzyme is a JavaScript testing library for React that allows developers to shallow render, fully mount, and interact with React components in tests. Because Enzyme depends on React's internal APIs—which change between major React versions—it requires a matching adapter to function correctly. These adapters bridge the gap between Enzyme's test APIs and the underlying React renderer for their target versions.
Both enzyme-adapter-react-16 and @wojtekmaj/enzyme-adapter-react-17 are official-style adapters that enable the Enzyme testing utility to work with specific versions of React. Enzyme itself is a JavaScript testing utility for React that lets you assert, manipulate, and traverse your React Components’ output. However, because Enzyme relies on internal React APIs that change between major versions, it requires version-specific adapters. Let’s compare these two adapters in depth.
enzyme-adapter-react-16 connects Enzyme to React 16’s rendering and lifecycle system. It uses the legacy react-test-renderer and React’s internal reconciler available in React 16.
// Setup for React 16
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
@wojtekmaj/enzyme-adapter-react-17 does the same for React 17. This adapter was created by Wojciech Maj (a well-known contributor to the React ecosystem) because the official Enzyme team did not release a React 17 adapter before sunsetting active development.
// Setup for React 17
import Enzyme from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
Enzyme.configure({ adapter: new Adapter() });
Both adapters allow you to write tests like:
import { shallow } from 'enzyme';
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('button')).toHaveLength(1);
enzyme-adapter-react-16 is published under the official enzyme organization on npm (airbnb/enzyme GitHub). However, as of 2021, the Enzyme project has been effectively deprecated. The repository is archived, and no new adapters are being developed by the original team.
@wojtekmaj/enzyme-adapter-react-17 is a community-maintained package that fills the gap left by the official team. It is widely adopted and works reliably with React 17, but it is not an official Airbnb/Enzyme release. The package documentation clearly states it exists because “Enzyme doesn’t officially support React 17 yet.”
🔴 Important: Neither adapter should be used in new projects. The Enzyme team recommends migrating to React Testing Library, which works seamlessly across React versions without adapters.
React 17 introduced a new JSX transform and minor event system changes, but no breaking component API changes. However, Enzyme’s deep integration with React internals means even subtle changes break compatibility.
enzyme-adapter-react-16 will fail or behave unpredictably with React 17 due to changes in how events are attached and how the reconciler works.@wojtekmaj/enzyme-adapter-react-17 patches these incompatibilities and supports the new JSX runtime (though most Enzyme usage doesn’t depend on JSX transform details).Example of a test that would break with the wrong adapter:
// MyComponent.jsx
function MyComponent({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
// Test
const mockFn = jest.fn();
const wrapper = shallow(<MyComponent onClick={mockFn} />);
wrapper.find('button').simulate('click');
expect(mockFn).toHaveBeenCalled(); // May fail in React 17 with v16 adapter
The React 17 adapter correctly maps Enzyme’s .simulate() to React 17’s event system.
Both packages declare strict peer dependencies on their respective React versions.
For React 16:
npm install --save-dev enzyme enzyme-adapter-react-16 react@16 react-dom@16
For React 17:
npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17 react@17 react-dom@17
Attempting to use enzyme-adapter-react-16 with React 17 will result in npm/yarn warnings about unmet peer dependencies — and likely runtime errors.
Since Enzyme is no longer actively maintained, both adapters are end-of-life solutions. They exist only to support legacy codebases.
enzyme-adapter-react-16 is your only official option — but plan to migrate away from Enzyme.@wojtekmaj/enzyme-adapter-react-17 is the de facto standard community adapter — but again, treat it as a temporary bridge.The recommended modern alternative is React Testing Library, which encourages testing behavior over implementation and works out-of-the-box with any React version:
// Modern equivalent with React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
render(<MyComponent onClick={mockFn} />);
fireEvent.click(screen.getByText('Click me'));
expect(mockFn).toHaveBeenCalled();
Despite the deprecation, some teams remain on Enzyme due to:
.state(), .instance(), or deep rendering controlIn those cases:
enzyme-adapter-react-16 only if your app is locked on React 16.@wojtekmaj/enzyme-adapter-react-17 only if you’ve moved to React 17 and cannot migrate off Enzyme immediately.But do not start new projects with either.
| Aspect | enzyme-adapter-react-16 | @wojtekmaj/enzyme-adapter-react-17 |
|---|---|---|
| React Version | React 16 only | React 17 only |
| Publisher | Official (Airbnb/Enzyme org) | Community (Wojciech Maj) |
| Maintenance Status | Deprecated (no updates) | Community-supported, but also deprecated |
| Event System Support | React 16 event model | React 17 event model |
| New Project Advice | ❌ Do not use | ❌ Do not use |
These adapters solve a narrow, version-specific compatibility problem for a testing library that is no longer maintained. Your best move is to avoid both in new code. If you’re stuck maintaining an old Enzyme test suite:
Enzyme served the community well for years, but the ecosystem has moved on — and so should your testing strategy.
Choose enzyme-adapter-react-16 only if your application is locked on React 16 and you rely on an existing Enzyme-based test suite that you cannot immediately migrate. This is the official adapter for React 16, but it will not work with React 17+. Like all Enzyme-related tools, it should be avoided in new development due to the project's deprecation.
Choose @wojtekmaj/enzyme-adapter-react-17 only if you are maintaining a legacy codebase that uses Enzyme for testing and has already upgraded to React 17. This community-maintained adapter correctly handles React 17's event system and reconciler changes. However, do not use it in new projects—migrate to React Testing Library instead, as Enzyme is no longer actively maintained.
Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.
Enzyme's API is meant to be intuitive and flexible by mimicking jQuery's API for DOM manipulation and traversal.
Are you here to check whether or not Enzyme is compatible with React 16? Are you currently using Enzyme 2.x? Great! Check out our migration guide for help moving on to Enzyme v3 where React 16 is supported.
To get started with enzyme, you can simply install it via npm. You will need to install enzyme along with an Adapter corresponding to the version of react (or other UI Component library) you are using. For instance, if you are using enzyme with React 16, you can run:
npm i --save-dev enzyme enzyme-adapter-react-16
Each adapter may have additional peer dependencies which you will need to install as well. For instance,
enzyme-adapter-react-16 has peer dependencies on react and react-dom.
At the moment, Enzyme has adapters that provide compatibility with React 16.x, React 15.x,
React 0.14.x and React 0.13.x.
The following adapters are officially provided by enzyme, and have the following compatibility with React:
| Enzyme Adapter Package | React semver compatibility |
|---|---|
enzyme-adapter-react-16 | ^16.4.0-0 |
enzyme-adapter-react-16.3 | ~16.3.0-0 |
enzyme-adapter-react-16.2 | ~16.2 |
enzyme-adapter-react-16.1 | ~16.0.0-0 || ~16.1 |
enzyme-adapter-react-15 | ^15.5.0 |
enzyme-adapter-react-15.4 | 15.0.0-0 - 15.4.x |
enzyme-adapter-react-14 | ^0.14.0 |
enzyme-adapter-react-13 | ^0.13.0 |
Finally, you need to configure enzyme to use the adapter you want it to use. To do this, you can use
the top level configure(...) API.
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
It is possible for the community to create additional (non-official) adapters that will make enzyme work with other libraries. If you have made one and it's not included in the list below, feel free to make a PR to this README and add a link to it! The known 3rd party adapters are:
| Adapter Package | For Library | Status |
|---|---|---|
enzyme-adapter-preact-pure | preact | (stable) |
enzyme-adapter-inferno | inferno | (work in progress) |
Enzyme is unopinionated regarding which test runner or assertion library you use, and should be compatible with all major test runners and assertion libraries out there. The documentation and examples for enzyme use Mocha and Chai, but you should be able to extrapolate to your framework of choice.
If you are interested in using enzyme with custom assertions and convenience functions for testing your React components, you can consider using:
chai-enzyme with Mocha/Chai.jasmine-enzyme with Jasmine.jest-enzyme with Jest.should-enzyme for should.js.expect-enzyme for expect.Using Enzyme with React Native
Using Enzyme with Tape and AVA
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import MyComponent from './MyComponent';
import Foo from './Foo';
describe('<MyComponent />', () => {
it('renders three <Foo /> components', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find(Foo)).to.have.lengthOf(3);
});
it('renders an `.icon-star`', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.icon-star')).to.have.lengthOf(1);
});
it('renders children when passed in', () => {
const wrapper = shallow((
<MyComponent>
<div className="unique" />
</MyComponent>
));
expect(wrapper.contains(<div className="unique" />)).to.equal(true);
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = shallow(<Foo onButtonClick={onButtonClick} />);
wrapper.find('button').simulate('click');
expect(onButtonClick).to.have.property('callCount', 1);
});
});
Read the full API Documentation
import React from 'react';
import sinon from 'sinon';
import { expect } from 'chai';
import { mount } from 'enzyme';
import Foo from './Foo';
describe('<Foo />', () => {
it('allows us to set props', () => {
const wrapper = mount(<Foo bar="baz" />);
expect(wrapper.props().bar).to.equal('baz');
wrapper.setProps({ bar: 'foo' });
expect(wrapper.props().bar).to.equal('foo');
});
it('simulates click events', () => {
const onButtonClick = sinon.spy();
const wrapper = mount((
<Foo onButtonClick={onButtonClick} />
));
wrapper.find('button').simulate('click');
expect(onButtonClick).to.have.property('callCount', 1);
});
it('calls componentDidMount', () => {
sinon.spy(Foo.prototype, 'componentDidMount');
const wrapper = mount(<Foo />);
expect(Foo.prototype.componentDidMount).to.have.property('callCount', 1);
Foo.prototype.componentDidMount.restore();
});
});
Read the full API Documentation
import React from 'react';
import { expect } from 'chai';
import { render } from 'enzyme';
import Foo from './Foo';
describe('<Foo />', () => {
it('renders three `.foo-bar`s', () => {
const wrapper = render(<Foo />);
expect(wrapper.find('.foo-bar')).to.have.lengthOf(3);
});
it('renders the title', () => {
const wrapper = render(<Foo title="unique" />);
expect(wrapper.text()).to.contain('unique');
});
});
Read the full API Documentation
Enzyme supports react hooks with some limitations in .shallow() due to upstream issues in React's shallow renderer:
useEffect() and useLayoutEffect() don't get called in the React shallow renderer. Related issue
useCallback() doesn't memoize callback in React shallow renderer. Related issue
ReactTestUtils.act() wrapIf you're using React 16.8+ and .mount(), Enzyme will wrap apis including .simulate(), .setProps(), .setContext(), .invoke() with ReactTestUtils.act() so you don't need to manually wrap it.
A common pattern to trigger handlers with .act() and assert is:
const wrapper = mount(<SomeComponent />);
act(() => wrapper.prop('handler')());
wrapper.update();
expect(/* ... */);
We cannot wrap the result of .prop() (or .props()) with .act() in Enzyme internally since it will break the equality of the returned value.
However, you could use .invoke() to simplify the code:
const wrapper = mount(<SomeComponent />);
wrapper.invoke('handler')();
expect(/* ... */);
See the Contributors Guide
Organizations and projects using enzyme can list themselves here.