Commit 9099570b authored by Fabrizio Castellarin's avatar Fabrizio Castellarin Committed by Dan Abramov
Browse files

Use a more sophisticated template for end-to-end testing. (#1187)

* Use a more sophisticated template for end-to-end testing.

* Not publish integration tests to npm

* Use "commander" for  cli argv handling

* Handle different scripts version forms and exits without a name given

* Prepare the commands for testing with a template

* Fix dev "template" path

* Add various features to test

* Test various features separately

* Test language features

* Comment unused e2e.sh lines

* Add "development" tests

* Test environment variables

* Test webpack plugins

* Replace kitchensink README

* Switch integration tests from jest to mocha

* Use `fs-extra`

* Use the correct folders

* Do some cleanup

* Print a better message for `--template`

* Test `npm start` with and without https

* Separate fast e2e testing from kitchensink testing

* Hide `--internal-testing-template` (former `--template`) CLI option
parent 7cd03f9f
Showing with 469 additions and 62 deletions
+469 -62
import React from 'react'
import aFileWithoutExt from './assets/aFileWithoutExt'
const text = aFileWithoutExt.includes('base64')
? atob(aFileWithoutExt.split('base64,')[1]).trim()
: aFileWithoutExt
export default () => (
<p id="feature-no-ext-inclusion">{text}.</p>
)
import React from 'react';
import ReactDOM from 'react-dom';
import NoExtInclusion from './NoExtInclusion';
describe('no ext inclusion', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<NoExtInclusion />, div);
});
});
import React from 'react'
import logo from './assets/logo.svg'
export default () => (
<img id="feature-svg-inclusion" src={logo} alt="logo" />
)
import React from 'react';
import ReactDOM from 'react-dom';
import SvgInclusion from './SvgInclusion';
describe('svg inclusion', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<SvgInclusion />, div);
});
});
import React from 'react'
import aFileWithExtUnknown from './assets/aFileWithExt.unknown'
const text = aFileWithExtUnknown.includes('base64')
? atob(aFileWithExtUnknown.split('base64,')[1]).trim()
: aFileWithExtUnknown
export default () => (
<p id="feature-unknown-ext-inclusion">{text}.</p>
)
import React from 'react';
import ReactDOM from 'react-dom';
import UnknownExtInclusion from './UnknownExtInclusion';
describe('unknown ext inclusion', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<UnknownExtInclusion />, div);
});
});
Whoooo, spooky!
This is just a file without an extension
{
"abstract": "This is an abstract."
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>
#feature-css-inclusion {
background: palevioletred;
color: papayawhip;
}
packages/react-scripts/fixtures/kitchensink/src/features/webpack/assets/tiniest-cat.jpg

