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('