Skip to content

Commit

Permalink
Improve failure output of the default mini reporter (#951)
Browse files Browse the repository at this point in the history
  • Loading branch information
Juan Soto authored and sindresorhus committed Aug 14, 2016
1 parent 28bb0d5 commit e4f90e0
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 72 deletions.
2 changes: 2 additions & 0 deletions lib/colors.js
Expand Up @@ -2,10 +2,12 @@
var chalk = require('chalk');

module.exports = {
title: chalk.white,
error: chalk.red,
skip: chalk.yellow,
todo: chalk.blue,
pass: chalk.green,
duration: chalk.gray.dim,
errorStack: chalk.gray,
stack: chalk.red
};
52 changes: 36 additions & 16 deletions lib/reporters/mini.js
Expand Up @@ -123,11 +123,11 @@ MiniReporter.prototype.unhandledError = function (err) {

MiniReporter.prototype.reportCounts = function (time) {
var lines = [
this.passCount > 0 ? '\n ' + colors.pass(this.passCount, 'passed') : '',
this.knownFailureCount > 0 ? '\n ' + colors.error(this.knownFailureCount, plur('known failure', this.knownFailureCount)) : '',
this.failCount > 0 ? '\n ' + colors.error(this.failCount, 'failed') : '',
this.skipCount > 0 ? '\n ' + colors.skip(this.skipCount, 'skipped') : '',
this.todoCount > 0 ? '\n ' + colors.todo(this.todoCount, 'todo') : ''
this.passCount > 0 ? '\n ' + colors.pass(this.passCount, 'passed') : '',
this.knownFailureCount > 0 ? '\n ' + colors.error(this.knownFailureCount, plur('known failure', this.knownFailureCount)) : '',
this.failCount > 0 ? '\n ' + colors.error(this.failCount, 'failed') : '',
this.skipCount > 0 ? '\n ' + colors.skip(this.skipCount, 'skipped') : '',
this.todoCount > 0 ? '\n ' + colors.todo(this.todoCount, 'todo') : ''
].filter(Boolean);

if (time && lines.length > 0) {
Expand All @@ -148,15 +148,15 @@ MiniReporter.prototype.finish = function (runStatus) {
var status = this.reportCounts(time);

if (this.rejectionCount > 0) {
status += '\n ' + colors.error(this.rejectionCount, plur('rejection', this.rejectionCount));
status += '\n ' + colors.error(this.rejectionCount, plur('rejection', this.rejectionCount));
}

if (this.exceptionCount > 0) {
status += '\n ' + colors.error(this.exceptionCount, plur('exception', this.exceptionCount));
status += '\n ' + colors.error(this.exceptionCount, plur('exception', this.exceptionCount));
}

if (runStatus.previousFailCount > 0) {
status += '\n ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun');
status += '\n ' + colors.error(runStatus.previousFailCount, 'previous', plur('failure', runStatus.previousFailCount), 'in test files that were not rerun');
}

var i = 0;
Expand All @@ -167,7 +167,7 @@ MiniReporter.prototype.finish = function (runStatus) {

var title = test.title;

status += '\n\n\n ' + colors.error(i + '.', title);
status += '\n\n ' + colors.title(title);
// TODO output description with link
// status += colors.stack(description);
});
Expand All @@ -181,10 +181,26 @@ MiniReporter.prototype.finish = function (runStatus) {

i++;

var description = ' ' + test.error.message + '\n ' + stripFirstLine(test.error.stack).trimRight();
var title = test.error ? test.title : 'Unhandled Error';
var description;
var errorTitle = ' ' + test.error.message + '\n';
var isPowerAssert = test.error.message.split('\n').length > 1;

status += '\n\n\n ' + colors.error(i + '.', test.title) + '\n';
status += colors.stack(description);
if (test.error) {
description = stripFirstLine(test.error.stack).trimRight();
} else {
description = JSON.stringify(test);
}

if (isPowerAssert) {
description = stripFirstLine(description).replace(/ {3}/g, ' ');
} else {
description.replace(/ {3}/g, ' ');
}

status += '\n\n ' + colors.title(title) + '\n';
status += colors.stack(errorTitle);
status += colors.errorStack(description);
});
}

Expand All @@ -197,18 +213,22 @@ MiniReporter.prototype.finish = function (runStatus) {
i++;

if (err.type === 'exception' && err.name === 'AvaError') {
status += '\n\n\n ' + colors.error(cross + ' ' + err.message);
status += '\n\n ' + colors.error(cross + ' ' + err.message);
} else {
var title = err.type === 'rejection' ? 'Unhandled Rejection' : 'Uncaught Exception';
var description = err.stack ? err.stack.trimRight() : JSON.stringify(err);
description = description.split('\n');
var errorTitle = description[0];
var errorStack = description.slice(1).join('\n');

status += '\n\n\n ' + colors.error(i + '.', title) + '\n';
status += ' ' + colors.stack(description);
status += '\n\n ' + colors.title(title) + '\n';
status += ' ' + colors.stack(errorTitle) + '\n';
status += colors.errorStack(errorStack);
}
});
}

