Skip to content

Commit e4f90e0

Browse files
Juan Sotosindresorhus
authored andcommitted
Improve failure output of the default mini reporter (#951)
1 parent 28bb0d5 commit e4f90e0

File tree

4 files changed

+92
-72
lines changed

4 files changed

+92
-72
lines changed

lib/colors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
var chalk = require('chalk');
33

44
module.exports = {
5+
title: chalk.white,
56
error: chalk.red,
67
skip: chalk.yellow,
78
todo: chalk.blue,
89
pass: chalk.green,
910
duration: chalk.gray.dim,
11+
errorStack: chalk.gray,
1012
stack: chalk.red
1113
};

lib/reporters/mini.js

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ MiniReporter.prototype.unhandledError = function (err) {
123123

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

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

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

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

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

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

168168
var title = test.title;
169169

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

182182
i++;
183183

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

186-
status += '\n\n\n ' + colors.error(i + '.', test.title) + '\n';
187-
status += colors.stack(description);
189+
if (test.error) {
190+
description = stripFirstLine(test.error.stack).trimRight();
191+
} else {
192+
description = JSON.stringify(test);
193+
}
194+
195+
if (isPowerAssert) {
196+
description = stripFirstLine(description).replace(/ {3}/g, ' ');
197+
} else {
198+
description.replace(/ {3}/g, ' ');
199+
}
200+
201+
status += '\n\n ' + colors.title(title) + '\n';
202+
status += colors.stack(errorTitle);
203+
status += colors.errorStack(description);
188204
});
189205
}
190206

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

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

205-
status += '\n\n\n ' + colors.error(i + '.', title) + '\n';
206-
status += ' ' + colors.stack(description);
224+
status += '\n\n ' + colors.title(title) + '\n';
225+
status += ' ' + colors.stack(errorTitle) + '\n';
226+
status += colors.errorStack(errorStack);
207227
}
208228
});
209229
}
210230

211-
return status + '\n';
231+
return status + '\n\n';
212232
};
213233

