Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 53 additions & 22 deletions lib/reporters/mini.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ var cliCursor = require('cli-cursor');
var lastLineTracker = require('last-line-stream/tracker');
var StringDecoder = require('string_decoder').StringDecoder;
var plur = require('plur');
var spinners = require('cli-spinners');
var chalk = require('chalk');
var colors = require('../colors');

function MiniReporter() {
if (!(this instanceof MiniReporter)) {
return new MiniReporter();
}

var spinnerDef = spinners.dots;
this.spinnerFrames = spinnerDef.frames.map(function (c) {
return chalk.gray.dim(c);
});
this.spinnerInterval = spinnerDef.interval;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using var dots = require('cli-spinners').dots above and just referencing dots.frames/dots.interval?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sindresorhus usually objects to that. I don't have a strong opinion either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this way leaves us open to having a command line option to configure your spinner:

$ ava --spinner=balloon

then

var spinnerDef = spinners[config.spinner];

(I considered waiting until April 1st to post this as a feature request, but I'm pretty sure I would have forgotten by then).


this.reset();
this.stream = process.stderr;
this.stringDecoder = new StringDecoder();
Expand All @@ -18,23 +26,50 @@ function MiniReporter() {
module.exports = MiniReporter;

MiniReporter.prototype.start = function () {
return '';
var self = this;
this.interval = setInterval(function () {
self.spinnerIndex = (self.spinnerIndex + 1) % self.spinnerFrames.length;
self.write(self.prefix());
}, this.spinnerInterval);
return this.prefix('');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The '' seems unnecessary here.

};

MiniReporter.prototype.reset = function () {
this.clearInterval();
this.passCount = 0;
this.failCount = 0;
this.skipCount = 0;
this.todoCount = 0;
this.rejectionCount = 0;
this.exceptionCount = 0;
this.currentStatus = '';
this.currentTest = '';
this.statusLineCount = 0;
this.spinnerIndex = 0;
this.lastLineTracker = lastLineTracker();
};

MiniReporter.prototype.spinnerChar = function () {
return this.spinnerFrames[this.spinnerIndex];
};

MiniReporter.prototype.clearInterval = function () {
clearInterval(this.interval);
this.interval = null;
};

MiniReporter.prototype.test = function (test) {
var status = '';
return this.prefix(this._test(test));
};

MiniReporter.prototype.prefix = function (str) {
str = str || this.currentTest;
this.currentTest = str;
// The space before the newline is required for proper formatting. (Not sure why).
return ' \n ' + this.spinnerChar() + ' ' + str;
};

MiniReporter.prototype._test = function (test) {
var title;

if (test.todo) {
Expand All @@ -51,18 +86,7 @@ MiniReporter.prototype.test = function (test) {
this.passCount++;
}

status += ' ' + title;
status += '\n\n';

if (this.passCount > 0) {
status += ' ' + colors.pass(this.passCount, 'passed');
}

if (this.failCount > 0) {
status += ' ' + colors.error(this.failCount, 'failed');
}

return status;
return title + '\n' + this.reportCounts();
};

MiniReporter.prototype.unhandledError = function (err) {
Expand All @@ -73,31 +97,38 @@ MiniReporter.prototype.unhandledError = function (err) {
}
};

MiniReporter.prototype.finish = function () {
var status = '\n';
MiniReporter.prototype.reportCounts = function () {
var status = '';

if (this.passCount > 0) {
status += ' ' + colors.pass(this.passCount, 'passed');
status += '\n ' + colors.pass(this.passCount, 'passed');
}

if (this.skipCount > 0) {
status += ' ' + colors.skip(this.skipCount, 'skipped');
status += '\n ' + colors.skip(this.skipCount, 'skipped');
}

if (this.todoCount > 0) {
status += ' ' + colors.todo(this.todoCount, 'todo');
status += '\n ' + colors.todo(this.todoCount, 'todo');
}

if (this.failCount > 0) {
status += ' ' + colors.error(this.failCount, 'failed');
status += '\n ' + colors.error(this.failCount, 'failed');
}

return status.length ? status : '\n';
};

MiniReporter.prototype.finish = function () {
this.clearInterval();
var status = this.reportCounts();

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));
}

var i = 0;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"caching-transform": "^1.0.0",
"chalk": "^1.0.0",
"cli-cursor": "^1.0.2",
"cli-spinners": "^0.1.2",
"co-with-promise": "^4.6.0",
"common-path-prefix": "^1.0.0",
"convert-source-map": "^1.1.2",
Expand Down
104 changes: 83 additions & 21 deletions test/reporters/mini.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@
var chalk = require('chalk');
var test = require('tap').test;
var AvaError = require('../../lib/ava-error');
var miniReporter = require('../../lib/reporters/mini');
var _miniReporter = require('../../lib/reporters/mini');
var beautifyStack = require('../../lib/beautify-stack');

function miniReporter() {
var reporter = _miniReporter();
reporter.start = function () {
return '';
};
return reporter;
}

process.stderr.setMaxListeners(50);

test('start', function (t) {
var reporter = miniReporter();
var reporter = _miniReporter();

t.is(reporter.start(), '');
t.is(reporter.start(), ' \n ⠋ ');
reporter.clearInterval();
t.end();
});

Expand All @@ -22,9 +31,10 @@ test('passing test', function (t) {
});

var expectedOutput = [
' ' + chalk.green('passed'),
' ',
' ⠋ ' + chalk.green('passed'),
'',
' ' + chalk.green('1 passed')
' ' + chalk.green('1 passed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -42,9 +52,58 @@ test('failing test', function (t) {
});

var expectedOutput = [
' ' + chalk.red('failed'),
' ',
' ⠋ ' + chalk.red('failed'),
'',
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
t.end();
});

test('passing test after failing', function (t) {
var reporter = miniReporter();

reporter.test({
title: 'failed',
error: {
message: 'assertion failed'
}
});

var actualOutput = reporter.test({title: 'passed'});

var expectedOutput = [
' ',
' ⠋ ' + chalk.green('passed'),
'',
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
t.end();
});

test('failing test after passing', function (t) {
var reporter = miniReporter();

reporter.test({title: 'passed'});

var actualOutput = reporter.test({
title: 'failed',
error: {
message: 'assertion failed'
}
});

var expectedOutput = [
' ',
' ⠋ ' + chalk.red('failed'),
'',
' ' + chalk.red('1 failed')
' ' + chalk.green('1 passed'),
' ' + chalk.red('1 failed')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -60,9 +119,10 @@ test('skipped test', function (t) {
});

var expectedOutput = [
' ' + chalk.yellow('- skipped'),
' ',
' ⠋ ' + chalk.yellow('- skipped'),
'',
''
' ' + chalk.yellow('1 skipped')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -79,9 +139,10 @@ test('todo test', function (t) {
});

var expectedOutput = [
' ' + chalk.blue('- todo'),
' ',
' ⠋ ' + chalk.blue('- todo'),
'',
''
' ' + chalk.blue('1 todo')
].join('\n');

t.is(actualOutput, expectedOutput);
Expand All @@ -95,7 +156,7 @@ test('results with passing tests', function (t) {

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

Expand All @@ -111,7 +172,7 @@ test('results with skipped tests', function (t) {

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

Expand All @@ -127,7 +188,7 @@ test('results with todo tests', function (t) {

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

Expand All @@ -143,8 +204,9 @@ 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') + ' ' + chalk.yellow('1 skipped'));
t.is(output[2], '');
t.is(output[1], ' ' + chalk.green('1 passed'));
t.is(output[2], ' ' + chalk.yellow('1 skipped'));
t.is(output[3], '');
t.end();
});

Expand All @@ -164,8 +226,8 @@ test('results with passing tests and rejections', 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.red('1 rejection'));
t.is(output[1], ' ' + chalk.green('1 passed'));
t.is(output[2], ' ' + chalk.red('1 rejection'));
t.is(output[3], '');
t.is(output[4], ' ' + chalk.red('1. Unhandled Rejection'));
t.match(output[5], /Error: failure/);
Expand All @@ -192,8 +254,8 @@ test('results with passing tests and exceptions', 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.red('2 exceptions'));
t.is(output[1], ' ' + chalk.green('1 passed'));
t.is(output[2], ' ' + chalk.red('2 exceptions'));
t.is(output[3], '');
t.is(output[4], ' ' + chalk.red('1. Uncaught Exception'));
t.match(output[5], /Error: failure/);
Expand All @@ -220,7 +282,7 @@ test('results with errors', function (t) {
var output = reporter.finish().split('\n');

t.is(output[0], '');
t.is(output[1], ' ' + chalk.red('1 failed'));
t.is(output[1], ' ' + chalk.red('1 failed'));
t.is(output[2], '');
t.is(output[3], ' ' + chalk.red('1. failed'));
t.match(output[4], /failure/);
Expand Down
7 changes: 6 additions & 1 deletion test/visual/lorem-ipsum.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ async function testFn(t) {
t.pass();
}

async function failFn(t) {
await delay(40);
t.fail();
}

for (var i = 0; i < 400; i++) {
test.serial('test number ' + i, testFn);
test.serial('test number ' + i, i === 125 ? failFn : testFn);
}
2 changes: 1 addition & 1 deletion test/visual/run-visual-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ run(
'You should see the entire contents of the Gettysburg address.',
'Three paragraphs with a blank line in between each.',
'There should be no other blank lines within the speech text.',
'The test counter should display "400 passed" at the bottom.'
'The test counter should display "399 passed 1 failed" at the bottom.'
]
))
;