Skip to content

Commit

Permalink
Add behavior e2e tests (facebook#5146)
Browse files Browse the repository at this point in the history
* Add new behavior e2e test script

* Add output for transparency
  • Loading branch information
Timer authored Sep 27, 2018
1 parent 7644f73 commit af61071
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 6 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build
my-app*
packages/react-scripts/template
packages/react-scripts/fixtures
fixtures/
14 changes: 8 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,25 @@ node_js:
cache:
yarn: true
directories:
- .npm
- .npm
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash
- export PATH="$HOME/.yarn/bin:$PATH"
install: true
script:
- 'if [ $TEST_SUITE = "simple" ]; then tasks/e2e-simple.sh; fi'
- 'if [ $TEST_SUITE = "installs" ]; then tasks/e2e-installs.sh; fi'
- 'if [ $TEST_SUITE = "kitchensink" ]; then tasks/e2e-kitchensink.sh; fi'
- 'if [ $TEST_SUITE = "kitchensink-eject" ]; then tasks/e2e-kitchensink-eject.sh; fi'
- 'if [ $TEST_SUITE = "old-node" ]; then tasks/e2e-old-node.sh; fi'
- 'if [ $TEST_SUITE = "simple" ]; then tasks/e2e-simple.sh; fi'
- 'if [ $TEST_SUITE = "installs" ]; then tasks/e2e-installs.sh; fi'
- 'if [ $TEST_SUITE = "kitchensink" ]; then tasks/e2e-kitchensink.sh; fi'
- 'if [ $TEST_SUITE = "kitchensink-eject" ]; then tasks/e2e-kitchensink-eject.sh; fi'
- 'if [ $TEST_SUITE = "old-node" ]; then tasks/e2e-old-node.sh; fi'
- 'if [ $TEST_SUITE = "behavior" ]; then tasks/e2e-behavior.sh; fi'
env:
matrix:
- TEST_SUITE=simple
- TEST_SUITE=installs
- TEST_SUITE=kitchensink
- TEST_SUITE=kitchensink-eject
- TEST_SUITE=behavior
matrix:
include:
- node_js: 4
Expand Down
8 changes: 8 additions & 0 deletions fixtures/behavior/builds-with-multiple-runtimes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "builds-with-multiple-runtimes",
"description": "Tests that a build succeeds with multiple runtime versions",
"dependencies": {
"dva": "2.4.0",
"ky": "0.3.0"
}
}
14 changes: 14 additions & 0 deletions fixtures/behavior/builds-with-multiple-runtimes/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import dva from 'dva';
import createHistory from 'history/createHashHistory';
import ky from 'ky';

