Skip to content

Commit

Permalink
Added jUnit Support (Fixes #16)
Browse files Browse the repository at this point in the history
  • Loading branch information
xjamundx committed Jul 21, 2013
1 parent 934d766 commit 3d00661
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
95 changes: 95 additions & 0 deletions lib/formatters/junit.js
@@ -0,0 +1,95 @@
/**
* @fileoverview jUnit Reporter
* @author Jamund Ferguson
*/

/*jshint node:true*/

//------------------------------------------------------------------------------
// Helper Functions
//------------------------------------------------------------------------------

function getMessageType(message, rules) {

if (message.fatal || rules[message.ruleId] === 2) {
return "Error";
} else {
return "Warning";
}

}

/**
* Replace special characters before write to output.
*
* Rules:
* - single quotes is the escape sequence for double-quotes
* - &lt; is the escape sequence for <
* - &gt; is the escape sequence for >
* - &quot; is the escape sequence for "
* - &apos; is the escape sequence for '
* - &amp; is the escape sequence for &
*
* @param {String} message to escape
* @return escaped message as {String}
*/
function escapeSpecialCharacters(str) {

str = str || "";
var pairs = {
"&": "&amp;",
"\"": "&quot;",
"'": "&apos;",
"<": "&lt;",
">": "&gt;"
};
for (var r in pairs) {
str = str.replace(new RegExp(r, "g"), pairs[r]);
}
return str || "";

}

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = function(results, config) {

var output = "",
rules = config.rules || {};

output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
output += "<testsuites>\n";

results.forEach(function(result) {

var messages = result.messages;

if (messages.length) {
output += "<testsuite package=\"org.eslint\" time=\"0\" tests=\"" + messages.length + "\" errors=\"" + messages.length + "\" name=\"" + result.filePath + "\">\n";
}

messages.forEach(function(message) {
var type = message.fatal ? "error" : "failure";
output += "<testcase time=\"0\" name=\"org.eslint." + (message.ruleId || "unknown") + "\">";
output += "<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\">";
output += "<![CDATA[";
output += "line " + message.line + ", col ";
output += message.column + ", " + getMessageType(message, rules);
output += " - " + escapeSpecialCharacters(message.message);
output += "]]>";
output += "</" + type + ">";
output += "</testcase>\n";
});

if (messages.length) {
output += "</testsuite>\n";
}

});

output += "</testsuites>\n";

return output;
};
136 changes: 136 additions & 0 deletions tests/lib/formatters/junit.js
@@ -0,0 +1,136 @@
/**
* @fileoverview Tests for jUnit Formatter.
* @author Jamund Ferguson
*/

/*jshint node:true*/

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var vows = require("vows"),
assert = require("assert"),
sinon = require("sinon"),
formatter = require("../../../lib/formatters/junit");

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

vows.describe("formatter:junit").addBatch({

"when there are no problems": {

topic: [],

"should not complain about anything": function(topic) {
var config = {}; // not needed for this test
var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites></testsuites>', result.replace(/\n/g, ""));
}
},

"when passed a single message": {

topic: [{
filePath: "foo.js",
messages: [{
message: "Unexpected foo.",
line: 5,
column: 10,
ruleId: "foo"
}]
}],

"should return a single <testcase> with a message and the line and col number in the body (error)": function(topic) {
var config = {
rules: { foo: 2 }
};

var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite package="org.eslint" time="0" tests="1" errors="1" name="foo.js"><testcase time="0" name="org.eslint.foo"><failure message="Unexpected foo."><![CDATA[line 5, col 10, Error - Unexpected foo.]]></failure></testcase></testsuite></testsuites>', result.replace(/\n/g, ""));
},

"should return a single <testcase> with a message and the line and col number in the body (warning)": function(topic) {
var config = {
rules: { foo: 1 }
};

var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite package="org.eslint" time="0" tests="1" errors="1" name="foo.js"><testcase time="0" name="org.eslint.foo"><failure message="Unexpected foo."><![CDATA[line 5, col 10, Warning - Unexpected foo.]]></failure></testcase></testsuite></testsuites>', result.replace(/\n/g, ""));
}

},

"when passed a fatal error message": {

topic: [{
filePath: "foo.js",
messages: [{
fatal: true,
message: "Unexpected foo.",
line: 5,
column: 10,
ruleId: "foo"
}]
}],

"should return a single <testcase> and an <error>": function(topic) {
var config = {};
var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite package="org.eslint" time="0" tests="1" errors="1" name="foo.js"><testcase time="0" name="org.eslint.foo"><error message="Unexpected foo."><![CDATA[line 5, col 10, Error - Unexpected foo.]]></error></testcase></testsuite></testsuites>', result.replace(/\n/g, ""));
}
},

"when passed multiple messages": {

topic: [{
filePath: "foo.js",
messages: [{
message: "Unexpected foo.",
line: 5,
column: 10,
ruleId: "foo"
}, {
message: "Unexpected bar.",
line: 6,
column: 11,
ruleId: "bar"
}]
}],

"should return a multiple <testcase>'s": function(topic) {
var config = {
rules: { foo: 2, bar: 1 }
};

var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite package="org.eslint" time="0" tests="2" errors="2" name="foo.js"><testcase time="0" name="org.eslint.foo"><failure message="Unexpected foo."><![CDATA[line 5, col 10, Error - Unexpected foo.]]></failure></testcase><testcase time="0" name="org.eslint.bar"><failure message="Unexpected bar."><![CDATA[line 6, col 11, Warning - Unexpected bar.]]></failure></testcase></testsuite></testsuites>', result.replace(/\n/g, ""));
}

},

"when passed special characters": {

topic: [{
filePath: "foo.js",
messages: [{
message: "Unexpected <foo></foo>.",
line: 5,
column: 10,
ruleId: "foo"
}]
}],

"should make them go away": function(topic) {
var config = {
rules: { foo: 1 }
};

var result = formatter(topic, config);
assert.equal('<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite package="org.eslint" time="0" tests="1" errors="1" name="foo.js"><testcase time="0" name="org.eslint.foo"><failure message="Unexpected &lt;foo&gt;&lt;/foo&gt;."><![CDATA[line 5, col 10, Warning - Unexpected &lt;foo&gt;&lt;/foo&gt;.]]></failure></testcase></testsuite></testsuites>', result.replace(/\n/g, ""));

}
},
}).export(module);

0 comments on commit 3d00661

Please sign in to comment.