From 06289da033d1eb60edfb4b2fce5aeb1e26e2714b Mon Sep 17 00:00:00 2001 From: James Talmage Date: Thu, 3 Mar 2016 17:52:28 -0500 Subject: [PATCH 1/6] Add busy indicator to mini reporter. Fixes #598. Add a spinner to the mini reporter to indicate ongoing test progress. Fixes #598. --- lib/reporters/mini.js | 35 ++++++++++++++++++++++++++++++++--- package.json | 1 + test/reporters/mini.js | 23 ++++++++++++++++------- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/lib/reporters/mini.js b/lib/reporters/mini.js index b38e734bc..11426c93c 100644 --- a/lib/reporters/mini.js +++ b/lib/reporters/mini.js @@ -3,6 +3,7 @@ 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 colors = require('../colors'); function MiniReporter() { @@ -10,6 +11,10 @@ function MiniReporter() { return new MiniReporter(); } + var spinnerDef = spinners.dots; + this.spinnerFrames = spinnerDef.frames; + this.spinnerInterval = spinnerDef.interval; + this.reset(); this.stream = process.stderr; this.stringDecoder = new StringDecoder(); @@ -18,10 +23,16 @@ function MiniReporter() { module.exports = MiniReporter; MiniReporter.prototype.start = function () { - return ''; + var self = this; + this.interval = setInterval(function () { + self.spinnerFrame = (self.spinnerFrame + 1) % self.spinnerFrames.length; + self.write(self.spinnerChar() + self.currentTest); + }, this.spinnerInterval); + return this.spinnerChar(); }; MiniReporter.prototype.reset = function () { + this.clearInterval(); this.passCount = 0; this.failCount = 0; this.skipCount = 0; @@ -29,12 +40,29 @@ MiniReporter.prototype.reset = function () { this.rejectionCount = 0; this.exceptionCount = 0; this.currentStatus = ''; + this.currentTest = ''; this.statusLineCount = 0; + this.spinnerFrame = 0; this.lastLineTracker = lastLineTracker(); }; +MiniReporter.prototype.spinnerChar = function () { + return this.spinnerFrames[this.spinnerFrame]; +}; + +MiniReporter.prototype.clearInterval = function () { + if (this.interval) { + clearInterval(this.interval); + } + this.interval = 0; +}; + MiniReporter.prototype.test = function (test) { - var status = ''; + this.currentTest = this._test(test); + return this.spinnerChar() + this.currentTest; +}; + +MiniReporter.prototype._test = function (test) { var title; if (test.todo) { @@ -51,7 +79,7 @@ MiniReporter.prototype.test = function (test) { this.passCount++; } - status += ' ' + title; + var status = ' ' + title; status += '\n\n'; if (this.passCount > 0) { @@ -74,6 +102,7 @@ MiniReporter.prototype.unhandledError = function (err) { }; MiniReporter.prototype.finish = function () { + this.clearInterval(); var status = '\n'; if (this.passCount > 0) { diff --git a/package.json b/package.json index 6e19c80f1..7e48ff811 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/test/reporters/mini.js b/test/reporters/mini.js index 14be504c3..0633a7f9d 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -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(), '⠋'); + reporter.clearInterval(); t.end(); }); @@ -22,7 +31,7 @@ test('passing test', function (t) { }); var expectedOutput = [ - ' ' + chalk.green('passed'), + '⠋ ' + chalk.green('passed'), '', ' ' + chalk.green('1 passed') ].join('\n'); @@ -42,7 +51,7 @@ test('failing test', function (t) { }); var expectedOutput = [ - ' ' + chalk.red('failed'), + '⠋ ' + chalk.red('failed'), '', ' ' + chalk.red('1 failed') ].join('\n'); @@ -60,7 +69,7 @@ test('skipped test', function (t) { }); var expectedOutput = [ - ' ' + chalk.yellow('- skipped'), + '⠋ ' + chalk.yellow('- skipped'), '', '' ].join('\n'); @@ -79,7 +88,7 @@ test('todo test', function (t) { }); var expectedOutput = [ - ' ' + chalk.blue('- todo'), + '⠋ ' + chalk.blue('- todo'), '', '' ].join('\n'); From 7d4b0999211ce2577782e9d36f90a17d1e50ce2a Mon Sep 17 00:00:00 2001 From: James Talmage Date: Sat, 5 Mar 2016 21:52:45 -0500 Subject: [PATCH 2/6] incorporate PR feedback. --- lib/reporters/mini.js | 34 +++++++++++++++++++-------------- test/reporters/mini.js | 10 +++++++--- test/visual/lorem-ipsum.js | 7 ++++++- test/visual/run-visual-tests.js | 2 +- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/lib/reporters/mini.js b/lib/reporters/mini.js index 11426c93c..17bfbccfd 100644 --- a/lib/reporters/mini.js +++ b/lib/reporters/mini.js @@ -4,6 +4,7 @@ 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() { @@ -12,7 +13,9 @@ function MiniReporter() { } var spinnerDef = spinners.dots; - this.spinnerFrames = spinnerDef.frames; + this.spinnerFrames = spinnerDef.frames.map(function (c) { + return chalk.dim(c); + }); this.spinnerInterval = spinnerDef.interval; this.reset(); @@ -25,10 +28,10 @@ module.exports = MiniReporter; MiniReporter.prototype.start = function () { var self = this; this.interval = setInterval(function () { - self.spinnerFrame = (self.spinnerFrame + 1) % self.spinnerFrames.length; - self.write(self.spinnerChar() + self.currentTest); + self.spinnerIndex = (self.spinnerIndex + 1) % self.spinnerFrames.length; + self.write(self.prefix()); }, this.spinnerInterval); - return this.spinnerChar(); + return this.prefix(''); }; MiniReporter.prototype.reset = function () { @@ -42,24 +45,27 @@ MiniReporter.prototype.reset = function () { this.currentStatus = ''; this.currentTest = ''; this.statusLineCount = 0; - this.spinnerFrame = 0; + this.spinnerIndex = 0; this.lastLineTracker = lastLineTracker(); }; MiniReporter.prototype.spinnerChar = function () { - return this.spinnerFrames[this.spinnerFrame]; + return this.spinnerFrames[this.spinnerIndex]; }; MiniReporter.prototype.clearInterval = function () { - if (this.interval) { - clearInterval(this.interval); - } - this.interval = 0; + clearInterval(this.interval); + this.interval = null; }; MiniReporter.prototype.test = function (test) { - this.currentTest = this._test(test); - return this.spinnerChar() + this.currentTest; + return this.prefix(this._test(test)); +}; + +MiniReporter.prototype.prefix = function (str) { + str = this.currentTest = str || this.currentTest; + // The space before the newline is required for proper formatting. (Not sure why). + return ' \n' + this.spinnerChar() + str; }; MiniReporter.prototype._test = function (test) { @@ -83,11 +89,11 @@ MiniReporter.prototype._test = function (test) { status += '\n\n'; if (this.passCount > 0) { - status += ' ' + colors.pass(this.passCount, 'passed'); + status += ' ' + colors.pass(this.passCount, 'passed'); } if (this.failCount > 0) { - status += ' ' + colors.error(this.failCount, 'failed'); + status += ' ' + colors.error(this.failCount, 'failed'); } return status; diff --git a/test/reporters/mini.js b/test/reporters/mini.js index 0633a7f9d..cbe300e5f 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -18,7 +18,7 @@ process.stderr.setMaxListeners(50); test('start', function (t) { var reporter = _miniReporter(); - t.is(reporter.start(), '⠋'); + t.is(reporter.start(), ' \n⠋'); reporter.clearInterval(); t.end(); }); @@ -31,9 +31,10 @@ test('passing test', function (t) { }); var expectedOutput = [ + ' ', '⠋ ' + chalk.green('passed'), '', - ' ' + chalk.green('1 passed') + ' ' + chalk.green('1 passed') ].join('\n'); t.is(actualOutput, expectedOutput); @@ -51,9 +52,10 @@ test('failing test', function (t) { }); var expectedOutput = [ + ' ', '⠋ ' + chalk.red('failed'), '', - ' ' + chalk.red('1 failed') + ' ' + chalk.red('1 failed') ].join('\n'); t.is(actualOutput, expectedOutput); @@ -69,6 +71,7 @@ test('skipped test', function (t) { }); var expectedOutput = [ + ' ', '⠋ ' + chalk.yellow('- skipped'), '', '' @@ -88,6 +91,7 @@ test('todo test', function (t) { }); var expectedOutput = [ + ' ', '⠋ ' + chalk.blue('- todo'), '', '' diff --git a/test/visual/lorem-ipsum.js b/test/visual/lorem-ipsum.js index fc1df4ec8..ce61f3bbd 100644 --- a/test/visual/lorem-ipsum.js +++ b/test/visual/lorem-ipsum.js @@ -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); } diff --git a/test/visual/run-visual-tests.js b/test/visual/run-visual-tests.js index 1d2c2a815..f3d9b63b8 100644 --- a/test/visual/run-visual-tests.js +++ b/test/visual/run-visual-tests.js @@ -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.' ] )) ; From 4583bcd8c44583290f3189bc17daf5d186b95580 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Sat, 5 Mar 2016 21:58:32 -0500 Subject: [PATCH 3/6] add some additional mini reporter tests verifies behavior when there are some passing / some failing --- test/reporters/mini.js | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/reporters/mini.js b/test/reporters/mini.js index cbe300e5f..d0bcf1ebc 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -62,6 +62,52 @@ test('failing test', function (t) { 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.green('1 passed') + ' ' + chalk.red('1 failed') + ].join('\n'); + + t.is(actualOutput, expectedOutput); + t.end(); +}); + test('skipped test', function (t) { var reporter = miniReporter(); From b32c813b77ca11de746b8758873172ebf8368712 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Sat, 5 Mar 2016 22:01:08 -0500 Subject: [PATCH 4/6] mini reporter should display pass/fail counts on separate lines --- lib/reporters/mini.js | 3 +++ test/reporters/mini.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/reporters/mini.js b/lib/reporters/mini.js index 17bfbccfd..bc97a2805 100644 --- a/lib/reporters/mini.js +++ b/lib/reporters/mini.js @@ -93,6 +93,9 @@ MiniReporter.prototype._test = function (test) { } if (this.failCount > 0) { + if (this.passCount > 0) { + status += '\n'; + } status += ' ' + colors.error(this.failCount, 'failed'); } diff --git a/test/reporters/mini.js b/test/reporters/mini.js index d0bcf1ebc..d0ccc86fa 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -78,7 +78,8 @@ test('passing test after failing', function (t) { ' ', '⠋ ' + chalk.green('passed'), '', - ' ' + chalk.green('1 passed') + ' ' + chalk.red('1 failed') + ' ' + chalk.green('1 passed'), + ' ' + chalk.red('1 failed') ].join('\n'); t.is(actualOutput, expectedOutput); @@ -101,7 +102,8 @@ test('failing test after passing', function (t) { ' ', '⠋ ' + 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); From d2739dfe5b32d88b2dcbf63f6466f01adc27a5ed Mon Sep 17 00:00:00 2001 From: James Talmage Date: Sun, 6 Mar 2016 03:05:13 -0500 Subject: [PATCH 5/6] add all counts to mini-reporter live update --- lib/reporters/mini.js | 40 ++++++++++++++++------------------------ test/reporters/mini.js | 25 +++++++++++++------------ 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/lib/reporters/mini.js b/lib/reporters/mini.js index bc97a2805..50d4d7a92 100644 --- a/lib/reporters/mini.js +++ b/lib/reporters/mini.js @@ -85,21 +85,7 @@ MiniReporter.prototype._test = function (test) { this.passCount++; } - var status = ' ' + title; - status += '\n\n'; - - if (this.passCount > 0) { - status += ' ' + colors.pass(this.passCount, 'passed'); - } - - if (this.failCount > 0) { - if (this.passCount > 0) { - status += '\n'; - } - status += ' ' + colors.error(this.failCount, 'failed'); - } - - return status; + return ' ' + title + '\n' + this.reportCounts(); }; MiniReporter.prototype.unhandledError = function (err) { @@ -110,32 +96,38 @@ MiniReporter.prototype.unhandledError = function (err) { } }; -MiniReporter.prototype.finish = function () { - this.clearInterval(); - 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; diff --git a/test/reporters/mini.js b/test/reporters/mini.js index d0ccc86fa..810a0d11e 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -122,7 +122,7 @@ test('skipped test', function (t) { ' ', '⠋ ' + chalk.yellow('- skipped'), '', - '' + ' ' + chalk.yellow('1 skipped') ].join('\n'); t.is(actualOutput, expectedOutput); @@ -142,7 +142,7 @@ test('todo test', function (t) { ' ', '⠋ ' + chalk.blue('- todo'), '', - '' + ' ' + chalk.blue('1 todo') ].join('\n'); t.is(actualOutput, expectedOutput); @@ -156,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'); @@ -172,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'); @@ -188,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'); @@ -204,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(); }); @@ -225,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/); @@ -253,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/); @@ -281,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/); From 08d1a669292d264da1e4ace93e84df15edcf24af Mon Sep 17 00:00:00 2001 From: James Talmage Date: Sun, 6 Mar 2016 03:26:16 -0500 Subject: [PATCH 6/6] move spinner over one space --- lib/reporters/mini.js | 9 +++++---- test/reporters/mini.js | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/reporters/mini.js b/lib/reporters/mini.js index 50d4d7a92..626c7aeda 100644 --- a/lib/reporters/mini.js +++ b/lib/reporters/mini.js @@ -14,7 +14,7 @@ function MiniReporter() { var spinnerDef = spinners.dots; this.spinnerFrames = spinnerDef.frames.map(function (c) { - return chalk.dim(c); + return chalk.gray.dim(c); }); this.spinnerInterval = spinnerDef.interval; @@ -63,9 +63,10 @@ MiniReporter.prototype.test = function (test) { }; MiniReporter.prototype.prefix = function (str) { - str = this.currentTest = str || this.currentTest; + 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; + return ' \n ' + this.spinnerChar() + ' ' + str; }; MiniReporter.prototype._test = function (test) { @@ -85,7 +86,7 @@ MiniReporter.prototype._test = function (test) { this.passCount++; } - return ' ' + title + '\n' + this.reportCounts(); + return title + '\n' + this.reportCounts(); }; MiniReporter.prototype.unhandledError = function (err) { diff --git a/test/reporters/mini.js b/test/reporters/mini.js index 810a0d11e..b0376ba43 100644 --- a/test/reporters/mini.js +++ b/test/reporters/mini.js @@ -18,7 +18,7 @@ process.stderr.setMaxListeners(50); test('start', function (t) { var reporter = _miniReporter(); - t.is(reporter.start(), ' \n⠋'); + t.is(reporter.start(), ' \n ⠋ '); reporter.clearInterval(); t.end(); }); @@ -32,7 +32,7 @@ test('passing test', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.green('passed'), + ' ⠋ ' + chalk.green('passed'), '', ' ' + chalk.green('1 passed') ].join('\n'); @@ -53,7 +53,7 @@ test('failing test', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.red('failed'), + ' ⠋ ' + chalk.red('failed'), '', ' ' + chalk.red('1 failed') ].join('\n'); @@ -76,7 +76,7 @@ test('passing test after failing', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.green('passed'), + ' ⠋ ' + chalk.green('passed'), '', ' ' + chalk.green('1 passed'), ' ' + chalk.red('1 failed') @@ -100,7 +100,7 @@ test('failing test after passing', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.red('failed'), + ' ⠋ ' + chalk.red('failed'), '', ' ' + chalk.green('1 passed'), ' ' + chalk.red('1 failed') @@ -120,7 +120,7 @@ test('skipped test', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.yellow('- skipped'), + ' ⠋ ' + chalk.yellow('- skipped'), '', ' ' + chalk.yellow('1 skipped') ].join('\n'); @@ -140,7 +140,7 @@ test('todo test', function (t) { var expectedOutput = [ ' ', - '⠋ ' + chalk.blue('- todo'), + ' ⠋ ' + chalk.blue('- todo'), '', ' ' + chalk.blue('1 todo') ].join('\n');