const app = dva({ history: createHistory() });
app.router(() => {
ky.get('https://canihazip.com/s')
.then(r => r.text())
.then(console.log, console.error)
.then(() => console.log('ok'));
return <div>Test</div>;
});
app.start('#root');
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
"format": "prettier --trailing-comma es5 --single-quote --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'"
},
"devDependencies": {
"cross-spawn": "^6.0.5",
"eslint": "5.6.0",
"execa": "1.0.0",
"fs-extra": "^7.0.0",
"husky": "1.0.0-rc.15",
"lerna": "2.9.1",
"lerna-changelog": "^0.8.0",
Expand Down
113 changes: 113 additions & 0 deletions tasks/e2e-behavior.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/bin/bash
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# ******************************************************************************
# This is an end-to-end kitchensink test intended to run on CI.
# You can also run it locally but it's slow.
# ******************************************************************************

# Start in tasks/ even if run from root directory
cd "$(dirname "$0")"

# CLI, app, and test module temporary locations
# http://unix.stackexchange.com/a/84980
temp_app_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_app_path'`
temp_module_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_module_path'`
custom_registry_url=http://localhost:4873
original_npm_registry_url=`npm get registry`
original_yarn_registry_url=`yarn config get registry`

function cleanup {
echo 'Cleaning up.'
ps -ef | grep 'react-scripts' | grep -v grep | awk '{print $2}' | xargs kill -9
cd "$root_path"
npm set registry "$original_npm_registry_url"
yarn config set registry "$original_yarn_registry_url"
}

# Error messages are redirected to stderr
function handle_error {
echo "$(basename $0): ERROR! An error was encountered executing line $1." 1>&2;
cleanup
echo 'Exiting with error.' 1>&2;
exit 1
}

function handle_exit {
cleanup
echo 'Exiting without error.' 1>&2;
exit
}

# Check for the existence of one or more files.
function exists {
for f in $*; do
test -e "$f"
done
}

# Exit the script with a helpful error message when any error is encountered
trap 'set +x; handle_error $LINENO $BASH_COMMAND' ERR

# Cleanup before exit on any termination signal
trap 'set +x; handle_exit' SIGQUIT SIGTERM SIGINT SIGKILL SIGHUP

# Echo every command being executed
set -x

# Go to root
cd ..
root_path=$PWD

if hash npm 2>/dev/null
then
npm i -g npm@latest
fi

# Bootstrap monorepo
yarn

# ******************************************************************************
# First, publish the monorepo.
# ******************************************************************************

# Start local registry
tmp_registry_log=`mktemp`
nohup npx [email protected] -c tasks/verdaccio.yaml &>$tmp_registry_log &
# Wait for `verdaccio` to boot
grep -q 'http address' <(tail -f $tmp_registry_log)

# Set registry to local registry
npm set registry "$custom_registry_url"
yarn config set registry "$custom_registry_url"

# Login so we can publish packages
(cd && npx [email protected] -u user -p password -e [email protected] -r "$custom_registry_url")

# Publish the monorepo
git clean -df
./tasks/publish.sh --yes --force-publish=* --skip-git --cd-version=prerelease --exact --npm-tag=latest

# ******************************************************************************
# Now that we have published them, create a clean app folder and install them.
# ******************************************************************************

# Install the app in a temporary location
cd $temp_app_path
npx create-react-app test-behavior

# ******************************************************************************
# Now that we used create-react-app to create an app depending on react-scripts,
# let's run through all of our behavior tests.
# ******************************************************************************

# Enter the app directory
cd "$temp_app_path/test-behavior"

node "$root_path"/tasks/test-behavior.js "$temp_app_path/test-behavior"

# Cleanup
cleanup
97 changes: 97 additions & 0 deletions tasks/test-behavior.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict';

const args = process.argv.slice(2);
const fs = require('fs-extra');
const path = require('path');
const os = require('os');
const spawn = require('cross-spawn');

const applicationPath = args.pop();
const applicationPackageJson = path.resolve(applicationPath, 'package.json');
const applicationSrc = path.resolve(applicationPath, 'src');
const applicationModules = path.resolve(applicationPath, 'node_modules');

const fixturePath = path.resolve(__dirname, '..', 'fixtures', 'behavior');
const fixtures = fs
.readdirSync(fixturePath)
.map(fixture => path.resolve(fixturePath, fixture))
.filter(path => fs.lstatSync(path).isDirectory);

const packageContents = require(applicationPackageJson);

function install({ root }) {
spawn.sync('yarnpkg', ['--cwd', root, 'install'], { cwd: root });
}

function startApp({ root }) {
const output = spawn
.sync('yarnpkg', ['start', '--smoke-test'], { cwd: root })
.output.join('');

if (!/Compiled successfully/.test(output)) {
throw new Error(output);
}

console.log('\t = application started: ', output);
}

function buildApp({ root }) {
const output = spawn
.sync('yarnpkg', ['build'], { cwd: root })
.output.join('');

if (!/Compiled successfully/.test(output)) {
throw new Error(output);
}

console.log('\t = application built: ', output);
}

console.log(`=> checking ${fixtures.length} fixtures`);
for (const fixture of fixtures) {
const {
name,
description,
dependencies,
devDependencies,
} = require(path.resolve(fixture, 'package.json'));
console.log(`\t * checking fixture ${name}`);
console.log(`\t ... this fixture: ${description}`);

fs.emptyDirSync(applicationSrc);
fs.emptyDirSync(applicationModules);
fs.copySync(path.resolve(fixture, 'src'), applicationSrc);

try {
fs.writeJsonSync(
applicationPackageJson,
Object.assign({}, packageContents, {
dependencies: Object.assign(
{},
packageContents.dependencies,
dependencies
),
devDependencies: Object.assign(
{},
packageContents.devDependencies,
devDependencies
),
}),
{
spaces: 2,
EOL: os.EOL,
}
);
install({ root: applicationPath });
startApp({ root: applicationPath });
buildApp({ root: applicationPath });
} catch (e) {
console.error(`\t ! failed on ${name}:`);
throw e;
} finally {
fs.writeJsonSync(applicationPackageJson, packageContents, {
spaces: 2,
EOL: os.EOL,
});
}
}

0 comments on commit af61071

Please sign in to comment.