Last active
December 10, 2015 20:28
-
-
Save JamesMGreene/4488251 to your computer and use it in GitHub Desktop.
Our old proprietary version of the QUnit JUnitLogger addon... compare to master branch version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict'; | |
var currentRun, currentModule, currentTest, assertCount; | |
// Gets called when a report is generated. | |
QUnit.jUnitReport = function(/* data */) { | |
// Override me! | |
}; | |
QUnit.begin(function() { | |
currentRun = { | |
modules: [], | |
total: 0, | |
passed: 0, | |
failed: 0, | |
start: new Date(), | |
time: 0 | |
}; | |
}); | |
QUnit.moduleStart(function(data) { | |
currentModule = { | |
name: data.name, | |
tests: [], | |
total: 0, | |
passed: 0, | |
failed: 0, | |
start: new Date(), | |
time: 0, | |
stdout: [], | |
stderr: [] | |
}; | |
currentRun.modules.push(currentModule); | |
}); | |
QUnit.testStart(function(data) { | |
// Setup default module if no module was specified | |
if (!currentModule) { | |
currentModule = { | |
name: data.module || 'default', | |
tests: [], | |
total: 0, | |
passed: 0, | |
failed: 0, | |
start: new Date(), | |
time: 0, | |
stdout: [], | |
stderr: [] | |
}; | |
currentRun.modules.push(currentModule); | |
} | |
// Reset the assertion count | |
assertCount = 0; | |
currentTest = { | |
name: data.name, | |
failedAssertions: [], | |
total: 0, | |
passed: 0, | |
failed: 0, | |
start: new Date(), | |
time: 0 | |
}; | |
currentModule.tests.push(currentTest); | |
}); | |
QUnit.log(function(data) { | |
assertCount++; | |
// Ignore passing assertions | |
if (!data.result) { | |
currentTest.failedAssertions.push(data); | |
// Add log message of failure to make it easier to find in Jenkins CI | |
currentModule.stdout.push('[' + currentModule.name + ', ' + currentTest.name + ', ' + assertCount + '] ' + data.message); | |
} | |
}); | |
QUnit.testDone(function(data) { | |
currentTest.time = (new Date()).getTime() - currentTest.start.getTime(); // ms | |
currentTest.total = data.total; | |
currentTest.passed = data.passed; | |
currentTest.failed = data.failed; | |
currentTest = null; | |
}); | |
QUnit.moduleDone(function(data) { | |
currentModule.time = (new Date()).getTime() - currentModule.start.getTime(); // ms | |
currentModule.total = data.total; | |
currentModule.passed = data.passed; | |
currentModule.failed = data.failed; | |
currentModule = null; | |
}); | |
QUnit.done(function(data) { | |
currentRun.time = data.runtime || ((new Date()).getTime() - currentRun.start.getTime()); // ms | |
currentRun.total = data.total; | |
currentRun.passed = data.passed; | |
currentRun.failed = data.failed; | |
generateReport(data, currentRun); | |
}); | |
var generateReport = function(results, run) { | |
var pad = function(n) { | |
return n < 10 ? '0' + n : n; | |
}; | |
var toISODateString = function(d) { | |
return d.getUTCFullYear() + '-' + | |
pad(d.getUTCMonth() + 1) + '-' + | |
pad(d.getUTCDate()) + 'T' + | |
pad(d.getUTCHours()) + ':' + | |
pad(d.getUTCMinutes()) + ':' + | |
pad(d.getUTCSeconds()) + 'Z'; | |
}; | |
var convertMillisToSeconds = function(ms) { | |
return Math.round(ms * 1000) / 1000000; | |
}; | |
var xmlEncode = function(text) { | |
var baseEntities = { | |
'"': '"', | |
"'": ''', | |
'<': '<', | |
'>': '>', | |
'&': '&' | |
}; | |
return ('' + text).replace(/[<>&\"\']/g, function(chr) { | |
return baseEntities[chr] || chr; | |
}); | |
}; | |
var XmlWriter = function(settings) { | |
settings = settings || {}; | |
var data = [], stack = [], lineBreakAt; | |
var addLineBreak = function(name) { | |
if (lineBreakAt[name] && data[data.length - 1] !== '\n') { | |
data.push('\n'); | |
} | |
}; | |
lineBreakAt = (function(items) { | |
var i, map = {}; | |
items = items || []; | |
i = items.length; | |
while (i--) { | |
map[items[i]] = {}; | |
} | |
return map; | |
})(settings.linebreak_at); | |
this.start = function(name, attrs, empty) { | |
if (!empty) { | |
stack.push(name); | |
} | |
data.push('<' + name); | |
for (var aname in attrs) { | |
data.push(' ' + xmlEncode(aname) + '="' + xmlEncode(attrs[aname]) + '"'); | |
} | |
data.push(empty ? ' />' : '>'); | |
addLineBreak(name); | |
}; | |
this.end = function() { | |
var name = stack.pop(); | |
addLineBreak(name); | |
data.push('</' + name + '>'); | |
addLineBreak(name); | |
}; | |
this.text = function(text) { | |
data.push(xmlEncode(text)); | |
}; | |
this.cdata = function(text) { | |
data.push('<![CDATA[' + text + ']]>'); | |
}; | |
this.comment = function(text) { | |
data.push('<!--' + text + '-->'); | |
}; | |
this.pi = function(name, text) { | |
data.push('<?' + name + (text ? ' ' + text : '') + '?>\n'); | |
}; | |
this.doctype = function(text) { | |
data.push('<!DOCTYPE' + text + '>\n'); | |
}; | |
this.getString = function() { | |
while (stack.length) { | |
this.end(); // internally calls `stack.pop();` | |
} | |
return data.join('').replace(/\n$/, ''); | |
}; | |
this.reset = function() { | |
data.length = 0; | |
stack.length = 0; | |
}; | |
// Start by writing the XML declaration | |
this.pi(settings.xmldecl || 'xml version="1.0" encoding="UTF-8"'); | |
}; | |
// Generate JUnit XML report! | |
var m, mLen, module, t, tLen, test, a, aLen, assertion, isEmptyElement, | |
xmlWriter = new XmlWriter({ | |
linebreak_at: ['testsuites', 'testsuite', 'testcase', 'failure', 'system-out', 'system-err'] | |
}); | |
xmlWriter.start('testsuites', { | |
name: (window && window.location && window.location.href) || (run.modules.length === 1 && run.modules[0].name) || null, | |
hostname: 'localhost', | |
tests: run.total, | |
failures: run.failed, | |
errors: 0, | |
time: convertMillisToSeconds(run.time), // ms → sec | |
timestamp: toISODateString(run.start) | |
}); | |
for (m = 0, mLen = run.modules.length; m < mLen; m++) { | |
module = run.modules[m]; | |
xmlWriter.start('testsuite', { | |
id: m, | |
name: module.name, | |
hostname: 'localhost', | |
tests: module.total, | |
failures: module.failed, | |
errors: 0, | |
time: convertMillisToSeconds(module.time), // ms → sec | |
timestamp: toISODateString(module.start) | |
}); | |
for (t = 0, tLen = module.tests.length; t < tLen; t++) { | |
test = module.tests[t]; | |
xmlWriter.start('testcase', { | |
name: test.name, | |
tests: test.total, | |
failures: test.failed, | |
errors: 0, | |
time: convertMillisToSeconds(test.time), // ms → sec | |
timestamp: toISODateString(test.start) | |
}); | |
for (a = 0, aLen = test.failedAssertions.length; a < aLen; a++) { | |
assertion = test.failedAssertions[a]; | |
isEmptyElement = assertion && !(assertion.actual && assertion.expected); | |
xmlWriter.start('failure', { type: 'AssertionFailedError', message: assertion.message }, isEmptyElement); | |
if (!isEmptyElement) { | |
xmlWriter.start('actual', { value: assertion.actual }, true); | |
xmlWriter.start('expected', { value: assertion.expected }, true); | |
xmlWriter.end(); //'failure' | |
} | |
} | |
xmlWriter.end(); //'testcase' | |
} | |
// Per-module stdout | |
if (module.stdout && module.stdout.length) { | |
xmlWriter.start('system-out'); | |
xmlWriter.cdata('\n' + module.stdout.join('\n') + '\n'); | |
xmlWriter.end(); //'system-out' | |
} | |
// Per-module stderr | |
if (module.stderr && module.stderr.length) { | |
xmlWriter.start('system-err'); | |
xmlWriter.cdata('\n' + module.stderr.join('\n') + '\n'); | |
xmlWriter.end(); //'system-err' | |
} | |
xmlWriter.end(); //'testsuite' | |
} | |
xmlWriter.end(); //'testsuites' | |
// Invoke the user-defined callback | |
QUnit.jUnitReport({ | |
results: results, | |
xml: xmlWriter.getString() | |
}); | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment