Skip to content

Commit

Permalink
Fix bug with XUnit reporter
Browse files Browse the repository at this point in the history
Passing grunt options to Reporter instance that may have
  reporterOptions property. It’s required for XUnit reporter.
Overriding the whole XUnit from mochajs due to bugs with
  test.isPending() methods. As described in:
  mochajs/mocha#2297
  kmiyashiro/grunt-mocha#163
  • Loading branch information
eugenet8k committed Sep 29, 2016
1 parent 2a42352 commit 93d3cad
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 29 deletions.
3 changes: 2 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ module.exports = function(grunt) {
jshint: {
all: [
'Gruntfile.js',
'tasks/**/*.js', ],
'tasks/**/*.js'
],
options: {
jshintrc: '.jshintrc'
}
Expand Down
42 changes: 25 additions & 17 deletions example-requirejs/Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,31 @@ module.exports = function(grunt) {
"use strict";

grunt.initConfig({

blanket_mocha : {
test: {
src: ['test.html'],
options : {
threshold : 60,
globalThreshold : 65,
log : true,
logErrors: true,
moduleThreshold : 60,
modulePattern : "./src/(.*?)/",
customThreshold: {
'./src/spelling/plurals.js': 50
}
}
blanket_mocha : {
options : {
threshold : 60,
globalThreshold : 65,
log : true,
logErrors: true,
moduleThreshold : 60,
modulePattern : "./src/(.*?)/",
customThreshold: {
'./src/spelling/plurals.js': 50
}
},
test: {
src: ['test.html'],
},
xunit: {
src: ['test.html'],
options : {
reporter: 'XUnit',
reporterOptions: {
output: 'test-results.xml'
}

}
}
}
});

// Loading dependencies
Expand All @@ -31,6 +38,7 @@ module.exports = function(grunt) {
}
}

grunt.registerTask('coverage', ['blanket_mocha']);
grunt.registerTask('coverage', ['blanket_mocha:test']);
grunt.registerTask('xunit', ['blanket_mocha:xunit']);
grunt.registerTask('default', ['blanket_mocha']);
};
2 changes: 1 addition & 1 deletion example-requirejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"devDependencies": {
"blanket": "~1.2.3",
"chai": "1.8.1",
"grunt-mocha-blanket": "0.6.2",
"grunt-mocha-blanket": "0.6.5",
"grunt-cli": "~1.2.0",
"grunt": "~0.4.5",
"mocha": "~3.1.0",
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"devDependencies": {
"blanket": "~1.2.3",
"chai": "1.8.1",
"grunt-mocha-blanket": "0.6.2",
"grunt-mocha-blanket": "0.6.5",
"grunt-cli": "~1.2.0",
"grunt": "~0.4.5",
"mocha": "~3.1.0"
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "grunt-mocha-blanket",
"description": "Headless Blanket.js code coverage and Mocha testing via PhantomJS",
"version": "0.6.2",
"version": "0.6.5",
"homepage": "https://github.com/eugenet8k/grunt-mocha-blanket",
"author": {
"name": "Dave Cadwallader",
Expand Down Expand Up @@ -41,19 +41,20 @@
"test": "grunt test"
},
"dependencies": {
"blanket": "~1.2.3",
"grunt-lib-phantomjs": "~1.1.0",
"lodash": "~2.4.1",
"mocha": "~3.1.0"
"blanket": "1.2.3",
"grunt-lib-phantomjs": "1.1.0",
"lodash": "2.4.1",
"mkdirp": "0.5.1",
"mocha": "3.1.0"
},
"peerDependencies": {
"grunt": "~0.4.5"
"grunt": "0.4.5"
},
"devDependencies": {
"grunt-cli": "1.2.0",
"grunt-contrib-connect": "1.0.2",
"grunt-contrib-jshint": "1.0.0",
"grunt": "~0.4.5"
"grunt": "0.4.5"
},
"keywords": [
"blanket",
Expand Down
8 changes: 8 additions & 0 deletions support/mocha-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,11 @@ exports.reduceStats = function(stats) {
exports.formatMs = function(ms) {
return (Math.ceil(ms * 100) / 100000).toFixed(2);
}

/*
* Overriding XUnit reporter from mochajs. Due to bug described in:
* https://github.com/mochajs/mocha/issues/2297
* https://github.com/kmiyashiro/grunt-mocha/issues/163
*/
var reporters = require('mocha').reporters;
reporters['XUnit'] = require('./xunit');
172 changes: 172 additions & 0 deletions support/xunit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**
* Overriden XUnit reporter from mochajs. Due to bug described in:
* https://github.com/mochajs/mocha/issues/2297
* https://github.com/kmiyashiro/grunt-mocha/issues/163
*
* test.isPending() by some reason is unavailable, using old school test.pending instead of.
*
* Module dependencies.
*/

var Base = require('mocha/lib/reporters/base');
var utils = require('mocha/lib/utils');
var inherits = utils.inherits;
var fs = require('fs');
var escape = utils.escape;
var mkdirp = require('mkdirp');
var path = require('path');

/**
* HTML tag helper.
*
* @param name
* @param attrs
* @param close
* @param content
* @return {string}
*/
function tag(name, attrs, close, content) {
var end = close ? '/>' : '>';
var pairs = [];
var tag;

for (var key in attrs) {
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
pairs.push(key + '="' + escape(attrs[key]) + '"');
}
}

tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
if (content) {
tag += content + '</' + name + end;
}
return tag;
}

/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/

/* eslint-disable no-unused-vars, no-native-reassign */
var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;
/* eslint-enable no-unused-vars, no-native-reassign */

/**
* Expose `XUnit`.
*/

exports = module.exports = XUnit;

/**
* Initialize a new `XUnit` reporter.
*
* @api public
* @param {Runner} runner
*/
function XUnit(runner, options) {
Base.call(this, runner);

var stats = this.stats;
var tests = [];
var self = this;

if (options.reporterOptions && options.reporterOptions.output) {
if (!fs.createWriteStream) {
throw new Error('file output not supported in browser');
}
mkdirp.sync(path.dirname(options.reporterOptions.output));
self.fileStream = fs.createWriteStream(options.reporterOptions.output);
}

runner.on('pending', function(test) {
tests.push(test);
});

runner.on('pass', function(test) {
tests.push(test);
});

runner.on('fail', function(test) {
tests.push(test);
});

runner.on('end', function() {
self.write(tag('testsuite', {
name: 'Mocha Tests',
tests: stats.tests,
failures: stats.failures,
errors: stats.failures,
skipped: stats.tests - stats.failures - stats.passes,
timestamp: (new Date()).toUTCString(),
time: (stats.duration / 1000) || 0
}, false));

tests.forEach(function(t) {
self.test(t);
});

self.write('</testsuite>');
});
}

/**
* Inherit from `Base.prototype`.
*/
inherits(XUnit, Base);

/**
* Override done to close the stream (if it's a file).
*
* @param failures
* @param {Function} fn
*/
XUnit.prototype.done = function(failures, fn) {
if (this.fileStream) {
this.fileStream.end(function() {
fn(failures);
});
} else {
fn(failures);
}
};

/**
* Write out the given line.
*
* @param {string} line
*/
XUnit.prototype.write = function(line) {
if (this.fileStream) {
this.fileStream.write(line + '\n');
} else if (typeof process === 'object' && process.stdout) {
process.stdout.write(line + '\n');
} else {
console.log(line);
}
};

/**
* Output tag for the given `test.`
*
* @param {Test} test
*/
XUnit.prototype.test = function(test) {
var attrs = {
classname: test.parent.fullTitle(),
name: test.title,
time: (test.duration / 1000) || 0
};

if (test.state === 'failed') {
var err = test.err;
this.write(tag('testcase', attrs, false, tag('failure', {}, false, escape(err.message) + '\n' + escape(err.stack))));
} else if (test.pending) {
this.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
} else {
this.write(tag('testcase', attrs, true));
}
};
9 changes: 7 additions & 2 deletions tasks/blanket_mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ module.exports = function(grunt) {

// Only hijack if we really need to
if (dest) {
grunt.file.delete(dest);
console.log = function() {
consoleLog.apply(console, arguments);
// FIXME: This breaks older versions of mocha
Expand Down Expand Up @@ -351,7 +352,7 @@ module.exports = function(grunt) {
if (Reporter === null) {
grunt.fatal('Specified reporter is unknown or unresolvable: ' + options.reporter);
}
reporter = new Reporter(runner);
reporter = new Reporter(runner, options);

// Launch PhantomJS.
phantomjs.spawn(url, {
Expand Down Expand Up @@ -401,7 +402,11 @@ module.exports = function(grunt) {
if (dest) {
// Restore console.log to original and write the output
console.log = consoleLog;
grunt.file.write(dest, output.join('\n'));

if (!grunt.file.exists(dest)) {
// Write only if our reporter ignored our `output` option
grunt.file.write(dest, output.join('\n'));
}
}
grunt.log.writeln();

Expand Down

0 comments on commit 93d3cad

Please sign in to comment.