Merge pull request #3 from matrix-org/bwindels/ci_script

Make tests run on CI environment
This commit is contained in:
David Baker 2018-08-02 13:01:47 +01:00 committed by GitHub
commit 1b01867b84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 180 additions and 63 deletions

View file

@ -34,17 +34,15 @@ puppeteer.launch({headless: false});
## How to run ## How to run
### Setup ### Setup
- install synapse with `sh synapse/install.sh`, this fetches the master branch at the moment. If anything fails here, please refer to the synapse README to see if you're missing one of the prerequisites.
- install riot with `sh riot/install.sh`, this fetches the master branch at the moment. Run `./install.sh`. This will:
- install dependencies with `npm install` (will download copy of chrome) - install synapse, fetches the master branch at the moment. If anything fails here, please refer to the synapse README to see if you're missing one of the prerequisites.
- have riot-web running on `localhost:8080` - install riot, this fetches the master branch at the moment.
- have a local synapse running at `localhost:8008` - install dependencies (will download copy of chrome)
### Run tests ### Run tests
Run tests with `sh run.sh`. Run tests with `./run.sh`.
You should see the terminal split with on top the server output (both riot static server, and synapse), and on the bottom the tests running.
Developer Guide Developer Guide
=============== ===============

View file

@ -54,14 +54,15 @@ function logConsole(page) {
function logXHRRequests(page) { function logXHRRequests(page) {
let buffer = ""; let buffer = "";
page.on('request', req => { page.on('requestfinished', async (req) => {
const type = req.resourceType(); const type = req.resourceType();
if (type === 'xhr' || type === 'fetch') { const response = await req.response();
buffer += `${req.method()} ${req.url()} \n`; //if (type === 'xhr' || type === 'fetch') {
if (req.method() === "POST") { buffer += `${type} ${response.status()} ${req.method()} ${req.url()} \n`;
buffer += " Post data: " + req.postData(); // if (req.method() === "POST") {
} // buffer += " Post data: " + req.postData();
} // }
//}
}); });
return { return {
logs() { logs() {

6
install.sh Executable file
View file

@ -0,0 +1,6 @@
#!/bin/bash
# run with PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true sh install.sh if chrome is already installed
set -e
./synapse/install.sh
./riot/install.sh
npm install

View file

@ -9,6 +9,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"puppeteer": "^1.5.0" "puppeteer": "^1.6.0"
} }
} }

16
riot/install.sh Normal file → Executable file
View file

@ -1,13 +1,17 @@
#!/bin/bash
RIOT_BRANCH=master RIOT_BRANCH=master
BASE_DIR=$(realpath $(dirname $0)) BASE_DIR=$(readlink -f $(dirname $0))
pushd $BASE_DIR if [ -d $BASE_DIR/riot-web ]; then
echo "riot is already installed"
exit
fi
cd $BASE_DIR
curl -L https://github.com/vector-im/riot-web/archive/${RIOT_BRANCH}.zip --output riot.zip curl -L https://github.com/vector-im/riot-web/archive/${RIOT_BRANCH}.zip --output riot.zip
unzip riot.zip unzip -q riot.zip
rm riot.zip rm riot.zip
mv riot-web-${RIOT_BRANCH} riot-web mv riot-web-${RIOT_BRANCH} riot-web
cp config-template/config.json riot-web/ cd riot-web
pushd riot-web
npm install npm install
npm run build npm run build
popd

59
riot/start.sh Normal file → Executable file
View file

@ -1,8 +1,51 @@
BASE_DIR=$(realpath $(dirname $0)) #!/bin/bash
pushd $BASE_DIR PORT=5000
pushd riot-web/webapp/ BASE_DIR=$(readlink -f $(dirname $0))
python -m SimpleHTTPServer 8080 & PIDFILE=$BASE_DIR/riot.pid
PID=$! CONFIG_BACKUP=config.e2etests_backup.json
popd
echo $PID > riot.pid if [ -f $PIDFILE ]; then
popd exit
fi
cd $BASE_DIR/
echo -n "starting riot on http://localhost:$PORT ... "
pushd riot-web/webapp/ > /dev/null
# backup config file before we copy template
if [ -f config.json ]; then
mv config.json $CONFIG_BACKUP
fi
cp $BASE_DIR/config-template/config.json .
LOGFILE=$(mktemp)
# run web server in the background, showing output on error
(
python -m SimpleHTTPServer $PORT > $LOGFILE 2>&1 &
PID=$!
echo $PID > $PIDFILE
# wait so subshell does not exit
# otherwise sleep below would not work
wait $PID; RESULT=$?
# NOT expected SIGTERM (128 + 15)
# from stop.sh?
if [ $RESULT -ne 143 ]; then
echo "failed"
cat $LOGFILE
rm $PIDFILE 2> /dev/null
fi
rm $LOGFILE
exit $RESULT
)&
# to be able to return the exit code for immediate errors (like address already in use)
# we wait for a short amount of time in the background and exit when the first
# child process exists
sleep 0.5 &
# wait the first child process to exit (python or sleep)
wait -n; RESULT=$?
# return exit code of first child to exit
if [ $RESULT -eq 0 ]; then
echo "running"
fi
exit $RESULT

24
riot/stop.sh Normal file → Executable file
View file

@ -1,6 +1,20 @@
BASE_DIR=$(realpath $(dirname $0)) #!/bin/bash
pushd $BASE_DIR > /dev/null BASE_DIR=$(readlink -f $(dirname $0))
PIDFILE=riot.pid PIDFILE=riot.pid
kill $(cat $PIDFILE) CONFIG_BACKUP=config.e2etests_backup.json
rm $PIDFILE
popd > /dev/null cd $BASE_DIR
if [ -f $PIDFILE ]; then
echo "stopping riot server ..."
PID=$(cat $PIDFILE)
rm $PIDFILE
kill $PID
# revert config file
cd riot-web/webapp
rm config.json
if [ -f $CONFIG_BACKUP ]; then
mv $CONFIG_BACKUP config.json
fi
fi

23
run.sh Normal file → Executable file
View file

@ -1,4 +1,19 @@
tmux \ #!/bin/bash
new-session "sh riot/stop.sh; sh synapse/stop.sh; sh synapse/start.sh; sh riot/start.sh; read"\; \
split-window "sleep 5; node start.js; sh riot/stop.sh; sh synapse/stop.sh; read"\; \ stop_servers() {
select-layout even-vertical ./riot/stop.sh
./synapse/stop.sh
}
handle_error() {
EXIT_CODE=$?
stop_servers
exit $EXIT_CODE
}
trap 'handle_error' ERR
./synapse/start.sh
./riot/start.sh
node start.js
stop_servers

View file

@ -25,12 +25,27 @@ const acceptServerNoticesInviteAndConsent = require('./tests/server-notices-cons
const homeserver = 'http://localhost:8008'; const homeserver = 'http://localhost:8008';
global.riotserver = 'http://localhost:8080'; global.riotserver = 'http://localhost:5000';
global.browser = null; global.browser = null;
let consoleLogs = null;
let xhrLogs = null;
let globalPage = null;
async function runTests() { async function runTests() {
global.browser = await puppeteer.launch(); console.log("running tests ...");
const options = {};
if (process.env.CHROME_PATH) {
const path = process.env.CHROME_PATH;
console.log(`(using external chrome/chromium at ${path}, make sure it's compatible with puppeteer)`);
options.executablePath = path;
}
global.browser = await puppeteer.launch(options);
const page = await helpers.newPage(); const page = await helpers.newPage();
globalPage = page;
consoleLogs = helpers.logConsole(page);
xhrLogs = helpers.logXHRRequests(page);
const username = 'user-' + helpers.randomInt(10000); const username = 'user-' + helpers.randomInt(10000);
const password = 'testtest'; const password = 'testtest';
@ -39,7 +54,7 @@ async function runTests() {
process.stdout.write('done\n'); process.stdout.write('done\n');
const noticesName = "Server Notices"; const noticesName = "Server Notices";
process.stdout.write(`* accepting "${noticesName}" and accepting terms & conditions ...`); process.stdout.write(`* accepting "${noticesName}" and accepting terms & conditions ... `);
await acceptServerNoticesInviteAndConsent(page, noticesName); await acceptServerNoticesInviteAndConsent(page, noticesName);
process.stdout.write('done\n'); process.stdout.write('done\n');
@ -55,8 +70,21 @@ function onSuccess() {
console.log('all tests finished successfully'); console.log('all tests finished successfully');
} }
function onFailure(err) { async function onFailure(err) {
let documentHtml = "no page";
if (globalPage) {
documentHtml = await globalPage.content();
}
console.log('failure: ', err); console.log('failure: ', err);
console.log('console.log output:');
console.log(consoleLogs.logs());
console.log('XHR requests:');
console.log(xhrLogs.logs());
console.log('document html:');
console.log(documentHtml);
process.exit(-1); process.exit(-1);
} }

18
synapse/install.sh Normal file → Executable file
View file

@ -1,3 +1,4 @@
#!/bin/bash
# config # config
SYNAPSE_BRANCH=master SYNAPSE_BRANCH=master
INSTALLATION_NAME=consent INSTALLATION_NAME=consent
@ -5,13 +6,20 @@ SERVER_DIR=installations/$INSTALLATION_NAME
CONFIG_TEMPLATE=consent CONFIG_TEMPLATE=consent
PORT=8008 PORT=8008
# set current directory to script directory # set current directory to script directory
BASE_DIR=$(realpath $(dirname $0)) BASE_DIR=$(readlink -f $(dirname $0))
pushd $BASE_DIR
if [ -d $BASE_DIR/$SERVER_DIR ]; then
echo "synapse is already installed"
exit
fi
cd $BASE_DIR
mkdir -p installations/ mkdir -p installations/
curl https://codeload.github.com/matrix-org/synapse/zip/$SYNAPSE_BRANCH --output synapse.zip curl https://codeload.github.com/matrix-org/synapse/zip/$SYNAPSE_BRANCH --output synapse.zip
unzip synapse.zip unzip -q synapse.zip
mv synapse-$SYNAPSE_BRANCH $SERVER_DIR mv synapse-$SYNAPSE_BRANCH $SERVER_DIR
pushd $SERVER_DIR cd $SERVER_DIR
virtualenv -p python2.7 env virtualenv -p python2.7 env
source env/bin/activate source env/bin/activate
pip install --upgrade pip pip install --upgrade pip
@ -29,5 +37,3 @@ sed -i "s#{{SYNAPSE_PORT}}#${PORT}/#g" homeserver.yaml
sed -i "s#{{FORM_SECRET}}#$(uuidgen)#g" homeserver.yaml sed -i "s#{{FORM_SECRET}}#$(uuidgen)#g" homeserver.yaml
sed -i "s#{{REGISTRATION_SHARED_SECRET}}#$(uuidgen)#g" homeserver.yaml sed -i "s#{{REGISTRATION_SHARED_SECRET}}#$(uuidgen)#g" homeserver.yaml
sed -i "s#{{MACAROON_SECRET_KEY}}#$(uuidgen)#g" homeserver.yaml sed -i "s#{{MACAROON_SECRET_KEY}}#$(uuidgen)#g" homeserver.yaml
popd #back to synapse root dir
popd #back to wherever we were

17
synapse/start.sh Normal file → Executable file
View file

@ -1,7 +1,12 @@
BASE_DIR=$(realpath $(dirname $0)) #!/bin/bash
pushd $BASE_DIR BASE_DIR=$(readlink -f $(dirname $0))
pushd installations/consent cd $BASE_DIR
cd installations/consent
source env/bin/activate source env/bin/activate
./synctl start LOGFILE=$(mktemp)
popd ./synctl start 2> $LOGFILE
popd EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
cat $LOGFILE
fi
exit $EXIT_CODE

9
synapse/stop.sh Normal file → Executable file
View file

@ -1,7 +1,6 @@
BASE_DIR=$(realpath $(dirname $0)) #!/bin/bash
pushd $BASE_DIR > /dev/null BASE_DIR=$(readlink -f $(dirname $0))
pushd installations/consent > /dev/null cd $BASE_DIR
cd installations/consent
source env/bin/activate source env/bin/activate
./synctl stop ./synctl stop
popd > /dev/null
popd > /dev/null

View file

@ -19,8 +19,6 @@ const acceptTerms = require('./consent');
const assert = require('assert'); const assert = require('assert');
module.exports = async function signup(page, username, password, homeserver) { module.exports = async function signup(page, username, password, homeserver) {
const consoleLogs = helpers.logConsole(page);
const xhrLogs = helpers.logXHRRequests(page);
await page.goto(helpers.riotUrl('/#/register')); await page.goto(helpers.riotUrl('/#/register'));
//click 'Custom server' radio button //click 'Custom server' radio button
if (homeserver) { if (homeserver) {
@ -55,7 +53,7 @@ module.exports = async function signup(page, username, password, homeserver) {
const error_text = await helpers.tryGetInnertext(page, '.mx_Login_error'); const error_text = await helpers.tryGetInnertext(page, '.mx_Login_error');
assert.strictEqual(!!error_text, false); assert.strictEqual(!!error_text, false);
//submit form //submit form
await page.screenshot({path: "beforesubmit.png", fullPage: true}); //await page.screenshot({path: "beforesubmit.png", fullPage: true});
await registerButton.click(); await registerButton.click();
//confirm dialog saying you cant log back in without e-mail //confirm dialog saying you cant log back in without e-mail