nightwatch
Version:
Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.
193 lines (154 loc) • 4.5 kB
JavaScript
const {GlobalReporter} = require('../../reporter');
const TestSuite = require('../../testsuite');
const Concurrency = require('../concurrency');
const {Logger} = require('../../utils');
class DefaultRunner {
get supportsConcurrency() {
return true;
}
get type() {
return 'nightwatch';
}
constructor(settings, argv, addtOpts) {
this.startTime = new Date().getTime();
this.settings = settings;
this.argv = argv;
this.addtOpts = addtOpts;
this.publishReport = true; // in-case of an uncaught exception, the report will not be published
this.globalReporter = new GlobalReporter(argv.reporter, settings, {
openReport: argv.open,
reportFileName: argv['report-filename']
});
}
get client() {
return this.currentSuite && this.currentSuite.client;
}
get results() {
return this.globalReporter.globalResults;
}
hasTestFailures() {
return this.globalReporter.hasTestFailures();
}
registerUncaughtErr(err) {
this.globalReporter.registerUncaughtErr(err);
}
/**
* @param {Error} [err]
* @return {Promise}
*/
closeOpenSessions(err) {
const inspectorServer = this.addtOpts?.globalsInstance?.inspectorServer;
if (inspectorServer) {
inspectorServer.closeSocket();
}
if (this.client?.sessionId && this.client?.startSessionEnabled) {
Logger.info(`Attempting to close session ${this.client.sessionId}...`);
const failures = !this.currentSuite.reporter.allTestsPassed;
return this.currentSuite.terminate(failures ? 'FAILED' : '', null, true);
}
return Promise.resolve();
}
async createTestSuite({modulePath, modules}) {
const {settings, argv, addtOpts} = this;
const testSuite = new TestSuite({modulePath, modules, settings, argv, addtOpts});
await testSuite.init();
return testSuite;
}
async runTestSuite(modulePath, modules) {
try {
this.currentSuite = await this.createTestSuite({modulePath, modules});
} catch (err) {
const Runner = require('../runner.js');
throw Runner.createError(err);
}
let possibleErr;
try {
await this.currentSuite.run();
} catch (err) {
possibleErr = err;
}
if (!this.argv['launch-url']) {
this.globalReporter.addTestSuiteResults(this.currentSuite.reporter.exportResults());
}
if (possibleErr instanceof Error) {
throw possibleErr;
}
}
async promiseFn(resolve, reject) {
const sourcePath = this.modulePathsCopy.shift();
try {
await this.runTestSuite(sourcePath, this.fullPaths);
if (this.modulePathsCopy.length === 0) {
resolve();
} else {
await this.promiseFn(resolve, reject);
}
} catch (err) {
reject(err);
}
}
printGlobalResults() {
this.globalReporter.create(this.startTime).print();
return this;
}
/**
* @param {Array} modules
* @return {Promise}
*/
runTests(modules) {
this.modulePathsCopy = modules.slice(0);
this.fullPaths = modules;
return new Promise(this.promiseFn.bind(this));
}
/**
* @return {Promise<boolean>}
*/
async reportResults() {
if (!this.isTestWorker()) {
this.printGlobalResults();
await this.globalReporter.save();
}
}
/**
*
* @param {Array} testEnvArray
* @param {Array} modules
* @return {Promise<number>}
*/
async runConcurrent(testEnvArray, modules, isTestWorkerEnabled, isSafariEnvPresent) {
this.concurrency = new Concurrency(this.settings, this.argv, isTestWorkerEnabled, isSafariEnvPresent);
this.globalReporter.setupChildProcessListener(this.concurrency);
const exitCode = await this.concurrency.runMultiple(testEnvArray, modules);
await this.reportResults();
return exitCode;
}
isTestWorker() {
return Concurrency.isTestWorker(this.argv);
}
/**
* Main entry-point of the runner
*
* @return {Promise}
*/
async run(modules) {
let possibleErr;
let result;
try {
result = await this.runTests(modules);
} catch (err) {
if (this.modulePathsCopy && this.modulePathsCopy.length > 0) {
this.globalReporter.skippedSuites = this.modulePathsCopy.length;
}
possibleErr = err;
}
await this.closeOpenSessions();
if (this.publishReport) {
await this.reportResults();
}
if (possibleErr) {
throw possibleErr;
}
return this.hasTestFailures(result);
}
}
module.exports = DefaultRunner;