Unverified Commit adab23fa authored by Joe Haddad's avatar Joe Haddad
Browse files

e2e: Reduce complexity of e2e and improve Jest coverage (#1484)

parent 65e63403
Showing with 145 additions and 103 deletions
+145 -103
{ {
"presets": ["latest"] "presets": ["react-app"]
} }
{ {
"dependencies": { "dependencies": {
"babel-preset-latest": "6.16.0",
"babel-register": "6.22.0", "babel-register": "6.22.0",
"babel-polyfill": "6.20.0", "babel-polyfill": "6.20.0",
"chai": "3.5.0", "chai": "3.5.0",
......
import React from 'react'; import React, { Component, PropTypes, createElement } from 'react';
class BuiltEmitter extends React.Component { class BuiltEmitter extends Component {
constructor(props) { static propTypes = {
super(props) feature: PropTypes.func.isRequired
this.callWhenDone = done => done();
} }
componentDidMount() { componentDidMount() {
this.callWhenDone(() => document.dispatchEvent(new Event('ReactFeatureDidMount'))); const { feature } = this.props
// Class components must call this.props.onReady when they're ready for the test.
// We will assume functional components are ready immediately after mounting.
if (!Component.isPrototypeOf(feature)) {
this.handleReady();
}
} }
render() { handleReady() {
const feature = React.cloneElement(React.Children.only(this.props.children), { document.dispatchEvent(new Event('ReactFeatureDidMount'));
setCallWhenDone: done => { }
this.callWhenDone = done;
}
});
return <div>{feature}</div>; render() {
const {
props: { feature },
handleReady
} = this;
return (
<div>
{createElement(feature, {
onReady: handleReady
})}
</div>
);
} }
} }
class App extends React.Component { class App extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -105,9 +117,7 @@ class App extends React.Component { ...@@ -105,9 +117,7 @@ class App extends React.Component {
case 'unknown-ext-inclusion': case 'unknown-ext-inclusion':
require.ensure([], () => this.setFeature(require('./features/webpack/UnknownExtInclusion').default)); require.ensure([], () => this.setFeature(require('./features/webpack/UnknownExtInclusion').default));
break; break;
default: default: throw new Error('Unknown feature!');
this.setFeature(null);
break;
} }
} }
...@@ -116,8 +126,11 @@ class App extends React.Component { ...@@ -116,8 +126,11 @@ class App extends React.Component {
} }
render() { render() {
const Feature = this.state.feature; const { feature } = this.state;
return Feature ? <BuiltEmitter><Feature /></BuiltEmitter> : null; if (feature !== null) {
return <BuiltEmitter feature={feature} />;
}
return null;
} }
} }
......
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});
import React from 'react' import React, { Component, PropTypes } from 'react'
import load from 'absoluteLoad' import load from 'absoluteLoad'
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load(); const users = load();
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import NodePath from './NodePath'; ...@@ -5,6 +5,8 @@ import NodePath from './NodePath';
describe('NODE_PATH', () => { describe('NODE_PATH', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<NodePath />, div); return new Promise(resolve => {
ReactDOM.render(<NodePath onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
function load() { function load() {
return [ return [
...@@ -9,21 +9,23 @@ function load() { ...@@ -9,21 +9,23 @@ function load() {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load(); const users = load();
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import ArrayDestructuring from './ArrayDestructuring'; ...@@ -5,6 +5,8 @@ import ArrayDestructuring from './ArrayDestructuring';
describe('array destructuring', () => { describe('array destructuring', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<ArrayDestructuring />, div); return new Promise(resolve => {
ReactDOM.render(<ArrayDestructuring onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
function load(users) { function load(users) {
return [ return [
...@@ -9,21 +9,23 @@ function load(users) { ...@@ -9,21 +9,23 @@ function load(users) {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load([{ id: 42, name: '42' }]); const users = load([{ id: 42, name: '42' }]);
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import ArraySpread from './ArraySpread'; ...@@ -5,6 +5,8 @@ import ArraySpread from './ArraySpread';
describe('array spread', () => { describe('array spread', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<ArraySpread />, div); return new Promise(resolve => {
ReactDOM.render(<ArraySpread onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
async function load() { async function load() {
return [ return [
...@@ -9,21 +9,23 @@ async function load() { ...@@ -9,21 +9,23 @@ async function load() {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = await load(); const users = await load();
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import AsyncAwait from './AsyncAwait'; ...@@ -5,6 +5,8 @@ import AsyncAwait from './AsyncAwait';
describe('async/await', () => { describe('async/await', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<AsyncAwait />, div); return new Promise(resolve => {
ReactDOM.render(<AsyncAwait onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
export default class extends React.Component {
users = [ users = [
{ id: 1, name: '1' }, { id: 1, name: '1' },
{ id: 2, name: '2' }, { id: 2, name: '2' },
...@@ -8,6 +12,10 @@ export default class extends React.Component { ...@@ -8,6 +12,10 @@ export default class extends React.Component {
{ id: 4, name: '4' } { id: 4, name: '4' }
]; ];
componentDidMount() {
this.props.onReady()
}
render() { render() {
return ( return (
<div id="feature-class-properties"> <div id="feature-class-properties">
......
...@@ -5,6 +5,8 @@ import ClassProperties from './ClassProperties'; ...@@ -5,6 +5,8 @@ import ClassProperties from './ClassProperties';
describe('class properties', () => { describe('class properties', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<ClassProperties />, div); return new Promise(resolve => {
ReactDOM.render(<ClassProperties onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
function load(prefix) { function load(prefix) {
return [ return [
...@@ -9,21 +9,23 @@ function load(prefix) { ...@@ -9,21 +9,23 @@ function load(prefix) {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load('user_'); const users = load('user_');
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import ComputedProperties from './ComputedProperties'; ...@@ -5,6 +5,8 @@ import ComputedProperties from './ComputedProperties';
describe('computed properties', () => { describe('computed properties', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<ComputedProperties />, div); return new Promise(resolve => {
ReactDOM.render(<ComputedProperties onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
const styled = ([style]) => style.trim() const styled = ([style]) => style.trim()
.split(/\s*;\s*/) .split(/\s*;\s*/)
...@@ -14,21 +14,23 @@ function load() { ...@@ -14,21 +14,23 @@ function load() {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load(); const users = load();
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import CustomInterpolation from './CustomInterpolation'; ...@@ -5,6 +5,8 @@ import CustomInterpolation from './CustomInterpolation';
describe('custom interpolation', () => { describe('custom interpolation', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<CustomInterpolation />, div); return new Promise(resolve => {
ReactDOM.render(<CustomInterpolation onReady={resolve} />, div);
});
}); });
}); });
import React from 'react' import React, { Component, PropTypes } from 'react'
function load(id = 0) { function load(id = 0) {
return [ return [
...@@ -9,21 +9,23 @@ function load(id = 0) { ...@@ -9,21 +9,23 @@ function load(id = 0) {
]; ];
} }
export default class extends React.Component { export default class extends Component {
static propTypes = {
onReady: PropTypes.func.isRequired
}
constructor(props) { constructor(props) {
super(props); super(props);
this.done = () => {};
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
this.done = done;
});
this.state = { users: [] }; this.state = { users: [] };
} }
async componentDidMount() { async componentDidMount() {
const users = load(); const users = load();
this.setState({ users }, () => this.done()); this.setState({ users });
}
componentDidUpdate() {
this.props.onReady();
} }
render() { render() {
......
...@@ -5,6 +5,8 @@ import DefaultParameters from './DefaultParameters'; ...@@ -5,6 +5,8 @@ import DefaultParameters from './DefaultParameters';
describe('default parameters', () => { describe('default parameters', () => {
it('renders without crashing', () => { it('renders without crashing', () => {
const div = document.createElement('div'); const div = document.createElement('div');
ReactDOM.render(<DefaultParameters />, div); return new Promise(resolve => {
ReactDOM.render(<DefaultParameters onReady={resolve} />, div);
});
}); });
}); });
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment