1 | Enzyme
|
2 | =======
|
3 |
|
4 | [![Join the chat at https://gitter.im/airbnb/enzyme](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/airbnb/enzyme?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5 |
|
6 | [![npm Version](https://img.shields.io/npm/v/enzyme.svg)](https://www.npmjs.com/package/enzyme) [![License](https://img.shields.io/npm/l/enzyme.svg)](https://github.com/airbnb/enzyme/blob/master/LICENSE.md) [![Build Status](https://travis-ci.org/airbnb/enzyme.svg)](https://travis-ci.org/airbnb/enzyme) [![Coverage Status](https://coveralls.io/repos/airbnb/enzyme/badge.svg?branch=master&service=github)](https://coveralls.io/github/airbnb/enzyme?branch=master)
|
7 |
|
8 |
|
9 | Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output.
|
10 | You can also manipulate, traverse, and in some ways simulate runtime given the output.
|
11 |
|
12 | Enzyme's API is meant to be intuitive and flexible by mimicking jQuery's API for DOM manipulation
|
13 | and traversal.
|
14 |
|
15 | Upgrading from Enzyme 2.x or React < 16
|
16 | ===========
|
17 |
|
18 | Are you here to check whether or not Enzyme is compatible with React 16? Are you currently using
|
19 | Enzyme 2.x? Great! Check out our [migration guide](/docs/guides/migration-from-2-to-3.md) for help
|
20 | moving on to Enzyme v3 where React 16 is supported.
|
21 |
|
22 | ### [Installation](/docs/installation/README.md)
|
23 |
|
24 | To get started with enzyme, you can simply install it via npm. You will need to install enzyme
|
25 | along with an Adapter corresponding to the version of react (or other UI Component library) you
|
26 | are using. For instance, if you are using enzyme with React 16, you can run:
|
27 |
|
28 | ```bash
|
29 | npm i --save-dev enzyme enzyme-adapter-react-16
|
30 | ```
|
31 |
|
32 | Each adapter may have additional peer dependencies which you will need to install as well. For instance,
|
33 | `enzyme-adapter-react-16` has peer dependencies on `react` and `react-dom`.
|
34 |
|
35 | At the moment, Enzyme has adapters that provide compatibility with `React 16.x`, `React 15.x`,
|
36 | `React 0.14.x` and `React 0.13.x`.
|
37 |
|
38 | The following adapters are officially provided by enzyme, and have the following compatibility with
|
39 | React:
|
40 |
|
41 | | Enzyme Adapter Package | React semver compatibility |
|
42 | | --- | --- |
|
43 | | `enzyme-adapter-react-16` | `^16.4.0-0` |
|
44 | | `enzyme-adapter-react-16.3` | `~16.3.0-0` |
|
45 | | `enzyme-adapter-react-16.2` | `~16.2` |
|
46 | | `enzyme-adapter-react-16.1` | `~16.0.0-0 \|\| ~16.1` |
|
47 | | `enzyme-adapter-react-15` | `^15.5.0` |
|
48 | | `enzyme-adapter-react-15.4` | `15.0.0-0 - 15.4.x` |
|
49 | | `enzyme-adapter-react-14` | `^0.14.0` |
|
50 | | `enzyme-adapter-react-13` | `^0.13.0` |
|
51 |
|
52 | Finally, you need to configure enzyme to use the adapter you want it to use. To do this, you can use
|
53 | the top level `configure(...)` API.
|
54 |
|
55 | ```js
|
56 | import Enzyme from 'enzyme';
|
57 | import Adapter from 'enzyme-adapter-react-16';
|
58 |
|
59 | Enzyme.configure({ adapter: new Adapter() });
|
60 | ```
|
61 |
|
62 | 3rd Party Adapters
|
63 | =============
|
64 |
|
65 | It is possible for the community to create additional (non-official) adapters that will make enzyme
|
66 | work with other libraries. If you have made one and it's not included in the list below, feel free
|
67 | to make a PR to this README and add a link to it! The known 3rd party adapters are:
|
68 |
|
69 | | Adapter Package | For Library | Status |
|
70 | | --- | --- | --- |
|
71 | | [`enzyme-adapter-preact-pure`](https://github.com/preactjs/enzyme-adapter-preact-pure) | [`preact`](https://github.com/developit/preact) | (stable) |
|
72 | |[`enzyme-adapter-inferno`](https://github.com/bbc/enzyme-adapter-inferno)|[`inferno`](https://github.com/infernojs/inferno)|(work in progress)|
|
73 |
|
74 | Running Enzyme Tests
|
75 | ===========
|
76 |
|
77 | Enzyme is unopinionated regarding which test runner or assertion library you use, and should be
|
78 | compatible with all major test runners and assertion libraries out there. The documentation and
|
79 | examples for enzyme use [mocha](https://mochajs.org/) and [chai](http://chaijs.com/), but you
|
80 | should be able to extrapolate to your framework of choice.
|
81 |
|
82 | If you are interested in using enzyme with custom assertions and convenience functions for
|
83 | testing your React components, you can consider using:
|
84 |
|
85 | * [`chai-enzyme`](https://github.com/producthunt/chai-enzyme) with Mocha/Chai.
|
86 | * [`jasmine-enzyme`](https://github.com/FormidableLabs/enzyme-matchers/tree/master/packages/jasmine-enzyme) with Jasmine.
|
87 | * [`jest-enzyme`](https://github.com/FormidableLabs/enzyme-matchers/tree/master/packages/jest-enzyme) with Jest.
|
88 | * [`should-enzyme`](https://github.com/rkotze/should-enzyme) for should.js.
|
89 | * [`expect-enzyme`](https://github.com/PsychoLlama/expect-enzyme) for expect.
|
90 |
|
91 |
|
92 | [Using Enzyme with Mocha](/docs/guides/mocha.md)
|
93 |
|
94 | [Using Enzyme with Karma](/docs/guides/karma.md)
|
95 |
|
96 | [Using Enzyme with Browserify](/docs/guides/browserify.md)
|
97 |
|
98 | [Using Enzyme with SystemJS](/docs/guides/systemjs.md)
|
99 |
|
100 | [Using Enzyme with Webpack](/docs/guides/webpack.md)
|
101 |
|
102 | [Using Enzyme with JSDOM](/docs/guides/jsdom.md)
|
103 |
|
104 | [Using Enzyme with React Native](/docs/guides/react-native.md)
|
105 |
|
106 | [Using Enzyme with Jest](/docs/guides/jest.md)
|
107 |
|
108 | [Using Enzyme with Lab](/docs/guides/lab.md)
|
109 |
|
110 | [Using Enzyme with Tape and AVA](/docs/guides/tape-ava.md)
|
111 |
|
112 | Basic Usage
|
113 | ===========
|
114 |
|
115 | ## [Shallow Rendering](/docs/api/shallow.md)
|
116 |
|
117 | ```javascript
|
118 | import React from 'react';
|
119 | import { expect } from 'chai';
|
120 | import { shallow } from 'enzyme';
|
121 | import sinon from 'sinon';
|
122 |
|
123 | import MyComponent from './MyComponent';
|
124 | import Foo from './Foo';
|
125 |
|
126 | describe('<MyComponent />', () => {
|
127 | it('renders three <Foo /> components', () => {
|
128 | const wrapper = shallow(<MyComponent />);
|
129 | expect(wrapper.find(Foo)).to.have.lengthOf(3);
|
130 | });
|
131 |
|
132 | it('renders an `.icon-star`', () => {
|
133 | const wrapper = shallow(<MyComponent />);
|
134 | expect(wrapper.find('.icon-star')).to.have.lengthOf(1);
|
135 | });
|
136 |
|
137 | it('renders children when passed in', () => {
|
138 | const wrapper = shallow((
|
139 | <MyComponent>
|
140 | <div className="unique" />
|
141 | </MyComponent>
|
142 | ));
|
143 | expect(wrapper.contains(<div className="unique" />)).to.equal(true);
|
144 | });
|
145 |
|
146 | it('simulates click events', () => {
|
147 | const onButtonClick = sinon.spy();
|
148 | const wrapper = shallow(<Foo onButtonClick={onButtonClick} />);
|
149 | wrapper.find('button').simulate('click');
|
150 | expect(onButtonClick).to.have.property('callCount', 1);
|
151 | });
|
152 | });
|
153 | ```
|
154 |
|
155 | Read the full [API Documentation](/docs/api/shallow.md)
|
156 |
|
157 |
|
158 |
|
159 | ## [Full DOM Rendering](/docs/api/mount.md)
|
160 |
|
161 | ```javascript
|
162 | import React from 'react';
|
163 | import sinon from 'sinon';
|
164 | import { expect } from 'chai';
|
165 | import { mount } from 'enzyme';
|
166 |
|
167 | import Foo from './Foo';
|
168 |
|
169 | describe('<Foo />', () => {
|
170 | it('allows us to set props', () => {
|
171 | const wrapper = mount(<Foo bar="baz" />);
|
172 | expect(wrapper.props().bar).to.equal('baz');
|
173 | wrapper.setProps({ bar: 'foo' });
|
174 | expect(wrapper.props().bar).to.equal('foo');
|
175 | });
|
176 |
|
177 | it('simulates click events', () => {
|
178 | const onButtonClick = sinon.spy();
|
179 | const wrapper = mount((
|
180 | <Foo onButtonClick={onButtonClick} />
|
181 | ));
|
182 | wrapper.find('button').simulate('click');
|
183 | expect(onButtonClick).to.have.property('callCount', 1);
|
184 | });
|
185 |
|
186 | it('calls componentDidMount', () => {
|
187 | sinon.spy(Foo.prototype, 'componentDidMount');
|
188 | const wrapper = mount(<Foo />);
|
189 | expect(Foo.prototype.componentDidMount).to.have.property('callCount', 1);
|
190 | Foo.prototype.componentDidMount.restore();
|
191 | });
|
192 | });
|
193 | ```
|
194 |
|
195 | Read the full [API Documentation](/docs/api/mount.md)
|
196 |
|
197 |
|
198 | ## [Static Rendered Markup](/docs/api/render.md)
|
199 |
|
200 | ```javascript
|
201 | import React from 'react';
|
202 | import { expect } from 'chai';
|
203 | import { render } from 'enzyme';
|
204 |
|
205 | import Foo from './Foo';
|
206 |
|
207 | describe('<Foo />', () => {
|
208 | it('renders three `.foo-bar`s', () => {
|
209 | const wrapper = render(<Foo />);
|
210 | expect(wrapper.find('.foo-bar')).to.have.lengthOf(3);
|
211 | });
|
212 |
|
213 | it('renders the title', () => {
|
214 | const wrapper = render(<Foo title="unique" />);
|
215 | expect(wrapper.text()).to.contain('unique');
|
216 | });
|
217 | });
|
218 | ```
|
219 |
|
220 | Read the full [API Documentation](/docs/api/render.md)
|
221 |
|
222 | ### React Hooks support
|
223 |
|
224 | Enzyme supports [react hooks](https://reactjs.org/docs/hooks-intro.html) with some limitations in [`.shallow()`](https://airbnb.io/enzyme/docs/api/shallow.html) due to upstream issues in React's shallow renderer:
|
225 |
|
226 | * `useEffect()` and `useLayoutEffect()` don't get called in the React shallow renderer. [Related issue](https://github.com/facebook/react/issues/15275)
|
227 |
|
228 | * `useCallback()` doesn't memoize callback in React shallow renderer. [Related issue](https://github.com/facebook/react/issues/15774)
|
229 |
|
230 | #### [`ReactTestUtils.act()`](https://reactjs.org/docs/test-utils.html#act) wrap
|
231 |
|
232 | If you're using React 16.8+ and `.mount()`, Enzyme will wrap apis including [`.simulate()`](https://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html), [`.setProps()`](https://airbnb.io/enzyme/docs/api/ReactWrapper/setProps.html), [`.setContext()`](https://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html), [`.invoke()`](https://airbnb.io/enzyme/docs/api/ReactWrapper/invoke.html) with [`ReactTestUtils.act()`](https://reactjs.org/docs/test-utils.html#act) so you don't need to manually wrap it.
|
233 |
|
234 | A common pattern to trigger handlers with `.act()` and assert is:
|
235 |
|
236 | ```javascript
|
237 | const wrapper = mount(<SomeComponent />);
|
238 | act(() => wrapper.prop('handler')());
|
239 | wrapper.update();
|
240 | expect(/* ... */);
|
241 | ```
|
242 |
|
243 | We cannot wrap the result of `.prop()` (or `.props()`) with `.act()` in Enzyme internally since it will break the equality of the returned value.
|
244 | However, you could use `.invoke()` to simplify the code:
|
245 |
|
246 | ```javascript
|
247 | const wrapper = mount(<SomeComponent />);
|
248 | wrapper.invoke('handler')();
|
249 | expect(/* ... */);
|
250 | ```
|
251 |
|
252 | ### Future
|
253 |
|
254 | [Enzyme Future](/docs/future.md)
|
255 |
|
256 |
|
257 | ### Contributing
|
258 |
|
259 | See the [Contributors Guide](/CONTRIBUTING.md)
|
260 |
|
261 | ### In the wild
|
262 |
|
263 | Organizations and projects using `enzyme` can list themselves [here](INTHEWILD.md).
|
264 |
|
265 | ### License
|
266 |
|
267 | [MIT](/LICENSE.md)
|