From ef69b73941a54456e0551893ac2e686cd5ee47b6 Mon Sep 17 00:00:00 2001 From: "P. Roebuck" Date: Tue, 30 Apr 2019 14:22:22 -0500 Subject: [PATCH] Rework reporter tests (#3892) Reworked stubs to use "sinon" package. Added logic to (hopefully) rethrow errors when stdout stubbed. Tests now use event constants. Noise reduction. Various mods for consistency. Now green across the board. --- test/reporters/base.spec.js | 258 +++++---- test/reporters/doc.spec.js | 358 +++++++----- test/reporters/dot.spec.js | 319 +++++++---- test/reporters/helpers.js | 69 ++- test/reporters/json-stream.spec.js | 204 +++---- test/reporters/json.spec.js | 26 +- test/reporters/landing.spec.js | 142 +++-- test/reporters/list.spec.js | 318 +++++++---- test/reporters/markdown.spec.js | 177 +++--- test/reporters/min.spec.js | 66 +-- test/reporters/nyan.spec.js | 597 ++++++++++++-------- test/reporters/progress.spec.js | 168 +++--- test/reporters/spec.spec.js | 215 +++++--- test/reporters/tap.spec.js | 858 ++++++++++++++++------------- test/reporters/xunit.spec.js | 546 ++++++++++-------- 15 files changed, 2528 insertions(+), 1793 deletions(-) diff --git a/test/reporters/base.spec.js b/test/reporters/base.spec.js index 40d1374537..739063f32a 100644 --- a/test/reporters/base.spec.js +++ b/test/reporters/base.spec.js @@ -1,124 +1,138 @@ 'use strict'; var assert = require('assert'); -var chaiExpect = require('chai').expect; -var Base = require('../../lib/reporters/base'); +var chai = require('chai'); +var sinon = require('sinon'); +var helpers = require('./helpers'); +var reporters = require('../../').reporters; + var AssertionError = assert.AssertionError; -var makeTest = require('./helpers').makeTest; -var createElements = require('./helpers').createElements; +var Base = reporters.Base; +var chaiExpect = chai.expect; +var createElements = helpers.createElements; +var makeTest = helpers.makeTest; describe('Base reporter', function() { + var sandbox; var stdout; - var stdoutWrite; - var useColors; - var err; - var errOut; - var test; function list(tests) { - Base.useColors = false; - var retval = Base.list(tests); - Base.useColors = useColors; - return retval; + try { + try { + Base.list(tests); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } } function generateDiff(actual, expected) { - Base.useColors = false; - var retval = Base.generateDiff(actual, expected); - Base.useColors = useColors; - return retval; + var diffStr; + + try { + try { + diffStr = Base.generateDiff(actual, expected); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } + + return diffStr; } + var gather = function(chunk, encoding, cb) { + stdout.push(chunk); + }; + beforeEach(function() { - useColors = Base.useColors; + sandbox = sinon.createSandbox(); + sandbox.stub(Base, 'useColors').value(false); + sandbox.stub(process.stdout, 'write').callsFake(gather); stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - stdoutWrite.call(process.stdout, string, enc, callback); - }; }); afterEach(function() { - process.stdout.write = stdoutWrite; + sandbox.restore(); }); describe('showDiff', function() { + var err; + beforeEach(function() { err = new AssertionError({actual: 'foo', expected: 'bar'}); }); it('should show diffs by default', function() { - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /- actual/); expect(errOut, 'to match', /\+ expected/); }); - it('should show diffs if property set to `true`', function() { + it("should show diffs if 'err.showDiff' is true", function() { err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /- actual/); expect(errOut, 'to match', /\+ expected/); }); - it('should not show diffs when showDiff property set to `false`', function() { + it("should not show diffs if 'err.showDiff' is false", function() { err.showDiff = false; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'not to match', /- actual/); expect(errOut, 'not to match', /\+ expected/); }); - it('should not show diffs when expected is not defined', function() { - err = new Error('ouch'); - - test = makeTest(err); + it("should not show diffs if 'expected' is not defined", function() { + var _err = new Error('ouch'); + var test = makeTest(_err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'not to match', /- actual/); expect(errOut, 'not to match', /\+ expected/); }); - it('should not show diffs when hideDiff is set', function() { - test = makeTest(err); + it("should not show diffs if 'hideDiff' is true", function() { + var test = makeTest(err); - Base.hideDiff = true; + sandbox.stub(Base, 'hideDiff').value(true); list([test]); - Base.hideDiff = false; // Revert to original value - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'not to match', /- actual/); expect(errOut, 'not to match', /\+ expected/); }); }); - describe('Getting two strings', function() { + describe('getting two strings', function() { // Fix regression V1.2.1(see: issue #1241) it('should show strings diff as is', function() { - err = new Error('test'); - + var err = new Error('test'); err.actual = 'foo\nbar'; err.expected = 'foo\nbaz'; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); - + var errOut = stdout.join('\n'); expect(errOut, 'not to match', /"foo\\nbar"/); expect(errOut, 'to match', /foo/).and('to match', /bar/); expect(errOut, 'to match', /test/); @@ -127,26 +141,19 @@ describe('Base reporter', function() { }); }); - describe('Diff generation', function() { - var oldInlineDiffs; - var actual; - var expected; - var output; + describe('diff generation', function() { + var inlineDiffsStub; beforeEach(function() { - oldInlineDiffs = Base.inlineDiffs; - }); - - afterEach(function() { - Base.inlineDiffs = oldInlineDiffs; + inlineDiffsStub = sandbox.stub(Base, 'inlineDiffs'); }); - it('should generate unified diffs if `inlineDiff === false`', function() { - actual = 'a foo unified diff'; - expected = 'a bar unified diff'; + it("should generate unified diffs if 'inlineDiffs' is false", function() { + var actual = 'a foo unified diff'; + var expected = 'a bar unified diff'; - Base.inlineDiffs = false; - output = generateDiff(actual, expected); + inlineDiffsStub.value(false); + var output = generateDiff(actual, expected); expect( output, @@ -155,12 +162,12 @@ describe('Base reporter', function() { ); }); - it('should generate inline diffs if `inlineDiffs === true`', function() { - actual = 'a foo inline diff'; - expected = 'a bar inline diff'; + it("should generate inline diffs if 'inlineDiffs' is true", function() { + var actual = 'a foo inline diff'; + var expected = 'a bar inline diff'; - Base.inlineDiffs = true; - output = generateDiff(actual, expected); + inlineDiffsStub.value(true); + var output = generateDiff(actual, expected); expect( output, @@ -170,39 +177,37 @@ describe('Base reporter', function() { }); }); - describe('Inline strings diff', function() { - it('should show single line diff if property set to `true`', function() { - err = new Error('test'); + describe('inline strings diff', function() { + beforeEach(function() { + sandbox.stub(Base, 'inlineDiffs').value(true); + }); + it("should show single line diff if 'inlineDiffs' is true", function() { + var err = new Error('test'); err.actual = 'a foo inline diff'; err.expected = 'a bar inline diff'; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); - Base.inlineDiffs = true; list([test]); - errOut = stdout.join('\n'); - + var errOut = stdout.join('\n'); expect(errOut, 'to match', /a foobar inline diff/); expect(errOut, 'to match', /test/); expect(errOut, 'to match', /actual/); expect(errOut, 'to match', /expected/); }); - it('should split lines when string has more than 4 line breaks', function() { - err = new Error('test'); - + it('should split lines if string has more than 4 line breaks', function() { + var err = new Error('test'); err.actual = 'a\nfoo\ninline\ndiff\nwith\nmultiple lines'; err.expected = 'a\nbar\ninline\ndiff\nwith\nmultiple lines'; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); - Base.inlineDiffs = true; list([test]); - errOut = stdout.join('\n'); - + var errOut = stdout.join('\n'); expect(errOut, 'to match', /1 \| a/); expect(errOut, 'to match', /2 \| foobar/); expect(errOut, 'to match', /3 \| inline/); @@ -215,21 +220,21 @@ describe('Base reporter', function() { }); }); - describe('unified diff reporter', function() { + describe('unified diff', function() { beforeEach(function() { - err = new Error('test'); + sandbox.stub(Base, 'inlineDiffs').value(false); }); it('should separate diff hunks by two dashes', function() { + var err = new Error('test'); err.actual = createElements({from: 2, to: 11}); err.expected = createElements({from: 1, to: 10}); err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); - Base.inlineDiffs = false; list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); var regexesToMatch = [ /\[/, @@ -257,16 +262,15 @@ describe('Base reporter', function() { }); it('should stringify objects', function() { - err = new Error('test'); - + var err = new Error('test'); err.actual = {key: 'a1'}; err.expected = {key: 'e1'}; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /"key"/); expect(errOut, 'to match', /test/); expect(errOut, 'to match', /- actual/); @@ -274,18 +278,18 @@ describe('Base reporter', function() { }); it('should stringify Object.create(null)', function() { - err = new Error('test'); + var err = new Error('test'); err.actual = Object.create(null); err.actual.hasOwnProperty = 1; err.expected = Object.create(null); err.expected.hasOwnProperty = 2; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /"hasOwnProperty"/); expect(errOut, 'to match', /test/); expect(errOut, 'to match', /- actual/); @@ -299,11 +303,11 @@ describe('Base reporter', function() { err.actual = false; err.expected = true; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /\+true/); expect(errOut, 'to match', /-false/); expect(errOut, 'to match', /- actual/); @@ -311,18 +315,21 @@ describe('Base reporter', function() { } }); - it('should interpret Chai custom error messages', function() { + it("should interpret 'chai' module custom error messages", function() { + var actual = 43; + var expected = 42; + try { - chaiExpect(43, 'custom error message').to.equal(42); + chaiExpect(actual, 'custom error message').to.equal(expected); } catch (err) { - err.actual = 43; - err.expected = 42; + err.actual = actual; + err.expected = expected; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /custom error message\n/) .and('to match', /\+42/) .and('to match', /-43/) @@ -331,20 +338,23 @@ describe('Base reporter', function() { } }); - it('should interpret assert module custom error messages', function() { + it("should interpret 'assert' module custom error messages", function() { + var actual = 43; + var expected = 42; + try { - assert.strictEqual(43, 42, 'custom error message'); + assert.strictEqual(actual, expected, 'custom error message'); // AssertionError: custom error message: expected 43 to equal 42. // assert.equal(43, 42, 'custom error message: expected 43 to equal 42.'); } catch (err) { - err.actual = 43; - err.expected = 42; + err.actual = actual; + err.expected = expected; err.showDiff = true; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n'); + var errOut = stdout.join('\n'); expect(errOut, 'to match', /custom error message\n/); expect(errOut, 'to match', /\+42/); expect(errOut, 'to match', /-43/); @@ -354,53 +364,57 @@ describe('Base reporter', function() { }); it('should remove message from stack', function() { - err = { + var err = { message: 'Error', stack: 'Error\nfoo\nbar', showDiff: false }; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n').trim(); + var errOut = stdout.join('\n').trim(); expect(errOut, 'to be', '1) test title:\n Error\n foo\n bar'); }); - it('should use the inspect() property if `message` is not set', function() { - err = { + it("should use 'inspect' if 'message' is not set", function() { + var err = { showDiff: false, inspect: function() { return 'an error happened'; } }; - test = makeTest(err); + var test = makeTest(err); + list([test]); - errOut = stdout.join('\n').trim(); + + var errOut = stdout.join('\n').trim(); expect(errOut, 'to be', '1) test title:\n an error happened'); }); - it('should set an empty message if `message` and `inspect()` are not set', function() { - err = { + it("should set an empty message if neither 'message' nor 'inspect' is set", function() { + var err = { showDiff: false }; - test = makeTest(err); + var test = makeTest(err); + list([test]); - errOut = stdout.join('\n').trim(); + + var errOut = stdout.join('\n').trim(); expect(errOut, 'to be', '1) test title:'); }); it('should not modify stack if it does not contain message', function() { - err = { + var err = { message: 'Error', stack: 'foo\nbar', showDiff: false }; - test = makeTest(err); + var test = makeTest(err); list([test]); - errOut = stdout.join('\n').trim(); + var errOut = stdout.join('\n').trim(); expect(errOut, 'to be', '1) test title:\n Error\n foo\n bar'); }); }); diff --git a/test/reporters/doc.spec.js b/test/reporters/doc.spec.js index 857922b83e..fb2703f83c 100644 --- a/test/reporters/doc.spec.js +++ b/test/reporters/doc.spec.js @@ -1,10 +1,17 @@ 'use strict'; +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; + var Doc = reporters.Doc; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers.js').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_SUITE_BEGIN = events.EVENT_SUITE_BEGIN; +var EVENT_SUITE_END = events.EVENT_SUITE_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; describe('Doc reporter', function() { var runner; @@ -12,178 +19,223 @@ describe('Doc reporter', function() { var runReporter = makeRunReporter(Doc); afterEach(function() { - runner = undefined; + runner = null; }); - describe('on suite', function() { - describe('if suite root does not exist', function() { - var expectedTitle = 'expectedTitle'; - var unescapedTitle = '
' + expectedTitle + '
'; - var suite = { - root: false, - title: expectedTitle + describe('event handlers', function() { + describe("on 'suite' event", function() { + describe('when suite root does not exist', function() { + var expectedTitle = 'expectedTitle'; + var unescapedTitle = '
' + expectedTitle + '
'; + var suite = { + root: false, + title: expectedTitle + }; + + it('should log html with indents and expected title', function() { + runner = createMockRunner( + 'suite', + EVENT_SUITE_BEGIN, + null, + null, + suite + ); + var stdout = runReporter(this, runner, options); + var expectedArray = [ + '
\n', + '

' + expectedTitle + '

\n', + '
\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + + it('should escape title where necessary', function() { + var suite = { + root: false, + title: unescapedTitle + }; + expectedTitle = + '<div>' + expectedTitle + '</div>'; + + runner = createMockRunner( + 'suite', + EVENT_SUITE_BEGIN, + null, + null, + suite + ); + var stdout = runReporter(this, runner, options); + var expectedArray = [ + '
\n', + '

' + expectedTitle + '

\n', + '
\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe('when suite root exists', function() { + var suite = { + root: true + }; + + it('should not log any html', function() { + runner = createMockRunner( + 'suite', + EVENT_SUITE_BEGIN, + null, + null, + suite + ); + var stdout = runReporter(this, runner, options); + expect(stdout, 'to be empty'); + }); + }); + }); + + describe("on 'suite end' event", function() { + describe('when suite root does not exist', function() { + var suite = { + root: false + }; + + it('should log expected html with indents', function() { + runner = createMockRunner( + 'suite end', + EVENT_SUITE_END, + null, + null, + suite + ); + var stdout = runReporter(this, runner, options); + var expectedArray = ['
\n', '
\n']; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe('when suite root exists', function() { + var suite = { + root: true + }; + + it('should not log any html', function() { + runner = createMockRunner( + 'suite end', + EVENT_SUITE_END, + null, + null, + suite + ); + var stdout = runReporter(this, runner, options); + expect(stdout, 'to be empty'); + }); + }); + }); + + describe("on 'pass' event", function() { + var expectedTitle = 'some tite'; + var expectedBody = 'some body'; + var test = { + title: expectedTitle, + body: expectedBody, + slow: function() { + return ''; + } }; - it('should log html with indents and expected title', function() { - runner = createMockRunner('suite', 'suite', null, null, suite); + + it('should log html with indents, expected title, and body', function() { + runner = createMockRunner('pass', EVENT_TEST_PASS, null, null, test); var stdout = runReporter(this, runner, options); var expectedArray = [ - '
\n', - '

' + expectedTitle + '

\n', - '
\n' + '
' + expectedTitle + '
\n', + '
' + expectedBody + '
\n' ]; expect(stdout, 'to equal', expectedArray); }); - it('should escape title where necessary', function() { - var suite = { - root: false, - title: unescapedTitle - }; - expectedTitle = '<div>' + expectedTitle + '</div>'; - runner = createMockRunner('suite', 'suite', null, null, suite); + + it('should escape title and body where necessary', function() { + var unescapedTitle = '
' + expectedTitle + '
'; + var unescapedBody = '
' + expectedBody + '
'; + test.title = unescapedTitle; + test.body = unescapedBody; + + var expectedEscapedTitle = + '<div>' + expectedTitle + '</div>'; + var expectedEscapedBody = + '<div>' + expectedBody + '</div>'; + runner = createMockRunner('pass', EVENT_TEST_PASS, null, null, test); var stdout = runReporter(this, runner, options); var expectedArray = [ - '
\n', - '

' + expectedTitle + '

\n', - '
\n' + '
' + expectedEscapedTitle + '
\n', + '
' + expectedEscapedBody + '
\n' ]; expect(stdout, 'to equal', expectedArray); }); }); - describe('if suite root does exist', function() { - var suite = { - root: true - }; - it('should not log any html', function() { - runner = createMockRunner('suite', 'suite', null, null, suite); - var stdout = runReporter(this, runner, options); - expect(stdout, 'to be empty'); - }); - }); - }); - describe('on suite end', function() { - describe('if suite root does not exist', function() { - var suite = { - root: false + describe("on 'fail' event", function() { + var expectedTitle = 'some tite'; + var expectedBody = 'some body'; + var expectedError = 'some error'; + var test = { + title: expectedTitle, + body: expectedBody, + slow: function() { + return ''; + } }; - it('should log expected html with indents', function() { - runner = createMockRunner('suite end', 'suite end', null, null, suite); + + it('should log html with indents, expected title, body, and error', function() { + runner = createMockRunner( + 'fail two args', + EVENT_TEST_FAIL, + null, + null, + test, + expectedError + ); var stdout = runReporter(this, runner, options); - var expectedArray = ['
\n', '
\n']; + var expectedArray = [ + '
' + expectedTitle + '
\n', + '
' +
+            expectedBody +
+            '
\n', + '
' + expectedError + '
\n' + ]; expect(stdout, 'to equal', expectedArray); }); - }); - describe('if suite root does exist', function() { - var suite = { - root: true - }; - it('should not log any html', function() { - runner = createMockRunner('suite end', 'suite end', null, null, suite); - var stdout = runReporter(this, runner, options); - expect(stdout, 'to be empty'); - }); - }); - }); - describe('on pass', function() { - var expectedTitle = 'some tite'; - var expectedBody = 'some body'; - var test = { - title: expectedTitle, - body: expectedBody, - slow: function() { - return ''; - } - }; - it('should log html with indents and expected title and body', function() { - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter(this, runner, options); - var expectedArray = [ - '
' + expectedTitle + '
\n', - '
' + expectedBody + '
\n' - ]; - expect(stdout, 'to equal', expectedArray); - }); - it('should escape title and body where necessary', function() { - var unescapedTitle = '
' + expectedTitle + '
'; - var unescapedBody = '
' + expectedBody + '
'; - test.title = unescapedTitle; - test.body = unescapedBody; - - var expectedEscapedTitle = - '<div>' + expectedTitle + '</div>'; - var expectedEscapedBody = - '<div>' + expectedBody + '</div>'; - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter(this, runner, options); - var expectedArray = [ - '
' + expectedEscapedTitle + '
\n', - '
' + expectedEscapedBody + '
\n' - ]; - expect(stdout, 'to equal', expectedArray); - }); - }); + it('should escape title, body, and error where necessary', function() { + var unescapedTitle = '
' + expectedTitle + '
'; + var unescapedBody = '
' + expectedBody + '
'; + var unescapedError = '
' + expectedError + '
'; + test.title = unescapedTitle; + test.body = unescapedBody; - describe('on fail', function() { - var expectedTitle = 'some tite'; - var expectedBody = 'some body'; - var expectedError = 'some error'; - var test = { - title: expectedTitle, - body: expectedBody, - slow: function() { - return ''; - } - }; - it('should log html with indents and expected title, body and error', function() { - runner = createMockRunner( - 'fail two args', - 'fail', - null, - null, - test, - expectedError - ); - var stdout = runReporter(this, runner, options); - var expectedArray = [ - '
' + expectedTitle + '
\n', - '
' +
-          expectedBody +
-          '
\n', - '
' + expectedError + '
\n' - ]; - expect(stdout, 'to equal', expectedArray); - }); - it('should escape title, body and error where necessary', function() { - var unescapedTitle = '
' + expectedTitle + '
'; - var unescapedBody = '
' + expectedBody + '
'; - var unescapedError = '
' + expectedError + '
'; - test.title = unescapedTitle; - test.body = unescapedBody; - - var expectedEscapedTitle = - '<div>' + expectedTitle + '</div>'; - var expectedEscapedBody = - '<div>' + expectedBody + '</div>'; - var expectedEscapedError = - '<div>' + expectedError + '</div>'; - runner = createMockRunner( - 'fail two args', - 'fail', - null, - null, - test, - unescapedError - ); - var stdout = runReporter(this, runner, options); - var expectedArray = [ - '
' + expectedEscapedTitle + '
\n', - '
' +
-          expectedEscapedBody +
-          '
\n', - '
' + expectedEscapedError + '
\n' - ]; - expect(stdout, 'to equal', expectedArray); + var expectedEscapedTitle = + '<div>' + expectedTitle + '</div>'; + var expectedEscapedBody = + '<div>' + expectedBody + '</div>'; + var expectedEscapedError = + '<div>' + expectedError + '</div>'; + runner = createMockRunner( + 'fail two args', + EVENT_TEST_FAIL, + null, + null, + test, + unescapedError + ); + var stdout = runReporter(this, runner, options); + var expectedArray = [ + '
' + expectedEscapedTitle + '
\n', + '
' +
+            expectedEscapedBody +
+            '
\n', + '
' + expectedEscapedError + '
\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); }); }); }); diff --git a/test/reporters/dot.spec.js b/test/reporters/dot.spec.js index 472ec63d01..4a23c7951e 100644 --- a/test/reporters/dot.spec.js +++ b/test/reporters/dot.spec.js @@ -1,155 +1,238 @@ 'use strict'; +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; -var Dot = reporters.Dot; + var Base = reporters.Base; +var Dot = reporters.Dot; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers.js').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; describe('Dot reporter', function() { - var runner; - var useColors; - var windowWidth; - var color; - var options = {}; + var sandbox; + var windowWidthStub; var runReporter = makeRunReporter(Dot); + var noop = function() {}; beforeEach(function() { - useColors = Base.useColors; - windowWidth = Base.window.width; - color = Base.color; - Base.useColors = false; - Base.window.width = 0; - Base.color = function(type, str) { + sandbox = sinon.createSandbox(); + windowWidthStub = sandbox.stub(Base.window, 'width').value(0); + sandbox.stub(Base, 'useColors').value(false); + sandbox.stub(Base, 'color').callsFake(function(type, str) { return type.replace(/ /g, '-') + '_' + str; - }; + }); }); afterEach(function() { - Base.useColors = useColors; - Base.window.width = windowWidth; - Base.color = color; - runner = undefined; + sandbox.restore(); }); - describe('on start', function() { - it('should write a newline', function() { - runner = createMockRunner('start', 'start'); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = ['\n']; - expect(stdout, 'to equal', expectedArray); - }); - }); - describe('on pending', function() { - describe('if window width is greater than 1', function() { - beforeEach(function() { - Base.window.width = 2; - }); - it('should write a newline followed by a comma', function() { - runner = createMockRunner('pending', 'pending'); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = ['\n ', 'pending_' + Base.symbols.comma]; - expect(stdout, 'to equal', expectedArray); - }); - }); - describe('if window width is equal to or less than 1', function() { - it('should write a comma', function() { - runner = createMockRunner('pending', 'pending'); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = ['pending_' + Base.symbols.comma]; + describe('event handlers', function() { + describe("on 'start' event", function() { + it('should write a newline', function() { + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = ['\n']; expect(stdout, 'to equal', expectedArray); }); }); - }); - describe('on pass', function() { - var test = { - duration: 1, - slow: function() { - return 2; - } - }; - describe('if window width is greater than 1', function() { - beforeEach(function() { - Base.window.width = 2; - }); - describe('if test speed is fast', function() { - it('should write a newline followed by a dot', function() { - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - expect(test.speed, 'to equal', 'fast'); - var expectedArray = ['\n ', 'fast_' + Base.symbols.dot]; + + describe("on 'pending' event", function() { + describe('when window width is greater than 1', function() { + beforeEach(function() { + windowWidthStub.value(2); + }); + + it('should write a newline followed by a comma', function() { + var runner = createMockRunner('pending', EVENT_TEST_PENDING); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = ['\n ', 'pending_' + Base.symbols.comma]; expect(stdout, 'to equal', expectedArray); }); }); - }); - describe('if window width is equal to or less than 1', function() { - describe('if test speed is fast', function() { - it('should write a grey dot', function() { - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - expect(test.speed, 'to equal', 'fast'); - var expectedArray = ['fast_' + Base.symbols.dot]; + + describe('when window width is less than or equal to 1', function() { + it('should write a comma', function() { + var runner = createMockRunner('pending', EVENT_TEST_PENDING); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = ['pending_' + Base.symbols.comma]; expect(stdout, 'to equal', expectedArray); }); }); - describe('if test speed is medium', function() { - it('should write a yellow dot', function() { - test.duration = 2; - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - expect(test.speed, 'to equal', 'medium'); - var expectedArray = ['medium_' + Base.symbols.dot]; - expect(stdout, 'to equal', expectedArray); + }); + + describe("on 'pass' event", function() { + var test = { + duration: 1, + slow: function() { + return 2; + } + }; + + describe('when window width is greater than 1', function() { + beforeEach(function() { + windowWidthStub.value(2); + }); + + describe('when test speed is fast', function() { + it('should write a newline followed by a dot', function() { + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + expect(test.speed, 'to equal', 'fast'); + var expectedArray = ['\n ', 'fast_' + Base.symbols.dot]; + expect(stdout, 'to equal', expectedArray); + }); }); }); - describe('if test speed is slow', function() { - it('should write a bright yellow dot', function() { - test.duration = 3; - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - expect(test.speed, 'to equal', 'slow'); - var expectedArray = ['bright-yellow_' + Base.symbols.dot]; - expect(stdout, 'to equal', expectedArray); + + describe('when window width is less than or equal to 1', function() { + describe('when test speed is fast', function() { + it('should write a grey dot', function() { + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + expect(test.speed, 'to equal', 'fast'); + var expectedArray = ['fast_' + Base.symbols.dot]; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe('when test speed is medium', function() { + it('should write a yellow dot', function() { + test.duration = 2; + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + expect(test.speed, 'to equal', 'medium'); + var expectedArray = ['medium_' + Base.symbols.dot]; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe('when test speed is slow', function() { + it('should write a bright yellow dot', function() { + test.duration = 3; + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + expect(test.speed, 'to equal', 'slow'); + var expectedArray = ['bright-yellow_' + Base.symbols.dot]; + expect(stdout, 'to equal', expectedArray); + }); }); }); }); - }); - describe('on fail', function() { - var test = { - test: { - err: 'some error' - } - }; - describe('if window width is greater than 1', function() { - beforeEach(function() { - Base.window.width = 2; + + describe("on 'fail' event", function() { + var test = { + test: { + err: 'some error' + } + }; + + describe('when window width is greater than 1', function() { + beforeEach(function() { + windowWidthStub.value(2); + }); + + it('should write a newline followed by an exclamation mark', function() { + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = ['\n ', 'fail_' + Base.symbols.bang]; + expect(stdout, 'to equal', expectedArray); + }); }); - it('should write a newline followed by an exclamation mark', function() { - runner = createMockRunner('fail', 'fail', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = ['\n ', 'fail_' + Base.symbols.bang]; - expect(stdout, 'to equal', expectedArray); + + describe('when window width is less than or equal to 1', function() { + it('should write an exclamation mark', function() { + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = ['fail_' + Base.symbols.bang]; + expect(stdout, 'to equal', expectedArray); + }); }); }); - describe('if window width is equal to or less than 1', function() { - it('should write an exclamation mark', function() { - runner = createMockRunner('fail', 'fail', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = ['fail_' + Base.symbols.bang]; - expect(stdout, 'to equal', expectedArray); + + describe("on 'end' event", function() { + it('should call epilogue', function() { + var runner = createMockRunner('end', EVENT_RUN_END); + var fakeThis = { + epilogue: sinon.stub() + }; + var options = {}; + runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(fakeThis.epilogue.called, 'to be true'); }); }); }); - describe('on end', function() { - it('should call the epilogue', function() { - runner = createMockRunner('end', 'end'); - var epilogueCalled = false; - var epilogue = function() { - epilogueCalled = true; - }; - runReporter({epilogue: epilogue}, runner, options); - expect(epilogueCalled, 'to be', true); - }); - }); }); diff --git a/test/reporters/helpers.js b/test/reporters/helpers.js index 5cb21a53f2..76b3d79307 100644 --- a/test/reporters/helpers.js +++ b/test/reporters/helpers.js @@ -1,17 +1,22 @@ 'use strict'; +var sinon = require('sinon'); var errors = require('../../lib/errors'); -var createUnsupportedError = errors.createUnsupportedError; -/* - This function prevents the constant use of creating a runnerEvent. - runStr is the argument that defines the runnerEvent. - ifStr1 is one possible reporter argument, as is ifStr2, and ifStr3 - arg1 and arg2 are the possible variables that need to be put into the - scope of this function for the tests to run properly. -*/ - var createStatsCollector = require('../../lib/stats-collector'); +var createUnsupportedError = errors.createUnsupportedError; + +/** + * Creates a mock runner object. + * + * @param {string} runStr - argument that defines the runnerEvent + * @param {string} ifStr1 - runner event + * @param {(string|null)} [ifStr2] - runner event + * @param {(string|null)} [ifStr3] - runner event + * @param {(*|null)} [arg1] - variable to be added to event handler's scope + * @param {(*|null)} [arg2] - variable to be added to event handler's scope + * @return {Object} mock runner instance + */ function createMockRunner(runStr, ifStr1, ifStr2, ifStr3, arg1, arg2) { var runnerFunction = createRunnerFunction( runStr, @@ -29,6 +34,20 @@ function createMockRunner(runStr, ifStr1, ifStr2, ifStr3, arg1, arg2) { return mockRunner; } +/** + * Creates an event handler function to be used by the runner. + * + * @description + * Arguments 'ifStr1', 'ifStr2', and 'ifStr3' should be `Runner.constants`. + * + * @param {string} runStr - argument that defines the runnerEvent + * @param {string} ifStr1 - runner event + * @param {(string|null)} [ifStr2] - runner event + * @param {(string|null)} [ifStr3] - runner event + * @param {(*|null)} [arg1] - variable to be added to event handler's scope + * @param {(*|null)} [arg2] - variable to be added to event handler's scope + * @return {Function} event handler for the requested runner events + */ function createRunnerFunction(runStr, ifStr1, ifStr2, ifStr3, arg1, arg2) { var test = null; switch (runStr) { @@ -178,23 +197,35 @@ function createRunReporterFunction(ctor) { * @return {string[]} Lines of output written to `stdout` */ var runReporter = function(stubSelf, runner, options, tee) { + var origStdoutWrite = process.stdout.write; + var stdoutWriteStub = sinon.stub(process.stdout, 'write'); var stdout = []; - // Reassign stream in order to make a copy of all reporter output - var stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); + var gather = function(chunk, enc, callback) { + stdout.push(chunk); if (tee) { - stdoutWrite.call(process.stdout, string, enc, callback); + origStdoutWrite.call(process.stdout, chunk); } }; - // Invoke reporter - ctor.call(stubSelf, runner, options); + // Reassign stream in order to make a copy of all reporter output + stdoutWriteStub.callsFake(gather); + + // Give `stubSelf` access to `ctor` prototype chain + Object.setPrototypeOf(stubSelf, ctor.prototype); - // Revert stream reassignment here so reporter output - // can't be corrupted if any test assertions throw - process.stdout.write = stdoutWrite; + try { + try { + // Invoke reporter + ctor.call(stubSelf, runner, options); + } finally { + // Revert stream reassignment here so reporter output + // can't be corrupted if any test assertions throw + stdoutWriteStub.restore(); + } + } catch (err) { + throw err; // Rethrow + } return stdout; }; diff --git a/test/reporters/json-stream.spec.js b/test/reporters/json-stream.spec.js index 8c9fcfff35..de83f861b2 100644 --- a/test/reporters/json-stream.spec.js +++ b/test/reporters/json-stream.spec.js @@ -1,15 +1,22 @@ 'use strict'; +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; +var utils = require('../../lib/utils'); + var JSONStream = reporters.JSONStream; +var createMockRunner = helpers.createMockRunner; +var dQuote = utils.dQuote; +var makeExpectedTest = helpers.makeExpectedTest; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeExpectedTest = require('./helpers').makeExpectedTest; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; describe('JSON Stream reporter', function() { - var runner; - var options = {}; var runReporter = makeRunReporter(JSONStream); var expectedTitle = 'some title'; var expectedFullTitle = 'full title'; @@ -27,119 +34,126 @@ describe('JSON Stream reporter', function() { message: expectedErrorMessage }; - afterEach(function() { - runner = undefined; - }); - - describe('on start', function() { - it('should write stringified start with expected total', function() { - runner = createMockRunner('start', 'start'); - var expectedTotal = 12; - runner.total = expectedTotal; - var stdout = runReporter({}, runner, options); - - expect( - stdout[0], - 'to equal', - '["start",{"total":' + expectedTotal + '}]\n' - ); - }); - }); - - describe('on pass', function() { - it('should write stringified test data', function() { - runner = createMockRunner('pass', 'pass', null, null, expectedTest); - var stdout = runReporter({}, runner, options); - - expect( - stdout[0], - 'to equal', - '["pass",{"title":"' + - expectedTitle + - '","fullTitle":"' + - expectedFullTitle + - '","duration":' + - expectedDuration + - ',"currentRetry":' + - currentRetry + - '}]\n' - ); - }); - }); - - describe('on fail', function() { - describe('if error stack exists', function() { - it('should write stringified test data with error data', function() { - expectedError.stack = expectedErrorStack; - runner = createMockRunner( - 'fail two args', - 'fail', - null, - null, - expectedTest, - expectedError - ); - + describe('event handlers', function() { + describe("on 'start' event", function() { + it('should write stringified start with expected total', function() { + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var expectedTotal = 12; + runner.total = expectedTotal; + var options = {}; var stdout = runReporter({}, runner, options); expect( stdout[0], 'to equal', - '["fail",{"title":"' + - expectedTitle + - '","fullTitle":"' + - expectedFullTitle + - '","duration":' + - expectedDuration + - ',"currentRetry":' + - currentRetry + - ',"err":"' + - expectedErrorMessage + - '","stack":"' + - expectedErrorStack + - '"}]\n' + '["start",{"total":' + expectedTotal + '}]\n' ); }); }); - describe('if error stack does not exist', function() { - it('should write stringified test data with error data', function() { - expectedError.stack = null; - runner = createMockRunner( - 'fail two args', - 'fail', + describe("on 'pass' event", function() { + it('should write stringified test data', function() { + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, null, null, - expectedTest, - expectedError + expectedTest ); - - var stdout = runReporter(this, runner, options); + var options = {}; + var stdout = runReporter({}, runner, options); expect( stdout[0], 'to equal', - '["fail",{"title":"' + - expectedTitle + - '","fullTitle":"' + - expectedFullTitle + - '","duration":' + + '["pass",{"title":' + + dQuote(expectedTitle) + + ',"fullTitle":' + + dQuote(expectedFullTitle) + + ',"duration":' + expectedDuration + ',"currentRetry":' + currentRetry + - ',"err":"' + - expectedErrorMessage + - '","stack":null}]\n' + '}]\n' ); }); }); - }); - describe('on end', function() { - it('should write end details', function() { - runner = createMockRunner('end', 'end'); - var stdout = runReporter(this, runner, options); - expect(stdout[0], 'to match', /end/); + describe("on 'fail' event", function() { + describe('when error stack exists', function() { + it('should write stringified test data with error data', function() { + expectedError.stack = expectedErrorStack; + var runner = createMockRunner( + 'fail two args', + EVENT_TEST_FAIL, + null, + null, + expectedTest, + expectedError + ); + var options = {}; + var stdout = runReporter({}, runner, options); + + expect( + stdout[0], + 'to equal', + '["fail",{"title":' + + dQuote(expectedTitle) + + ',"fullTitle":' + + dQuote(expectedFullTitle) + + ',"duration":' + + expectedDuration + + ',"currentRetry":' + + currentRetry + + ',"err":' + + dQuote(expectedErrorMessage) + + ',"stack":' + + dQuote(expectedErrorStack) + + '}]\n' + ); + }); + }); + + describe('when error stack does not exist', function() { + it('should write stringified test data with error data', function() { + expectedError.stack = null; + var runner = createMockRunner( + 'fail two args', + EVENT_TEST_FAIL, + null, + null, + expectedTest, + expectedError + ); + var options = {}; + var stdout = runReporter(this, runner, options); + + expect( + stdout[0], + 'to equal', + '["fail",{"title":' + + dQuote(expectedTitle) + + ',"fullTitle":' + + dQuote(expectedFullTitle) + + ',"duration":' + + expectedDuration + + ',"currentRetry":' + + currentRetry + + ',"err":' + + dQuote(expectedErrorMessage) + + ',"stack":null}]\n' + ); + }); + }); + }); + + describe("on 'end' event", function() { + it('should write summary statistics', function() { + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + var stdout = runReporter(this, runner, options); + expect(stdout[0], 'to match', /end/); + }); }); }); }); diff --git a/test/reporters/json.spec.js b/test/reporters/json.spec.js index 5d7a37c564..f6299dd134 100644 --- a/test/reporters/json.spec.js +++ b/test/reporters/json.spec.js @@ -7,8 +7,11 @@ var Runner = Mocha.Runner; var Test = Mocha.Test; describe('JSON reporter', function() { - var suite, runner; + var sandbox; + var suite; + var runner; var testTitle = 'json test 1'; + var noop = function() {}; beforeEach(function() { var mocha = new Mocha({ @@ -16,8 +19,18 @@ describe('JSON reporter', function() { }); suite = new Suite('JSON suite', 'root'); runner = new Runner(suite); + var options = {}; /* eslint no-unused-vars: off */ - var mochaReporter = new mocha._reporter(runner); + var mochaReporter = new mocha._reporter(runner, options); + }); + + beforeEach(function() { + sandbox = sinon.createSandbox(); + sandbox.stub(process.stdout, 'write').callsFake(noop); + }); + + afterEach(function() { + sandbox.restore(); }); it('should have 1 test failure', function(done) { @@ -29,9 +42,8 @@ describe('JSON reporter', function() { }) ); - var stdoutWrite = sinon.stub(process.stdout, 'write'); runner.run(function(failureCount) { - stdoutWrite.restore(); + sandbox.restore(); expect(runner, 'to satisfy', { testResults: { failures: [ @@ -52,9 +64,8 @@ describe('JSON reporter', function() { it('should have 1 test pending', function(done) { suite.addTest(new Test(testTitle)); - var stdoutWrite = sinon.stub(process.stdout, 'write'); runner.run(function(failureCount) { - stdoutWrite.restore(); + sandbox.restore(); expect(runner, 'to satisfy', { testResults: { pending: [ @@ -83,9 +94,8 @@ describe('JSON reporter', function() { }) ); - var stdoutWrite = sinon.stub(process.stdout, 'write'); runner.run(function(failureCount) { - stdoutWrite.restore(); + sandbox.restore(); expect(runner, 'to satisfy', { testResults: { failures: [ diff --git a/test/reporters/landing.spec.js b/test/reporters/landing.spec.js index dd73d9e5b3..acb2ee3ef6 100644 --- a/test/reporters/landing.spec.js +++ b/test/reporters/landing.spec.js @@ -1,20 +1,25 @@ 'use strict'; -var sandbox = require('sinon').createSandbox(); -var Mocha = require('../..'); -var reporters = Mocha.reporters; -var Landing = reporters.Landing; -var constants = Mocha.Runnable.constants; -var STATE_FAILED = constants.STATE_FAILED; -var STATE_PASSED = constants.STATE_PASSED; +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); +var reporters = require('../../').reporters; +var states = require('../../').Runnable.constants; + var Base = reporters.Base; +var Landing = reporters.Landing; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_END = events.EVENT_TEST_END; + +var STATE_FAILED = states.STATE_FAILED; +var STATE_PASSED = states.STATE_PASSED; describe('Landing reporter', function() { - var runner; - var options = {}; + var sandbox; var runReporter = makeRunReporter(Landing); var resetCode = '\u001b[0m'; var expectedArray = [ @@ -29,73 +34,98 @@ describe('Landing reporter', function() { ]; beforeEach(function() { + sandbox = sinon.createSandbox(); sandbox.stub(Base, 'useColors').value(false); sandbox.stub(Base.window, 'width').value(1); }); afterEach(function() { sandbox.restore(); - runner = undefined; }); - describe('on start', function() { - it('should write new lines', function() { - sandbox.stub(Base.cursor, 'hide'); - - runner = createMockRunner('start', 'start'); - var stdout = runReporter({}, runner, options); + describe('event handlers', function() { + describe("on 'start' event", function() { + it('should write newlines', function() { + sandbox.stub(Base.cursor, 'hide'); - expect(stdout[0], 'to equal', '\n\n\n '); - }); + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + var stdout = runReporter({}, runner, options); + sandbox.restore(); - it('should call cursor hide', function() { - sandbox.stub(Base.cursor, 'hide'); + expect(stdout[0], 'to equal', '\n\n\n '); + }); - runner = createMockRunner('start', 'start'); - runReporter({}, runner, options); + it('should call cursor hide', function() { + var hideCursorStub = sandbox.stub(Base.cursor, 'hide'); - expect(Base.cursor.hide, 'was called'); - }); - }); + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + runReporter({}, runner, options); + sandbox.restore(); - describe('on test end', function() { - describe('if test has failed', function() { - it('should write expected landing strip', function() { - var test = { - state: STATE_FAILED - }; - runner = createMockRunner('test end', 'test end', null, null, test); - runner.total = 12; - var stdout = runReporter({}, runner, options); - - expect(stdout, 'to equal', expectedArray); + expect(hideCursorStub.called, 'to be true'); }); }); - describe('if test has not failed', function() { - it('should write expected landing strip', function() { - var test = { - state: STATE_PASSED - }; - runner = createMockRunner('test end', 'test end', null, null, test); - var stdout = runReporter({}, runner, options); + describe("on 'test end' event", function() { + describe('when test passes', function() { + it('should write expected landing strip', function() { + var test = { + state: STATE_PASSED + }; + var runner = createMockRunner( + 'test end', + EVENT_TEST_END, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({}, runner, options); + sandbox.restore(); + + expect(stdout, 'to equal', expectedArray); + }); + }); - expect(stdout, 'to equal', expectedArray); + describe('when test fails', function() { + it('should write expected landing strip', function() { + var test = { + state: STATE_FAILED + }; + var runner = createMockRunner( + 'test end', + EVENT_TEST_END, + null, + null, + test + ); + runner.total = 12; + var options = {}; + var stdout = runReporter({}, runner, options); + sandbox.restore(); + + expect(stdout, 'to equal', expectedArray); + }); }); }); - }); - describe('on end', function() { - it('should call cursor show and epilogue', function() { - var reporterStub = {epilogue: function() {}}; - sandbox.stub(Base.cursor, 'show'); - sandbox.stub(reporterStub, 'epilogue'); - runner = createMockRunner('end', 'end'); + describe("on 'end' event", function() { + it('should call cursor show and epilogue', function() { + var showCursorStub = sandbox.stub(Base.cursor, 'show'); - runReporter(reporterStub, runner, options); + var fakeThis = { + epilogue: sinon.spy() + }; + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + runReporter(fakeThis, runner, options); + sandbox.restore(); - expect(reporterStub.epilogue, 'was called'); - expect(Base.cursor.show, 'was called'); + expect(fakeThis.epilogue.calledOnce, 'to be true'); + expect(showCursorStub.called, 'to be true'); + }); }); }); }); diff --git a/test/reporters/list.spec.js b/test/reporters/list.spec.js index c9eceb87fe..c10272e953 100644 --- a/test/reporters/list.spec.js +++ b/test/reporters/list.spec.js @@ -1,144 +1,246 @@ 'use strict'; -var sandbox = require('sinon').createSandbox(); +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; -var List = reporters.List; + var Base = reporters.Base; +var List = reporters.List; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_BEGIN = events.EVENT_TEST_BEGIN; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; describe('List reporter', function() { - var runner; - var options = {}; + var sandbox; var runReporter = makeRunReporter(List); var expectedTitle = 'some title'; var expectedDuration = 100; + var noop = function() {}; var test = { fullTitle: function() { return expectedTitle; }, duration: expectedDuration, - slow: function() {} + slow: noop }; beforeEach(function() { + sandbox = sinon.createSandbox(); sandbox.stub(Base, 'useColors').value(false); }); afterEach(function() { sandbox.restore(); - runner = undefined; }); - describe('on start and test', function() { - it('should write expected new line and title to the console', function() { - runner = createMockRunner('start test', 'start', 'test', null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - - var startString = '\n'; - var testString = ' ' + expectedTitle + ': '; - var expectedArray = [startString, testString]; - expect(stdout, 'to equal', expectedArray); + describe('event handlers', function() { + describe("on 'start' and 'test' events", function() { + it('should write expected newline and title', function() { + var runner = createMockRunner( + 'start test', + EVENT_RUN_BEGIN, + EVENT_TEST_BEGIN, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + var stdout = runReporter(fakeThis, runner, options); + sandbox.restore(); + + var startString = '\n'; + var testString = ' ' + expectedTitle + ': '; + var expectedArray = [startString, testString]; + expect(stdout, 'to equal', expectedArray); + }); }); - }); - describe('on pending', function() { - it('should write expected title to the console', function() { - runner = createMockRunner('pending test', 'pending', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - expect(stdout[0], 'to equal', ' - ' + expectedTitle + '\n'); + describe("on 'pending' event", function() { + it('should write expected title', function() { + var runner = createMockRunner( + 'pending test', + EVENT_TEST_PENDING, + null, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + var stdout = runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(stdout[0], 'to equal', ' - ' + expectedTitle + '\n'); + }); }); - }); - describe('on pass', function() { - it('should call cursor CR', function() { - sandbox.stub(Base.cursor, 'CR'); - runner = createMockRunner('pass', 'pass', null, null, test); - runReporter({epilogue: function() {}}, runner, options); - - expect(Base.cursor.CR, 'was called'); - }); - it('should write expected symbol, title and duration to the console', function() { - var expectedOkSymbol = 'OK'; - sandbox.stub(Base.symbols, 'ok').value(expectedOkSymbol); - sandbox.stub(Base.cursor, 'CR'); - - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - - expect( - stdout[0], - 'to be', - ' ' + - expectedOkSymbol + - ' ' + - expectedTitle + - ': ' + - expectedDuration + - 'ms\n' - ); + describe("on 'pass' event", function() { + var crStub; + + beforeEach(function() { + crStub = sandbox.stub(Base.cursor, 'CR').callsFake(noop); + }); + + it('should call cursor CR', function() { + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(crStub.called, 'to be true'); + }); + + it('should write expected symbol, title, and duration', function() { + var expectedOkSymbol = 'OK'; + sandbox.stub(Base.symbols, 'ok').value(expectedOkSymbol); + + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + var stdout = runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect( + stdout[0], + 'to be', + ' ' + + expectedOkSymbol + + ' ' + + expectedTitle + + ': ' + + expectedDuration + + 'ms\n' + ); + }); }); - }); - describe('on fail', function() { - it('should call cursor CR', function() { - sandbox.stub(Base.cursor, 'CR'); - - runner = createMockRunner('fail', 'fail', null, null, test); - runReporter({epilogue: function() {}}, runner, options); - expect(Base.cursor.CR, 'was called'); - }); - it('should write expected error number and title', function() { - sandbox.stub(Base.cursor, 'CR'); - - var expectedErrorCount = 1; - runner = createMockRunner('fail', 'fail', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - - expect( - stdout[0], - 'to be', - ' ' + expectedErrorCount + ') ' + expectedTitle + '\n' - ); - }); - it('should immediately construct fail strings', function() { - var actual = {a: 'actual'}; - var expected = {a: 'expected'}; - var checked = false; - var err; - test = {}; - runner = createMockRunner('fail', 'fail', null, null, test); - runner.on = runner.once = function(event, callback) { - if ( - !checked && - event === 'fail' && - callback.toString().includes('stringifyDiffObjs') // target correct fail event callback - ) { - err = new Error('fake failure object with actual/expected'); - err.actual = actual; - err.expected = expected; - err.showDiff = true; - callback(test, err); - checked = true; - } - }; - runReporter({epilogue: function() {}}, runner, options); - - expect(typeof err.actual, 'to be', 'string'); - expect(typeof err.expected, 'to be', 'string'); + describe("on 'fail' event", function() { + var crStub; + + beforeEach(function() { + crStub = sandbox.stub(Base.cursor, 'CR').callsFake(noop); + }); + + it('should call cursor CR', function() { + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(crStub.called, 'to be true'); + }); + + it('should write expected error number and title', function() { + var expectedErrorCount = 1; + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + var fakeThis = { + epilogue: noop + }; + var stdout = runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect( + stdout[0], + 'to be', + ' ' + expectedErrorCount + ') ' + expectedTitle + '\n' + ); + }); + + it('should immediately construct fail strings', function() { + var actual = {a: 'actual'}; + var expected = {a: 'expected'}; + var checked = false; + var err; + test = {}; + + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + runner.on = runner.once = function(event, callback) { + if ( + !checked && + event === 'fail' && + callback.toString().includes('stringifyDiffObjs') // target correct fail event callback + ) { + err = new Error('fake failure object with actual/expected'); + err.actual = actual; + err.expected = expected; + err.showDiff = true; + callback(test, err); + checked = true; + } + }; + var options = {}; + var fakeThis = { + epilogue: noop + }; + runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(typeof err.actual, 'to be', 'string'); + expect(typeof err.expected, 'to be', 'string'); + }); }); - }); - - describe('on end', function() { - it('should call epilogue', function() { - var reporterStub = {epilogue: function() {}}; - sandbox.stub(reporterStub, 'epilogue'); - - runner = createMockRunner('end', 'end'); - runReporter(reporterStub, runner, options); - expect(reporterStub.epilogue, 'was called'); + describe("on 'end' event", function() { + it('should call epilogue', function() { + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + var fakeThis = { + epilogue: sinon.spy() + }; + runReporter(fakeThis, runner, options); + sandbox.restore(); + + expect(fakeThis.epilogue.calledOnce, 'to be true'); + }); }); }); }); diff --git a/test/reporters/markdown.spec.js b/test/reporters/markdown.spec.js index 842d7c7643..e068c58cea 100644 --- a/test/reporters/markdown.spec.js +++ b/test/reporters/markdown.spec.js @@ -1,102 +1,115 @@ 'use strict'; +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; + var Markdown = reporters.Markdown; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_SUITE_BEGIN = events.EVENT_SUITE_BEGIN; +var EVENT_SUITE_END = events.EVENT_SUITE_END; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; describe('Markdown reporter', function() { - var runner; - var options = {}; var runReporter = makeRunReporter(Markdown); var expectedTitle = 'expected title'; var expectedFullTitle = 'full title'; var sluggedFullTitle = 'full-title'; + var noop = function() {}; - afterEach(function() { - runner = undefined; - }); - - describe("on 'suite'", function() { - it("should write expected slugged titles on 'end' event", function() { - var expectedSuite = { - title: expectedTitle, - fullTitle: function() { - return expectedFullTitle; - }, - suites: [ - { - title: expectedTitle, - fullTitle: function() { - return expectedFullTitle; - }, - suites: [] - } - ] - }; - runner = createMockRunner( - 'suite suite end', - 'suite', - 'suite end', - 'end', - expectedSuite - ); - runner.suite = expectedSuite; - var stdout = runReporter({}, runner, options); + describe('event handlers', function() { + describe("on 'suite' event", function() { + it("should write expected slugged titles on 'end' event", function() { + var expectedSuite = { + title: expectedTitle, + fullTitle: function() { + return expectedFullTitle; + }, + suites: [ + { + title: expectedTitle, + fullTitle: function() { + return expectedFullTitle; + }, + suites: [] + } + ] + }; + var runner = createMockRunner( + 'suite suite end', + EVENT_SUITE_BEGIN, + EVENT_SUITE_END, + EVENT_RUN_END, + expectedSuite + ); + runner.suite = expectedSuite; + var options = {}; + var stdout = runReporter({}, runner, options); - var expectedArray = [ - '# TOC\n', - ' - [' + - expectedTitle + - '](#' + - sluggedFullTitle + - ')\n - [' + - expectedTitle + - '](#' + - sluggedFullTitle + - ')\n', - '\n ' + expectedTitle + '\n' - ]; + var expectedArray = [ + '# TOC\n', + ' - [' + + expectedTitle + + '](#' + + sluggedFullTitle + + ')\n - [' + + expectedTitle + + '](#' + + sluggedFullTitle + + ')\n', + '\n ' + expectedTitle + '\n' + ]; - expect(stdout, 'to equal', expectedArray); + expect(stdout, 'to equal', expectedArray); + }); }); - }); - describe("on 'pass'", function() { - it("should write test code inside js code block, on 'end' event", function() { - var expectedSuite = { - title: expectedTitle, - fullTitle: function() { - return expectedFullTitle; - }, - suites: [] - }; - var expectedDuration = 1000; - var currentRetry = 1; - var expectedBody = 'some body'; - var expectedTest = { - title: expectedTitle, - fullTitle: function() { - return expectedFullTitle; - }, - duration: expectedDuration, - currentRetry: function() { - return currentRetry; - }, - slow: function() {}, - body: expectedBody - }; - runner = createMockRunner('pass end', 'pass', 'end', null, expectedTest); - runner.suite = expectedSuite; - var stdout = runReporter({}, runner, options); - var expectedArray = [ - '# TOC\n', - ' - [' + expectedTitle + '](#' + sluggedFullTitle + ')\n', - expectedTitle + '.\n\n```js\n' + expectedBody + '\n```\n\n' - ]; + describe("on 'pass' event", function() { + it("should write test code inside js code block, on 'end' event", function() { + var expectedSuite = { + title: expectedTitle, + fullTitle: function() { + return expectedFullTitle; + }, + suites: [] + }; + var expectedDuration = 1000; + var currentRetry = 1; + var expectedBody = 'some body'; + var expectedTest = { + title: expectedTitle, + fullTitle: function() { + return expectedFullTitle; + }, + duration: expectedDuration, + currentRetry: function() { + return currentRetry; + }, + slow: noop, + body: expectedBody + }; + var runner = createMockRunner( + 'pass end', + EVENT_TEST_PASS, + EVENT_RUN_END, + null, + expectedTest + ); + runner.suite = expectedSuite; + var options = {}; + var stdout = runReporter({}, runner, options); + + var expectedArray = [ + '# TOC\n', + ' - [' + expectedTitle + '](#' + sluggedFullTitle + ')\n', + expectedTitle + '.\n\n```js\n' + expectedBody + '\n```\n\n' + ]; - expect(stdout, 'to equal', expectedArray); + expect(stdout, 'to equal', expectedArray); + }); }); }); }); diff --git a/test/reporters/min.spec.js b/test/reporters/min.spec.js index f88adf31d7..1fe46333cf 100644 --- a/test/reporters/min.spec.js +++ b/test/reporters/min.spec.js @@ -1,45 +1,47 @@ 'use strict'; +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; + var Min = reporters.Min; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; describe('Min reporter', function() { - var runner; - var options = {}; var runReporter = makeRunReporter(Min); - - afterEach(function() { - runner = undefined; - }); - - describe('on start', function() { - it('should clear screen then set cursor position', function() { - runner = createMockRunner('start', 'start'); - var stdout = runReporter({epilogue: function() {}}, runner, options); - - var expectedArray = ['\u001b[2J', '\u001b[1;3H']; - expect(stdout, 'to equal', expectedArray); + var noop = function() {}; + + describe('event handlers', function() { + describe("on 'start' event", function() { + it('should clear screen then set cursor position', function() { + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + var fakeThis = { + epilogue: noop + }; + var stdout = runReporter(fakeThis, runner, options); + + var expectedArray = ['\u001b[2J', '\u001b[1;3H']; + expect(stdout, 'to equal', expectedArray); + }); }); - }); - describe('on end', function() { - it('should call epilogue', function() { - var calledEpilogue = false; - runner = createMockRunner('end', 'end'); - runReporter( - { - epilogue: function() { - calledEpilogue = true; - } - }, - runner, - options - ); - - expect(calledEpilogue, 'to be', true); + describe("on 'end' event", function() { + it('should call epilogue', function() { + var fakeThis = { + epilogue: sinon.stub().callsFake(noop) + }; + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + runReporter(fakeThis, runner, options); + + expect(fakeThis.epilogue.called, 'to be true'); + }); }); }); }); diff --git a/test/reporters/nyan.spec.js b/test/reporters/nyan.spec.js index b1ad3a22a3..05d2e1bf77 100644 --- a/test/reporters/nyan.spec.js +++ b/test/reporters/nyan.spec.js @@ -1,172 +1,205 @@ 'use strict'; -var sandbox = require('sinon').createSandbox(); +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; -var NyanCat = reporters.Nyan; + var Base = reporters.Base; +var NyanCat = reporters.Nyan; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; describe('Nyan reporter', function() { - describe('events', function() { - var runner; - var options = {}; - var runReporter = makeRunReporter(NyanCat); + var sandbox; + var noop = function() {}; - afterEach(function() { - sandbox.restore(); - runner = undefined; - }); + beforeEach(function() { + sandbox = sinon.createSandbox(); + }); - describe('on start', function() { + afterEach(function() { + sandbox.restore(); + }); + + describe('event handlers', function() { + var runReporter = makeRunReporter(NyanCat); + + describe("on 'start' event", function() { it('should call draw', function() { - var reporterStub = { - draw: function() {}, - generateColors: function() {} + var fakeThis = { + draw: sinon.stub().callsFake(noop), + generateColors: noop }; - sandbox.stub(reporterStub, 'draw'); - runner = createMockRunner('start', 'start'); - runReporter(reporterStub, runner, options); + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + runReporter(fakeThis, runner, options); - expect(reporterStub.draw, 'was called'); + expect(fakeThis.draw.called, 'to be true'); }); }); - describe('on pending', function() { + + describe("on 'pending' event", function() { it('should call draw', function() { - var reporterStub = { - draw: function() {}, - generateColors: function() {} + var fakeThis = { + draw: sinon.stub().callsFake(noop), + generateColors: noop }; - sandbox.stub(reporterStub, 'draw'); + var runner = createMockRunner('pending', EVENT_TEST_PENDING); + var options = {}; + runReporter(fakeThis, runner, options); - runner = createMockRunner('pending', 'pending'); - runReporter(reporterStub, runner, options); - - expect(reporterStub.draw, 'was called'); + expect(fakeThis.draw.called, 'to be true'); }); }); - describe('on pass', function() { - it('should call draw', function() { - var reporterStub = { - draw: function() {}, - generateColors: function() {} - }; - sandbox.stub(reporterStub, 'draw'); + describe("on 'pass' event", function() { + it('should call draw', function() { var test = { duration: '', - slow: function() {} + slow: noop }; - runner = createMockRunner('pass', 'pass', null, null, test); - runReporter(reporterStub, runner, options); + var fakeThis = { + draw: sinon.stub().callsFake(noop), + generateColors: noop + }; + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + runReporter(fakeThis, runner, options); - expect(reporterStub.draw, 'was called'); + expect(fakeThis.draw.called, 'to be true'); }); }); - describe('on fail', function() { - it('should call draw', function() { - var reporterStub = { - draw: function() {}, - generateColors: function() {} - }; - sandbox.stub(reporterStub, 'draw'); + describe("on 'fail' event", function() { + it('should call draw', function() { var test = { err: '' }; - runner = createMockRunner('fail', 'fail', null, null, test); - runReporter(reporterStub, runner, options); + var fakeThis = { + draw: sinon.stub().callsFake(noop), + generateColors: noop + }; + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + runReporter(fakeThis, runner, options); - expect(reporterStub.draw, 'was called'); + expect(fakeThis.draw.called, 'to be true'); }); }); - describe('on end', function() { + + describe("on 'end' event", function() { it('should call epilogue', function() { - var reporterStub = { - draw: function() {}, - generateColors: function() {}, - epilogue: function() {} + var fakeThis = { + draw: noop, + epilogue: sinon.stub().callsFake(noop), + generateColors: noop }; - sandbox.stub(reporterStub, 'epilogue'); - - runner = createMockRunner('end', 'end'); - runReporter(reporterStub, runner, options); + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + runReporter(fakeThis, runner, options); - expect(reporterStub.epilogue, 'was called'); + expect(fakeThis.epilogue.called, 'to be true'); }); - it('should write numberOfLines amount of new lines', function() { + + it('should write numberOfLines amount of newlines', function() { var expectedNumberOfLines = 4; - runner = createMockRunner('end', 'end'); - var stdout = runReporter( - { - draw: function() {}, - generateColors: function() {}, - epilogue: function() {} - }, - runner, - options - ); + var fakeThis = { + draw: noop, + epilogue: noop, + generateColors: noop + }; + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + var stdout = runReporter(fakeThis, runner, options); - var arrayOfNewlines = stdout.filter(function(value) { + var isBlankLine = function(value) { return value === '\n'; - }); + }; - expect(arrayOfNewlines, 'to have length', expectedNumberOfLines); + expect( + stdout.filter(isBlankLine), + 'to have length', + expectedNumberOfLines + ); }); + it('should call Base show', function() { - sandbox.stub(Base.cursor, 'show'); - - runner = createMockRunner('end', 'end'); - runReporter( - { - draw: function() {}, - generateColors: function() {}, - epilogue: function() {} - }, - runner, - options - ); + var showCursorStub = sandbox.stub(Base.cursor, 'show'); + var fakeThis = { + draw: noop, + epilogue: noop, + generateColors: noop + }; + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + runReporter(fakeThis, runner, options); + sandbox.restore(); - expect(Base.cursor.show, 'was called'); + expect(showCursorStub.called, 'to be true'); }); }); }); - describe('draw', function() { + describe('#draw', function() { + var stdoutWriteStub; var stdout; - var stdoutWrite; beforeEach(function() { + stdoutWriteStub = sandbox.stub(process.stdout, 'write'); + stdoutWriteStub.callsFake(function(chunk, encoding, cb) { + stdout.push(chunk); + }); stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - }; }); - afterEach(function() { - process.stdout.write = stdoutWrite; - }); - - describe('if tick is false', function() { + describe("when 'tick' is false", function() { it('should draw face with expected spaces, _ and ^', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 2, pending: 1, failures: 0}; - - nyanCat.draw.call({ + var fakeThis = { tick: false, - appendRainbow: function() {}, - rainbowify: function() {}, - drawScoreboard: function() {}, - drawRainbow: function() {}, + appendRainbow: noop, + rainbowify: noop, + drawScoreboard: noop, + drawRainbow: noop, drawNyanCat: NyanCat.prototype.drawNyanCat, scoreboardWidth: 0, trajectories: [[]], - face: function() {}, - cursorUp: function() {} - }); + face: noop, + cursorUp: noop + }; + + try { + try { + nyanCat.draw.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } var expectedArray = [ '\u001b[0C', @@ -185,23 +218,35 @@ describe('Nyan reporter', function() { expect(stdout, 'to equal', expectedArray); }); }); - describe('if tick is true', function() { + + describe("when 'tick' is true", function() { it('should draw face with expected spaces, _ and ~', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 2, pending: 1, failures: 0}; - - nyanCat.draw.call({ + var fakeThis = { tick: true, - appendRainbow: function() {}, - rainbowify: function() {}, - drawScoreboard: function() {}, - drawRainbow: function() {}, + appendRainbow: noop, + rainbowify: noop, + drawScoreboard: noop, + drawRainbow: noop, drawNyanCat: NyanCat.prototype.drawNyanCat, scoreboardWidth: 0, trajectories: [[]], - face: function() {}, - cursorUp: function() {} - }); + face: noop, + cursorUp: noop + }; + + try { + try { + nyanCat.draw.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } var expectedArray = [ '\u001b[0C', @@ -222,102 +267,136 @@ describe('Nyan reporter', function() { }); }); - describe('cursorDown', function() { + describe('#cursorDown', function() { + var stdoutWriteStub; var stdout; - var stdoutWrite; beforeEach(function() { + stdoutWriteStub = sandbox.stub(process.stdout, 'write'); + stdoutWriteStub.callsFake(function(chunk, encoding, cb) { + stdout.push(chunk); + }); stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string) { - stdout.push(string); - }; - }); - - afterEach(function() { - process.stdout.write = stdoutWrite; }); it('should write cursor down interaction with expected number', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); var expectedNumber = 25; - nyanCat.cursorDown(expectedNumber); + try { + try { + nyanCat.cursorDown(expectedNumber); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } + var expectedArray = ['\u001b[' + expectedNumber + 'B']; expect(stdout, 'to equal', expectedArray); }); }); - describe('cursorUp', function() { + describe('#cursorUp', function() { + var stdoutWriteStub; var stdout; - var stdoutWrite; beforeEach(function() { + stdoutWriteStub = sandbox.stub(process.stdout, 'write'); + stdoutWriteStub.callsFake(function(chunk, encoding, cb) { + stdout.push(chunk); + }); stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - }; - }); - - afterEach(function() { - process.stdout.write = stdoutWrite; }); it('should write cursor up interaction with expected number', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); var expectedNumber = 25; - nyanCat.cursorUp(expectedNumber); + try { + try { + nyanCat.cursorUp(expectedNumber); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } + var expectedArray = ['\u001b[' + expectedNumber + 'A']; expect(stdout, 'to equal', expectedArray); }); }); - describe('rainbowify', function() { - describe('useColors is false', function() { + describe('#rainbowify', function() { + var useColorsStub; + + beforeEach(function() { + useColorsStub = sandbox.stub(Base, 'useColors'); + }); + + afterEach(function() { + sandbox.restore(); + }); + + describe("when 'useColors' is false", function() { beforeEach(function() { - sandbox.stub(Base, 'useColors').value(false); + useColorsStub.value(false); }); it('should return argument string', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - var expectedString = 'hello'; - var outputString = nyanCat.rainbowify(expectedString); + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + + var inputString = 'hello'; + var outputString = nyanCat.rainbowify(inputString); + sandbox.restore(); + var expectedString = inputString; expect(outputString, 'to be', expectedString); }); }); - describe('useColors is true', function() { + + describe("when 'useColors' is true", function() { beforeEach(function() { - sandbox.stub(Base, 'useColors').value(true); + useColorsStub.value(true); }); it('should return rainbowified string from the given string and predefined codes', function() { - var startCode = '\u001b[38;5;'; - var endCode = '\u001b[0m'; - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - var expectedString = 'hello'; + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + + var inputString = 'hello'; var colorCode = 'somecode'; - var expectedRainbowifyString = - startCode + colorCode + 'm' + expectedString + endCode; - var outputString = nyanCat.rainbowify.call( - { - rainbowColors: [colorCode], - colorIndex: 0 - }, - expectedString - ); + var fakeThis = { + rainbowColors: [colorCode], + colorIndex: 0 + }; + var outputString = nyanCat.rainbowify.call(fakeThis, inputString); + sandbox.restore(); - expect(outputString, 'to be', expectedRainbowifyString); + var startCode = '\u001b[38;5;'; + var endCode = '\u001b[0m'; + var expectedString = + startCode + colorCode + 'm' + inputString + endCode; + expect(outputString, 'to be', expectedString); }); }); }); - describe('appendRainbow', function() { - describe('if tick is true', function() { - it('should set an _ segment', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + describe('#appendRainbow', function() { + describe("when 'tick' is true", function() { + it('should set an underscore segment', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); var expectedSegment; var inputArray = []; var trajectories = [inputArray, inputArray, inputArray, inputArray]; @@ -333,8 +412,11 @@ describe('Nyan reporter', function() { expect(expectedSegment, 'to be', '_'); }); - it('should shift each trajectory item, if its length is greater of equal to its max width', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + + it('should shift each trajectory item if its length is greater than or equal to its max width', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); var rainbowifyResult = 'rainbowify'; var inputArray = ['itemToShify']; @@ -359,9 +441,12 @@ describe('Nyan reporter', function() { expect(trajectories, 'to equal', expectedTrajectories); }); }); - describe('if tick is false', function() { - it('should set an - segment', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + + describe("when 'tick' is false", function() { + it('should set a dash segment', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); var expectedSegment; var inputArray = []; var trajectories = [inputArray, inputArray, inputArray, inputArray]; @@ -380,42 +465,45 @@ describe('Nyan reporter', function() { }); }); - describe('drawScoreboard', function() { - var stdoutWrite; + describe('#drawScoreboard', function() { var stdout; - var cachedColor; - var showOutput = false; beforeEach(function() { - stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - if (showOutput) { - stdoutWrite.call(process.stdout, string, enc, callback); - } - }; - cachedColor = Base.color; - Base.color = function(type, n) { + sandbox.stub(Base, 'color').callsFake(function(type, n) { return type + n; - }; - }); - - afterEach(function() { - process.stdout.write = stdoutWrite; - Base.color = cachedColor; + }); + var stdoutWriteStub = sandbox.stub(process.stdout, 'write'); + stdoutWriteStub.callsFake(function(chunk, encoding, cb) { + stdout.push(chunk); + }); + stdout = []; }); it('should write scoreboard with color set with each stat', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + var passes = 2; var pending = 1; var failures = 1; - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - nyanCat.drawScoreboard.call({ - cursorUp: function() {}, + + var fakeThis = { + cursorUp: noop, stats: {passes: passes, pending: pending, failures: failures}, numberOfLines: 4 - }); + }; + + try { + try { + nyanCat.drawScoreboard.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } + var expectedArray = [ ' ', 'green' + passes, @@ -432,40 +520,40 @@ describe('Nyan reporter', function() { }); it('should call cursorUp with given numberOfLines', function() { - var expectedCursorArgument = null; var expectedNumberOfLines = 1000; - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - nyanCat.drawScoreboard.call({ - cursorUp: function(lines) { - expectedCursorArgument = lines; - }, + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + var fakeThis = { + cursorUp: sinon.spy(), stats: {passes: 0, pending: 0, failures: 0}, numberOfLines: expectedNumberOfLines - }); + }; - expect(expectedCursorArgument, 'to be', expectedNumberOfLines); + try { + try { + nyanCat.drawScoreboard.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } + + expect(fakeThis.cursorUp.calledWith(expectedNumberOfLines), 'to be true'); }); }); - describe('drawRainbow', function() { - var stdoutWrite; + describe('#drawRainbow', function() { var stdout; - var showOutput = false; beforeEach(function() { + var stdoutWriteStub = sandbox.stub(process.stdout, 'write'); + stdoutWriteStub.callsFake(function(chunk, encoding, cb) { + stdout.push(chunk); + }); stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - if (showOutput) { - stdoutWrite.call(process.stdout, string, enc, callback); - } - }; - }); - - afterEach(function() { - process.stdout.write = stdoutWrite; }); it('should write width, contents and newline for each trajectory', function() { @@ -474,13 +562,25 @@ describe('Nyan reporter', function() { var expectedContents = 'input'; var inputArray = [expectedContents]; var trajectories = [inputArray]; - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - nyanCat.drawRainbow.call({ - cursorUp: function() {}, + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + var fakeThis = { + cursorUp: noop, trajectories: trajectories, scoreboardWidth: expectedWidth, numberOfLines: 1 - }); + }; + + try { + try { + nyanCat.drawRainbow.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } var expectedArray = [ '\u001b[' + expectedWidth + 'C', @@ -494,41 +594,66 @@ describe('Nyan reporter', function() { var expectedCursorArgument = null; var expectedNumberOfLines = 1000; - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); - nyanCat.drawRainbow.call({ + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); + var fakeThis = { cursorUp: function(lines) { expectedCursorArgument = lines; }, trajectories: [['input']], scoreboardWidth: 1, numberOfLines: expectedNumberOfLines - }); + }; + + try { + try { + nyanCat.drawRainbow.call(fakeThis); + } finally { + sandbox.restore(); + } + } catch (err) { + throw err; // Rethrow + } expect(expectedCursorArgument, 'to be', expectedNumberOfLines); }); }); - describe('face', function() { - it('expected face:(x .x) when "failures" at least one', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + + describe('#face', function() { + it('should expect "( x .x)" if any failures', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 2, pending: 1, failures: 1}; + expect(nyanCat.face(), 'to be', '( x .x)'); }); - it('expected face:(x .x) when "pending" at least one and no failing', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + it('should expect "( o .o)" if any pending but none failing', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 2, pending: 1, failures: 0}; + expect(nyanCat.face(), 'to be', '( o .o)'); }); - it('expected face:(^ .^) when "passing" only', function() { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + it('should expect "( ^ .^)" if all passing', function() { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 1, pending: 0, failures: 0}; + expect(nyanCat.face(), 'to be', '( ^ .^)'); }); - it('expected face:(- .-) when otherwise', function(done) { - var nyanCat = new NyanCat({on: function() {}, once: function() {}}); + it('should expect "( - .-)" otherwise', function(done) { + var runner = {on: noop, once: noop}; + var options = {}; + var nyanCat = new NyanCat(runner, options); nyanCat.stats = {passes: 0, pending: 0, failures: 0}; + expect(nyanCat.face(), 'to be', '( - .-)'); done(); }); diff --git a/test/reporters/progress.spec.js b/test/reporters/progress.spec.js index cdea9c643e..0d45abeaf7 100644 --- a/test/reporters/progress.spec.js +++ b/test/reporters/progress.spec.js @@ -1,107 +1,117 @@ 'use strict'; -var sandbox = require('sinon').createSandbox(); +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; -var Progress = reporters.Progress; + var Base = reporters.Base; +var Progress = reporters.Progress; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_END = events.EVENT_TEST_END; describe('Progress reporter', function() { - var stdout; - var stdoutWrite; - var runner; + var sandbox; var runReporter = makeRunReporter(Progress); + var noop = function() {}; beforeEach(function() { - stdout = []; - stdoutWrite = process.stdout.write; - process.stdout.write = function(string, enc, callback) { - stdout.push(string); - stdoutWrite.call(process.stdout, string, enc, callback); - }; + sandbox = sinon.createSandbox(); }); afterEach(function() { sandbox.restore(); - process.stdout.write = stdoutWrite; }); - describe('on start', function() { - it('should call cursor hide', function() { - sandbox.stub(Base.cursor, 'hide'); + describe('event handlers', function() { + describe("on 'start' event", function() { + it('should call cursor hide', function() { + var hideCursorStub = sandbox.stub(Base.cursor, 'hide'); - runner = createMockRunner('start', 'start'); - runReporter({}, runner, {}); + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + var options = {}; + runReporter({}, runner, options); + sandbox.restore(); - expect(Base.cursor.hide, 'was called'); + expect(hideCursorStub.called, 'to be true'); + }); }); - }); - - describe('on test end', function() { - describe('if line has not changed', function() { - it('should return and not write anything', function() { - sandbox.stub(Base, 'useColors').value(false); - sandbox.stub(Base.cursor, 'CR'); - sandbox.stub(Base.window, 'width').value(-3); - var expectedTotal = 1; - var expectedOptions = {}; - runner = createMockRunner('test end', 'test end'); - runner.total = expectedTotal; - var stdout = runReporter({}, runner, expectedOptions); - - expect(stdout, 'to equal', []); + describe("on 'test end' event", function() { + describe('when line has changed', function() { + it('should write expected progress of open and close options', function() { + var crCursorStub = sandbox.stub(Base.cursor, 'CR').callsFake(noop); + sandbox.stub(Base, 'useColors').value(false); + sandbox.stub(Base.window, 'width').value(5); + + var expectedTotal = 12; + var expectedOpen = 'OpEn'; + var expectedClose = 'cLoSe'; + var expectedIncomplete = 'iNcOmPlEtE'; + var expectedOptions = { + open: expectedOpen, + complete: 'cOmPlEtE', + incomplete: expectedIncomplete, + close: expectedClose + }; + + var runner = createMockRunner('test end', EVENT_TEST_END); + runner.total = expectedTotal; + var options = { + reporterOptions: expectedOptions + }; + var stdout = runReporter({}, runner, options); + sandbox.restore(); + + var expectedArray = [ + '\u001b[J', + ' ' + expectedOpen, + '', + expectedIncomplete, + expectedClose + ]; + + expect(crCursorStub.called, 'to be true'); + expect(stdout, 'to equal', expectedArray); + }); }); - }); - describe('if line has changed', function() { - it('should write expected progress of open and close options', function() { - sandbox.stub(Base, 'useColors').value(false); - sandbox.stub(Base.cursor, 'CR'); - sandbox.stub(Base.window, 'width').value(5); - - var expectedTotal = 12; - var expectedOpen = 'OpEn'; - var expectedClose = 'cLoSe'; - var expectedIncomplete = 'iNcOmPlEtE'; - var expectedOptions = { - open: expectedOpen, - complete: 'cOmPlEtE', - incomplete: expectedIncomplete, - close: expectedClose - }; - var options = { - reporterOptions: expectedOptions - }; - runner = createMockRunner('test end', 'test end'); - runner.total = expectedTotal; - var stdout = runReporter({}, runner, options); - - var expectedArray = [ - '\u001b[J', - ' ' + expectedOpen, - '', - expectedIncomplete, - expectedClose - ]; - expect(Base.cursor.CR, 'was called'); - expect(stdout, 'to equal', expectedArray); + + describe('when line has not changed', function() { + it('should not write anything', function() { + sandbox.stub(Base, 'useColors').value(false); + sandbox.stub(Base.cursor, 'CR').callsFake(noop); + sandbox.stub(Base.window, 'width').value(-3); + + var expectedTotal = 1; + var runner = createMockRunner('test end', EVENT_TEST_END); + runner.total = expectedTotal; + var options = {}; + var stdout = runReporter({}, runner, options); + sandbox.restore(); + + expect(stdout, 'to equal', []); + }); }); }); - }); - describe('on end', function() { - it('should call cursor show and epilogue', function() { - var reporterStub = {epilogue: function() {}}; - sandbox.stub(Base.cursor, 'show'); - sandbox.stub(reporterStub, 'epilogue'); - - runner = createMockRunner('end', 'end'); - runReporter(reporterStub, runner, {}); + describe("on 'end' event", function() { + it('should call cursor show and epilogue', function() { + var showCursorStub = sandbox.stub(Base.cursor, 'show'); + var fakeThis = { + epilogue: sinon.spy() + }; + var runner = createMockRunner('end', EVENT_RUN_END); + var options = {}; + runReporter(fakeThis, runner, options); + sandbox.restore(); - expect(reporterStub.epilogue, 'was called'); - expect(Base.cursor.show, 'was called'); + expect(fakeThis.epilogue.calledOnce, 'to be true'); + expect(showCursorStub.called, 'to be true'); + }); }); }); }); diff --git a/test/reporters/spec.spec.js b/test/reporters/spec.spec.js index 5f7584e33e..608bc7f512 100644 --- a/test/reporters/spec.spec.js +++ b/test/reporters/spec.spec.js @@ -1,104 +1,163 @@ 'use strict'; +var sinon = require('sinon'); +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; -var Spec = reporters.Spec; + var Base = reporters.Base; +var Spec = reporters.Spec; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_SUITE_BEGIN = events.EVENT_SUITE_BEGIN; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; describe('Spec reporter', function() { - var runner; - var options = {}; var runReporter = makeRunReporter(Spec); - var useColors; var expectedTitle = 'expectedTitle'; + var noop = function() {}; + var sandbox; beforeEach(function() { - useColors = Base.useColors; - Base.useColors = false; + sandbox = sinon.createSandbox(); + sandbox.stub(Base, 'useColors').value(false); }); afterEach(function() { - Base.useColors = useColors; - runner = undefined; + sandbox.restore(); }); - describe('on suite', function() { - it('should return title', function() { - var suite = { - title: expectedTitle - }; - runner = createMockRunner('suite', 'suite', null, null, suite); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = [expectedTitle + '\n']; - expect(stdout, 'to equal', expectedArray); - }); - }); - describe('on pending', function() { - it('should return title', function() { - var suite = { - title: expectedTitle - }; - runner = createMockRunner('pending test', 'pending', null, null, suite); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = [' - ' + expectedTitle + '\n']; - expect(stdout, 'to equal', expectedArray); + describe('event handlers', function() { + describe("on 'suite' event", function() { + it('should return title', function() { + var suite = { + title: expectedTitle + }; + var runner = createMockRunner( + 'suite', + EVENT_SUITE_BEGIN, + null, + null, + suite + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = [expectedTitle + '\n']; + expect(stdout, 'to equal', expectedArray); + }); }); - }); - describe('on pass', function() { - describe('if test speed is slow', function() { - it('should return expected tick, title and duration', function() { - var expectedDuration = 2; - var test = { - title: expectedTitle, - duration: expectedDuration, - slow: function() { - return 1; - } + + describe("on 'pending' event", function() { + it('should return title', function() { + var suite = { + title: expectedTitle }; - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedString = - ' ' + - Base.symbols.ok + - ' ' + - expectedTitle + - ' (' + - expectedDuration + - 'ms)' + - '\n'; - expect(stdout[0], 'to be', expectedString); + var runner = createMockRunner( + 'pending test', + EVENT_TEST_PENDING, + null, + null, + suite + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = [' - ' + expectedTitle + '\n']; + expect(stdout, 'to equal', expectedArray); }); }); - describe('if test speed is fast', function() { - it('should return expected tick, title and without a duration', function() { - var expectedDuration = 1; + + describe("on 'pass' event", function() { + describe('when test speed is slow', function() { + it('should return expected tick, title, and duration', function() { + var expectedDuration = 2; + var test = { + title: expectedTitle, + duration: expectedDuration, + slow: function() { + return 1; + } + }; + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedString = + ' ' + + Base.symbols.ok + + ' ' + + expectedTitle + + ' (' + + expectedDuration + + 'ms)' + + '\n'; + expect(stdout[0], 'to be', expectedString); + }); + }); + + describe('when test speed is fast', function() { + it('should return expected tick, title without a duration', function() { + var expectedDuration = 1; + var test = { + title: expectedTitle, + duration: expectedDuration, + slow: function() { + return 2; + } + }; + var runner = createMockRunner( + 'pass', + EVENT_TEST_PASS, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedString = + ' ' + Base.symbols.ok + ' ' + expectedTitle + '\n'; + expect(stdout[0], 'to be', expectedString); + }); + }); + }); + + describe("on 'fail' event", function() { + it('should return title and function count', function() { + var functionCount = 1; var test = { - title: expectedTitle, - duration: expectedDuration, - slow: function() { - return 2; - } + title: expectedTitle }; - runner = createMockRunner('pass', 'pass', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedString = - ' ' + Base.symbols.ok + ' ' + expectedTitle + '\n'; - expect(stdout[0], 'to be', expectedString); + var runner = createMockRunner( + 'fail', + EVENT_TEST_FAIL, + null, + null, + test + ); + var options = {}; + var stdout = runReporter({epilogue: noop}, runner, options); + sandbox.restore(); + + var expectedArray = [ + ' ' + functionCount + ') ' + expectedTitle + '\n' + ]; + expect(stdout, 'to equal', expectedArray); }); }); }); - describe('on fail', function() { - it('should return title and function count', function() { - var functionCount = 1; - var test = { - title: expectedTitle - }; - runner = createMockRunner('fail', 'fail', null, null, test); - var stdout = runReporter({epilogue: function() {}}, runner, options); - var expectedArray = [' ' + functionCount + ') ' + expectedTitle + '\n']; - expect(stdout, 'to equal', expectedArray); - }); - }); }); diff --git a/test/reporters/tap.spec.js b/test/reporters/tap.spec.js index c0a5419d37..f3bfe8d473 100644 --- a/test/reporters/tap.spec.js +++ b/test/reporters/tap.spec.js @@ -1,246 +1,295 @@ 'use strict'; +var events = require('../../').Runner.constants; +var helpers = require('./helpers'); var reporters = require('../../').reporters; + var TAP = reporters.TAP; +var createMockRunner = helpers.createMockRunner; +var makeRunReporter = helpers.createRunReporterFunction; -var createMockRunner = require('./helpers').createMockRunner; -var makeRunReporter = require('./helpers.js').createRunReporterFunction; +var EVENT_RUN_BEGIN = events.EVENT_RUN_BEGIN; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_END = events.EVENT_TEST_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; describe('TAP reporter', function() { - var runner; var runReporter = makeRunReporter(TAP); var expectedTitle = 'some title'; var countAfterTestEnd = 2; - var test; + var noop = function() {}; - beforeEach(function() { - test = { + function createTest() { + return { fullTitle: function() { return expectedTitle; }, - slow: function() {} + slow: noop }; - }); - - afterEach(function() { - runner = undefined; - test = undefined; - }); + } describe('TAP12 spec', function() { - var options = {}; - - describe('on start', function() { - var expectedSuite = 'some suite'; - var expectedTotal = 10; - var expectedString; - var stdout; - - before(function() { - runner = createMockRunner('start', 'start'); - runner.suite = expectedSuite; - runner.grepTotal = function(string) { - expectedString = string; - return expectedTotal; - }; - stdout = runReporter({}, runner, options); - }); - - it('should not write the TAP specification version', function() { - expect(stdout, 'not to contain', 'TAP version'); - }); - it('should write the number of tests that it plans to run', function() { - var expectedArray = ['1..' + expectedTotal + '\n']; - expect(stdout, 'to equal', expectedArray); - 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() {}; - - var stdout = runReporter({}, runner, options); - - var expectedMessage = - 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; - expect(stdout[0], 'to equal', expectedMessage); - }); - }); + var options = { + reporterOptions: { + tapVersion: '12' + } + }; - 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() {}; + describe('event handlers', function() { + describe("on 'start' event", function() { + var expectedSuite = 'some suite'; + var expectedTotal = 10; + var expectedString; + var stdout = []; + + before(function() { + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + runner.suite = expectedSuite; + runner.grepTotal = function(string) { + expectedString = string; + return expectedTotal; + }; + stdout = runReporter({}, runner, options); + }); - var stdout = runReporter({}, runner, options); + it('should not write a TAP specification version', function() { + expect(stdout, 'not to contain', 'TAP version'); + }); - var expectedMessage = - 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n'; - expect(stdout[0], 'to equal', expectedMessage); + it('should write the number of tests that it plans to run', function() { + var expectedArray = ['1..' + expectedTotal + '\n']; + 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 expectedErrorMessage = 'some error'; - var error = { - message: expectedErrorMessage - }; - runner = createMockRunner( - 'test end fail', - 'test end', - 'fail', + describe("on 'pending' event", function() { + var stdout = []; + + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'start test', + EVENT_TEST_END, + EVENT_TEST_PENDING, null, - test, - error + test ); - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedErrorMessage + '\n' - ]; - expect(stdout, 'to equal', expectedArray); + it('should write expected message including count and title', function() { + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; + expect(stdout[0], 'to equal', expectedMessage); }); }); - 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', + describe("on 'pass' event", function() { + var stdout; + + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'start test', + EVENT_TEST_END, + EVENT_TEST_PASS, null, - test, - error + test ); runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedStack + '\n' - ]; - expect(stdout, 'to equal', expectedArray); + it('should write expected message including count and title', function() { + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\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 expectedStack = 'some stack'; - var expectedErrorMessage = 'some error'; - var error = { - stack: expectedStack, - message: expectedErrorMessage - }; - runner = createMockRunner( - 'test end fail', - 'test end', - 'fail', - null, - test, - error - ); - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; - runner.suite = ''; - runner.grepTotal = function() {}; + describe("on 'fail' event", function() { + var expectedErrorMessage = 'some error'; + var expectedStack = 'some stack'; + + describe("when 'error' has only message", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + message: expectedErrorMessage + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message and error message', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedErrorMessage + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); - var stdout = runReporter({}, runner, options); + describe("when 'error' has only stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + stack: expectedStack + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message and stack', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedStack + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ' + expectedErrorMessage + '\n', - ' ' + expectedStack + '\n' - ]; - expect(stdout, 'to equal', expectedArray); + describe("when 'error' has both message and stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + stack: expectedStack, + message: expectedErrorMessage + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message, error message, and stack', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ' + expectedErrorMessage + '\n', + ' ' + expectedStack + '\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe("when 'error' has neither message nor stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = {}; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = runner.once = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message only', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\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 = createMockRunner( - 'test end fail', - 'test end', - 'fail', - null, - test, - error + describe("on 'end' event", function() { + var stdout; + + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'fail end pass', + EVENT_TEST_FAIL, + EVENT_RUN_END, + EVENT_TEST_PASS, + test ); - runner.on = runner.once = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + it('should write total tests, passes, and failures', function() { + var numberOfPasses = 1; + var numberOfFails = 1; + 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() {}; - - var stdout = runReporter({}, runner, options); - - 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); - }); - }); }); describe('TAP13 spec', function() { @@ -250,229 +299,270 @@ describe('TAP reporter', function() { } }; - describe('on start', function() { - var expectedSuite = 'some suite'; - var expectedTotal = 10; - var expectedString; - var stdout; - - before(function() { - runner = createMockRunner('start', 'start'); - runner.suite = expectedSuite; - runner.grepTotal = function(string) { - expectedString = string; - return expectedTotal; - }; - - stdout = runReporter({}, runner, options); - }); + describe('event handlers', function() { + describe("on 'start' event", function() { + var expectedSuite = 'some suite'; + var expectedTotal = 10; + var expectedString; + var stdout; + + before(function() { + var runner = createMockRunner('start', EVENT_RUN_BEGIN); + runner.suite = expectedSuite; + runner.grepTotal = function(string) { + expectedString = string; + return expectedTotal; + }; + stdout = runReporter({}, runner, options); + }); - it('should write the TAP specification version', function() { - var tapVersion = options.reporterOptions.tapVersion; - var expectedFirstLine = 'TAP version ' + tapVersion + '\n'; - expect(stdout[0], 'to equal', expectedFirstLine); - }); - it('should write the number of tests that it plans to run', function() { - var expectedSecondLine = '1..' + expectedTotal + '\n'; - expect(stdout[1], 'to equal', expectedSecondLine); - expect(expectedString, 'to be', expectedSuite); - }); - }); + it('should write the TAP specification version', function() { + var tapVersion = options.reporterOptions.tapVersion; + var expectedFirstLine = 'TAP version ' + tapVersion + '\n'; + expect(stdout[0], 'to equal', expectedFirstLine); + }); - 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() {}; - - var stdout = runReporter({}, runner, options); - - var expectedMessage = - 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; - expect(stdout[0], 'to equal', expectedMessage); + it('should write the number of tests that it plans to run', function() { + var expectedSecondLine = '1..' + expectedTotal + '\n'; + expect(stdout[1], 'to equal', expectedSecondLine); + expect(expectedString, 'to be', expectedSuite); + }); }); - }); - - 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() {}; - var stdout = runReporter({}, runner, options); + describe("on 'pending' event", function() { + var stdout; - 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() { - var expectedErrorMessage = 'some error'; - var error = { - message: expectedErrorMessage - }; - runner = createMockRunner( - 'test end fail', - 'test end', - 'fail', + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'start test', + EVENT_TEST_END, + EVENT_TEST_PENDING, null, - test, - error + test ); - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' message: |-\n', - ' ' + expectedErrorMessage + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + it('should write expected message including count and title', function() { + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + ' # SKIP -\n'; + expect(stdout[0], 'to equal', expectedMessage); }); }); - 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', + describe("on 'pass' event", function() { + var stdout; + + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'start test', + EVENT_TEST_END, + EVENT_TEST_PASS, null, - test, - error + test ); runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' stack: |-\n', - ' ' + expectedStack + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + it('should write expected message including count and title', function() { + var expectedMessage = + 'ok ' + countAfterTestEnd + ' ' + expectedTitle + '\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 expectedStack = 'some stack'; - var expectedErrorMessage = 'some error'; - var error = { - stack: expectedStack, - message: expectedErrorMessage - }; - runner = createMockRunner( - 'test end fail', - 'test end', - 'fail', - null, - test, - error - ); - runner.on = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; - runner.suite = ''; - runner.grepTotal = function() {}; + describe("on 'fail' event", function() { + var expectedErrorMessage = 'some error'; + var expectedStack = 'some stack'; + + describe("when 'error' has only message", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + message: expectedErrorMessage + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message and error message', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); - var stdout = runReporter({}, runner, options); + describe("when 'error' has only stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + stack: expectedStack + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message and stack', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); - var expectedArray = [ - 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', - ' ---\n', - ' message: |-\n', - ' ' + expectedErrorMessage + '\n', - ' stack: |-\n', - ' ' + expectedStack + '\n', - ' ...\n' - ]; - expect(stdout, 'to equal', expectedArray); + describe("when 'error' has both message and stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = { + stack: expectedStack, + message: expectedErrorMessage + }; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message, error message, and stack', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\n', + ' ---\n', + ' message: |-\n', + ' ' + expectedErrorMessage + '\n', + ' stack: |-\n', + ' ' + expectedStack + '\n', + ' ...\n' + ]; + expect(stdout, 'to equal', expectedArray); + }); + }); + + describe("when 'error' has neither message nor stack", function() { + var stdout; + + before(function() { + var test = createTest(); + var error = {}; + var runner = createMockRunner( + 'test end fail', + EVENT_TEST_END, + EVENT_TEST_FAIL, + null, + test, + error + ); + runner.on = runner.once = function(event, callback) { + if (event === EVENT_TEST_END) { + callback(); + } else if (event === EVENT_TEST_FAIL) { + callback(test, error); + } + }; + runner.suite = ''; + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + + it('should write expected message only', function() { + var expectedArray = [ + 'not ok ' + countAfterTestEnd + ' ' + expectedTitle + '\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 = createMockRunner( - 'test end fail', - 'test end', - 'fail', - null, - test, - error + describe("on 'end' event", function() { + var stdout; + + before(function() { + var test = createTest(); + var runner = createMockRunner( + 'fail end pass', + EVENT_TEST_FAIL, + EVENT_RUN_END, + EVENT_TEST_PASS, + test ); - runner.on = runner.once = function(event, callback) { - if (event === 'test end') { - callback(); - } else if (event === 'fail') { - callback(test, error); - } - }; runner.suite = ''; - runner.grepTotal = function() {}; - - var stdout = runReporter({}, runner, options); + runner.grepTotal = noop; + stdout = runReporter({}, runner, options); + }); + it('should write total tests, passes, and failures', function() { + var numberOfPasses = 1; + var numberOfFails = 1; + 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() {}; - - var stdout = runReporter({}, runner, options); - - 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); - }); - }); }); }); diff --git a/test/reporters/xunit.spec.js b/test/reporters/xunit.spec.js index 35555968a1..26fce4a1c4 100644 --- a/test/reporters/xunit.spec.js +++ b/test/reporters/xunit.spec.js @@ -1,25 +1,34 @@ 'use strict'; +var EventEmitter = require('events').EventEmitter; var fs = require('fs'); -var mkdirp = require('mkdirp'); +var os = require('os'); var path = require('path'); -var assert = require('assert'); +var mkdirp = require('mkdirp'); +var rimraf = require('rimraf'); +var sinon = require('sinon'); var createStatsCollector = require('../../lib/stats-collector'); -var EventEmitter = require('events').EventEmitter; +var events = require('../../').Runner.constants; var reporters = require('../../').reporters; -var constants = require('../../lib/runnable').constants; -var STATE_FAILED = constants.STATE_FAILED; -var STATE_PASSED = constants.STATE_PASSED; +var states = require('../../').Runnable.constants; + +var Base = reporters.Base; var XUnit = reporters.XUnit; +var EVENT_RUN_END = events.EVENT_RUN_END; +var EVENT_TEST_END = events.EVENT_TEST_END; +var EVENT_TEST_FAIL = events.EVENT_TEST_FAIL; +var EVENT_TEST_PASS = events.EVENT_TEST_PASS; +var EVENT_TEST_PENDING = events.EVENT_TEST_PENDING; + +var STATE_FAILED = states.STATE_FAILED; +var STATE_PASSED = states.STATE_PASSED; + describe('XUnit reporter', function() { - var stdout; - var stdoutWrite; - // the runner parameter of the reporter + var sandbox; var runner; + var noop = function() {}; - var callbackArgument = null; - var expectedFailure = 'some-failures'; var expectedLine = 'some-line'; var expectedClassName = 'fullTitle'; var expectedTitle = 'some title'; @@ -27,192 +36,286 @@ describe('XUnit reporter', function() { var expectedDiff = '\n + expected - actual\n\n -foo\n +bar\n '; var expectedStack = 'some-stack'; - var expectedWrite = null; beforeEach(function() { - stdout = []; - runner = {on: function() {}, once: function() {}}; + runner = {on: noop, once: noop}; createStatsCollector(runner); }); - describe('if reporter options output is given', function() { - var expectedOutput = 'some-output'; + describe("when 'reporterOptions.output' is provided", function() { + var expectedOutput = path.join(path.sep, 'path', 'to', 'some-output'); var options = { reporterOptions: { output: expectedOutput } }; - describe('but it cant create a write stream', function() { - it('should throw expected error', function() { - var fsCreateWriteStream = fs.createWriteStream; - fs.createWriteStream = false; - - var boundXUnit = XUnit.bind({}, runner, options); - expect(boundXUnit, 'to throw', 'file output not supported in browser'); - fs.createWriteStream = fsCreateWriteStream; + + describe('when fileStream can be created', function() { + var mkdirpSync; + var fsCreateWriteStream; + + beforeEach(function() { + sandbox = sinon.createSandbox(); + mkdirpSync = sandbox.stub(mkdirp, 'sync'); + fsCreateWriteStream = sandbox.stub(fs, 'createWriteStream'); }); - }); - describe('and it can create a write stream', function() { - it('should locate the output dir, create it, then assign as fileStream', function() { - var expectedDirectory; - var mkdirpSync = mkdirp.sync; - var pathDirname = path.dirname; - var fsCreateWriteStream = fs.createWriteStream; - mkdirp.sync = function(directory) { - expectedDirectory = directory; - }; - path.dirname = function(location) { - return location; - }; - fs.createWriteStream = function(streamDetails) { - return streamDetails; - }; - var contextVariables = { + it('should open given file for writing, recursively creating directories in pathname', function() { + var fakeThis = { fileStream: null }; - XUnit.call(contextVariables, runner, options); + XUnit.call(fakeThis, runner, options); - expect(expectedDirectory, 'to be', expectedOutput); - expect(contextVariables.fileStream, 'to be', expectedOutput); + var expectedDirectory = path.dirname(expectedOutput); + expect(mkdirpSync.calledWith(expectedDirectory), 'to be true'); + expect(fsCreateWriteStream.calledWith(expectedOutput), 'to be true'); + }); - fs.createWriteStream = fsCreateWriteStream; - mkdirp.sync = mkdirpSync; - path.dirname = pathDirname; + afterEach(function() { + sandbox.restore(); }); }); - }); - describe("on 'pending', 'pass' and 'fail' events", function() { - it("should add test to tests called on 'end' event", function() { - var pendingTest = { - name: 'pending', - slow: function() {} - }; - var failTest = { - name: 'fail', - slow: function() {} - }; - var passTest = { - name: 'pass', - slow: function() {} - }; - runner.on = runner.once = function(event, callback) { - if (event === 'pending') { - callback(pendingTest); - } - if (event === 'pass') { - callback(passTest); - } - if (event === 'fail') { - callback(failTest); - } - if (event === 'end') { - callback(); - } - }; + describe('when fileStream cannot be created', function() { + describe('when given an invalid pathname', function() { + var tmpdir; + var invalidPath; - var calledTests = []; - XUnit.call( - { - write: function() {}, - test: function(test) { - calledTests.push(test); + beforeEach(function createInvalidPath() { + tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'mocha-test-')); + + function touch(filename) { + fs.closeSync(fs.openSync(filename, 'w')); } - }, - runner - ); - var expectedCalledTests = [pendingTest, passTest, failTest]; - expect(calledTests, 'to equal', expectedCalledTests); + // Create path where file 'some-file' used as directory + invalidPath = path.join( + tmpdir, + 'some-file', + path.basename(expectedOutput) + ); + touch(path.dirname(invalidPath)); + }); + + it('should throw system error', function() { + var options = { + reporterOptions: { + output: invalidPath + } + }; + var boundXUnit = XUnit.bind({}, runner, options); + expect( + boundXUnit, + 'to throw', + expect.it('to be an', Error).and('to satisfy', { + syscall: 'mkdir', + code: 'EEXIST', + path: path.dirname(invalidPath) + }) + ); + }); + + afterEach(function() { + rimraf.sync(tmpdir); + }); + }); + + describe('when run in browser', function() { + beforeEach(function() { + sandbox = sinon.createSandbox(); + sandbox.stub(fs, 'createWriteStream').value(false); + }); + + it('should throw unsupported error', function() { + var boundXUnit = XUnit.bind({}, runner, options); + expect( + boundXUnit, + 'to throw', + 'file output not supported in browser' + ); + }); + + afterEach(function() { + sandbox.restore(); + }); + }); }); }); - describe('done', function() { - describe('if fileStream is truthy', function() { - it('should run callback with failure inside streams end', function() { - var xunit = new XUnit({on: function() {}, once: function() {}}); - var callback = function(failures) { - callbackArgument = failures; + describe('event handlers', function() { + describe("on 'pending', 'pass' and 'fail' events", function() { + it("should add test to tests called on 'end' event", function() { + var pendingTest = { + name: 'pending', + slow: noop + }; + var failTest = { + name: 'fail', + slow: noop + }; + var passTest = { + name: 'pass', + slow: noop }; - var calledEnd = false; - var fileStream = { - end: function(callback) { - calledEnd = true; + runner.on = runner.once = function(event, callback) { + if (event === EVENT_TEST_PENDING) { + callback(pendingTest); + } else if (event === EVENT_TEST_PASS) { + callback(passTest); + } else if (event === EVENT_TEST_FAIL) { + callback(failTest); + } else if (event === EVENT_RUN_END) { callback(); } }; - xunit.done.call({fileStream: fileStream}, expectedFailure, callback); - expect(calledEnd, 'to be', true); - expect(callbackArgument, 'to be', expectedFailure); - }); - }); - describe('if fileStream is falsy', function() { - it('should run callback with failure', function() { - var xunit = new XUnit({on: function() {}, once: function() {}}); - var callback = function(failures) { - callbackArgument = failures; + var calledTests = []; + var fakeThis = { + write: noop, + test: function(test) { + calledTests.push(test); + } }; - xunit.done.call({fileStream: false}, expectedFailure, callback); + XUnit.call(fakeThis, runner); - expect(callbackArgument, 'to be', expectedFailure); + var expectedCalledTests = [pendingTest, passTest, failTest]; + expect(calledTests, 'to equal', expectedCalledTests); }); }); }); - describe('write', function() { - describe('if fileStream is truthy', function() { - it('should call fileStream write with line and new line', function() { - var xunit = new XUnit({on: function() {}, once: function() {}}); - var fileStream = { - write: function(write) { - expectedWrite = write; + describe('#done', function() { + var xunit; + var options = { + reporterOptions: {} + }; + var expectedNFailures = 13; + var callback; + + beforeEach(function() { + sandbox = sinon.createSandbox(); + callback = sandbox.spy(); + }); + + afterEach(function() { + callback = null; + xunit = null; + sandbox.restore(); + }); + + describe('when output directed to file', function() { + var fakeThis; + + beforeEach(function() { + xunit = new XUnit(runner, options); + + fakeThis = { + fileStream: { + end: sinon.stub().callsFake(function(chunk, encoding, cb) { + if (typeof arguments[0] === 'function') { + cb = arguments[0]; + } + cb(); + }), + write: function(chunk, encoding, cb) {} } }; - xunit.write.call({fileStream: fileStream}, expectedLine); + }); - expect(expectedWrite, 'to be', expectedLine + '\n'); + it("should run completion callback via 'fileStream.end'", function() { + xunit.done.call(fakeThis, expectedNFailures, callback); + + expect(fakeThis.fileStream.end.calledOnce, 'to be true'); + expect(callback.calledOnce, 'to be true'); + expect(callback.calledWith(expectedNFailures), 'to be true'); }); }); - describe('if fileStream is falsy and stdout exists', function() { - it('should call write with line and new line', function() { - stdoutWrite = process.stdout.write; - process.stdout.write = function(string) { - stdout.push(string); - }; - var xunit = new XUnit({on: function() {}, once: function() {}}); - xunit.write.call({fileStream: false}, expectedLine); + describe('when output directed to stdout (or console)', function() { + var fakeThis; + + beforeEach(function() { + xunit = new XUnit(runner, options); + fakeThis = {}; + }); - process.stdout.write = stdoutWrite; + it('should run completion callback', function() { + xunit.done.call(fakeThis, expectedNFailures, callback); - expect(stdout[0], 'to be', expectedLine + '\n'); + expect(callback.calledOnce, 'to be true'); + expect(callback.calledWith(expectedNFailures), 'to be true'); }); }); - describe('if fileStream is falsy and stdout does not exist', function() { - it('should call write with line', function() { - stdoutWrite = process; + }); + + describe('#write', function() { + // :TODO: Method should be named 'writeln', not 'write' + describe('when output directed to file', function() { + var fileStream = { + write: sinon.spy() + }; + + it("should call 'fileStream.write' with line and newline", function() { + var xunit = new XUnit(runner); + var fakeThis = {fileStream: fileStream}; + xunit.write.call(fakeThis, expectedLine); + + expect(fileStream.write.calledWith(expectedLine + '\n'), 'to be true'); + }); + }); + + describe('when output directed to stdout', function() { + it("should call 'process.stdout.write' with line and newline", function() { + var xunit = new XUnit(runner); + var fakeThis = {fileStream: false}; + var stdoutWriteStub = sinon.stub(process.stdout, 'write'); + xunit.write.call(fakeThis, expectedLine); + stdoutWriteStub.restore(); + + expect(stdoutWriteStub.calledWith(expectedLine + '\n'), 'to be true'); + }); + }); + + describe('when output directed to console', function() { + it("should call 'console.log' with line", function() { + // :TODO: XUnit needs a trivially testable means to force console.log() + var realProcess = process; process = false; // eslint-disable-line no-native-reassign, no-global-assign - var cachedConsoleLog = console.log; - console.log = function(string) { - stdout.push(string); - }; - var xunit = new XUnit({on: function() {}, once: function() {}}); - xunit.write.call({fileStream: false}, expectedLine); + var xunit = new XUnit(runner); + var fakeThis = {fileStream: false}; + var consoleLogStub = sinon.stub(console, 'log'); + xunit.write.call(fakeThis, expectedLine); + consoleLogStub.restore(); - console.log = cachedConsoleLog; - process = stdoutWrite; // eslint-disable-line no-native-reassign, no-global-assign - expect(stdout[0], 'to be', expectedLine); + process = realProcess; // eslint-disable-line no-native-reassign, no-global-assign + + expect(consoleLogStub.calledWith(expectedLine), 'to be true'); }); }); }); - describe('test', function() { + describe('#test', function() { + var expectedWrite; + var fakeThis = { + write: function(str) { + expectedWrite = str; + } + }; + + beforeEach(function() { + sandbox = sinon.createSandbox(); + sandbox.stub(Base, 'useColors').value(false); + }); + + afterEach(function() { + sandbox.restore(); + expectedWrite = null; + }); + describe('on test failure', function() { it('should write expected tag with error details', function() { - var xunit = new XUnit({on: function() {}, once: function() {}}); + var xunit = new XUnit(runner); var expectedTest = { state: STATE_FAILED, title: expectedTitle, @@ -229,14 +332,9 @@ describe('XUnit reporter', function() { stack: expectedStack } }; - xunit.test.call( - { - write: function(string) { - expectedWrite = string; - } - }, - expectedTest - ); + + xunit.test.call(fakeThis, expectedTest); + sandbox.restore(); var expectedTag = ''; - expect(expectedWrite, 'to be', expectedTag); }); }); + describe('on test in any other state', function() { it('should write expected tag', function() { - var xunit = new XUnit({on: function() {}, once: function() {}}); - + var xunit = new XUnit(runner); var expectedTest = { isPending: function() { return false; @@ -305,14 +396,9 @@ describe('XUnit reporter', function() { }, duration: false }; - xunit.test.call( - { - write: function(string) { - expectedWrite = string; - } - }, - expectedTest - ); + + xunit.test.call(fakeThis, expectedTest); + sandbox.restore(); var expectedTag = ''; - expect(expectedWrite, 'to be', expectedTag); }); }); + it('should write expected summary statistics', function() { - var count = 0; + var numTests = 0; + var numPass = 0; + var numFail = 0; var simpleError = { actual: 'foo', expected: 'bar', @@ -333,8 +421,14 @@ describe('XUnit reporter', function() { stack: expectedStack }; var generateTest = function(passed) { - var t = { - title: expectedTitle + count, + numTests++; + if (passed) { + numPass++; + } else { + numFail++; + } + return { + title: [expectedTitle, numTests].join(': '), state: passed ? STATE_PASSED : STATE_FAILED, isPending: function() { return false; @@ -349,26 +443,36 @@ describe('XUnit reporter', function() { }, duration: 1000 }; - return t; }; var runner = new EventEmitter(); createStatsCollector(runner); var xunit = new XUnit(runner); expectedWrite = ''; - xunit.write = function(string) { - expectedWrite += string; - }; + sandbox.stub(xunit, 'write').callsFake(function(str) { + expectedWrite += str; + }); // 3 tests, no failures (i.e. tests that could not run), and 2 errors - runner.emit('test end'); - runner.emit('pass', generateTest(true)); - runner.emit('test end'); - runner.emit('fail', generateTest(false), simpleError); - runner.emit('test end'); - runner.emit('fail', generateTest(false), simpleError); - runner.emit('end'); + runner.emit(EVENT_TEST_PASS, generateTest(true)); + runner.emit(EVENT_TEST_END); + runner.emit(EVENT_TEST_FAIL, generateTest(false), simpleError); + runner.emit(EVENT_TEST_END); + runner.emit(EVENT_TEST_FAIL, generateTest(false), simpleError); + runner.emit(EVENT_TEST_END); + runner.emit(EVENT_RUN_END); + + sandbox.restore(); + + var expectedNumPass = 1; + var expectedNumFail = 2; + var expectedNumTests = 3; + + expect(expectedNumPass, 'to be', numPass); + expect(expectedNumFail, 'to be', numFail); + expect(expectedNumTests, 'to be', numTests); + // :NOTE: Mocha test "fail" is an XUnit "error" var expectedTag = '= 0, - 'it should contain the text "Mocha Tests"' - ); + expect(lines[0], 'to contain', customSuiteName); }); - it('should use the custom suite name as the suite name when provided in the reporter options', function() { - // arrange + it('should use default name otherwise', function() { + var defaultSuiteName = 'Mocha Tests'; var options = { - reporterOptions: { - // this time, with a custom suite name - suiteName: 'Mocha Is Great!' - } + reporterOptions: {} }; var xunit = new XUnit(runner, options); xunit.fileStream = fileStream; - // act (trigger the end event to force xunit reporter to write the output) - events['end'](); + // Trigger end event to force XUnit reporter to write its output + events[EVENT_RUN_END](); - // assert - assert( - lines[0].indexOf('