diff --git a/test/reporters/xunit.spec.js b/test/reporters/xunit.spec.js new file mode 100644 index 0000000000..8b54776784 --- /dev/null +++ b/test/reporters/xunit.spec.js @@ -0,0 +1,316 @@ +'use strict'; + +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var path = require('path'); +var reporters = require('../../').reporters; +var XUnit = reporters.XUnit; + +describe('XUnit reporter', function () { + var stdout; + var stdoutWrite; + var runner; + + beforeEach(function () { + stdout = []; + runner = { + on: function () {} + }; + }); + + describe('if reporter options output is given', function () { + var expectedOutput = '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); + boundXUnit.should.throw('file output not supported in browser'); + fs.createWriteStream = fsCreateWriteStream; + }); + }); + 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 = { + fileStream: null + }; + XUnit.call(contextVariables, runner, options); + + expectedDirectory.should.equal(expectedOutput); + contextVariables.fileStream.should.equal(expectedOutput); + + fs.createWriteStream = fsCreateWriteStream; + mkdirp.sync = mkdirpSync; + path.dirname = pathDirname; + }); + }); + }); + + 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 = function (event, callback) { + if (event === 'pending') { + callback(pendingTest); + } + if (event === 'pass') { + callback(passTest); + } + if (event === 'fail') { + callback(failTest); + } + if (event === 'end') { + callback(); + } + }; + + var calledTests = []; + XUnit.call({ + write: function () {}, + test: function (test) { + calledTests.push(test); + } + }, runner); + + var expectedCalledTests = [ + pendingTest, + passTest, + failTest + ]; + calledTests.should.deepEqual(expectedCalledTests); + }); + }); + + describe('done', function () { + describe('if fileStream is truthly', function () { + it('should run callback with failure inside streams end', function () { + var xunit = new XUnit({on: function () {}}); + var callbackArgument = null; + var callback = function (failures) { + callbackArgument = failures; + }; + var calledEnd = false; + var expectedFailure = 'some-failures'; + var fileStream = { + end: function (callback) { + calledEnd = true; + callback(); + } + }; + xunit.done.call( + { fileStream: fileStream }, + expectedFailure, + callback + ); + + calledEnd.should.be.true(); + callbackArgument.should.equal(expectedFailure); + }); + }); + describe('if fileStream is falsy', function () { + it('should run callback with failure', function () { + var xunit = new XUnit({on: function () {}}); + var callbackArgument = null; + var callback = function (failures) { + callbackArgument = failures; + }; + var expectedFailure = 'some-failures'; + xunit.done.call( + { fileStream: false }, + expectedFailure, + callback + ); + + callbackArgument.should.equal(expectedFailure); + }); + }); + }); + + describe('write', function () { + describe('if fileStream is truthly', function () { + it('should call fileStream write with line and new line', function () { + var expectedWrite = null; + var xunit = new XUnit({on: function () {}}); + var fileStream = { + write: function (write) { + expectedWrite = write; + } + }; + var expectedLine = 'some-line'; + xunit.write.call( + { fileStream: fileStream }, + expectedLine + ); + + expectedWrite.should.equal(expectedLine + '\n'); + }); + }); + 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 () {}}); + var expectedLine = 'some-line'; + xunit.write.call( + { fileStream: false }, + expectedLine + ); + + process.stdout.write = stdoutWrite; + + stdout[0].should.equal(expectedLine + '\n'); + }); + }); + describe('if fileStream is falsy and stdout does not exist', function () { + it('should call write with line', function () { + stdoutWrite = 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 () {}}); + var expectedLine = 'some-line'; + xunit.write.call( + { fileStream: false }, + expectedLine + ); + + console.log = cachedConsoleLog; + process = stdoutWrite; // eslint-disable-line no-native-reassign, no-global-assign + stdout[0].should.equal(expectedLine); + }); + }); + }); + + describe('test', function () { + describe('on test failure', function () { + it('should write expected tag with error details', function () { + var xunit = new XUnit({on: function () {}}); + + var expectedWrite = null; + var expectedClassName = 'fullTitle'; + var expectedTitle = 'some title'; + var expectedMessage = 'some message'; + var expectedStack = 'some-stack'; + var expectedTest = { + state: 'failed', + title: expectedTitle, + parent: { + fullTitle: function () { + return expectedClassName; + } + }, + duration: 1000, + err: { + message: expectedMessage, + stack: expectedStack + } + }; + xunit.test.call( + { + write: function (string) { + expectedWrite = string; + } + }, + expectedTest + ); + + var expectedTag = '' + expectedMessage + '\n' + expectedStack + ''; + + expectedWrite.should.equal(expectedTag); + }); + }); + describe('on test pending', function () { + it('should write expected tag', function () { + var xunit = new XUnit({on: function () {}}); + + var expectedClassName = 'fullTitle'; + var expectedTitle = 'some title'; + var expectedTest = { + isPending: function () { return true; }, + title: expectedTitle, + parent: { + fullTitle: function () { + return expectedClassName; + } + }, + duration: 1000 + }; + var expectedWrite = null; + xunit.test.call( + { + write: function (string) { + expectedWrite = string; + } + }, + expectedTest + ); + + var expectedTag = ''; + + expectedWrite.should.equal(expectedTag); + }); + }); + describe('on test in any other state', function () { + it('should write expected tag', function () { + var xunit = new XUnit({on: function () {}}); + + var expectedClassName = 'fullTitle'; + var expectedTitle = 'some title'; + var expectedTest = { + isPending: function () { return false; }, + title: expectedTitle, + parent: { + fullTitle: function () { + return expectedClassName; + } + }, + duration: false + }; + var expectedWrite = null; + xunit.test.call( + { + write: function (string) { + expectedWrite = string; + } + }, + expectedTest + ); + + var expectedTag = ''; + + expectedWrite.should.equal(expectedTag); + }); + }); + }); +});