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

284 lines
7.8 KiB
JavaScript

var fs = require('fs');
var path = require('path');
var util = require('util');
var mkpath = require('mkpath');
var Logger = require('../util/logger.js');
var colors = Logger.colors;
var format = util.format;
var Utils = require('../util/utils.js');
var Q = require('q');
var Reporter = module.exports = function(globalResults, testResults, globalStartTime, options) {
this.globalResults = globalResults;
this.testResults = testResults;
this.globalStartTime = globalStartTime;
this.options = options;
this.reporter = options.reporter || 'junit';
};
var printf = function() {
console.log(format.apply(null, arguments));
};
/**
* @static
* @param err
* @param testname
* @param time
* @return {string}
*/
Reporter.getTestOutput = function (err, testname, time) {
var symbol;
if (Utils.isErrorObject(err)) {
symbol = Logger.colors.red(Utils.symbols.fail);
testname = Logger.colors.red(testname);
} else {
symbol = Logger.colors.green(Utils.symbols.ok);
}
var args = [
'%s %s', symbol, testname
];
if (time > 20) {
args[0] += ' %s';
args.push(Logger.colors.yellow(Utils.format('(%s)', Utils.formatElapsedTime(time))));
}
return Utils.format.apply(null, args);
};
Reporter.printAssertions = function(test) {
test.assertions.forEach(function(a) {
if (a.failure !== false) {
var message = a.stackTrace.split('\n');
message.unshift(a.fullMsg);
Utils.showStackTrace(message.join('\n'));
}
});
if (test.stackTrace) {
Utils.showStackTrace(test.stackTrace);
}
};
Reporter.prototype.get = function() {
var fileName = __dirname + '/reporters/' + this.reporter + '.js';
if (fs.existsSync(fileName)) {
return require(fileName);
}
fileName = path.resolve(this.reporter);
if (fs.existsSync(fileName)) {
var reporter = require(fileName);
if (typeof reporter.write == 'function') {
return reporter;
}
throw new Error('The reporter module must have a public `write` method defined.');
}
throw new Error('The reporter file name cannot be resolved. Using path: ' + fileName);
};
/**
* @param {object} globals
* @returns {function}
*/
Reporter.prototype.globalReporter = function(globals) {
var reporterFn = Utils.checkFunction('reporter', globals) || function() {};
return Utils.makeFnAsync(2, reporterFn, globals);
};
Reporter.prototype.isDisabled = function() {
return this.options.output_folder === false;
};
Reporter.prototype.createFolder = function(cb) {
if (this.isDisabled()) {
cb(null);
} else {
mkpath(this.options.output_folder, cb);
}
};
Reporter.prototype.save = function() {
var self = this;
var deferred = Q.defer();
this.createFolder(function(err) {
if (self.isDisabled()) {
deferred.resolve();
} else {
if (err) {
deferred.reject(err);
return;
}
var reporter = self.get();
reporter.write(self.globalResults, self.options, function(err) {
if (err) {
console.log(colors.yellow(format('Warning: Failed to save report file to folder: %s', self.options.output_folder)));
console.log(err.stack);
}
deferred.resolve(err);
});
}
});
return deferred.promise;
};
Reporter.prototype.printTotalResults = function() {
var elapsedTime = new Date().getTime() - this.globalStartTime;
process.stdout.write('\n');
if (this.testsFailed()) {
var countMessage = this.getTestsFailedMessage();
console.log(colors.light_red(' _________________________________________________'));
console.log(
format('\n %s', colors.light_red('TEST FAILURE:')),
countMessage,
format('(%s)', Utils.formatElapsedTime(elapsedTime))
);
this.printFailureSummary();
console.log('');
} else {
if (!this.shouldShowSummary()) {
return;
}
var message = this.getTestsPassedMessage();
printf('%s (%s)', message, Utils.formatElapsedTime(elapsedTime));
}
};
Reporter.prototype.testsFailed = function() {
return Object.keys(this.globalResults.modules).some(function(moduleKey) {
return this.globalResults.modules[moduleKey].failures > 0 || this.globalResults.modules[moduleKey].errors > 0;
}.bind(this));
};
Reporter.prototype.shouldShowSummary = function() {
var modules = Object.keys(this.globalResults.modules);
if (modules.length > 1) {
return true;
}
if (modules.length <= 0) {
return false;
}
return Object.keys(this.globalResults.modules[modules[0]].completed).length > 1;
};
Reporter.prototype.hasAssertionCount = function() {
return Object.keys(this.globalResults.modules).length > 0 &&
(this.globalResults.failed > 0 || this.globalResults.passed > 0);
};
Reporter.prototype.getTestsPassedMessage = function() {
var hasCount = this.hasAssertionCount();
var message;
var count;
if (hasCount) {
count = this.globalResults.passed;
message = colors.green(format('OK. %s %s passed.', count, (count > 1 ? ' total assertions' : ' assertion')));
} else {
count = this.getTotalTestsCount();
message = format('%s tests passed.', colors.green('OK. ' + count));
}
return message;
};
Reporter.prototype.getTotalTestsCount = function() {
var module;
return Object.keys(this.globalResults.modules).reduce(function(count, moduleKey) {
module = this.globalResults.modules[moduleKey];
return count + module.tests - module.skipped.length;
}.bind(this), 0);
};
Reporter.prototype.getTestsFailedMessage = function() {
var hasCount = this.hasAssertionCount();
if (!hasCount && this.testResults.errmessages === 0) {
return '';
}
var errorsMsg = '';
var failedMsg = 'assertions';
var passedMsg = format('%s passed', colors.green(this.globalResults.passed));
if (!this.options.start_session) {
failedMsg = 'tests';
var passedCount = Math.max(0, this.getTotalTestsCount() - this.globalResults.failed);
passedMsg = format('%s passed', colors.green(passedCount));
}
var skipped = '';
if (this.testResults.skipped) {
skipped = format(' and %s skipped', colors.cyan(this.testResults.skipped));
}
if (this.globalResults.errors) {
var suffix = this.globalResults.errors > 1 ? 's' : '';
errorsMsg += format('%s error%s during execution, ', colors.red(this.globalResults.errors), suffix);
}
return format('%s %s %s failed, %s%s.', errorsMsg, colors.red(this.globalResults.failed), failedMsg, passedMsg, skipped);
};
Reporter.prototype.printFailureSummary = function() {
Object.keys(this.globalResults.modules).forEach(function(moduleKey) {
var testSuite = this.globalResults.modules[moduleKey];
if (testSuite.failures > 0 || testSuite.errors > 0) {
console.log('\n' + colors.red(format(' %s %s', Utils.symbols.fail, moduleKey)));
Object.keys(testSuite.completed).forEach(function(testcase) {
var test = testSuite.completed[testcase];
if (test.failed > 0 || test.errors > 0) {
printf('\n - %s %s', testcase, colors.yellow('(' + Utils.formatElapsedTime(test.timeMs) + ')'));
if (test.assertions.length > 0 && this.options.start_session) {
Reporter.printAssertions(test);
} else if (test.stackTrace) {
Utils.showStackTrace(test.stackTrace);
}
}
}.bind(this));
if (Array.isArray(testSuite.errmessages)) {
testSuite.errmessages.forEach(function(err) {
console.log('');
Utils.showStackTrace(err);
console.log('');
});
}
if (testSuite.skipped.length > 0) {
console.log(colors.cyan(' SKIPPED:'));
testSuite.skipped.forEach(function(testcase) {
printf(' - %s', testcase);
});
}
}
}.bind(this));
if (Array.isArray(this.globalResults.errmessages)) {
this.globalResults.errmessages.forEach(function(err) {
console.log('');
Utils.showStackTrace(err);
console.log('');
}.bind(this));
}
};