morpha
Version:
A Web-IDE or Desktop-IDE creator.
263 lines (226 loc) • 7.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
exports.default = getClientReporter;
var _utils = require('../../common/utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function getClientReporter(ipc) {
var mocha = (0, _utils.safeRequire)('mocha');
var utils = (0, _utils.safeRequire)('mocha/lib/utils');
var diff = (0, _utils.safeRequire)('diff');
var Base = mocha.reporters.Base;
var color = function color(type, str) {
return '\x1B[' + Base.colors[type] + 'm' + str + '\x1B[0m';
};
var objToString = Object.prototype.toString;
var ClientReporter = function (_Base) {
(0, _inherits3.default)(ClientReporter, _Base);
function ClientReporter(runner) {
(0, _classCallCheck3.default)(this, ClientReporter);
var _this = (0, _possibleConstructorReturn3.default)(this, (ClientReporter.__proto__ || (0, _getPrototypeOf2.default)(ClientReporter)).call(this, runner));
function ipcListen(keys) {
keys.forEach(function (key) {
runner.on(key, function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
ipc.send.apply(ipc, ['mocha-reporter', key].concat(args));
});
});
}
ipc.send('mocha-repoter', 'pre', runner);
ipcListen(['start', 'suite', 'suite end', 'pass', 'pending', 'fail']);
runner.on('end', function () {
ipc.send('mocha-reporter', 'end', _this.stats, formatErrors(_this.failures));
});
return _this;
}
return ClientReporter;
}(Base);
function formatErrors(failures) {
return failures.map(function (test) {
// format
var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n');
// msg
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 = stack.indexOf(message);
var actual = err.actual;
var expected = err.expected;
var escape = true;
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) {
escape = false;
if (!(utils.isString(actual) && utils.isString(expected))) {
err.actual = actual = utils.stringify(actual);
err.expected = expected = utils.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);
if (Base.inlineDiffs) {
msg += inlineDiff(err, escape);
} else {
msg += unifiedDiff(err, escape);
}
}
// indent stack trace
stack = stack.replace(/^/gm, ' ');
// console.log(fmt, (i + 1), test.fullTitle(), msg, stack);
return {
fmt: fmt,
fullTitle: test.fullTitle(),
msg: msg,
stack: stack
};
});
}
function sameType(a, b) {
return objToString.call(a) === objToString.call(b);
}
/**
* Returns an inline diff between 2 strings with coloured ANSI output
*
* @api private
* @param {Error} err with actual/expected
* @param {boolean} escape
* @return {string} Diff
*/
function inlineDiff(err, escape) {
var msg = errorDiff(err, 'WordsWithSpace', escape);
// linenos
var lines = msg.split('\n');
if (lines.length > 4) {
var width = String(lines.length).length;
msg = lines.map(function (str, i) {
return pad(++i, width) + ' |' + ' ' + str;
}).join('\n');
}
// legend
msg = '\n' + color('diff removed', 'actual') + ' ' + color('diff added', 'expected') + '\n\n' + msg + '\n';
// indent
msg = msg.replace(/^/gm, ' ');
return msg;
}
/**
* Returns a unified diff between two strings.
*
* @api private
* @param {Error} err with actual/expected
* @param {boolean} escape
* @return {string} The diff.
*/
function unifiedDiff(err, escape) {
var indent = ' ';
function cleanUp(line) {
if (escape) {
line = escapeInvisibles(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');
}
/**
* Return a character diff for `err`.
*
* @api private
* @param {Error} err
* @param {string} type
* @param {boolean} escape
* @return {string}
*/
function errorDiff(err, type, escape) {
var actual = escape ? escapeInvisibles(err.actual) : err.actual;
var expected = escape ? escapeInvisibles(err.expected) : err.expected;
return diff['diff' + type](actual, expected).map(function (str) {
if (str.added) {
return colorLines('diff added', str.value);
}
if (str.removed) {
return colorLines('diff removed', str.value);
}
return str.value;
}).join('');
}
/**
* Returns a string with all invisible characters in plain text
*
* @api private
* @param {string} line
* @return {string}
*/
function escapeInvisibles(line) {
return line.replace(/\t/g, '<tab>').replace(/\r/g, '<CR>').replace(/\n/g, '<LF>\n');
}
/**
* Color lines for `str`, using the color `name`.
* @param {string} name
* @param {string} str
* @return {string}
*/
function colorLines(name, str) {
return str.split('\n').map(function (str) {
return color(name, str);
}).join('\n');
}
/**
* Pad the given `str` to `len`.
*
* @api private
* @param {string} str
* @param {string} len
* @return {string}
*/
function pad(str, len) {
str = String(str);
return Array(len - str.length + 1).join(' ') + str;
}
return ClientReporter;
}