691 Bytes

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
module.exports = function() { return `haha` }
...@@ -12,7 +12,7 @@ var path = require('path'); ...@@ -12,7 +12,7 @@ var path = require('path');
var spawn = require('cross-spawn'); var spawn = require('cross-spawn');
var chalk = require('chalk'); var chalk = require('chalk');
module.exports = function(appPath, appName, verbose, originalDirectory) { module.exports = function(appPath, appName, verbose, originalDirectory, template) {
var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name; var ownPackageName = require(path.join(__dirname, '..', 'package.json')).name;
var ownPath = path.join(appPath, 'node_modules', ownPackageName); var ownPath = path.join(appPath, 'node_modules', ownPackageName);
var appPackage = require(path.join(appPath, 'package.json')); var appPackage = require(path.join(appPath, 'package.json'));
...@@ -41,7 +41,13 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { ...@@ -41,7 +41,13 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
} }
// Copy the files for the user // Copy the files for the user
fs.copySync(path.join(ownPath, 'template'), appPath); var templatePath = template ? path.resolve(originalDirectory, template) : path.join(ownPath, 'template');
if (fs.existsSync(templatePath)) {
fs.copySync(templatePath, appPath);
} else {
console.error('Could not locate supplied template: ' + chalk.green(templatePath));
return;
}
// Rename gitignore after the fact to prevent npm from renaming it to .npmignore // Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862 // See: https://github.com/npm/npm/issues/1862
...@@ -76,6 +82,16 @@ module.exports = function(appPath, appName, verbose, originalDirectory) { ...@@ -76,6 +82,16 @@ module.exports = function(appPath, appName, verbose, originalDirectory) {
} }
args.push('react', 'react-dom'); args.push('react', 'react-dom');
// Install additional template dependencies, if present
var templateDependenciesPath = path.join(appPath, '.template.dependencies.json');
if (fs.existsSync(templateDependenciesPath)) {
var templateDependencies = require(templateDependenciesPath).dependencies;
args = args.concat(Object.keys(templateDependencies).map(function (key) {
return key + '@' + templateDependencies[key];
}));
fs.unlinkSync(templateDependenciesPath);
}
console.log('Installing react and react-dom using ' + command + '...'); console.log('Installing react and react-dom using ' + command + '...');
console.log(); console.log();
......
#!/bin/bash
# Copyright (c) 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
# ******************************************************************************
# This is an end-to-end 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 and app temporary locations
# http://unix.stackexchange.com/a/84980
temp_cli_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_cli_path'`
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
}
# 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
}
function create_react_app {
node "$temp_cli_path"/node_modules/create-react-app/index.js $*
}
# 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
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.
npm install -g yarn@0.17.10 # TODO: remove version when https://github.com/yarnpkg/yarn/issues/2142 is fixed.
yarn cache clean
fi
# ******************************************************************************
# First, pack and install create-react-app.
# ******************************************************************************
# Pack CLI
cd $root_path/packages/create-react-app
cli_path=$PWD/`npm pack`
# Install the CLI in a temporary location
cd $temp_cli_path
npm install $cli_path
# ******************************************************************************
# Test --scripts-version with a version number
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=0.4.0 test-app-version-number
cd test-app-version-number
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts
grep '"version": "0.4.0"' node_modules/react-scripts/package.json
# ******************************************************************************
# Test --scripts-version with a tarball url
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=https://registry.npmjs.org/react-scripts/-/react-scripts-0.4.0.tgz test-app-tarball-url
cd test-app-tarball-url
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts
grep '"version": "0.4.0"' node_modules/react-scripts/package.json
# ******************************************************************************
# Test --scripts-version with a custom fork of react-scripts
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=react-scripts-fork test-app-fork
cd test-app-fork
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts-fork
# ******************************************************************************
# Test nested folder path as the project name
# ******************************************************************************
#Testing a path that exists
cd $temp_app_path
mkdir test-app-nested-paths-t1
cd test-app-nested-paths-t1
mkdir -p test-app-nested-paths-t1/aa/bb/cc/dd
create_react_app test-app-nested-paths-t1/aa/bb/cc/dd
cd test-app-nested-paths-t1/aa/bb/cc/dd
npm start -- --smoke-test
#Testing a path that does not exist
cd $temp_app_path
create_react_app test-app-nested-paths-t2/aa/bb/cc/dd
cd test-app-nested-paths-t2/aa/bb/cc/dd
npm start -- --smoke-test
#Testing a path that is half exists
cd $temp_app_path
mkdir -p test-app-nested-paths-t3/aa
create_react_app test-app-nested-paths-t3/aa/bb/cc/dd
cd test-app-nested-paths-t3/aa/bb/cc/dd
npm start -- --smoke-test
# Cleanup
cleanup
#!/bin/bash
# Copyright (c) 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
# ******************************************************************************
# 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 and app temporary locations
# http://unix.stackexchange.com/a/84980
temp_cli_path=`mktemp -d 2>/dev/null || mktemp -d -t 'temp_cli_path'`
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
}
# 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
}
function create_react_app {
node "$temp_cli_path"/node_modules/create-react-app/index.js $*
}
# 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
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.
npm install -g yarn@0.17.10 # TODO: remove version when https://github.com/yarnpkg/yarn/issues/2142 is fixed.
yarn cache clean
fi
# ******************************************************************************
# First, pack react-scripts and create-react-app so we can use them.
# ******************************************************************************
# Pack CLI
cd $root_path/packages/create-react-app
cli_path=$PWD/`npm pack`
# Go to react-scripts
cd $root_path/packages/react-scripts
# Save package.json because we're going to touch it
cp package.json package.json.orig
# Replace own dependencies (those in the `packages` dir) with the local paths
# 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`
# Restore package.json
rm package.json
mv package.json.orig package.json
# ******************************************************************************
# Now that we have packed them, create a clean app folder and install them.
# ******************************************************************************
# Install the CLI in a temporary location
cd $temp_cli_path
npm install $cli_path
# Install the app in a temporary location
cd $temp_app_path
create_react_app --scripts-version=$scripts_path --internal-testing-template=$root_path/packages/react-scripts/fixtures/kitchensink test-kitchensink
# ******************************************************************************
# Now that we used create-react-app to create an app depending on react-scripts,
# let's make sure all npm scripts are in the working state.
# ******************************************************************************
# Enter the app directory
cd test-kitchensink
# Test the build
NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build
# Check for expected output
test -e build/*.html
test -e build/static/js/main.*.js
# Unit tests
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
CI=true \
NODE_PATH=src \
npm test -- --no-cache --testPathPattern="/src/"
# Test "development" environment
tmp_server_log=`mktemp`
PORT=3001 \
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
NODE_PATH=src \
nohup npm start &>$tmp_server_log &
grep -q 'The app is running at:' <(tail -f $tmp_server_log)
E2E_URL="http://localhost:3001" \
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
CI=true NODE_PATH=src \
node node_modules/.bin/mocha --require babel-register --require babel-polyfill integration/*.test.js
# Test "production" environment
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
# ******************************************************************************
# Finally, let's check that everything still works after ejecting.
# ******************************************************************************
# Eject...
echo yes | npm run eject
# ...but still link to the local packages
npm link $root_path/packages/babel-preset-react-app
npm link $root_path/packages/eslint-config-react-app
npm link $root_path/packages/react-dev-utils
npm link $root_path/packages/react-scripts
# ...and we need to remove template's .babelrc
rm .babelrc
# Test the build
NODE_PATH=src REACT_APP_SHELL_ENV_MESSAGE=fromtheshell npm run build
# Check for expected output
test -e build/*.html
test -e build/static/js/main.*.js
# Unit tests
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
CI=true \
NODE_PATH=src \
npm test -- --no-cache --testPathPattern="/src/"
# Test "development" environment
tmp_server_log=`mktemp`
PORT=3002 \
REACT_APP_SHELL_ENV_MESSAGE=fromtheshell \
NODE_PATH=src \
nohup npm start &>$tmp_server_log &
grep -q 'The app is running at:' <(tail -f $tmp_server_log)
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
# 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
# Cleanup
cleanup
...@@ -195,66 +195,6 @@ npm test -- --watch=no ...@@ -195,66 +195,6 @@ npm test -- --watch=no
# Test the server # Test the server
npm start -- --smoke-test npm start -- --smoke-test
# ******************************************************************************
# Test --scripts-version with a version number
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=0.4.0 test-app-version-number
cd test-app-version-number
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts
grep '"version": "0.4.0"' node_modules/react-scripts/package.json
# ******************************************************************************
# Test --scripts-version with a tarball url
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=https://registry.npmjs.org/react-scripts/-/react-scripts-0.4.0.tgz test-app-tarball-url
cd test-app-tarball-url
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts
grep '"version": "0.4.0"' node_modules/react-scripts/package.json
# ******************************************************************************
# Test --scripts-version with a custom fork of react-scripts
# ******************************************************************************
cd $temp_app_path
create_react_app --scripts-version=react-scripts-fork test-app-fork
cd test-app-fork
# Check corresponding scripts version is installed.
test -e node_modules/react-scripts-fork
# ******************************************************************************
# Test nested folder path as the project name
# ******************************************************************************
#Testing a path that exists
cd $temp_app_path
mkdir test-app-nested-paths-t1
cd test-app-nested-paths-t1
mkdir -p test-app-nested-paths-t1/aa/bb/cc/dd
create_react_app test-app-nested-paths-t1/aa/bb/cc/dd
cd test-app-nested-paths-t1/aa/bb/cc/dd
npm start -- --smoke-test
#Testing a path that does not exist
cd $temp_app_path
create_react_app test-app-nested-paths-t2/aa/bb/cc/dd
cd test-app-nested-paths-t2/aa/bb/cc/dd
npm start -- --smoke-test
#Testing a path that is half exists
cd $temp_app_path
mkdir -p test-app-nested-paths-t3/aa
create_react_app test-app-nested-paths-t3/aa/bb/cc/dd
cd test-app-nested-paths-t3/aa/bb/cc/dd
npm start -- --smoke-test
# Cleanup # Cleanup
cleanup cleanup
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