Skip to content

Commit

Permalink
Rip out sinon, mocha, and jsdom dependencies
Browse files Browse the repository at this point in the history
This refactor addresses several issues regarding enzyme working in a variety of environments, and
the library just generally not making any assumptions about the environment that tests will be
run in.

For the most part, this amounts to:

- remove direct dependency on jsdom
- remove direct dependency on sinon
- remove assumed dependency on mocha

In addition to this, I would like to create several "example" projects that are some basic boilerplate
to getting enzyme up and running with some combination of bundler/test runner/etc.  These projects
can end up being devDependencies to enzyme and we can run their tests as part of our tests, which will
ensure that changes we make to enzyme will be compatible with environments we claim to support moving
forward.

Lastly, as a matter of organization, tests have been moved from `src/__tests__/*` to `tests/*`.

Left to do for this to be mergable is:

  [ ] Add a "guides" section in the docs explaining how to use enzyme in different environments
  [ ] Add example projects as dev dependencies, include their tests in enzyme's test script
  • Loading branch information
lelandrichardson committed Feb 2, 2016
1 parent ad02abf commit d4adcaa
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 253 deletions.
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ If you are interested in using enzyme with custom Chai.js assertions and conveni
testing your React components, you can consider using [chai-enzyme](https://github.com/producthunt/chai-enzyme).


[Using Enzyme with Mocha](/docs/guides/mocha.md)
[Using Enzyme with Karma](/docs/guides/karma.md)
[Using Enzyme with Jasmine](/docs/guides/jasmine.md)


### [Installation](/docs/installation/README.md)

To get started with enzyme, you can simply install it with npm:
Expand All @@ -46,6 +51,7 @@ Basic Usage
## [Shallow Rendering](/docs/api/shallow.md)

```jsx
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';

Expand Down Expand Up @@ -86,22 +92,14 @@ Read the full [API Documentation](/docs/api/shallow.md)



## [JSDOM Full Rendering](/docs/api/mount.md)
## [Full DOM Rendering](/docs/api/mount.md)

```jsx
import {
describeWithDOM,
mount,
spyLifecycle,
} from 'enzyme';

describeWithDOM('<Foo />', () => {
import React from 'react';
import sinon from 'sinon';
import { mount } from 'enzyme';

it('calls componentDidMount', () => {
spyLifecycle(Foo);
const wrapper = mount(<Foo />);
expect(Foo.prototype.componentDidMount.calledOnce).to.equal(true);
});
describe('<Foo />', () => {

it('allows us to set props', () => {
const wrapper = mount(<Foo bar="baz" />);
Expand All @@ -118,6 +116,13 @@ describeWithDOM('<Foo />', () => {
wrapper.find('button').simulate('click');
expect(onButtonClick.calledOnce).to.equal(true);
});

it('calls componentDidMount', () => {
sinon.spy(Foo.prototype, 'componentDidMount');
const wrapper = mount(<Foo />);
expect(Foo.prototype.componentDidMount.calledOnce).to.be.true;
Foo.prototype.componentDidMount.restore();
});

});
```
Expand All @@ -128,6 +133,7 @@ Read the full [API Documentation](/docs/api/mount.md)
## [Static Rendered Markup](/docs/api/render.md)

```jsx
import React from 'react';
import { render } from 'enzyme';

describe('<Foo />', () => {
Expand Down
7 changes: 5 additions & 2 deletions docs/api/mount.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ Full DOM rendering is ideal for use cases where you have components that may int
or may require the full lifecycle in order to fully test the component (ie, `componentDidMount`
etc.)

Full DOM rendering depends on a library called [jsdom](https://github.com/tmpvar/jsdom) which is
essentially a headless browser implemented completely in JS.
Full DOM rendering requires that a full DOM API be available at the global scope. This means that
it must be run in an environment that at least "looks like" a browser environment. If you do not
want to run your tests inside of a browswer, the recommended approach to using `mount` is to depend
on a library called [jsdom](https://github.com/tmpvar/jsdom) which is essentially a headless browser
implemented completely in JS.

```jsx
import { mount } from 'enzyme';
Expand Down
21 changes: 21 additions & 0 deletions docs/guides/mocha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Using Enzyme with Mocha

```bash
npm i --save-dev enzyme-mocha
```

```jsx
import { mount } from 'enzyme';
import { describeWithDOM } from 'enzyme-mocha';

describe('<Foo />', () => {

it('calls componentDidMount', () => {
spy(Foo.prototype, 'componentDidMount');
const wrapper = mount(<Foo />);
expect(Foo.prototype.componentDidMount.calledOnce).to.be.true;
});

});

```
29 changes: 0 additions & 29 deletions docs/installation/jsdom.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,3 @@ nvm use 0.12
```bash
nvm use 4
```

### Preventing tests from failing on old versions

If you are worried about tests not passing on versions of node that don't support jsdom, Enzyme
comes with a helper function to wrap your tests in a safety layer such that any tests written
inside of that function will be skipped if jsdom is not available. (Note that this is for mocha
only).

```jsx
import { mount, shallow } from 'enzyme';

describe('MyComponent', () => {
describeWithDOM('interaction', () => {
// these tests will get skipped if jsdom is not available...
it('should do something', () => {
const wrapper = mount(<MyComponent />);
// ...
});
});
describe('non-interaction', () => {
// these tests will always run
it('should do something', () => {
const wrapper = shallow(<MyComponent />);
// ...
});
});
});

```
22 changes: 8 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@
"check": "npm run lint && npm run test:all",
"build": "babel src --out-dir build",
"test": "npm run lint && npm run test:only",
"test:only": "mocha --require withDom.js --compilers js:babel-core/register --recursive src/**/__tests__/*.js",
"test:only": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js",
"test:single": "mocha --require withDom.js --compilers js:babel-core/register --watch",
"test:watch": "mocha --require withDom.js --compilers js:babel-core/register --recursive src/**/__tests__/*.js --watch",
"test:describeWithDOMOnly": "mocha --compilers js:babel-core/register --recursive src/**/__tests__/describeWithDOM/describeWithDOMOnly-spec.js",
"test:describeWithDOMSkip": "mocha --compilers js:babel-core/register --recursive src/**/__tests__/describeWithDOM/describeWithDOMSkip-spec.js",
"test:all": "npm run react:13 && npm test && npm run test:describeWithDOMOnly && npm run test:describeWithDOMSkip && npm run react:14 && npm test && npm run test:describeWithDOMOnly && npm run test:describeWithDOMSkip",
"test:watch": "mocha --require withDom.js --compilers js:babel-core/register --recursive test/*.js --watch",
"test:all": "npm run react:13 && npm test && npm run react:14 && npm test",
"react:clean": "rimraf node_modules/react node_modules/react-dom node_modules/react-addons-test-utils",
"react:13": "npm run react:clean && npm i react@0.13",
"react:14": "npm run react:clean && npm i react@0.14 react-dom@0.14 react-addons-test-utils@0.14",
Expand All @@ -27,7 +25,7 @@
"docs:build": "npm run docs:prepare && gitbook build",
"docs:watch": "npm run docs:prepare && gitbook serve",
"docs:publish": "npm run docs:clean && npm run docs:build && cd _book && git init && git commit --allow-empty -m 'update book' && git fetch https://github.com/airbnb/enzyme.git gh-pages && git checkout -b gh-pages && git add . && git commit -am 'update book' && git push https://github.com/airbnb/enzyme.git gh-pages --force",
"travis": "babel-istanbul cover --report html _mocha -- --recursive src/**/__tests__/*.js"
"travis": "babel-node ./node_modules/.bin/istanbul cover --report html _mocha -- --require withDom.js test --recursive"
},
"repository": {
"type": "git",
Expand All @@ -54,14 +52,12 @@
"is-subset": "^0.1.1",
"object.assign": "^4.0.3",
"object.values": "^1.0.3",
"sinon": "^1.17.3",
"underscore": "^1.8.3"
},
"devDependencies": {
"babel-cli": "^6.3.17",
"babel-core": "^6.3.21",
"babel-eslint": "^4.1.8",
"babel-istanbul": "^0.5.9",
"babel-preset-airbnb": "^1.0.1",
"babel-register": "^6.3.13",
"chai": "^3.5.0",
Expand All @@ -70,15 +66,13 @@
"eslint-config-airbnb": "^4.0.0",
"eslint-plugin-react": "^3.16.1",
"gitbook-cli": "^1.0.1",
"istanbul": "^0.4.2",
"istanbul": "^1.0.0-alpha.2",
"jsdom": "^6.1.0",
"mocha": "^2.4.5",
"rimraf": "^2.5.1"
"rimraf": "^2.5.1",
"sinon": "^1.15.4"
},
"peerDependencies": {
"react": "0.13.x || 0.14.x"
},
"optionalDependencies": {
"jsdom": "^3.1.2 || ^5.6.1 || ^6.1.0 || ^7.2.2",
"mocha-jsdom": "^1.0.0"
}
}
26 changes: 0 additions & 26 deletions src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,6 @@ export function propsOfNode(node) {
return (node && node.props) || {};
}

export function onPrototype(Component, lifecycle, method) {
const proto = Component.prototype;
Object.getOwnPropertyNames(proto).forEach((name) => {
if (typeof proto[name] !== 'function') return;
switch (name) {
case 'componentDidMount':
case 'componentWillMount':
case 'componentDidUnmount':
case 'componentWillUnmount':
case 'componentWillReceiveProps':
case 'componentDidUpdate':
case 'componentWillUpdate':
case 'shouldComponentUpdate':
case 'render':
if (lifecycle) lifecycle(proto, name);
break;
case 'constructor':
// don't spy on the constructor, even though it shows up in the prototype
break;
default:
if (method) method(proto, name);
break;
}
});
}

export function getNode(node) {
return isDOMComponent(node) ? findDOMNode(node) : node;
}
Expand Down
34 changes: 0 additions & 34 deletions src/__tests__/_helpers.js

This file was deleted.

19 changes: 0 additions & 19 deletions src/__tests__/describeWithDOM/describeWithDOMOnly-spec.js

This file was deleted.

19 changes: 0 additions & 19 deletions src/__tests__/describeWithDOM/describeWithDOMSkip-spec.js

This file was deleted.

46 changes: 0 additions & 46 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,8 @@
import cheerio from 'cheerio';
import Sinon from 'sinon';
import ReactWrapper from './ReactWrapper';
import ShallowWrapper from './ShallowWrapper';
import { describeWithDOM } from './describeWithDOM';
import { onPrototype } from './Utils';
import { renderToStaticMarkup } from './react-compat';

/**
* @class Enzyme
*/

export let sinon = Sinon.sandbox.create();

export function useSetStateHack() {
let cleanup = false;
before(() => {
if (typeof global.document === 'undefined') {
cleanup = true;
global.document = {};
}
});
after(() => {
if (cleanup) {
delete global.document;
}
});
}

export function spySetup() {
sinon = Sinon.sandbox.create();
}

export function spyTearDown() {
sinon.restore();
}

export function useSinon() {
beforeEach(spySetup);
afterEach(spyTearDown);
}

export function spyLifecycle(Component) {
onPrototype(Component, (proto, name) => sinon.spy(proto, name));
}

export function spyMethods(Component) {
onPrototype(Component, null, (proto, name) => sinon.spy(proto, name));
}

/**
* Mounts and renders a react component into the document and provides a testing wrapper around it.
*
Expand Down Expand Up @@ -87,4 +42,3 @@ export function render(node) {

export { ShallowWrapper as ShallowWrapper };
export { ReactWrapper as ReactWrapper };
export { describeWithDOM as describeWithDOM };
File renamed without changes.
8 changes: 4 additions & 4 deletions src/__tests__/Debug-spec.js → test/Debug-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
spaces,
indent,
debugNode,
} from '../Debug';
import { mount } from '../';
import { describeWithDOM, itIf } from './_helpers';
import { REACT013 } from '../version';
} from '../src/Debug';
import { mount } from '../src/';
import { describeWithDOM,itIf } from './_helpers';
import { REACT013 } from '../src/version';

describe('debug', () => {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { describeWithDOM, describeIf } from './_helpers';
import React from 'react';
import { expect } from 'chai';
import sinon from 'sinon';
import {
mount,
render,
ReactWrapper,
} from '../';
import { REACT013 } from '../version';
} from '../src/';
import sinon from 'sinon';
import { REACT013 } from '../src/version';

describeWithDOM('mount', () => {

Expand Down
Loading

0 comments on commit d4adcaa

Please sign in to comment.