kocha
Version:
Modern, simpler Mocha clone, no globals, lint friendly
265 lines (217 loc) • 7 kB
JavaScript
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var diff = require('diff');
var ms = require('ms');
var stringify = require('stringifier').stringify;
var color = require('../utils/color');
var colorLines = color.colorLines;
/**
* Save timer references to avoid Sinon interfering.
* See: https://github.com/mochajs/mocha/issues/237
*/
/* eslint-disable no-unused-vars, no-native-reassign */
var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;
/* eslint-enable no-unused-vars, no-native-reassign */
/**
* Default symbol map.
*/
var symbols = {
ok: '✓',
err: '✖',
dot: '․',
comma: ',',
bang: '!'
// With node.js on Windows: use symbols available in terminal default fonts
};if (process.platform === 'win32') {
symbols.ok = '\u221A';
symbols.err = '\xD7';
symbols.dot = '.';
}
/**
* Outut the given `failures` as a list.
* @api public
* @param {Array} failures
*/
var list = function list(failures) {
console.log();
failures.forEach(function (test, i) {
var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n');
var msg = void 0;
var err = test.err;
var message = void 0;
if (err.message && typeof err.message.toString === 'function') {
message = err.message + '';
} else if (typeof err.inspect === 'function') {
message = err.inspect() + '';
} else {
message = '';
}
var stack = err.stack || message;
var index = message ? stack.indexOf(message) : -1;
var actual = err.actual;
var expected = err.expected;
if (index === -1) {
msg = message;
} else {
index += message.length;
msg = stack.slice(0, index
// remove msg from stack
);stack = stack.slice(index + 1);
}
// uncaught
if (err.uncaught) {
msg = 'Uncaught ' + msg;
}
// explicitly show diff
if (err.showDiff !== false && sameType(actual, expected) && expected !== undefined) {
if (!(typeof actual === 'string' && typeof expected === 'string')) {
err.actual = actual = stringify(actual);
err.expected = expected = stringify(expected);
}
fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
var match = message.match(/^([^:]+): expected/);
msg = '\n ' + color('error message', match ? match[1] : msg);
msg += unifiedDiff(err);
}
// indent stack trace
stack = stack.replace(/^/gm, ' ');
console.log(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
*/
var Base = function () {
function Base(runner) {
_classCallCheck(this, Base);
var stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 };
var failures = this.failures = [];
this.runner = runner;
runner.stats = stats;
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 () {
stats.tests = stats.tests || 0;
stats.tests++;
});
runner.on('pass', function (test) {
stats.passes = stats.passes || 0;
if (test.duration > test.slow()) {
test.speed = 'slow';
} else if (test.duration > test.slow() / 2) {
test.speed = 'medium';
} else {
test.speed = '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;
});
runner.on('pending', function () {
stats.pending++;
});
}
/**
* Output common epilogue used by many of
* the bundled reporters.
*
* @api public
*/
_createClass(Base, [{
key: 'epilogue',
value: function epilogue() {
var stats = this.stats;
var fmt = void 0;
console.log();
fmt = color('bright pass', ' ') + color('green', ' %d passing') + color('light', ' (%s)');
console.log(fmt, stats.passes || 0, ms(stats.duration));
if (stats.pending > 0) {
fmt = color('pending', ' ') + color('pending', ' %d pending');
console.log(fmt, stats.pending);
}
if (stats.failures > 0) {
fmt = color('fail', ' %d failing');
console.log(fmt, stats.failures);
Base.list(this.failures);
console.log();
}
console.log();
}
}]);
return Base;
}();
/**
* Returns a unified diff between two strings.
*
* @api private
* @param {Error} err with actual/expected
* @return {string} The diff.
*/
function unifiedDiff(err) {
var indent = ' ';
function cleanUp(line) {
if (line[0] === '+') {
return indent + colorLines('diff added', line);
}
if (line[0] === '-') {
return indent + colorLines('diff removed', line);
}
if (line.match(/@@/)) {
return null;
}
if (line.match(/\\ No newline/)) {
return null;
}
return indent + line;
}
function notBlank(line) {
return typeof line !== 'undefined' && line !== null;
}
var msg = diff.createPatch('string', err.actual, err.expected);
var lines = msg.split('\n').splice(4);
return '\n ' + colorLines('diff added', '+ expected') + ' ' + colorLines('diff removed', '- actual') + '\n\n' + lines.map(cleanUp).filter(notBlank).join('\n');
}
/**
* Object#toString reference.
*/
var objToString = Object.prototype.toString;
/**
* Check that a / b have the same type.
*
* @api private
* @param {Object} a
* @param {Object} b
* @return {boolean}
*/
var sameType = function sameType(a, b) {
return objToString.call(a) === objToString.call(b);
};
exports = module.exports = Base;
exports.list = list;
exports.symbols = symbols;
;