mirror of
https://github.com/zhigang1992/create-react-app.git
synced 2026-05-18 04:24:19 +08:00
E2e jsdom fix (#1470)
* E2E: run tests when react is ready * Entangle e2e with callbacks * Remove unused e2e lines
This commit is contained in:
committed by
Dan Abramov
parent
bc2fc80898
commit
1d586aaf31
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"babel-preset-latest": "6.16.0",
|
||||
"babel-register": "6.18.0",
|
||||
"babel-register": "6.22.0",
|
||||
"babel-polyfill": "6.20.0",
|
||||
"chai": "3.5.0",
|
||||
"jsdom": "9.8.3",
|
||||
|
||||
@@ -5,9 +5,6 @@ const path = require('path')
|
||||
|
||||
let getMarkup
|
||||
let resourceLoader
|
||||
// this value could be tweaked in order to let the resource
|
||||
// retriever get every file and jsdom execute react
|
||||
let timeToWaitForJsToExecute
|
||||
|
||||
if (process.env.E2E_FILE) {
|
||||
const file = path.isAbsolute(process.env.E2E_FILE)
|
||||
@@ -21,8 +18,6 @@ if (process.env.E2E_FILE) {
|
||||
null,
|
||||
fs.readFileSync(path.join(path.dirname(file), resource.url.pathname), 'utf8')
|
||||
)
|
||||
|
||||
timeToWaitForJsToExecute = 0
|
||||
} else if (process.env.E2E_URL) {
|
||||
getMarkup = () => new Promise(resolve => {
|
||||
http.get(process.env.E2E_URL, (res) => {
|
||||
@@ -32,11 +27,7 @@ if (process.env.E2E_FILE) {
|
||||
})
|
||||
})
|
||||
|
||||
resourceLoader = (resource, callback) => {
|
||||
return resource.defaultFetch(callback)
|
||||
}
|
||||
|
||||
timeToWaitForJsToExecute = 100
|
||||
resourceLoader = (resource, callback) => resource.defaultFetch(callback)
|
||||
} else {
|
||||
it.only('can run jsdom (at least one of "E2E_FILE" or "E2E_URL" environment variables must be provided)', () => {
|
||||
expect(new Error('This isn\'t the error you are looking for.')).toBeUndefined()
|
||||
@@ -47,16 +38,16 @@ export default feature => new Promise(async resolve => {
|
||||
const markup = await getMarkup()
|
||||
const host = process.env.E2E_URL || 'http://localhost:3000'
|
||||
const doc = jsdom.jsdom(markup, {
|
||||
features : {
|
||||
FetchExternalResources : ['script', 'css'],
|
||||
ProcessExternalResources : ['script'],
|
||||
features: {
|
||||
FetchExternalResources: ['script', 'css'],
|
||||
ProcessExternalResources: ['script'],
|
||||
},
|
||||
created: (_, win) => win.addEventListener('ReactFeatureDidMount', () => resolve(doc), true),
|
||||
deferClose: true,
|
||||
resourceLoader,
|
||||
url: `${host}#${feature}`,
|
||||
virtualConsole: jsdom.createVirtualConsole().sendTo(console),
|
||||
})
|
||||
|
||||
doc.defaultView.addEventListener('load', () => {
|
||||
setTimeout(() => resolve(doc), timeToWaitForJsToExecute)
|
||||
}, false)
|
||||
doc.close()
|
||||
})
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
import React from 'react';
|
||||
|
||||
class BuiltEmitter extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.callWhenDone = done => done();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.callWhenDone(() => document.dispatchEvent(new Event('ReactFeatureDidMount')));
|
||||
}
|
||||
|
||||
render() {
|
||||
const feature = React.cloneElement(React.Children.only(this.props.children), {
|
||||
setCallWhenDone: done => {
|
||||
this.callWhenDone = done;
|
||||
}
|
||||
});
|
||||
|
||||
return <div>{feature}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -96,7 +118,7 @@ class App extends React.Component {
|
||||
|
||||
render() {
|
||||
const Feature = this.state.feature;
|
||||
return Feature ? <Feature /> : null;
|
||||
return Feature ? <BuiltEmitter><Feature /></BuiltEmitter> : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load([{ id: 42, name: '42' }]);
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = await load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load('user_');
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -18,12 +18,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const { users } = await load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -12,6 +12,11 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
@@ -20,7 +25,7 @@ export default class extends React.Component {
|
||||
for (let user of load(4)) {
|
||||
users.push(user);
|
||||
}
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load({ age: 42 });
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
load().then(users => {
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load();
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load({ id: 0, user: { id: 42, name: '42' } });
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -13,12 +13,17 @@ export default class extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.done = () => {};
|
||||
this.props.setCallWhenDone && this.props.setCallWhenDone((done) => {
|
||||
this.done = done;
|
||||
});
|
||||
|
||||
this.state = { users: [] };
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const users = load('user_');
|
||||
this.setState({ users });
|
||||
this.setState({ users }, () => this.done());
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -22,8 +22,6 @@ temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'`
|
||||
function cleanup {
|
||||
echo 'Cleaning up.'
|
||||
cd $root_path
|
||||
# Uncomment when snapshot testing is enabled by default:
|
||||
# rm ./packages/react-scripts/template/src/__snapshots__/App.test.js.snap
|
||||
rm -rf $temp_cli_path $temp_app_path
|
||||
}
|
||||
|
||||
@@ -60,14 +58,6 @@ root_path=$PWD
|
||||
|
||||
npm install
|
||||
|
||||
# If the node version is < 4, the script should just give an error.
|
||||
if [ `node --version | sed -e 's/^v//' -e 's/\..\+//g'` -lt 4 ]
|
||||
then
|
||||
cd $temp_app_path
|
||||
err_output=`node "$root_path"/packages/create-react-app/index.js test-node-version 2>&1 > /dev/null || echo ''`
|
||||
[[ $err_output =~ You\ are\ running\ Node ]] && exit 0 || exit 1
|
||||
fi
|
||||
|
||||
if [ "$USE_YARN" = "yes" ]
|
||||
then
|
||||
# Install Yarn so that the test can use it to install packages.
|
||||
|
||||
@@ -22,8 +22,6 @@ temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'`
|
||||
function cleanup {
|
||||
echo 'Cleaning up.'
|
||||
cd $root_path
|
||||
# Uncomment when snapshot testing is enabled by default:
|
||||
# rm ./packages/react-scripts/template/src/__snapshots__/App.test.js.snap
|
||||
rm -rf $temp_cli_path $temp_app_path
|
||||
}
|
||||
|
||||
@@ -60,14 +58,6 @@ root_path=$PWD
|
||||
|
||||
npm install
|
||||
|
||||
# If the node version is < 4, the script should just give an error.
|
||||
if [ `node --version | sed -e 's/^v//' -e 's/\..\+//g'` -lt 4 ]
|
||||
then
|
||||
cd $temp_app_path
|
||||
err_output=`node "$root_path"/packages/create-react-app/index.js test-node-version 2>&1 > /dev/null || echo ''`
|
||||
[[ $err_output =~ You\ are\ running\ Node ]] && exit 0 || exit 1
|
||||
fi
|
||||
|
||||
if [ "$USE_YARN" = "yes" ]
|
||||
then
|
||||
# Install Yarn so that the test can use it to install packages.
|
||||
@@ -93,9 +83,6 @@ cp package.json package.json.orig
|
||||
# of those packages.
|
||||
node $root_path/tasks/replace-own-deps.js
|
||||
|
||||
# Remove .npmignore so the test template is added
|
||||
rm $root_path/packages/react-scripts/.npmignore
|
||||
|
||||
# Finally, pack react-scripts
|
||||
scripts_path=$root_path/packages/react-scripts/`npm pack`
|
||||
|
||||
@@ -151,14 +138,7 @@ E2E_URL="http://localhost:3001" \
|
||||
E2E_FILE=./build/index.html \
|
||||
CI=true \
|
||||
NODE_PATH=src \
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js
|
||||
|
||||
# Uncomment when snapshot testing is enabled by default:
|
||||
# test -e src/__snapshots__/App.test.js.snap
|
||||
|
||||
# Test the server
|
||||
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell NODE_PATH=src npm start -- --smoke-test
|
||||
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell HTTPS=true NODE_PATH=src npm start -- --smoke-test
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
|
||||
|
||||
# ******************************************************************************
|
||||
# Finally, let's check that everything still works after ejecting.
|
||||
@@ -199,20 +179,14 @@ E2E_URL="http://localhost:3002" \
|
||||
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
|
||||
CI=true NODE_PATH=src \
|
||||
NODE_ENV=production \
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
|
||||
|
||||
# Test "production" environment
|
||||
E2E_FILE=./build/index.html \
|
||||
CI=true \
|
||||
NODE_ENV=production \
|
||||
NODE_PATH=src \
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.js
|
||||
|
||||
# Uncomment when snapshot testing is enabled by default:
|
||||
# test -e src/__snapshots__/App.test.js.snap
|
||||
|
||||
# Test the server
|
||||
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell NODE_PATH=src npm start -- --smoke-test
|
||||
node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
|
||||
|
||||
# Cleanup
|
||||
cleanup
|
||||
|
||||
Reference in New Issue
Block a user