mirror of
https://github.com/wassname/talk.git
synced 2026-06-28 01:01:01 +08:00
241 lines
6.5 KiB
JavaScript
Executable File
241 lines
6.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
process.env['NODE_ENV'] = 'test';
|
|
|
|
const browserstack = require('browserstack-local');
|
|
const { onshutdown, shutdown } = require('../bin/util');
|
|
const program = require('commander');
|
|
const Table = require('cli-table2');
|
|
const serve = require('../serve');
|
|
const childProcess = require('child_process');
|
|
const uuid = require('uuid').v4;
|
|
const mongoose = require('../services/mongoose');
|
|
|
|
// Make things colorful!
|
|
require('colors');
|
|
|
|
function startTunnel(key, localIdentifier) {
|
|
const bs_local = new browserstack.Local();
|
|
|
|
// Code to start browserstack local before start of test
|
|
console.log('Connecting local');
|
|
|
|
return new Promise((resolve, reject) => {
|
|
bs_local.start(
|
|
{
|
|
key,
|
|
logFile: './test/e2e/bslocal.log',
|
|
verbose: 'true',
|
|
force: 'true',
|
|
onlyAutomate: 'true',
|
|
localIdentifier,
|
|
},
|
|
error => {
|
|
if (error) {
|
|
reject(error);
|
|
}
|
|
resolve();
|
|
}
|
|
);
|
|
onshutdown([() => bs_local.stop(function() {})]);
|
|
});
|
|
}
|
|
|
|
function seleniumInstall() {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
const nw = childProcess.spawn(
|
|
'./node_modules/.bin/selenium-standalone',
|
|
['install'],
|
|
{
|
|
stdio: 'inherit',
|
|
}
|
|
);
|
|
nw.on('close', code => {
|
|
code === 0 ? resolve() : reject();
|
|
});
|
|
} catch (ex) {
|
|
reject(ex);
|
|
}
|
|
});
|
|
}
|
|
|
|
function nightwatch(env, config, reportsFolder, browserstack, timeout) {
|
|
return new Promise((resolve, reject) => {
|
|
try {
|
|
const nw = childProcess.spawn(
|
|
'./node_modules/.bin/nightwatch',
|
|
['--config', config, '--env', env],
|
|
{
|
|
env: Object.assign({}, process.env, {
|
|
BROWSERSTACK_LOCAL_IDENTIFIER: browserstack.localIdentifier,
|
|
BROWSERSTACK_KEY: browserstack.key,
|
|
BROWSERSTACK_USER: browserstack.user,
|
|
REPORTS_FOLDER: `${reportsFolder}/${env}`,
|
|
WAIT_FOR_TIMEOUT: timeout,
|
|
}),
|
|
stdio: 'inherit',
|
|
}
|
|
);
|
|
nw.on('close', code => {
|
|
code === 0 ? resolve() : reject();
|
|
});
|
|
} catch (ex) {
|
|
reject(ex);
|
|
}
|
|
});
|
|
}
|
|
|
|
function printResults(browsers, succeeded, retries) {
|
|
let table = new Table({
|
|
head: ['Browser'.cyan, 'Status'.cyan, 'Retries'.cyan],
|
|
});
|
|
|
|
for (let browser of browsers) {
|
|
const wasSuccessful = browser in succeeded;
|
|
table.push([
|
|
browser,
|
|
wasSuccessful ? 'success'.green : 'failed'.red,
|
|
wasSuccessful ? succeeded[browser] : retries,
|
|
]);
|
|
}
|
|
|
|
console.log(table.toString());
|
|
}
|
|
|
|
function printSection(txt) {
|
|
console.log('*****************************'.magenta);
|
|
console.log(`${'*'.magenta} ${txt.cyan}`);
|
|
console.log('*****************************'.magenta);
|
|
}
|
|
|
|
async function runBrowserTests(
|
|
browsers,
|
|
config,
|
|
retries = 1,
|
|
reportsFolder,
|
|
browserstack,
|
|
timeout
|
|
) {
|
|
const succeeded = {};
|
|
for (let browser of browsers) {
|
|
for (let t = 0; t < retries + 1; t++) {
|
|
try {
|
|
printSection(`e2e test for ${browser} #${t}`);
|
|
await nightwatch(browser, config, reportsFolder, browserstack, timeout);
|
|
succeeded[browser] = t;
|
|
console.log(`\n==> Succeeded e2e for ${browser} #${t}\n`.green);
|
|
break;
|
|
} catch (ex) {
|
|
if (ex) {
|
|
console.log('There was an error while starting the test runner:\n\n');
|
|
process.stderr.write(`${ex.stack}\n`);
|
|
}
|
|
console.log(`\n==> Failed e2e for ${browser} #${t}\n`.red);
|
|
}
|
|
}
|
|
}
|
|
printResults(browsers, succeeded, retries);
|
|
return Object.keys(succeeded).length === browsers.length;
|
|
}
|
|
|
|
class E2E {
|
|
constructor(opts) {
|
|
this.browserstackEnabled = Boolean(opts.bsKey && opts.browserstack);
|
|
if (this.browserstackEnabled && opts.headless) {
|
|
console.error('--browserstack and --headless cannot be combined');
|
|
process.exit(1);
|
|
}
|
|
|
|
this.localIdentifier = uuid();
|
|
this.retries = Number.parseInt(opts.retries);
|
|
this.browserstack = {};
|
|
this.date = new Date()
|
|
.toISOString()
|
|
.replace(/[T.]/g, '-')
|
|
.replace(/:/g, '');
|
|
this.browsers = opts.browsers.split(',').map(browser => {
|
|
if (opts.headless) {
|
|
return `${browser}-headless`;
|
|
}
|
|
|
|
return browser;
|
|
});
|
|
this.timeout = opts.timeout;
|
|
this.reportsFolder = `${opts.reportsFolder}/${this.date}`;
|
|
this.config = this.browserstackEnabled
|
|
? 'nightwatch-browserstack.conf.js'
|
|
: 'nightwatch.conf.js';
|
|
this.tunnel = opts.tunnel;
|
|
this.bsKey = opts.bsKey;
|
|
this.bsUser = opts.bsUser;
|
|
}
|
|
|
|
async start() {
|
|
let exitCode = 0;
|
|
try {
|
|
if (this.tunnel && this.bsKey) {
|
|
await startTunnel(this.bsKey, this.localIdentifier);
|
|
}
|
|
|
|
console.log('Dropping test database');
|
|
await mongoose.connection.dropDatabase();
|
|
console.log('Starting the server');
|
|
await serve({ websockets: true });
|
|
|
|
if (this.browserstackEnabled) {
|
|
browserstack.localIdentifier = this.localIdentifier;
|
|
browserstack.key = this.bsKey;
|
|
browserstack.user = this.bsUser;
|
|
} else {
|
|
// Install selenium standalone.
|
|
await seleniumInstall();
|
|
}
|
|
|
|
// Run the tests.
|
|
const succeeded = await runBrowserTests(
|
|
this.browsers,
|
|
this.config,
|
|
this.retries,
|
|
this.reportsFolder,
|
|
browserstack,
|
|
this.timeout
|
|
);
|
|
if (!succeeded) {
|
|
exitCode = 1;
|
|
}
|
|
} catch (err) {
|
|
console.log('There was an error:\n\n');
|
|
process.stderr.write(`${err.stack}\n`);
|
|
process.exit(2);
|
|
} finally {
|
|
console.log('Shutting down');
|
|
shutdown();
|
|
process.exit(exitCode);
|
|
}
|
|
}
|
|
}
|
|
|
|
program
|
|
.version('0.1.0')
|
|
.description(
|
|
'Perform e2e testing locally or if browserstack credentials are provided on browserstack.'
|
|
)
|
|
.option('-u, --bs-user [user]', 'Browserstack user', 'coralproject2')
|
|
.option(
|
|
'-k, --bs-key [key]',
|
|
'Browserstack api key',
|
|
process.env.BROWSERSTACK_KEY
|
|
)
|
|
.option('--browserstack', 'Enables Browserstack testing')
|
|
.option('--no-tunnel', 'Dont start browserstack-local')
|
|
.option('-b, --browsers [list of browsers]', 'Browsers to test', 'chrome')
|
|
.option('-r, --retries [number]', 'Number of retries before failing', '1')
|
|
.option('--headless', 'Start in headless mode for local e2e')
|
|
.option('--reports-folder [folder]', 'Reports folder', './test/e2e/reports')
|
|
.option('--timeout [number]', 'Timeout for WaitForConditions', '10000')
|
|
.parse(process.argv);
|
|
|
|
const e2e = new E2E(program);
|
|
e2e.start();
|