enzyme-adapter-react-16 vs @wojtekmaj/enzyme-adapter-react-17
React Testing Adapters for Legacy Enzyme Setups
enzyme-adapter-react-16@wojtekmaj/enzyme-adapter-react-17
React Testing Adapters for Legacy Enzyme Setups

@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.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
enzyme-adapter-react-16637,19019,896314 kB2812 years agoMIT
@wojtekmaj/enzyme-adapter-react-17416,249296258 kB1-MIT

Enzyme React Adapters: enzyme-adapter-react-16 vs @wojtekmaj/enzyme-adapter-react-17

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.

🧪 Core Purpose: Bridging Enzyme to React Internals

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);

⚠️ Maintenance Status and Official Support

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.

🔄 Compatibility with React Features

React 16 vs React 17 Differences

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.

🛠️ Installation and Peer Dependencies

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.

📉 Long-Term Viability and Migration Path

Since Enzyme is no longer actively maintained, both adapters are end-of-life solutions. They exist only to support legacy codebases.

  • If you’re on React 16, enzyme-adapter-react-16 is your only official option — but plan to migrate away from Enzyme.
  • If you’ve upgraded to React 17, @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();

✅ When You Might Still Use These Adapters

Despite the deprecation, some teams remain on Enzyme due to:

  • Large existing test suites that would be costly to rewrite
  • Heavy reliance on Enzyme-specific features like .state(), .instance(), or deep rendering control
  • Lack of bandwidth for migration

In those cases:

  • Use enzyme-adapter-react-16 only if your app is locked on React 16.
  • Use @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.

🆚 Summary: Key Differences

Aspectenzyme-adapter-react-16@wojtekmaj/enzyme-adapter-react-17
React VersionReact 16 onlyReact 17 only
PublisherOfficial (Airbnb/Enzyme org)Community (Wojciech Maj)
Maintenance StatusDeprecated (no updates)Community-supported, but also deprecated
Event System SupportReact 16 event modelReact 17 event model
New Project Advice❌ Do not use❌ Do not use

💡 Final Recommendation

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:

  • Match the adapter exactly to your React version.
  • Treat any test instability as a sign to prioritize migration to React Testing Library.

Enzyme served the community well for years, but the ecosystem has moved on — and so should your testing strategy.

How to Choose: enzyme-adapter-react-16 vs @wojtekmaj/enzyme-adapter-react-17
  • enzyme-adapter-react-16:

    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.

  • @wojtekmaj/enzyme-adapter-react-17:

    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.

README for enzyme-adapter-react-16

Enzyme

Join the chat at https://gitter.im/enzymejs/enzyme

npm Version License Build Status Coverage Status

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.

Upgrading from Enzyme 2.x or React < 16

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.

Installation

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 PackageReact 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.415.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() });

3rd Party Adapters

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 PackageFor LibraryStatus
enzyme-adapter-preact-purepreact(stable)
enzyme-adapter-infernoinferno(work in progress)

Running Enzyme Tests

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:

Using Enzyme with Mocha

Using Enzyme with Karma

Using Enzyme with Browserify

Using Enzyme with SystemJS

Using Enzyme with Webpack

Using Enzyme with JSDOM

Using Enzyme with React Native

Using Enzyme with Jest

Using Enzyme with Lab

Using Enzyme with Tape and AVA

Basic Usage

Shallow Rendering

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

Full DOM Rendering

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

Static Rendered Markup

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

React Hooks support

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() wrap

If 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(/* ... */);

Future

Enzyme Future

Contributing

See the Contributors Guide

In the wild

Organizations and projects using enzyme can list themselves here.

License

MIT