nightwatch
Version:
Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.
118 lines (89 loc) • 2.91 kB
JavaScript
const {Logger} = require('../utils');
const analyticsCollector = require('../utils/analytics.js');
module.exports = class {
constructor(proc = process) {
this.__exitCode = 0;
this.testRunner = null;
this.process = proc;
this.finishCallback = null;
this.addExitListener();
this.process.once('uncaughtException', err => {
this.uncaught(err);
});
this.process.on('unhandledRejection', this.unhandled.bind(this));
}
addExitListener() {
// when used programmatically, nightwatch will keep adding exit listeners for each test suite
const listeners = this.process.listeners('exit');
const isAlreadyAdded = listeners.find(item => {
return item.name.includes('exitHandlerNightwatch');
});
if (!isAlreadyAdded) {
this.exitHandler = function exitHandlerNightwatch(code) {
return this.onExit(code);
}.bind(this);
this.process.on('exit', this.exitHandler);
}
}
setTestRunner(testRunner) {
this.testRunner = testRunner;
return this;
}
setExitCode(code) {
this.__exitCode = code;
return this;
}
get exitCode() {
return this.__exitCode;
}
onExit(code) {
this.process.exitCode = code || this.exitCode;
}
unhandled(err) {
this.uncaught(err, {type: 'unhandledRejection'});
}
getCurrentPromise(err) {
if (this.testRunner) {
const {currentSuite} = this.testRunner;
if (currentSuite && (currentSuite.uncaughtError instanceof Error)) {
Logger.error('An additional uncaught error occurred while trying to handle the previous one – ' + err.stack);
return;
}
this.testRunner.registerUncaughtErr(err);
if (currentSuite) {
currentSuite.emptyQueue();
currentSuite.setUncaughtError(err);
}
if (this.testRunner.publishReport) {
this.testRunner.publishReport = false;
this.testRunner.reportResults().then(() => {}).catch(err => console.error(err));
}
}
}
uncaught(err, {type = 'uncaughtException'} = {}) {
Logger.setOutputEnabled(true); // force log for uncaught exception
Logger.enable();
Logger.error(`${type}: ${err.message}\n${err.stack}`);
analyticsCollector.collectErrorEvent(err, true);
if (['TimeoutError', 'NoSuchElementError'].includes(err.name) && this.testRunner.type !== 'cucumber') {
this.closeProcess(err);
if (this.testRunner && this.testRunner.publishReport) {
this.testRunner.publishReport = false;
this.testRunner.reportResults().catch(() => {}).then(function() {});
}
return;
}
this.getCurrentPromise(err);
return this.closeProcess(err);
}
closeProcess(err) {
if (this.finishCallback) {
this.finishCallback(err);
}
this.setExitCode(1).exit();
}
exit() {
this.process.exit && this.process.exit(this.exitCode);
return this;
}
};