Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of github.com:stubbornella/csslint

  • Loading branch information...
commit 14033f64bbcdc44557c1906f348c3ccc88d7858f 2 parents e14628b + e6f90a9
@nzakas nzakas authored
Showing with 159 additions and 0 deletions.
  1. +105 −0 src/formatters/junit-xml.js
  2. +54 −0 tests/formatters/junit-xml.js
View
105 src/formatters/junit-xml.js
@@ -0,0 +1,105 @@
+/*global CSSLint*/
+CSSLint.addFormatter({
+ //format information
+ id: "junit-xml",
+ name: "JUNIT XML format",
+
+ /**
+ * Return opening root XML tag.
+ * @return {String} to prepend before all results
+ */
+ startFormat: function(){
+ return "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>";
+ },
+
+ /**
+ * Return closing root XML tag.
+ * @return {String} to append after all results
+ */
+ endFormat: function() {
+ return "</testsuites>";
+ },
+
+ /**
+ * Given CSS Lint results for a file, return output for this format.
+ * @param results {Object} with error and warning messages
+ * @param filename {String} relative file path
+ * @param options {Object} (UNUSED for now) specifies special handling of output
+ * @return {String} output for results
+ */
+ formatResults: function(results, filename, options) {
+
+ var messages = results.messages,
+ output = [],
+ tests = {
+ 'error': 0,
+ 'failure': 0
+ };
+
+ /**
+ * Generate a source string for a rule.
+ * JUNIT source strings usually resemble Java class names e.g
+ * net.csslint.SomeRuleName
+ * @param {Object} rule
+ * @return rule source as {String}
+ */
+ var generateSource = function(rule) {
+ if (!rule || !('name' in rule)) {
+ return "";
+ }
+ return 'net.csslint.' + rule.name.replace(/\s/g,'');
+ };
+
+ /**
+ * 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 >
+ *
+ * @param {String} message to escape
+ * @return escaped message as {String}
+ */
+ var escapeSpecialCharacters = function(str) {
+
+ if (!str || str.constructor !== String) {
+ return "";
+ }
+
+ return str.replace(/\"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+
+ };
+
+ if (messages.length > 0) {
+
+ messages.forEach(function (message, i) {
+
+ // since junit has no warning class
+ // all issues as errors
+ var type = message.type === 'warning' ? 'error' : message.type;
+
+ //ignore rollups for now
+ if (!message.rollup) {
+
+ // build the test case seperately, once joined
+ // we'll add it to a custom array filtered by type
+ output.push("<testcase time=\"0\" name=\"" + generateSource(message.rule) + "\">");
+ output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\"><![CDATA[" + message.line + ':' + message.col + ':' + escapeSpecialCharacters(message.evidence) + "]]></" + type + ">");
+ output.push("</testcase>");
+
+ tests[type] += 1;
+
+ }
+
+ });
+
+ output.unshift("<testsuite time=\"0\" tests=\"" + messages.length + "\" skipped=\"0\" errors=\"" + tests.error + "\" failures=\"" + tests.failure + "\" package=\"net.csslint\" name=\"" + filename + "\">");
+ output.push("</testsuite>");
+
+ }
+
+ return output.join("");
+
+ }
+});
View
54 tests/formatters/junit-xml.js
@@ -0,0 +1,54 @@
+(function(){
+
+ /*global YUITest, CSSLint*/
+ var Assert = YUITest.Assert;
+
+ YUITest.TestRunner.add(new YUITest.TestCase({
+
+ name: "JUNIT XML formatter test",
+
+ "File with no problems should say so": function(){
+
+ var result = { messages: [], stats: [] },
+ expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites></testsuites>";
+ Assert.areEqual(expected, CSSLint.format(result, "FILE", "junit-xml"));
+
+ },
+
+ "File with problems should list them": function(){
+
+ var result = { messages: [
+ { type: "warning", line: 1, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: { name: "A Rule"} },
+ { type: "error", line: 2, col: 1, message: "BOGUS", evidence: "ALSO BOGUS", rule: { name: "Some Other Rule"} }
+ ], stats: [] },
+
+ file = "<testsuite time=\"0\" tests=\"2\" skipped=\"0\" errors=\"2\" failures=\"0\" package=\"net.csslint\" name=\"FILE\">",
+ error1 = "<testcase time=\"0\" name=\"net.csslint.ARule\"><error message=\"BOGUS\"><![CDATA[1:1:ALSO BOGUS]]></error></testcase>",
+ error2 = "<testcase time=\"0\" name=\"net.csslint.SomeOtherRule\"><error message=\"BOGUS\"><![CDATA[2:1:ALSO BOGUS]]></error></testcase>",
+ expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>" + file + error1 + error2 + "</testsuite></testsuites>",
+ actual = CSSLint.format(result, "FILE", "junit-xml");
+
+ Assert.areEqual(expected, actual);
+
+ },
+
+ "Formatter should escape special characters": function() {
+
+ var specialCharsSting = 'sneaky, "sneaky", <sneaky>',
+ result = { messages: [
+ { type: "warning", line: 1, col: 1, message: specialCharsSting, evidence: "ALSO BOGUS", rule: [] },
+ { type: "error", line: 2, col: 1, message: specialCharsSting, evidence: "ALSO BOGUS", rule: [] }
+ ], stats: [] },
+
+ file = "<testsuite time=\"0\" tests=\"2\" skipped=\"0\" errors=\"2\" failures=\"0\" package=\"net.csslint\" name=\"FILE\">",
+ error1 = "<testcase time=\"0\" name=\"\"><error message=\"sneaky, 'sneaky', &lt;sneaky&gt;\"><![CDATA[1:1:ALSO BOGUS]]></error></testcase>",
+ error2 = "<testcase time=\"0\" name=\"\"><error message=\"sneaky, 'sneaky', &lt;sneaky&gt;\"><![CDATA[2:1:ALSO BOGUS]]></error></testcase>",
+ expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>" + file + error1 + error2 + "</testsuite></testsuites>",
+ actual = CSSLint.format(result, "FILE", "junit-xml");
+
+ Assert.areEqual(expected, actual);
+
+ }
+
+ }));
+})();
Please sign in to comment.
Something went wrong with that request. Please try again.