237 lines
4.4 KiB
JavaScript
237 lines
4.4 KiB
JavaScript
|
|
||
|
/**
|
||
|
* Module dependencies.
|
||
|
*/
|
||
|
|
||
|
var tty = require('tty');
|
||
|
|
||
|
/**
|
||
|
* Check if both stdio streams are associated with a tty.
|
||
|
*/
|
||
|
|
||
|
var isatty = tty.isatty(1) && tty.isatty(2);
|
||
|
|
||
|
/**
|
||
|
* Expose `Base`.
|
||
|
*/
|
||
|
|
||
|
exports = module.exports = Base;
|
||
|
|
||
|
/**
|
||
|
* Enable coloring by default.
|
||
|
*/
|
||
|
|
||
|
exports.useColors = isatty;
|
||
|
|
||
|
/**
|
||
|
* Default color map.
|
||
|
*/
|
||
|
|
||
|
exports.colors = {
|
||
|
'pass': 90
|
||
|
, 'fail': 31
|
||
|
, 'bright pass': 92
|
||
|
, 'bright fail': 91
|
||
|
, 'bright yellow': 93
|
||
|
, 'pending': 36
|
||
|
, 'suite': 0
|
||
|
, 'error title': 0
|
||
|
, 'error message': 31
|
||
|
, 'error stack': 90
|
||
|
, 'checkmark': 32
|
||
|
, 'fast': 90
|
||
|
, 'medium': 33
|
||
|
, 'slow': 31
|
||
|
, 'green': 32
|
||
|
, 'light': 90
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Color `str` with the given `type`,
|
||
|
* allowing colors to be disabled,
|
||
|
* as well as user-defined color
|
||
|
* schemes.
|
||
|
*
|
||
|
* @param {String} type
|
||
|
* @param {String} str
|
||
|
* @return {String}
|
||
|
* @api private
|
||
|
*/
|
||
|
|
||
|
var color = exports.color = function(type, str) {
|
||
|
if (!exports.useColors) return str;
|
||
|
return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Expose term window size, with some
|
||
|
* defaults for when stderr is not a tty.
|
||
|
*/
|
||
|
|
||
|
exports.window = {
|
||
|
width: isatty
|
||
|
? process.stdout.getWindowSize
|
||
|
? process.stdout.getWindowSize(1)[0]
|
||
|
: tty.getWindowSize()[1]
|
||
|
: 75
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Expose some basic cursor interactions
|
||
|
* that are common among reporters.
|
||
|
*/
|
||
|
|
||
|
exports.cursor = {
|
||
|
hide: function(){
|
||
|
process.stdout.write('\033[?25l');
|
||
|
},
|
||
|
|
||
|
show: function(){
|
||
|
process.stdout.write('\033[?25h');
|
||
|
},
|
||
|
|
||
|
deleteLine: function(){
|
||
|
process.stdout.write('\033[2K');
|
||
|
},
|
||
|
|
||
|
beginningOfLine: function(){
|
||
|
process.stdout.write('\033[0G');
|
||
|
},
|
||
|
|
||
|
CR: function(){
|
||
|
exports.cursor.deleteLine();
|
||
|
exports.cursor.beginningOfLine();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* A test is considered slow if it
|
||
|
* exceeds the following value in milliseconds.
|
||
|
*/
|
||
|
|
||
|
exports.slow = 75;
|
||
|
|
||
|
/**
|
||
|
* Outut the given `failures` as a list.
|
||
|
*
|
||
|
* @param {Array} failures
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
exports.list = function(failures){
|
||
|
console.error();
|
||
|
failures.forEach(function(test, i){
|
||
|
// format
|
||
|
var fmt = color('error title', ' %s) %s:\n')
|
||
|
+ color('error message', ' %s')
|
||
|
+ color('error stack', '\n%s\n');
|
||
|
|
||
|
// msg
|
||
|
var err = test.err
|
||
|
, message = err.message || ''
|
||
|
, stack = err.stack || message
|
||
|
, index = stack.indexOf(message) + message.length
|
||
|
, msg = stack.slice(0, index);
|
||
|
|
||
|
// indent stack trace without msg
|
||
|
stack = stack.slice(index + 1)
|
||
|
.replace(/^/gm, ' ');
|
||
|
|
||
|
console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Initialize a new `Base` reporter.
|
||
|
*
|
||
|
* All other reporters generally
|
||
|
* inherit from this reporter, providing
|
||
|
* stats such as test duration, number
|
||
|
* of tests passed / failed etc.
|
||
|
*
|
||
|
* @param {Runner} runner
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
function Base(runner) {
|
||
|
var self = this
|
||
|
, stats = this.stats = { suites: 0, tests: 0, passes: 0, failures: 0 }
|
||
|
, failures = this.failures = [];
|
||
|
|
||
|
if (!runner) return;
|
||
|
this.runner = runner;
|
||
|
|
||
|
runner.on('start', function(){
|
||
|
stats.start = new Date;
|
||
|
});
|
||
|
|
||
|
runner.on('suite', function(suite){
|
||
|
stats.suites = stats.suites || 0;
|
||
|
suite.root || stats.suites++;
|
||
|
});
|
||
|
|
||
|
runner.on('test end', function(test){
|
||
|
stats.tests = stats.tests || 0;
|
||
|
stats.tests++;
|
||
|
});
|
||
|
|
||
|
runner.on('pass', function(test){
|
||
|
stats.passes = stats.passes || 0;
|
||
|
|
||
|
var medium = exports.slow / 2;
|
||
|
test.speed = test.duration > exports.slow
|
||
|
? 'slow'
|
||
|
: test.duration > medium
|
||
|
? 'medium'
|
||
|
: 'fast';
|
||
|
|
||
|
stats.passes++;
|
||
|
});
|
||
|
|
||
|
runner.on('fail', function(test, err){
|
||
|
stats.failures = stats.failures || 0;
|
||
|
stats.failures++;
|
||
|
test.err = err;
|
||
|
failures.push(test);
|
||
|
});
|
||
|
|
||
|
runner.on('end', function(){
|
||
|
stats.end = new Date;
|
||
|
stats.duration = new Date - stats.start;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Output common epilogue used by many of
|
||
|
* the bundled reporters.
|
||
|
*
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
Base.prototype.epilogue = function(){
|
||
|
var stats = this.stats
|
||
|
, fmt;
|
||
|
|
||
|
console.log();
|
||
|
|
||
|
// failure
|
||
|
if (stats.failures) {
|
||
|
fmt = color('bright fail', ' ✖')
|
||
|
+ color('fail', ' %d of %d tests failed')
|
||
|
+ color('light', ':')
|
||
|
|
||
|
console.error(fmt, stats.failures, this.runner.total);
|
||
|
Base.list(this.failures);
|
||
|
console.error();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// pass
|
||
|
fmt = color('bright pass', ' ✔')
|
||
|
+ color('green', ' %d tests complete')
|
||
|
+ color('light', ' (%dms)');
|
||
|
|
||
|
console.log(fmt, stats.tests || 0, stats.duration);
|
||
|
console.log();
|
||
|
};
|