From d3c2df92d68b9a724fbb34a2b4962e5626025e95 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 09:30:30 +0200 Subject: [PATCH 01/31] added test to make sure first line of report is version line --- test/reporters/tap.spec.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 5030cbde5c..945a6d0e83 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -33,6 +33,17 @@ describe('TAP reporter', function() { }); describe('on start', function() { + it('should write expected version on first line', function() { + runner = createMockRunner('start', 'start'); + runner.grepTotal = function(string) {}; + TAP.call({}, runner); + + var expectedFirstLine = 'TAP version 13\n'; + process.stdout.write = stdoutWrite; + + expect(stdout[0], 'to equal', expectedFirstLine); + }); + it('should hand runners suite into grepTotal and log the total', function() { var expectedSuite = 'some suite'; var expectedTotal = 10; From c067a6efa2963de394042a2fa215e2ca54c4676a Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 09:31:24 +0200 Subject: [PATCH 02/31] reporter will now print version line as first line --- lib/reporters/tap.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index feaf7ea21a..1c7b55931a 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -32,6 +32,7 @@ function TAP(runner) { var failures = 0; runner.on('start', function() { + console.log('TAP version 13'); var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }); From 9c78b61bc0ed99857a8013c0d456074e238a52c2 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 09:34:13 +0200 Subject: [PATCH 03/31] Changed test to look for plan (1..N) on second line. Was failing since it matched entire output array and first line is now the version line per TAP v13 spec. --- test/reporters/tap.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 945a6d0e83..175ad4b2c1 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -56,10 +56,10 @@ describe('TAP reporter', function() { }; TAP.call({}, runner); - var expectedArray = ['1..' + expectedTotal + '\n']; + var expectedSecondLine = '1..' + expectedTotal + '\n'; process.stdout.write = stdoutWrite; - expect(stdout, 'to equal', expectedArray); + expect(stdout[1], 'to equal', expectedSecondLine); expect(expectedString, 'to be', expectedSuite); }); }); From 78ab6c52753051469ab1c0ef74c473471800b264 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 10:27:36 +0200 Subject: [PATCH 04/31] Added integration tests to make sure we conform to spec. Only expect now is that version line is first line, more to come. Removed the previously added unit test which now is superflous. --- test/integration/reporters.spec.js | 26 ++++++++++++++++++++++++++ test/reporters/tap.spec.js | 11 ----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 4e95622dee..8abb9d5f6c 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -99,4 +99,30 @@ describe('reporters', function() { }); }); }); + + describe('tap', function() { + describe('produces valid TAP v13 output', function() { + var runFixtureAndValidateOutput = function(fixture) { + it('for ' + fixture, function(done) { + var args = ['--reporter=tap']; + run(fixture, args, function(err, res) { + if (err) { + done(err); + return; + } + + // see https://testanything.org/tap-version-13-specification.html + + // first line must be `TAP version 13` + var firstLine = res.output.split('\n', 1)[0]; + expect(firstLine, 'to equal', 'TAP version 13'); + done(); + }); + }); + }; + + runFixtureAndValidateOutput('passing.fixture.js'); + runFixtureAndValidateOutput('uncaught.fixture.js'); + }); + }); }); diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 175ad4b2c1..71b29a386a 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -33,17 +33,6 @@ describe('TAP reporter', function() { }); describe('on start', function() { - it('should write expected version on first line', function() { - runner = createMockRunner('start', 'start'); - runner.grepTotal = function(string) {}; - TAP.call({}, runner); - - var expectedFirstLine = 'TAP version 13\n'; - process.stdout.write = stdoutWrite; - - expect(stdout[0], 'to equal', expectedFirstLine); - }); - it('should hand runners suite into grepTotal and log the total', function() { var expectedSuite = 'some suite'; var expectedTotal = 10; From b59af191e91ae9994a55735d6dfade0767a5a54f Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 11:12:34 +0200 Subject: [PATCH 05/31] Extended integration test to validate plan, test is growing... --- test/integration/reporters.spec.js | 55 ++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 8abb9d5f6c..f25f4313d1 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -102,7 +102,7 @@ describe('reporters', function() { describe('tap', function() { describe('produces valid TAP v13 output', function() { - var runFixtureAndValidateOutput = function(fixture) { + var runFixtureAndValidateOutput = function(fixture, expected) { it('for ' + fixture, function(done) { var args = ['--reporter=tap']; run(fixture, args, function(err, res) { @@ -111,18 +111,61 @@ describe('reporters', function() { return; } + var outputLines = res.output.split('\n'); + // see https://testanything.org/tap-version-13-specification.html - // first line must be `TAP version 13` - var firstLine = res.output.split('\n', 1)[0]; - expect(firstLine, 'to equal', 'TAP version 13'); + // Version + var expectedVersion = 13; + // first line must be version line + expect( + outputLines[0], + 'to equal', + 'TAP version ' + expectedVersion + ); + + // Plan + var expectedPlan = '1..' + expected.numTests; + // plan must appear once + expect(outputLines, 'to contain', expectedPlan); + expect( + outputLines.filter(l => l === expectedPlan), + 'to have length', + 1 + ); + // plan cannot appear in middle of the output + var testLineMatcher = function(line) { + return line.match(/^not ok/) || line.match(/^ok/); + }; + var firstTestLine = outputLines.findIndex(testLineMatcher); + expect(firstTestLine, 'to be greater than', -1); + var lastTestLine = + outputLines.length - + 1 - + outputLines + .slice() + .reverse() + .findIndex(testLineMatcher); + var planLine = outputLines.findIndex(function(line) { + return line === expectedPlan; + }); + expect( + planLine < firstTestLine || planLine > lastTestLine, + 'to equal', + true + ); + done(); }); }); }; - runFixtureAndValidateOutput('passing.fixture.js'); - runFixtureAndValidateOutput('uncaught.fixture.js'); + runFixtureAndValidateOutput('passing.fixture.js', { + numTests: 2 + }); + runFixtureAndValidateOutput('uncaught.fixture.js', { + numTests: 2 + }); }); }); }); From ddc5b17092770ce93b853b65afa8c145944f78ba Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 11:21:34 +0200 Subject: [PATCH 06/31] removed some section comments and minor restructure --- test/integration/reporters.spec.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index f25f4313d1..5a92c4f4ef 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -111,12 +111,11 @@ describe('reporters', function() { return; } - var outputLines = res.output.split('\n'); + var expectedVersion = 13; + var expectedPlan = '1..' + expected.numTests; - // see https://testanything.org/tap-version-13-specification.html + var outputLines = res.output.split('\n'); - // Version - var expectedVersion = 13; // first line must be version line expect( outputLines[0], @@ -124,8 +123,6 @@ describe('reporters', function() { 'TAP version ' + expectedVersion ); - // Plan - var expectedPlan = '1..' + expected.numTests; // plan must appear once expect(outputLines, 'to contain', expectedPlan); expect( @@ -138,6 +135,7 @@ describe('reporters', function() { return line.match(/^not ok/) || line.match(/^ok/); }; var firstTestLine = outputLines.findIndex(testLineMatcher); + // there must be at least one test line expect(firstTestLine, 'to be greater than', -1); var lastTestLine = outputLines.length - From f030a4b3b9859ab7cfa8d1d500ee21e310ed0c8f Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 11:53:31 +0200 Subject: [PATCH 07/31] broke out testLineMatcher to testLinePredicate with minor refactor. --- test/integration/reporters.spec.js | 45 ++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 5a92c4f4ef..6527c8e47b 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -101,6 +101,10 @@ describe('reporters', function() { }); describe('tap', function() { + var testLinePredicate = function(line) { + return line.match(/^not ok/) != null || line.match(/^ok/) != null; + }; + describe('produces valid TAP v13 output', function() { var runFixtureAndValidateOutput = function(fixture, expected) { it('for ' + fixture, function(done) { @@ -131,10 +135,7 @@ describe('reporters', function() { 1 ); // plan cannot appear in middle of the output - var testLineMatcher = function(line) { - return line.match(/^not ok/) || line.match(/^ok/); - }; - var firstTestLine = outputLines.findIndex(testLineMatcher); + var firstTestLine = outputLines.findIndex(testLinePredicate); // there must be at least one test line expect(firstTestLine, 'to be greater than', -1); var lastTestLine = @@ -143,7 +144,7 @@ describe('reporters', function() { outputLines .slice() .reverse() - .findIndex(testLineMatcher); + .findIndex(testLinePredicate); var planLine = outputLines.findIndex(function(line) { return line === expectedPlan; }); @@ -165,5 +166,39 @@ describe('reporters', function() { numTests: 2 }); }); + + it('places exceptions correctly in YAML blocks', function(done) { + var args = ['--reporter=tap']; + run('uncaught.fixture.js', args, function(err, res) { + if (err) { + done(err); + return; + } + + var outputLines = res.output.split('\n'); + for (var i = 0; i + 1 < outputLines.length; i++) { + console.log('>', outputLines[i]); + console.log('\t', testLinePredicate(outputLines[i])); + console.log('\t', testLinePredicate(outputLines[i + 1])); + if ( + testLinePredicate(outputLines[i]) && + testLinePredicate(outputLines[i + 1]) === false + ) { + var blockLinesStart = i + 1; + var blockLinesEnd = + i + 1 + outputLines.slice(i + 1).findIndex(anythingElsePredicate); + var blockLines = + blockLinesEnd > blockLinesStart + ? outputLines.slice(blockLinesStart, blockLinesEnd) + : outputLines.slice(blockLinesStart); + console.log(i); + console.log(blockLines); + i += blockLines.length; + } + } + + done(); + }); + }); }); }); From 43c94c8411d05db5ff8476a9c98c1e767367d7f9 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 12:10:43 +0200 Subject: [PATCH 08/31] added a bunch of predicates to identify lines --- test/integration/reporters.spec.js | 36 +++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 6527c8e47b..bb7063de78 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -101,9 +101,35 @@ describe('reporters', function() { }); describe('tap', function() { + var not = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; + var versionPredicate = function(line) { + return line.match(/^TAP version \d+$/) != null; + }; + var planPredicate = function(line) { + return line.match(/^1\.\.\d+$/) != null; + }; var testLinePredicate = function(line) { return line.match(/^not ok/) != null || line.match(/^ok/) != null; }; + var diagnosticPredicate = function(line) { + return line.match(/^#/) != null; + }; + var bailOutPredicate = function(line) { + return line.match(/^Bail out!/) != null; + }; + var anythingElsePredicate = function(line) { + return ( + versionPredicate(line) === false && + planPredicate(line) === false && + testLinePredicate(line) === false && + diagnosticPredicate(line) === false && + bailOutPredicate(line) === false + ); + }; describe('produces valid TAP v13 output', function() { var runFixtureAndValidateOutput = function(fixture, expected) { @@ -177,22 +203,20 @@ describe('reporters', function() { var outputLines = res.output.split('\n'); for (var i = 0; i + 1 < outputLines.length; i++) { - console.log('>', outputLines[i]); - console.log('\t', testLinePredicate(outputLines[i])); - console.log('\t', testLinePredicate(outputLines[i + 1])); if ( testLinePredicate(outputLines[i]) && testLinePredicate(outputLines[i + 1]) === false ) { var blockLinesStart = i + 1; var blockLinesEnd = - i + 1 + outputLines.slice(i + 1).findIndex(anythingElsePredicate); + i + + 1 + + outputLines.slice(i + 1).findIndex(not(anythingElsePredicate)); var blockLines = blockLinesEnd > blockLinesStart ? outputLines.slice(blockLinesStart, blockLinesEnd) : outputLines.slice(blockLinesStart); - console.log(i); - console.log(blockLines); + i += blockLines.length; } } From 8d369b7cd3ad82f549159aa0736f4f7ca45b8f62 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 13:59:54 +0200 Subject: [PATCH 09/31] stacks and errors are now wrapped inside YAML blocks --- lib/reporters/tap.js | 19 ++++++++++++++----- test/integration/reporters.spec.js | 5 ++++- test/reporters/tap.spec.js | 16 ++++++++++++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 1c7b55931a..2244f07a93 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -53,11 +53,20 @@ function TAP(runner) { runner.on('fail', function(test, err) { failures++; console.log('not ok %d %s', n, title(test)); - if (err.message) { - console.log(err.message.replace(/^/gm, ' ')); - } - if (err.stack) { - console.log(err.stack.replace(/^/gm, ' ')); + var emitYamlBlock = err.message != null || err.stack != null; + if (emitYamlBlock) { + console.log(' ---'); + if (err.message) { + console.log(' message: ' + err.message); + } + // stack needs to be last in yaml due to literal style indicator (|) + if (err.stack) { + console.log(' stack: |-'); + if (err.stack) { + console.log(err.stack.replace(/^/gm, ' ')); + } + } + console.log(' ...'); } }); diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index bb7063de78..89428478eb 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -202,6 +202,7 @@ describe('reporters', function() { } var outputLines = res.output.split('\n'); + for (var i = 0; i + 1 < outputLines.length; i++) { if ( testLinePredicate(outputLines[i]) && @@ -216,8 +217,10 @@ describe('reporters', function() { blockLinesEnd > blockLinesStart ? outputLines.slice(blockLinesStart, blockLinesEnd) : outputLines.slice(blockLinesStart); - i += blockLines.length; + + expect(blockLines[0], 'to match', /^\s+\-\-\-/); + expect(blockLines[blockLines.length - 1], 'to match', /^\s+\.\.\./); } } diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 71b29a386a..8845b6b891 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -121,7 +121,9 @@ describe('TAP reporter', function() { var expectedArray = [ 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedErrorMessage + '\n' + ' ---\n', + ' message: ' + expectedErrorMessage + '\n', + ' ...\n' ]; expect(stdout, 'to equal', expectedArray); }); @@ -148,7 +150,10 @@ describe('TAP reporter', function() { var expectedArray = [ 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedStack + '\n' + ' ---\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' ]; expect(stdout, 'to equal', expectedArray); }); @@ -185,8 +190,11 @@ describe('TAP reporter', function() { var expectedArray = [ 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedErrorMessage + '\n', - ' ' + expectedStack + '\n' + ' ---\n', + ' message: ' + expectedErrorMessage + '\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' ]; expect(stdout, 'to equal', expectedArray); }); From 96777440946bbd48c52e8c419ec4759a3bdb9816 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 14:04:33 +0200 Subject: [PATCH 10/31] changed arrow function to ye olde function to appease bots --- test/integration/reporters.spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 89428478eb..3f5efd3de6 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -156,7 +156,9 @@ describe('reporters', function() { // plan must appear once expect(outputLines, 'to contain', expectedPlan); expect( - outputLines.filter(l => l === expectedPlan), + outputLines.filter(function(l) { + return l === expectedPlan; + }), 'to have length', 1 ); From 30474417e8d90214da6eee168becf9e2a4a829f9 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 8 Aug 2018 15:24:54 +0200 Subject: [PATCH 11/31] found linter and made code conform, `npm run test` now clean. --- test/integration/reporters.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 3f5efd3de6..fc4967a854 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -221,7 +221,7 @@ describe('reporters', function() { : outputLines.slice(blockLinesStart); i += blockLines.length; - expect(blockLines[0], 'to match', /^\s+\-\-\-/); + expect(blockLines[0], 'to match', /^\s+---/); expect(blockLines[blockLines.length - 1], 'to match', /^\s+\.\.\./); } } From 253d76ac8fd6f5f7c21978a3e54559cd2e0b5dbf Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 08:25:32 +0200 Subject: [PATCH 12/31] added reporters.fixture.js for testing reporter capabilities --- .../integration/fixtures/reporters.fixture.js | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 test/integration/fixtures/reporters.fixture.js diff --git a/test/integration/fixtures/reporters.fixture.js b/test/integration/fixtures/reporters.fixture.js new file mode 100644 index 0000000000..ab16bc0eed --- /dev/null +++ b/test/integration/fixtures/reporters.fixture.js @@ -0,0 +1,63 @@ +'use strict'; + +/** + * This file generates a wide range of output to test reporter functionality. + */ + +describe('Animals', function() { + + it('should consume organic material', function(done) { done(); }); + it('should breathe oxygen', function(done) { + // we're a jellyfish + var actualBreathe = 'nothing'; + var expectedBreathe = 'oxygen'; + expect(actualBreathe, 'to equal', expectedBreathe); + done(); + }); + it('should be able to move', function(done) { done(); }); + it('should reproduce sexually', function(done) { done(); }); + it('should grow from a hollow sphere of cells', function(done) { done(); }); + + describe('Vertebrates', function() { + describe('Mammals', function() { + it('should give birth to live young', function(done) { + var expectedMammal = { + consumesMaterial: 'organic', + breathe: 'oxygen', + reproduction: { + type: 'sexually', + spawnType: 'live', + } + }; + var platypus = JSON.parse(JSON.stringify(expectedMammal)); + platypus['reproduction']['spawnType'] = 'hard-shelled egg'; + + expect(platypus, 'to equal', expectedMammal); + done(); + }); + + describe('Blue Whale', function() { + it('should be the largest of all mammals', function(done) { done(); }); + it('should have a body in some shade of blue', function(done) { + var bodyColor = 'blueish_grey'; + var shadesOfBlue = ['cyan', 'light_blue', 'blue', 'indigo']; + expect(bodyColor, 'to be one of', shadesOfBlue); + + done(); + }); + }); + }); + describe('Birds', function() { + it('should have feathers', function(done) { done(); }); + it('should lay hard-shelled eggs', function(done) { done(); }); + }); + }); + + describe('Tardigrades', function() { + it('should answer to "water bear"', function(done) { done(); }); + it('should be able to survive global mass extinction events', function(done) { + throw new Error("How do we even test for this without causing one?") + done(); + }); + }); +}); From e00b99cbc21b4f1b202b304bc460d65acf27f1c6 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 09:26:06 +0200 Subject: [PATCH 13/31] Fixed error message potentially breaking YAML block, some cleanup. err.message is now placed inside YAML block as a literal so that newline doesn't break any YAML parser. --- lib/reporters/tap.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 2244f07a93..512af6c26a 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -57,14 +57,12 @@ function TAP(runner) { if (emitYamlBlock) { console.log(' ---'); if (err.message) { - console.log(' message: ' + err.message); + console.log(' message: |-'); + console.log(err.message.replace(/^/gm, ' ')); } - // stack needs to be last in yaml due to literal style indicator (|) if (err.stack) { console.log(' stack: |-'); - if (err.stack) { - console.log(err.stack.replace(/^/gm, ' ')); - } + console.log(err.stack.replace(/^/gm, ' ')); } console.log(' ...'); } From 1e559b3c06192fd9d04a3cb0836ed538dd41dc9f Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 09:52:48 +0200 Subject: [PATCH 14/31] TAP now inherits from Base --- lib/reporters/tap.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 512af6c26a..c51ffc2c23 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -7,6 +7,7 @@ */ var Base = require('./base'); +var inherits = require('../utils').inherits; /** * Expose `TAP`. @@ -27,6 +28,7 @@ exports = module.exports = TAP; function TAP(runner) { Base.call(this, runner); + var self = this; var n = 1; var passes = 0; var failures = 0; @@ -75,6 +77,11 @@ function TAP(runner) { }); } +/** + * Inherit from `Base.prototype`. + */ +inherits(TAP, Base); + /** * Return a TAP-safe title of `test` * From 419fc3383e64e078e88e61b1226696408e2a8fbe Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 11:28:58 +0200 Subject: [PATCH 15/31] TAP no longer inherits from Base, decided not to use any Base functionality --- lib/reporters/tap.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index c51ffc2c23..512af6c26a 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -7,7 +7,6 @@ */ var Base = require('./base'); -var inherits = require('../utils').inherits; /** * Expose `TAP`. @@ -28,7 +27,6 @@ exports = module.exports = TAP; function TAP(runner) { Base.call(this, runner); - var self = this; var n = 1; var passes = 0; var failures = 0; @@ -77,11 +75,6 @@ function TAP(runner) { }); } -/** - * Inherit from `Base.prototype`. - */ -inherits(TAP, Base); - /** * Return a TAP-safe title of `test` * From 3551db32d6c88a132c9cab2fb38653360f97908d Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 11:34:40 +0200 Subject: [PATCH 16/31] TAP unit tests now expect message starting with literal --- test/reporters/tap.spec.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 8845b6b891..84d6c5a16b 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -122,7 +122,8 @@ describe('TAP reporter', function() { var expectedArray = [ 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', ' ---\n', - ' message: ' + expectedErrorMessage + '\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', ' ...\n' ]; expect(stdout, 'to equal', expectedArray); @@ -191,7 +192,8 @@ describe('TAP reporter', function() { var expectedArray = [ 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', ' ---\n', - ' message: ' + expectedErrorMessage + '\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', ' stack: |-\n', ' ' + expectedStack + '\n', ' ...\n' From 68d8b9cccd0942b1daeaf32c2c56344cdffbc56b Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 9 Aug 2018 11:35:50 +0200 Subject: [PATCH 17/31] TAP integration tests use reporters fixture instead of uncaught --- test/integration/reporters.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index fc4967a854..12c87fd5d2 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -190,14 +190,14 @@ describe('reporters', function() { runFixtureAndValidateOutput('passing.fixture.js', { numTests: 2 }); - runFixtureAndValidateOutput('uncaught.fixture.js', { - numTests: 2 + runFixtureAndValidateOutput('reporters.fixture.js', { + numTests: 12 }); }); it('places exceptions correctly in YAML blocks', function(done) { var args = ['--reporter=tap']; - run('uncaught.fixture.js', args, function(err, res) { + run('reporters.fixture.js', args, function(err, res) { if (err) { done(err); return; From 3b5f88f81e18eb352a58ac349a8e066a6683d4ea Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 19 Sep 2018 09:54:27 +0200 Subject: [PATCH 18/31] refactored yaml indentation to clean things up --- lib/reporters/tap.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 512af6c26a..51e6fa6a34 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -31,6 +31,10 @@ function TAP(runner) { var passes = 0; var failures = 0; + function yamlIndent(level) { + return Array(level + 1).join(' '); + } + runner.on('start', function() { console.log('TAP version 13'); var total = runner.grepTotal(runner.suite); @@ -55,16 +59,16 @@ function TAP(runner) { console.log('not ok %d %s', n, title(test)); var emitYamlBlock = err.message != null || err.stack != null; if (emitYamlBlock) { - console.log(' ---'); + console.log(yamlIndent(1), '---'); if (err.message) { - console.log(' message: |-'); - console.log(err.message.replace(/^/gm, ' ')); + console.log(yamlIndent(2), 'message: |-'); + console.log(err.message.replace(/^/gm, yamlIndent(3))); } if (err.stack) { - console.log(' stack: |-'); - console.log(err.stack.replace(/^/gm, ' ')); + console.log(yamlIndent(2), 'stack: |-'); + console.log(err.stack.replace(/^/gm, yamlIndent(3))); } - console.log(' ...'); + console.log(yamlIndent(1), '...'); } }); From 3cac7f1d4faca8c6944e3f7c405372c3179f999b Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 19 Sep 2018 10:17:58 +0200 Subject: [PATCH 19/31] fix to refactored indent which added an extra space on some lines --- lib/reporters/tap.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 51e6fa6a34..f2f419e121 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -59,16 +59,16 @@ function TAP(runner) { console.log('not ok %d %s', n, title(test)); var emitYamlBlock = err.message != null || err.stack != null; if (emitYamlBlock) { - console.log(yamlIndent(1), '---'); + console.log(yamlIndent(1) + '---'); if (err.message) { - console.log(yamlIndent(2), 'message: |-'); + console.log(yamlIndent(2) + 'message: |-'); console.log(err.message.replace(/^/gm, yamlIndent(3))); } if (err.stack) { - console.log(yamlIndent(2), 'stack: |-'); + console.log(yamlIndent(2) + 'stack: |-'); console.log(err.stack.replace(/^/gm, yamlIndent(3))); } - console.log(yamlIndent(1), '...'); + console.log(yamlIndent(1) + '...'); } }); From b5b88a1bbd577f1918760b8f6c67634da84236d7 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Wed, 19 Sep 2018 10:46:24 +0200 Subject: [PATCH 20/31] Retrigger appveyor test From ce24d96d04b1bf1f0eb38c6b4d4ff99b410fbd15 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 13:09:09 +0200 Subject: [PATCH 21/31] TAP reporter inherits Base --- lib/reporters/tap.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index f2f419e121..a2ce55fbcd 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -7,6 +7,7 @@ */ var Base = require('./base'); +var inherits = require('../utils').inherits; /** * Expose `TAP`. @@ -89,3 +90,8 @@ function TAP(runner) { function title(test) { return test.fullTitle().replace(/#/g, ''); } + +/** + * Inherit from `Base.prototype`. + */ +inherits(TAP, Base); From d5b519d2ecc39cb23dd905c1ccf309f4a872fb47 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 13:17:32 +0200 Subject: [PATCH 22/31] TAP reporter uses runner.stats rather than internal tracking --- lib/reporters/tap.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index a2ce55fbcd..907cc998df 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -29,8 +29,6 @@ function TAP(runner) { Base.call(this, runner); var n = 1; - var passes = 0; - var failures = 0; function yamlIndent(level) { return Array(level + 1).join(' '); @@ -51,12 +49,10 @@ function TAP(runner) { }); runner.on('pass', function(test) { - passes++; console.log('ok %d %s', n, title(test)); }); runner.on('fail', function(test, err) { - failures++; console.log('not ok %d %s', n, title(test)); var emitYamlBlock = err.message != null || err.stack != null; if (emitYamlBlock) { @@ -74,9 +70,9 @@ function TAP(runner) { }); runner.once('end', function() { - console.log('# tests ' + (passes + failures)); - console.log('# pass ' + passes); - console.log('# fail ' + failures); + console.log('# tests ' + (runner.stats.passes + runner.stats.failures)); + console.log('# pass ' + runner.stats.passes); + console.log('# fail ' + runner.stats.failures); }); } From 32424089e90c9669d5628f09956ef6c36a4104d1 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 13:59:50 +0200 Subject: [PATCH 23/31] added support for `spec` reporterOption and started implementing `TAP12Producer` and `TAP13Producer`. --- lib/reporters/tap.js | 35 +++- test/reporters/tap.spec.js | 372 ++++++++++++++++++++----------------- 2 files changed, 230 insertions(+), 177 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 907cc998df..b9c073830e 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -25,19 +25,31 @@ exports = module.exports = TAP; * @api public * @param {Runner} runner */ -function TAP(runner) { +function TAP(runner, options) { Base.call(this, runner); + var self = this; var n = 1; function yamlIndent(level) { return Array(level + 1).join(' '); } + var tapSpec = '12'; + if (options && options.reporterOptions) { + if (options.reporterOptions.spec) { + var tapSpec = options.reporterOptions.spec; + } + } + + if (tapSpec === '13') { + this.producer = new TAP13Producer(); + } else { + this.producer = new TAP12Producer(); + } + runner.on('start', function() { - console.log('TAP version 13'); - var total = runner.grepTotal(runner.suite); - console.log('%d..%d', 1, total); + self.producer.writeStart(runner); }); runner.on('test end', function() { @@ -91,3 +103,18 @@ function title(test) { * Inherit from `Base.prototype`. */ inherits(TAP, Base); + +function TAP12Producer() {} + +TAP12Producer.prototype.writeStart = function(runner) { + var total = runner.grepTotal(runner.suite); + console.log('%d..%d', 1, total); +}; + +function TAP13Producer() {} + +TAP13Producer.prototype.writeStart = function(runner) { + console.log('TAP version 13'); + var total = runner.grepTotal(runner.suite); + console.log('%d..%d', 1, total); +}; diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 84d6c5a16b..5d43268f1c 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -32,116 +32,60 @@ describe('TAP reporter', function() { process.stdout.write = stdoutWrite; }); - describe('on start', function() { - it('should hand runners suite into grepTotal and log the total', function() { - var expectedSuite = 'some suite'; - var expectedTotal = 10; - var expectedString; - runner = createMockRunner('start', 'start'); - runner.suite = expectedSuite; - runner.grepTotal = function(string) { - expectedString = string; - return expectedTotal; - }; - TAP.call({}, runner); - - var expectedSecondLine = '1..' + expectedTotal + '\n'; - process.stdout.write = stdoutWrite; - - expect(stdout[1], 'to equal', expectedSecondLine); - expect(expectedString, 'to be', expectedSuite); - }); - }); - - describe('on pending', function() { - it('should write expected message including count and title', function() { - runner = createMockRunner( - 'start test', - 'test end', - 'pending', - null, - test - ); - runner.suite = ''; - runner.grepTotal = function() {}; - TAP.call({}, runner); - - process.stdout.write = stdoutWrite; - - var expectedMessage = - 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; - expect(stdout[0], 'to equal', expectedMessage); - }); - }); - - describe('on pass', function() { - it('should write expected message including count and title', function() { - runner = createMockRunner('start test', 'test end', 'pass', null, test); - - runner.suite = ''; - runner.grepTotal = function() {}; - TAP.call({}, runner); + describe('TAP12 spec', function() { + describe('on start', function() { + it('should hand runners suite into grepTotal and log the total', function() { + var expectedSuite = 'some suite'; + var expectedTotal = 10; + var expectedString; + runner = createMockRunner('start', 'start'); + runner.suite = expectedSuite; + runner.grepTotal = function(string) { + expectedString = string; + return expectedTotal; + }; + TAP.call({}, runner); - process.stdout.write = stdoutWrite; + var expectedArray = ['1..' + expectedTotal + '\n']; + process.stdout.write = stdoutWrite; - var expectedMessage = - 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n'; - expect(stdout[0], 'to equal', expectedMessage); + expect(stdout, 'to equal', expectedArray); + expect(expectedString, 'to be', expectedSuite); + }); }); }); - describe('on fail', function() { - describe('if there is an error message', function() { - it('should write expected message and error message', function() { - var expectedTitle = 'some title'; - var countAfterTestEnd = 2; - var expectedErrorMessage = 'some error'; - var test = { - fullTitle: function() { - return expectedTitle; - }, - slow: function() {} - }; - var error = { - message: expectedErrorMessage + describe('TAP13 spec', function() { + var options = {reporterOptions: {spec: '13'}}; + describe('on start', function() { + it('should hand runners suite into grepTotal and log the total', function() { + var expectedSuite = 'some suite'; + var expectedTotal = 10; + var expectedString; + runner = createMockRunner('start', 'start'); + runner.suite = expectedSuite; + runner.grepTotal = function(string) { + expectedString = string; + return expectedTotal; }; - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } - if (event === 'fail') { - callback(test, error); - } - }; - runner.suite = ''; - runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); + var expectedSecondLine = '1..' + expectedTotal + '\n'; process.stdout.write = stdoutWrite; - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' message: |-\n', - ' ' + expectedErrorMessage + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + expect(stdout[1], 'to equal', expectedSecondLine); + expect(expectedString, 'to be', expectedSuite); }); }); - describe('if there is an error stack', function() { - it('should write expected message and stack', function() { - var expectedStack = 'some stack'; - var error = { - stack: expectedStack - }; + + describe('on pending', function() { + it('should write expected message including count and title', function() { runner = createMockRunner( - 'test end fail', + 'start test', 'test end', - 'fail', + 'pending', null, - test, - error + test ); runner.suite = ''; runner.grepTotal = function() {}; @@ -149,103 +93,185 @@ describe('TAP reporter', function() { process.stdout.write = stdoutWrite; - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' stack: |-\n', - ' ' + expectedStack + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; + expect(stdout[0], 'to equal', expectedMessage); }); }); - describe('if there is an error stack and error message', function() { - it('should write expected message and stack', function() { - var expectedTitle = 'some title'; - var countAfterTestEnd = 2; - var expectedStack = 'some stack'; - var expectedErrorMessage = 'some error'; - var test = { - fullTitle: function() { - return expectedTitle; - }, - slow: function() {} - }; - var error = { - stack: expectedStack, - message: expectedErrorMessage - }; - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } - if (event === 'fail') { - callback(test, error); - } - }; + + describe('on pass', function() { + it('should write expected message including count and title', function() { + runner = createMockRunner('start test', 'test end', 'pass', null, test); + runner.suite = ''; runner.grepTotal = function() {}; TAP.call({}, runner); process.stdout.write = stdoutWrite; - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' message: |-\n', - ' ' + expectedErrorMessage + '\n', - ' stack: |-\n', - ' ' + expectedStack + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n'; + expect(stdout[0], 'to equal', expectedMessage); }); }); - describe('if there is no error stack or error message', function() { - it('should write expected message only', function() { - var error = {}; - runner.on = runner.once = function(event, callback) { - if (event === 'test end') { - callback(); - } - if (event === 'fail') { - callback(test, error); - } - }; + + describe('on fail', function() { + describe('if there is an error message', function() { + it('should write expected message and error message', function() { + var expectedTitle = 'some title'; + var countAfterTestEnd = 2; + var expectedErrorMessage = 'some error'; + var test = { + fullTitle: function() { + return expectedTitle; + }, + slow: function() {} + }; + var error = { + message: expectedErrorMessage + }; + runner.on = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + describe('if there is an error stack', function() { + it('should write expected message and stack', function() { + var expectedStack = 'some stack'; + var error = { + stack: expectedStack + }; + runner = createMockRunner( + 'test end fail', + 'test end', + 'fail', + null, + test, + error + ); + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + describe('if there is an error stack and error message', function() { + it('should write expected message and stack', function() { + var expectedTitle = 'some title'; + var countAfterTestEnd = 2; + var expectedStack = 'some stack'; + var expectedErrorMessage = 'some error'; + var test = { + fullTitle: function() { + return expectedTitle; + }, + slow: function() {} + }; + var error = { + stack: expectedStack, + message: expectedErrorMessage + }; + runner.on = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + describe('if there is no error stack or error message', function() { + it('should write expected message only', function() { + var error = {}; + runner.on = runner.once = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + }); + + describe('on end', function() { + it('should write total tests, passes and failures', function() { + var numberOfPasses = 1; + var numberOfFails = 1; + runner = createMockRunner('fail end pass', 'fail', 'end', 'pass', test); runner.suite = ''; runner.grepTotal = function() {}; TAP.call({}, runner); process.stdout.write = stdoutWrite; + var totalTests = numberOfPasses + numberOfFails; var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n' + 'ok ' + numberOfPasses + ' ' + expectedTitle + '\n', + 'not ok ' + numberOfFails + ' ' + expectedTitle + '\n', + '# tests ' + totalTests + '\n', + '# pass ' + numberOfPasses + '\n', + '# fail ' + numberOfFails + '\n' ]; expect(stdout, 'to equal', expectedArray); }); }); }); - - describe('on end', function() { - it('should write total tests, passes and failures', function() { - var numberOfPasses = 1; - var numberOfFails = 1; - runner = createMockRunner('fail end pass', 'fail', 'end', 'pass', test); - runner.suite = ''; - runner.grepTotal = function() {}; - TAP.call({}, runner); - - process.stdout.write = stdoutWrite; - - var totalTests = numberOfPasses + numberOfFails; - var expectedArray = [ - 'ok ' + numberOfPasses + ' ' + expectedTitle + '\n', - 'not ok ' + numberOfFails + ' ' + expectedTitle + '\n', - '# tests ' + totalTests + '\n', - '# pass ' + numberOfPasses + '\n', - '# fail ' + numberOfFails + '\n' - ]; - expect(stdout, 'to equal', expectedArray); - }); - }); }); From 61e8c799fea79dfcc71221a036d988b2301e2c5d Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 14:15:13 +0200 Subject: [PATCH 24/31] TAP13 tests now run with proper spec selected --- test/reporters/tap.spec.js | 117 ++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 7 deletions(-) diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index 5d43268f1c..b292f9806a 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -53,6 +53,109 @@ describe('TAP reporter', function() { expect(expectedString, 'to be', expectedSuite); }); }); + + describe('on fail', function() { + describe('if there is an error message', function() { + it('should write expected message and error message', function() { + var expectedTitle = 'some title'; + var countAfterTestEnd = 2; + var expectedErrorMessage = 'some error'; + var test = { + fullTitle: function() { + return expectedTitle; + }, + slow: function() {} + }; + var error = { + message: expectedErrorMessage + }; + runner.on = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedErrorMessage + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + describe('if there is an error stack', function() { + it('should write expected message and stack', function() { + var expectedStack = 'some stack'; + var error = { + stack: expectedStack + }; + runner = createMockRunner( + 'test end fail', + 'test end', + 'fail', + null, + test, + error + ); + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedStack + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + describe('if there is an error stack and error message', function() { + it('should write expected message and stack', function() { + var expectedTitle = 'some title'; + var countAfterTestEnd = 2; + var expectedStack = 'some stack'; + var expectedErrorMessage = 'some error'; + var test = { + fullTitle: function() { + return expectedTitle; + }, + slow: function() {} + }; + var error = { + stack: expectedStack, + message: expectedErrorMessage + }; + runner.on = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedErrorMessage + '\n', + ' ' + expectedStack + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + }); }); describe('TAP13 spec', function() { @@ -89,7 +192,7 @@ describe('TAP reporter', function() { ); runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -105,7 +208,7 @@ describe('TAP reporter', function() { runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -140,7 +243,7 @@ describe('TAP reporter', function() { }; runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -170,7 +273,7 @@ describe('TAP reporter', function() { ); runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -210,7 +313,7 @@ describe('TAP reporter', function() { }; runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -239,7 +342,7 @@ describe('TAP reporter', function() { }; runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; @@ -258,7 +361,7 @@ describe('TAP reporter', function() { runner = createMockRunner('fail end pass', 'fail', 'end', 'pass', test); runner.suite = ''; runner.grepTotal = function() {}; - TAP.call({}, runner); + TAP.call({}, runner, options); process.stdout.write = stdoutWrite; From 8dc5b6589396ecea408cd111b5dd9f414cf9b796 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 14:16:45 +0200 Subject: [PATCH 25/31] extracted fail reporting to producers --- lib/reporters/tap.js | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index b9c073830e..7331d8216f 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -31,10 +31,6 @@ function TAP(runner, options) { var self = this; var n = 1; - function yamlIndent(level) { - return Array(level + 1).join(' '); - } - var tapSpec = '12'; if (options && options.reporterOptions) { if (options.reporterOptions.spec) { @@ -65,20 +61,7 @@ function TAP(runner, options) { }); runner.on('fail', function(test, err) { - console.log('not ok %d %s', n, title(test)); - var emitYamlBlock = err.message != null || err.stack != null; - if (emitYamlBlock) { - console.log(yamlIndent(1) + '---'); - if (err.message) { - console.log(yamlIndent(2) + 'message: |-'); - console.log(err.message.replace(/^/gm, yamlIndent(3))); - } - if (err.stack) { - console.log(yamlIndent(2) + 'stack: |-'); - console.log(err.stack.replace(/^/gm, yamlIndent(3))); - } - console.log(yamlIndent(1) + '...'); - } + self.producer.writeFail(n, test, err); }); runner.once('end', function() { @@ -111,10 +94,41 @@ TAP12Producer.prototype.writeStart = function(runner) { console.log('%d..%d', 1, total); }; +TAP12Producer.prototype.writeFail = function(n, test, err) { + console.log('not ok %d %s', n, title(test)); + if (err.message) { + console.log(err.message.replace(/^/gm, ' ')); + } + if (err.stack) { + console.log(err.stack.replace(/^/gm, ' ')); + } +}; + function TAP13Producer() {} +TAP13Producer.prototype.yamlIndent = function(level) { + return Array(level + 1).join(' '); +}; + TAP13Producer.prototype.writeStart = function(runner) { console.log('TAP version 13'); var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }; + +TAP13Producer.prototype.writeFail = function(n, test, err) { + console.log('not ok %d %s', n, title(test)); + var emitYamlBlock = err.message != null || err.stack != null; + if (emitYamlBlock) { + console.log(this.yamlIndent(1) + '---'); + if (err.message) { + console.log(this.yamlIndent(2) + 'message: |-'); + console.log(err.message.replace(/^/gm, this.yamlIndent(3))); + } + if (err.stack) { + console.log(this.yamlIndent(2) + 'stack: |-'); + console.log(err.stack.replace(/^/gm, this.yamlIndent(3))); + } + console.log(this.yamlIndent(1) + '...'); + } +}; From 4b11a319436732d12e05aae8b6ace6be69440249 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 14:25:04 +0200 Subject: [PATCH 26/31] added missing tests to TAP12 spec which are identical to TAP13 expectations --- test/reporters/tap.spec.js | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index b292f9806a..ef72ee0c26 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -54,6 +54,43 @@ describe('TAP reporter', function() { }); }); + describe('on pending', function() { + it('should write expected message including count and title', function() { + runner = createMockRunner( + 'start test', + 'test end', + 'pending', + null, + test + ); + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; + expect(stdout[0], 'to equal', expectedMessage); + }); + }); + + describe('on pass', function() { + it('should write expected message including count and title', function() { + runner = createMockRunner('start test', 'test end', 'pass', null, test); + + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n'; + expect(stdout[0], 'to equal', expectedMessage); + }); + }); + describe('on fail', function() { describe('if there is an error message', function() { it('should write expected message and error message', function() { @@ -155,6 +192,51 @@ describe('TAP reporter', function() { expect(stdout, 'to equal', expectedArray); }); }); + describe('if there is no error stack or error message', function() { + it('should write expected message only', function() { + var error = {}; + runner.on = runner.once = function(event, callback) { + if (event === 'test end') { + callback(); + } + if (event === 'fail') { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + }); + describe('on end', function() { + it('should write total tests, passes and failures', function() { + var numberOfPasses = 1; + var numberOfFails = 1; + runner = createMockRunner('fail end pass', 'fail', 'end', 'pass', test); + runner.suite = ''; + runner.grepTotal = function() {}; + TAP.call({}, runner); + + process.stdout.write = stdoutWrite; + + var totalTests = numberOfPasses + numberOfFails; + var expectedArray = [ + 'ok ' + numberOfPasses + ' ' + expectedTitle + '\n', + 'not ok ' + numberOfFails + ' ' + expectedTitle + '\n', + '# tests ' + totalTests + '\n', + '# pass ' + numberOfPasses + '\n', + '# fail ' + numberOfFails + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); }); }); From 38b8ce3d16841bfce4edc75f8199874a510999a0 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 14:27:01 +0200 Subject: [PATCH 27/31] extracted pending reporting to producers --- lib/reporters/tap.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 7331d8216f..c88cbb12d8 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -53,7 +53,7 @@ function TAP(runner, options) { }); runner.on('pending', function(test) { - console.log('ok %d %s # SKIP -', n, title(test)); + self.producer.writePending(n, test); }); runner.on('pass', function(test) { @@ -104,6 +104,10 @@ TAP12Producer.prototype.writeFail = function(n, test, err) { } }; +TAP12Producer.prototype.writePending = function(n, test) { + console.log('ok %d %s # SKIP -', n, title(test)); +}; + function TAP13Producer() {} TAP13Producer.prototype.yamlIndent = function(level) { @@ -132,3 +136,7 @@ TAP13Producer.prototype.writeFail = function(n, test, err) { console.log(this.yamlIndent(1) + '...'); } }; + +TAP13Producer.prototype.writePending = function(n, test) { + console.log('ok %d %s # SKIP -', n, title(test)); +}; From 7951bf07165c7494e28058d734eb4b02de7b98f9 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 16:16:06 +0200 Subject: [PATCH 28/31] extracted pass reporting to producers --- lib/reporters/tap.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index c88cbb12d8..de844d3839 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -57,7 +57,7 @@ function TAP(runner, options) { }); runner.on('pass', function(test) { - console.log('ok %d %s', n, title(test)); + self.producer.writePass(n, test); }); runner.on('fail', function(test, err) { @@ -108,6 +108,10 @@ TAP12Producer.prototype.writePending = function(n, test) { console.log('ok %d %s # SKIP -', n, title(test)); }; +TAP12Producer.prototype.writePass = function(n, test) { + console.log('ok %d %s', n, title(test)); +}; + function TAP13Producer() {} TAP13Producer.prototype.yamlIndent = function(level) { @@ -140,3 +144,7 @@ TAP13Producer.prototype.writeFail = function(n, test, err) { TAP13Producer.prototype.writePending = function(n, test) { console.log('ok %d %s # SKIP -', n, title(test)); }; + +TAP13Producer.prototype.writePass = function(n, test) { + console.log('ok %d %s', n, title(test)); +}; From ff80cf4b5e29018086abe3e9fa8297e2aeb3fccf Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 16:30:47 +0200 Subject: [PATCH 29/31] extracted end reporting to producers and refactored to common base --- lib/reporters/tap.js | 57 +++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index de844d3839..93da27dcdf 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -65,9 +65,7 @@ function TAP(runner, options) { }); runner.once('end', function() { - console.log('# tests ' + (runner.stats.passes + runner.stats.failures)); - console.log('# pass ' + runner.stats.passes); - console.log('# fail ' + runner.stats.failures); + self.producer.writeEnd(runner); }); } @@ -87,6 +85,36 @@ function title(test) { */ inherits(TAP, Base); +/** + * Initialize a new `TAPProducer`. Should only be used as a base class. + * + * @private + * @class + * @api private + */ +function TAPProducer() {} + +TAPProducer.prototype.writePending = function(n, test) { + console.log('ok %d %s # SKIP -', n, title(test)); +}; + +TAPProducer.prototype.writePass = function(n, test) { + console.log('ok %d %s', n, title(test)); +}; + +TAPProducer.prototype.writeEnd = function(runner) { + console.log('# tests ' + (runner.stats.passes + runner.stats.failures)); + console.log('# pass ' + runner.stats.passes); + console.log('# fail ' + runner.stats.failures); +}; + +/** + * Initialize a new `TAP12Producer` which will produce output conforming to the TAP12 spec. + * + * @private + * @class + * @api private + */ function TAP12Producer() {} TAP12Producer.prototype.writeStart = function(runner) { @@ -104,14 +132,15 @@ TAP12Producer.prototype.writeFail = function(n, test, err) { } }; -TAP12Producer.prototype.writePending = function(n, test) { - console.log('ok %d %s # SKIP -', n, title(test)); -}; - -TAP12Producer.prototype.writePass = function(n, test) { - console.log('ok %d %s', n, title(test)); -}; +inherits(TAP12Producer, TAPProducer); +/** + * Initialize a new `TAP13Producer` which will produce output conforming to the TAP13 spec. + * + * @private + * @class + * @api private + */ function TAP13Producer() {} TAP13Producer.prototype.yamlIndent = function(level) { @@ -141,10 +170,4 @@ TAP13Producer.prototype.writeFail = function(n, test, err) { } }; -TAP13Producer.prototype.writePending = function(n, test) { - console.log('ok %d %s # SKIP -', n, title(test)); -}; - -TAP13Producer.prototype.writePass = function(n, test) { - console.log('ok %d %s', n, title(test)); -}; +inherits(TAP13Producer, TAPProducer); From 0496ef348bd53dd9569f91c1e366e91cda046269 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 16:34:33 +0200 Subject: [PATCH 30/31] fixed bad redeclare --- lib/reporters/tap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reporters/tap.js b/lib/reporters/tap.js index 93da27dcdf..e8ec3aa3dd 100644 --- a/lib/reporters/tap.js +++ b/lib/reporters/tap.js @@ -34,7 +34,7 @@ function TAP(runner, options) { var tapSpec = '12'; if (options && options.reporterOptions) { if (options.reporterOptions.spec) { - var tapSpec = options.reporterOptions.spec; + tapSpec = options.reporterOptions.spec; } } From 42035e737af1ae1532db20538023bdef89ab2d04 Mon Sep 17 00:00:00 2001 From: Tobias Mollstam Date: Thu, 20 Sep 2018 16:44:02 +0200 Subject: [PATCH 31/31] fix to integrations tests to use TAP13 spec --- test/integration/reporters.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/reporters.spec.js b/test/integration/reporters.spec.js index 12c87fd5d2..cd6910f7df 100644 --- a/test/integration/reporters.spec.js +++ b/test/integration/reporters.spec.js @@ -134,7 +134,7 @@ describe('reporters', function() { describe('produces valid TAP v13 output', function() { var runFixtureAndValidateOutput = function(fixture, expected) { it('for ' + fixture, function(done) { - var args = ['--reporter=tap']; + var args = ['--reporter=tap', '--reporter-options', 'spec=13']; run(fixture, args, function(err, res) { if (err) { done(err); @@ -196,7 +196,7 @@ describe('reporters', function() { }); it('places exceptions correctly in YAML blocks', function(done) { - var args = ['--reporter=tap']; + var args = ['--reporter=tap', '--reporter-options', 'spec=13']; run('reporters.fixture.js', args, function(err, res) { if (err) { done(err);