UNPKG

kocha

Version:

Modern, simpler Mocha clone, no globals, lint friendly

265 lines (217 loc) 7 kB
'use strict'; 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;