214234
MiniReporter.prototype.section = function () {

lib/run-status.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ RunStatus.prototype.handleTest = function (test) {
107107

108108
if (test.error) {
109109
if (test.error.name !== 'AssertionError') {
110-
test.error.message = 'failed with "' + test.error.message + '"';
110+
test.error.message = 'Error: ' + test.error.message;
111111
}
112112

113113
this.errors.push(test);

test/reporters/mini.js

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ test('passing test', function (t) {
4949
' ',
5050
' ' + graySpinner + ' passed',
5151
'',
52-
' ' + chalk.green('1 passed')
52+
' ' + chalk.green('1 passed')
5353
].join('\n');
5454

5555
t.is(actualOutput, expectedOutput);
@@ -68,8 +68,8 @@ test('known failure test', function (t) {
6868
' ',
6969
' ' + graySpinner + ' ' + chalk.red('known failure'),
7070
'',
71-
' ' + chalk.green('1 passed'),
72-
' ' + chalk.red('1 known failure')
71+
' ' + chalk.green('1 passed'),
72+
' ' + chalk.red('1 known failure')
7373
].join('\n');
7474

7575
t.is(actualOutput, expectedOutput);
@@ -90,7 +90,7 @@ test('failing test', function (t) {
9090
' ',
9191
' ' + graySpinner + ' ' + chalk.red('failed'),
9292
'',
93-
' ' + chalk.red('1 failed')
93+
' ' + chalk.red('1 failed')
9494
].join('\n');
9595

9696
t.is(actualOutput, expectedOutput);
@@ -112,7 +112,7 @@ test('failed known failure test', function (t) {
112112
' ',
113113
' ' + graySpinner + ' ' + chalk.red('known failure'),
114114
'',
115-
' ' + chalk.red('1 failed')
115+
' ' + chalk.red('1 failed')
116116
].join('\n');
117117

118118
t.is(actualOutput, expectedOutput);
@@ -135,8 +135,8 @@ test('passing test after failing', function (t) {
135135
' ',
136136
' ' + graySpinner + ' passed',
137137
'',
138-
' ' + chalk.green('1 passed'),
139-
' ' + chalk.red('1 failed')
138+
' ' + chalk.green('1 passed'),
139+
' ' + chalk.red('1 failed')
140140
].join('\n');
141141

142142
t.is(actualOutput, expectedOutput);
@@ -159,8 +159,8 @@ test('failing test after passing', function (t) {
159159
' ',
160160
' ' + graySpinner + ' ' + chalk.red('failed'),
161161
'',
162-
' ' + chalk.green('1 passed'),
163-
' ' + chalk.red('1 failed')
162+
' ' + chalk.green('1 passed'),
163+
' ' + chalk.red('1 failed')
164164
].join('\n');
165165

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

200200
var actualOutput = reporter.finish({});
201201
var expectedOutput = [
202-
'\n ' + chalk.green('1 passed'),
203-
''
202+
'\n ' + chalk.green('1 passed'),
203+
'\n'
204204
].join('\n');
205205

206206
t.is(actualOutput, expectedOutput);
@@ -221,12 +221,11 @@ test('results with passing known failure tests', function (t) {
221221
};
222222
var actualOutput = reporter.finish(runStatus);
223223
var expectedOutput = [
224-
'\n ' + chalk.green('1 passed'),
225-
' ' + chalk.red('1 known failure'),
224+
'\n ' + chalk.green('1 passed'),
225+
' ' + chalk.red('1 known failure'),
226226
'',
227-
'',
228-
' ' + chalk.red('1. known failure'),
229-
''
227+
' ' + chalk.white('known failure'),
228+
'\n'
230229
].join('\n');
231230

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

242241
var actualOutput = reporter.finish({});
243242
var expectedOutput = [
244-
'\n ' + chalk.yellow('1 skipped'),
245-
''
243+
'\n ' + chalk.yellow('1 skipped'),
244+
'\n'
246245
].join('\n');
247246

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

258257
var actualOutput = reporter.finish({});
259258
var expectedOutput = [
260-
'\n ' + chalk.blue('1 todo'),
261-
''
259+
'\n ' + chalk.blue('1 todo'),
260+
'\n'
262261
].join('\n');
263262

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

275274
t.is(output[0], '');
276-
t.is(output[1], ' ' + chalk.green('1 passed'));
277-
t.is(output[2], ' ' + chalk.yellow('1 skipped'));
275+
t.is(output[1], ' ' + chalk.green('1 passed'));
276+
t.is(output[2], ' ' + chalk.yellow('1 skipped'));
278277
t.is(output[3], '');
279278
t.end();
280279
});
@@ -298,18 +297,16 @@ test('results with passing tests and rejections', function (t) {
298297
var output = reporter.finish(runStatus);
299298
compareLineOutput(t, output, [
300299
'',
301-
' ' + chalk.green('1 passed'),
302-
' ' + chalk.red('1 rejection'),
303-
'',
300+
' ' + chalk.green('1 passed'),
301+
' ' + chalk.red('1 rejection'),
304302
'',
305-
' ' + chalk.red('1. Unhandled Rejection'),
303+
' ' + chalk.white('Unhandled Rejection'),
306304
/Error: failure/,
307305
/test\/reporters\/mini\.js/,
308306
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
309307
'',
310-
'',
311-
' ' + chalk.red('2. Unhandled Rejection'),
312-
' ' + colors.stack('stack line with trailing whitespace')
308+
' ' + chalk.white('Unhandled Rejection'),
309+
' ' + colors.stack('stack line with trailing whitespace')
313310
]);
314311
t.end();
315312
});
@@ -333,17 +330,15 @@ test('results with passing tests and exceptions', function (t) {
333330
var output = reporter.finish(runStatus);
334331
compareLineOutput(t, output, [
335332
'',
336-
' ' + chalk.green('1 passed'),
337-
' ' + chalk.red('2 exceptions'),
333+
' ' + chalk.green('1 passed'),
334+
' ' + chalk.red('2 exceptions'),
338335
'',
339-
'',
340-
' ' + chalk.red('1. Uncaught Exception'),
336+
' ' + chalk.white('Uncaught Exception'),
341337
/Error: failure/,
342338
/test\/reporters\/mini\.js/,
343339
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
344340
'',
345-
'',
346-
' ' + chalk.red(cross + ' A futuristic test runner')
341+
' ' + chalk.red(cross + ' A futuristic test runner')
347342
]);
348343
t.end();
349344
});
@@ -368,20 +363,22 @@ test('results with errors', function (t) {
368363
};
369364

370365
var output = reporter.finish(runStatus);
366+
367+
var expectedStack = colors.error(' failure two\n') + colors.errorStack('stack line with trailing whitespace');
368+
expectedStack = expectedStack.split('\n');
369+
371370
compareLineOutput(t, output, [
372371
'',
373-
' ' + chalk.red('1 failed'),
372+
' ' + chalk.red('1 failed'),
374373
'',
375-
'',
376-
' ' + chalk.red('1. failed one'),
374+
' ' + chalk.white('failed one'),
377375
/failure/,
378376
/test\/reporters\/mini\.js/,
379377
compareLineOutput.SKIP_UNTIL_EMPTY_LINE,
380378
'',
381-
'',
382-
' ' + chalk.red('2. failed two')
379+
' ' + chalk.white('failed two')
383380
].concat(
384-
colors.stack(' failure two\n stack line with trailing whitespace').split('\n')
381+
expectedStack
385382
));
386383
t.end();
387384
});
@@ -397,8 +394,8 @@ test('results with 1 previous failure', function (t) {
397394
var output = reporter.finish(runStatus);
398395
compareLineOutput(t, output, [
399396
'',
400-
' ' + colors.todo('1 todo'),
401-
' ' + colors.error('1 previous failure in test files that were not rerun')
397+
' ' + colors.todo('1 todo'),
398+
' ' + colors.error('1 previous failure in test files that were not rerun')
402399
]);
403400
t.end();
404401
});
@@ -414,8 +411,8 @@ test('results with 2 previous failures', function (t) {
414411
var output = reporter.finish(runStatus);
415412
compareLineOutput(t, output, [
416413
'',
417-
' ' + colors.todo('1 todo'),
418-
' ' + colors.error('2 previous failures in test files that were not rerun')
414+
' ' + colors.todo('1 todo'),
415+
' ' + colors.error('2 previous failures in test files that were not rerun')
419416
]);
420417
t.end();
421418
});
@@ -427,7 +424,7 @@ test('empty results after reset', function (t) {
427424
reporter.reset();
428425

429426
var output = reporter.finish({});
430-
t.is(output, '\n');
427+
t.is(output, '\n\n');
431428
t.end();
432429
});
433430

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

450447
var actualOutput = reporter.finish({});
451448
var expectedOutput = [
452-
'\n ' + chalk.green('1 passed') + time,
453-
''
449+
'\n ' + chalk.green('1 passed') + time,
450+
'\n'
454451
].join('\n');
455452

456453
t.is(actualOutput, expectedOutput);
@@ -487,8 +484,8 @@ test('silently handles errors without body', function (t) {
487484
};
488485
var actualOutput = reporter.finish(runStatus);
489486
var expectedOutput = [
490-
'\n ' + colors.error('1 failed'),
491-
''
487+
'\n ' + colors.error('1 failed'),
488+
'\n'
492489
].join('\n');
493490
t.is(actualOutput, expectedOutput);
494491
t.end();
@@ -504,8 +501,8 @@ test('does not handle errors with body in rejections', function (t) {
504501
};
505502
var actualOutput = reporter.finish(runStatus);
506503
var expectedOutput = [
507-
'\n ' + colors.error('1 rejection'),
508-
''
504+
'\n ' + colors.error('1 rejection'),
505+
'\n'
509506
].join('\n');
510507
t.is(actualOutput, expectedOutput);
511508
t.end();
@@ -522,9 +519,10 @@ test('returns description based on error itself if no stack available', function
522519
};
523520
var actualOutput = reporter.finish(runStatus);
524521
var expectedOutput = [
525-
'\n ' + colors.error('1 exception'),
526-
'\n\n ' + colors.error('1. Uncaught Exception'),
527-
' ' + colors.stack(JSON.stringify({error: err1})) + '\n'
522+
'\n ' + colors.error('1 exception'),
523+
'\n ' + colors.title('Uncaught Exception'),
524+
' ' + colors.stack(JSON.stringify({error: err1})),
525+
'\n\n'
528526
].join('\n');
529527
t.is(actualOutput, expectedOutput);
530528
t.end();

0 commit comments

Comments
 (0)