Skip to content

Commit

Permalink
Added mount/unmount to ReactWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
lelandrichardson committed Feb 2, 2016
1 parent f648aee commit 2bc779a
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 10 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"version": "npm run build",
"clean": "rimraf build",
"lint": "eslint src/**",
"test": "mocha --compilers js:babel-core/register --recursive src/**/__tests__/*.js",
"test": "mocha --compilers js:babel-core/register --recursive withDom.js src/**/__tests__/*.js",
"check": "npm run lint && npm run test:all",
"build": "babel src --out-dir build",
"test:watch": "mocha --compilers js:babel-core/register --recursive src/**/__tests__/*.js --watch",
"test:watch": "mocha --compilers js:babel-core/register --recursive withDom.js 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",
Expand Down
20 changes: 20 additions & 0 deletions src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ export default class ReactWrapper {
return this;
}

unmount() {
if (this.root !== this) {
throw new Error('ReactWrapper::unmount() can only be called on the root');
}
this.single(() => {
this.component.setState({ mount: false });
});
return this;
}

mount() {
if (this.root !== this) {
throw new Error('ReactWrapper::mount() can only be called on the root');
}
this.single(() => {
this.component.setState({ mount: true });
});
return this;
}

/**
* A method that sets the props of the root component, and re-renders. Useful for when you are
* wanting to test how the component behaves over time with changing props. Calling this, for
Expand Down
5 changes: 4 additions & 1 deletion src/ReactWrapperComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default function createWrapperComponent(node, options = {}) {

getInitialState() {
return {
mount: true,
props: this.props.props,
context: this.props.context,
};
Expand Down Expand Up @@ -62,8 +63,10 @@ export default function createWrapperComponent(node, options = {}) {

render() {
const { Component } = this.props;
const { mount, props } = this.state;
if (!mount) return null;
return (
<Component {...this.state.props} />
<Component {...props} />
);
},
};
Expand Down
65 changes: 63 additions & 2 deletions src/__tests__/ReactWrapper-spec.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { describeWithDOM, describeIf } from './_helpers';
import React from 'react';
import { expect } from 'chai';
import sinon from 'sinon';
import {
mount,
render,
ReactWrapper,
describeWithDOM,
} from '../';
import { describeIf } from './_helpers';
import { REACT013 } from '../version';

describeWithDOM('mount', () => {
Expand Down Expand Up @@ -468,6 +467,68 @@ describeWithDOM('mount', () => {
});
});


describe('.mount()', () => {
it('should call componentWillUnmount()', () => {
const willMount = sinon.spy();
const didMount = sinon.spy();
const willUnmount = sinon.spy();

class Foo extends React.Component {
constructor(props) {
super(props);
this.componentWillUnmount = willUnmount;
this.componentWillMount = willMount;
this.componentDidMount = didMount;
}
render() {
return (
<div className={this.props.id}>
{this.props.id}
</div>
);
}
}
const wrapper = mount(<Foo id="foo" />);
expect(willMount.callCount).to.equal(1);
expect(didMount.callCount).to.equal(1);
expect(willUnmount.callCount).to.equal(0);
wrapper.unmount();
expect(willMount.callCount).to.equal(1);
expect(didMount.callCount).to.equal(1);
expect(willUnmount.callCount).to.equal(1);
wrapper.mount();
expect(willMount.callCount).to.equal(2);
expect(didMount.callCount).to.equal(2);
expect(willUnmount.callCount).to.equal(1);
});
});

describe('.unmount()', () => {
it('should call componentWillUnmount()', () => {
const spy = sinon.spy();

class Foo extends React.Component {
constructor(props) {
super(props);
this.componentWillUnmount = spy;
}
render() {
return (
<div className={this.props.id}>
{this.props.id}
</div>
);
}
}
const wrapper = mount(<Foo id="foo" />);
expect(spy.calledOnce).to.equal(false);
wrapper.unmount();
expect(spy.calledOnce).to.equal(true);
});

});

describe('.simulate(eventName, data)', () => {

it('should simulate events', () => {
Expand Down
8 changes: 3 additions & 5 deletions src/__tests__/Utils-spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react/addons';
import { describeWithDOM } from './_helpers.js';
import React from 'react';
import { expect } from 'chai';
import sinon from 'sinon';
import {
Expand All @@ -12,10 +13,7 @@ import {
selectorType,
mapNativeEventNames,
} from '../Utils';
import {
describeWithDOM,
mount,
} from '../';
import { mount } from '../';

describe('Utils', () => {

Expand Down
11 changes: 11 additions & 0 deletions src/__tests__/_helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
export function describeWithDOM(a, b) {
describe('(uses jsdom)', () => {
if (global.document) {
describe(a, b);
} else {
// if jsdom isn't available, skip every test in this describe context
describe.skip(a, b);
}
});
}

/**
* Simple wrapper around mocha describe which allows a boolean to be passed in first which
* determines whether or not the test will be run
Expand Down
22 changes: 22 additions & 0 deletions withDom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
if (!global.document) {
try {
const jsdom = require('jsdom').jsdom; // could throw

const exposedProperties = ['window', 'navigator', 'document'];

global.document = jsdom('');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === 'undefined') {
exposedProperties.push(property);
global[property] = document.defaultView[property];
}
});

global.navigator = {
userAgent: 'node.js',
};
} catch (e) {
// jsdom is not supported...
}
}

0 comments on commit 2bc779a

Please sign in to comment.