return status + '\n';
return status + '\n\n';
};

MiniReporter.prototype.section = function () {
Expand Down
2 changes: 1 addition & 1 deletion lib/run-status.js
Expand Up @@ -107,7 +107,7 @@ RunStatus.prototype.handleTest = function (test) {

if (test.error) {
if (test.error.name !== 'AssertionError') {
test.error.message = 'failed with "' + test.error.message + '"';
test.error.message = 'Error: ' + test.error.message;
}

this.errors.push(test);
Expand Down
108 changes: 53 additions & 55 deletions test/reporters/mini.js
Expand Up @@ -49,7 +49,7 @@ test('passing test', function (t) {
' ',
' ' + graySpinner + ' passed',
'',
' ' + chalk.green('1 passed')
' ' + chalk.green('1 passed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -68,8 +68,8 @@ test('known failure test', function (t) {
' ',
' ' + graySpinner + ' ' + chalk.red('known failure'),
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 known failure')
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 known failure')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -90,7 +90,7 @@ test('failing test', function (t) {
' ',
' ' + graySpinner + ' ' + chalk.red('failed'),
'',
' ' + chalk.red('1 failed')
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -112,7 +112,7 @@ test('failed known failure test', function (t) {
' ',
' ' + graySpinner + ' ' + chalk.red('known failure'),
'',
' ' + chalk.red('1 failed')
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -135,8 +135,8 @@ test('passing test after failing', function (t) {
' ',
' ' + graySpinner + ' passed',
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -159,8 +159,8 @@ test('failing test after passing', function (t) {
' ',
' ' + graySpinner + ' ' + chalk.red('failed'),
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand Down Expand Up @@ -199,8 +199,8 @@ test('results with passing tests', function (t) {

var actualOutput = reporter.finish({});
var expectedOutput = [
'\n ' + chalk.green('1 passed'),
''
'\n ' + chalk.green('1 passed'),
'\n'
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -221,12 +221,11 @@ test('results with passing known failure tests', function (t) {
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + chalk.green('1 passed'),
' ' + chalk.red('1 known failure'),
'\n ' + chalk.green('1 passed'),
' ' + chalk.red('1 known failure'),
'',
'',
' ' + chalk.red('1. known failure'),
''
' ' + chalk.white('known failure'),
'\n'
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -241,8 +240,8 @@ test('results with skipped tests', function (t) {

var actualOutput = reporter.finish({});
var expectedOutput = [
'\n ' + chalk.yellow('1 skipped'),
''
'\n ' + chalk.yellow('1 skipped'),
'\n'
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -257,8 +256,8 @@ test('results with todo tests', function (t) {

var actualOutput = reporter.finish({});
var expectedOutput = [
'\n ' + chalk.blue('1 todo'),
''
'\n ' + chalk.blue('1 todo'),
'\n'
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -273,8 +272,8 @@ test('results with passing skipped tests', function (t) {
var output = reporter.finish({}).split('\n');

t.is(output[0], '');
t.is(output[1], ' ' + chalk.green('1 passed'));
t.is(output[2], ' ' + chalk.yellow('1 skipped'));
t.is(output[1], ' ' + chalk.green('1 passed'));
t.is(output[2], ' ' + chalk.yellow('1 skipped'));
t.is(output[3], '');
t.end();
});
Expand All @@ -298,18 +297,16 @@ test('results with passing tests and rejections', function (t) {
var output = reporter.finish(runStatus);
compareLineOutput(t, output, [
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 rejection'),
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 rejection'),
'',
' ' + chalk.red('1. Unhandled Rejection'),
' ' + chalk.white('Unhandled Rejection'),
/Error: failure/,
/test\/reporters\/mini\.js/,
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
'',
'',
' ' + chalk.red('2. Unhandled Rejection'),
' ' + colors.stack('stack line with trailing whitespace')
' ' + chalk.white('Unhandled Rejection'),
' ' + colors.stack('stack line with trailing whitespace')
]);
t.end();
});
Expand All @@ -333,17 +330,15 @@ test('results with passing tests and exceptions', function (t) {
var output = reporter.finish(runStatus);
compareLineOutput(t, output, [
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('2 exceptions'),
' ' + chalk.green('1 passed'),
' ' + chalk.red('2 exceptions'),
'',
'',
' ' + chalk.red('1. Uncaught Exception'),
' ' + chalk.white('Uncaught Exception'),
/Error: failure/,
/test\/reporters\/mini\.js/,
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
'',
'',
' ' + chalk.red(cross + ' A futuristic test runner')
' ' + chalk.red(cross + ' A futuristic test runner')
]);
t.end();
});
Expand All @@ -368,20 +363,22 @@ test('results with errors', function (t) {
};

var output = reporter.finish(runStatus);

var expectedStack = colors.error(' failure two\n') + colors.errorStack('stack line with trailing whitespace');
expectedStack = expectedStack.split('\n');

compareLineOutput(t, output, [
'',
' ' + chalk.red('1 failed'),
' ' + chalk.red('1 failed'),
'',
'',
' ' + chalk.red('1. failed one'),
' ' + chalk.white('failed one'),
/failure/,
/test\/reporters\/mini\.js/,
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
'',
'',
' ' + chalk.red('2. failed two')
' ' + chalk.white('failed two')
].concat(
colors.stack(' failure two\n stack line with trailing whitespace').split('\n')
expectedStack
));
t.end();
});
Expand All @@ -397,8 +394,8 @@ test('results with 1 previous failure', function (t) {
var output = reporter.finish(runStatus);
compareLineOutput(t, output, [
'',
' ' + colors.todo('1 todo'),
' ' + colors.error('1 previous failure in test files that were not rerun')
' ' + colors.todo('1 todo'),
' ' + colors.error('1 previous failure in test files that were not rerun')
]);
t.end();
});
Expand All @@ -414,8 +411,8 @@ test('results with 2 previous failures', function (t) {
var output = reporter.finish(runStatus);
compareLineOutput(t, output, [
'',
' ' + colors.todo('1 todo'),
' ' + colors.error('2 previous failures in test files that were not rerun')
' ' + colors.todo('1 todo'),
' ' + colors.error('2 previous failures in test files that were not rerun')
]);
t.end();
});
Expand All @@ -427,7 +424,7 @@ test('empty results after reset', function (t) {
reporter.reset();

var output = reporter.finish({});
t.is(output, '\n');
t.is(output, '\n\n');
t.end();
});

Expand All @@ -449,8 +446,8 @@ test('results with watching enabled', function (t) {

var actualOutput = reporter.finish({});
var expectedOutput = [
'\n ' + chalk.green('1 passed') + time,
''
'\n ' + chalk.green('1 passed') + time,
'\n'
].join('\n');

t.is(actualOutput, expectedOutput);
Expand Down Expand Up @@ -487,8 +484,8 @@ test('silently handles errors without body', function (t) {
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 failed'),
''
'\n ' + colors.error('1 failed'),
'\n'
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
Expand All @@ -504,8 +501,8 @@ test('does not handle errors with body in rejections', function (t) {
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 rejection'),
''
'\n ' + colors.error('1 rejection'),
'\n'
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
Expand All @@ -522,9 +519,10 @@ test('returns description based on error itself if no stack available', function
};
var actualOutput = reporter.finish(runStatus);
var expectedOutput = [
'\n ' + colors.error('1 exception'),
'\n\n ' + colors.error('1. Uncaught Exception'),
' ' + colors.stack(JSON.stringify({error: err1})) + '\n'
'\n ' + colors.error('1 exception'),
'\n ' + colors.title('Uncaught Exception'),
' ' + colors.stack(JSON.stringify({error: err1})),
'\n\n'
].join('\n');
t.is(actualOutput, expectedOutput);
t.end();
Expand Down

0 comments on commit e4f90e0

Please sign in to comment.