Files
tasks/tests/node_modules/nightwatch/lib/runner/run.js

288 lines
8.6 KiB
JavaScript

var Walk = require('./walk.js');
var TestSuite = require('./testsuite.js');
var Logger = require('../util/logger.js');
var Reporter = require('./reporter.js');
var path = require('path');
var Q = require('q');
var globalResults;
var currentTestSuite;
var finishCallback;
function processListener() {
process.on('exit', function (code) {
var exitCode = code;
if (exitCode === 0 && globalResults && (globalResults.errors > 0 || globalResults.failed > 0)) {
exitCode = 1;
}
process.exit(exitCode);
});
process.on('uncaughtException', function (err) {
if (currentTestSuite) {
var testCase = currentTestSuite.getCurrentTestCase();
if (testCase/* && testCase.running*/) {
testCase.catchHandler(err);
return;
}
}
if (finishCallback) {
finishCallback(err);
}
});
}
function Runner(testSource, opts, additionalOpts, doneCb) {
this.testSource = testSource || [];
this.options = opts;
this.additionalOpts = additionalOpts;
this.doneCb = doneCb || function() {};
this.globalStartTime = new Date().getTime();
this.currentTestSuite = null;
globalResults = this.globalResults = {
passed : 0,
failed : 0,
errors : 0,
skipped : 0,
tests : 0,
errmessages : [],
modules : {}
};
this.setOptions();
}
Runner.prototype.setOptions = function() {
this.options.parallelMode = process.env.__NIGHTWATCH_PARALLEL_MODE == '1';
if (this.options.parallelMode) {
this.options.currentEnv = process.env.__NIGHTWATCH_ENV_KEY;
}
this.options.live_output = this.additionalOpts.live_output;
this.options.detailed_output = this.additionalOpts.detailed_output;
this.options.start_session = this.additionalOpts.start_session;
this.options.report_prefix = '';
this.options.test_worker = this.additionalOpts.test_worker;
};
Runner.prototype.runTestModule = function(modulePath, fullPaths) {
try {
currentTestSuite = this.currentTestSuite = new TestSuite(modulePath, fullPaths, this.options, this.additionalOpts, this.doneCb);
} catch (err) {
this.doneCb(err);
return null;
}
var moduleKey = this.currentTestSuite.getReportKey();
this.globalResults.modules[moduleKey] = {
completed : {},
skipped : null,
time : null,
timestamp : null,
group : this.currentTestSuite.getGroupName()
};
return this.currentTestSuite
.on('testcase:finished', function(results, errors, time) {
this.globalResults.modules[moduleKey].completed[this.currentTestSuite.currentTest] = {
passed : results.passed,
failed : results.failed,
errors : results.errors,
skipped : results.skipped,
assertions : [].concat(results.tests),
timeMs : time,
time : (time/1000).toPrecision(4),
stackTrace : results.stackTrace
};
if (Array.isArray(errors) && errors.length) {
this.globalResults.errmessages = this.globalResults.errmessages.concat(errors);
}
this.globalResults.passed += results.passed;
this.globalResults.failed += results.failed;
this.globalResults.errors += results.errors;
this.globalResults.skipped += results.skipped;
this.globalResults.tests += results.tests.length;
this.globalResults.assertions = this.globalResults.tests;
if (this.options.output && this.options.detailed_output &&
(this.options.modulesNo > 1 || results.tests !== this.globalResults.tests || results.steps.length > 1)
) {
this.currentTestSuite.printResult(time);
} else if (this.options.output && !this.options.detailed_output) {
var error = (results.failed > 0 || results.errors > 0) ? new Error('') : null;
console.log(Reporter.getTestOutput(error, this.currentTestSuite.currentTest, time));
if (error !== null) {
Reporter.printAssertions(results.tests);
}
}
}.bind(this))
.run()
.then(function onTestSuiteResolved(testResults) {
var testSuiteResult = this.globalResults.modules[moduleKey];
testSuiteResult.skipped = testResults.steps;
testSuiteResult.timestamp = testResults.timestamp;
testSuiteResult.time = (testResults.time/1000).toPrecision(4);
testSuiteResult.tests = Object.keys(testSuiteResult.completed).length + (testSuiteResult.skipped && testSuiteResult.skipped.length || 0);
var failures = 0;
var errors = testResults.errors || 0;
Object.keys(testSuiteResult.completed).forEach(function(item) {
if (testSuiteResult.completed[item].failed > 0) {
failures++;
}
});
testSuiteResult.errmessages = testResults.errmessages || [];
testSuiteResult.failures = failures;
testSuiteResult.errors = errors;
if (typeof process.send == 'function') {
process.send(JSON.stringify({
type: 'testsuite_finished',
itemKey: process.env.__NIGHTWATCH_ENV_LABEL,
moduleKey: moduleKey,
results: this.globalResults.modules[moduleKey],
errmessages: testSuiteResult.errmessages,
passed: this.globalResults.passed,
failed: this.globalResults.failed,
errors: this.globalResults.errors,
skipped: this.globalResults.skipped,
tests: this.globalResults.tests
}));
}
return testResults;
}.bind(this));
};
Runner.readPaths = function(testSource, opts, cb) {
var deferred = Q.defer();
cb = cb || function() {};
if (typeof testSource == 'string') {
testSource = [testSource];
}
var fullPaths = testSource.map(function (p) {
if (p.indexOf(process.cwd()) === 0 || path.resolve(p) === p) {
return p;
}
return path.join(process.cwd(), p);
});
if (fullPaths.length === 0) {
throw new Error('No source folder defined. Check configuration.');
}
var errorMessage = ['No tests defined! using source folder:', fullPaths];
if (opts.tag_filter) {
errorMessage.push('; using tags:', opts.tag_filter);
}
Walk.readPaths(fullPaths, function (err, modules) {
if (err) {
if (err.code == 'ENOENT') {
var error = new Error('Cannot read source folder: ' + err.path);
cb(error, false);
deferred.reject(error);
return;
}
cb(err, false);
deferred.reject(err);
return;
}
opts.modulesNo = modules.length;
if (modules.length === 0) {
var error2 = new Error(errorMessage.join(' '));
cb(error2);
deferred.reject(error2);
return;
}
cb(null, modules, fullPaths);
deferred.resolve([modules, fullPaths]);
}, opts);
return deferred.promise;
};
Runner.prototype.run = function runner() {
var deferred = Q.defer();
var self = this;
finishCallback = this.doneCb;
Runner.readPaths(this.testSource, this.options)
.spread(function(modulePaths, fullPaths) {
(function runNextModule() {
var modulePath = modulePaths.shift();
var promise = self.runTestModule(modulePath, fullPaths);
if (promise === null) {
deferred.resolve();
return;
}
promise.then(function(testResults) {
if (modulePaths.length) {
setImmediate(runNextModule);
} else {
var reporter = new Reporter(self.globalResults, testResults, self.globalStartTime, {
output_folder : self.additionalOpts.output_folder,
filename_prefix : self.options.report_prefix,
globals : self.options.globals,
reporter : self.additionalOpts.reporter,
start_session : self.options.start_session
});
if (self.options.output) {
reporter.printTotalResults(self.globalResults, testResults);
}
reporter.save().then(function() {
reporter.globalReporter(self.options.globals)(self.globalResults, function() {
try {
self.doneCb(null, self.globalResults);
deferred.resolve(self.globalResults);
} catch (err) {
deferred.reject(err);
}
});
}, function(err) {
console.log(Logger.colors.yellow('Output folder doesn\'t exist and cannot be created.'));
console.log(err.stack);
self.doneCb(null);
deferred.resolve();
});
}
}, function(err) {
self.doneCb(err, self.globalResults);
}).catch(function(err) {
deferred.reject(err);
});
})();
})
.catch(function(err) {
self.doneCb(err, false);
})
.catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
};
processListener();
module.exports = Runner;