2 var count
= 0, suiteCount
= 0, currentSuite
, currentTest
, suites
= [], assertCount
, start
, results
= {failed
:0, passed
:0, total
:0, time
:0};
4 QUnit
.jUnitReport = function(data
) {
5 // Gets called when a report is generated
8 QUnit
.moduleStart(function(data
) {
18 suites
.push(currentSuite
);
21 QUnit
.moduleDone(function(data
) {
24 QUnit
.testStart(function(data
) {
25 if(!start
){ start
= new Date(); }
35 // Setup default suite if no module was specified
46 suites
.push(currentSuite
);
49 currentSuite
.tests
.push(currentTest
);
52 QUnit
.testDone(function(data
) {
53 currentTest
.failed
= data
.failed
;
54 currentTest
.total
= data
.total
;
55 currentSuite
.failures
+= data
.failed
;
57 results
.failed
+= data
.failed
;
58 results
.passed
+= data
.passed
;
59 results
.total
+= data
.total
;
62 QUnit
.log(function(data
) {
66 currentTest
.failures
.push(data
.message
);
68 // Add log message of failure to make it easier to find in jenkins UI
69 currentSuite
.stdout
+= '[' + currentSuite
.name
+ ', ' + currentTest
.name
+ ', ' + assertCount
+ '] ' + data
.message
+ '\n';
73 QUnit
.done(function(data
) {
74 function ISODateString(d
) {
76 return n
< 10 ? '0' + n
: n
;
79 return d
.getUTCFullYear() + '-' +
80 pad(d
.getUTCMonth() + 1)+'-' +
81 pad(d
.getUTCDate()) + 'T' +
82 pad(d
.getUTCHours()) + ':' +
83 pad(d
.getUTCMinutes()) + ':' +
84 pad(d
.getUTCSeconds()) + 'Z';
87 // Generate XML report
88 var i
, ti
, fi
, test
, suite
,
89 xmlWriter
= new XmlWriter({
90 linebreak_at
: "testsuites,testsuite,testcase,failure,system-out,system-err"
94 xmlWriter
.start('testsuites');
96 for (i
= 0; i
< suites
.length
; i
++) {
100 for (ti
= 0; ti
< suite
.tests
.length
; ti
++) {
101 test
= suite
.tests
[ti
];
103 test
.time
= (now
.getTime() - test
.start
.getTime()) / 1000;
104 suite
.time
+= test
.time
;
107 xmlWriter
.start('testsuite', {
111 failures
: suite
.failures
,
112 hostname
: "localhost",
113 tests
: suite
.tests
.length
,
114 time
: Math
.round(suite
.time
* 1000) / 1000,
115 timestamp
: ISODateString(now
)
118 for (ti
= 0; ti
< suite
.tests
.length
; ti
++) {
119 test
= suite
.tests
[ti
];
121 xmlWriter
.start('testcase', {
125 time
: Math
.round(test
.time
* 1000) / 1000
128 for (fi
= 0; fi
< test
.failures
.length
; fi
++) {
129 xmlWriter
.start('failure', {type
: "AssertionFailedError", message
: test
.failures
[fi
]}, true);
132 xmlWriter
.end('testcase');
136 xmlWriter
.start('system-out');
137 xmlWriter
.cdata('\n' + suite
.stdout
);
138 xmlWriter
.end('system-out');
142 xmlWriter
.start('system-err');
143 xmlWriter
.cdata('\n' + suite
.stderr
);
144 xmlWriter
.end('system-err');
147 xmlWriter
.end('testsuite');
150 xmlWriter
.end('testsuites');
152 results
.time
= new Date() - start
;
156 xml
: xmlWriter
.getString()
160 function XmlWriter(settings
) {
161 function addLineBreak(name
) {
162 if (lineBreakAt
[name
] && data
[data
.length
- 1] !== '\n') {
167 function makeMap(items
, delim
, map
) {
172 if (typeof(items
) === "string") {
173 items
= items
.split(',');
186 function encode(text
) {
195 return ('' + text
).replace(/[<>&\"\']/g, function(chr
) {
196 return baseEntities
[chr
] || chr
;
200 var data
= [], stack
= [], lineBreakAt
;
202 settings
= settings
|| {};
203 lineBreakAt
= makeMap(settings
.linebreak_at
|| 'mytag');
205 this.start = function(name
, attrs
, empty
) {
210 data
.push('<', name
);
212 for (var aname
in attrs
) {
213 data
.push(" " + encode(aname
), '="', encode(attrs
[aname
]), '"');
216 data
.push(empty
? ' />' : '>');
220 this.end = function(name
) {
223 data
.push('</', name
, '>');
227 this.text = function(text
) {
228 data
.push(encode(text
));
231 this.cdata = function(text
) {
232 data
.push('<![CDATA[', text
, ']]>');
235 this.comment = function(text
) {
236 data
.push('<!--', text
, '-->');
239 this.pi = function(name
, text
) {
241 data
.push('<?', name
, ' ', text
, '?>\n');
243 data
.push('<?', name
, '?>\n');
247 this.doctype = function(text
) {
248 data
.push('<!DOCTYPE', text
, '>\n');
251 this.getString = function() {
252 for (var i
= stack
.length
- 1; i
>= 0; i
--) {
258 return data
.join('').replace(/\n$/, '');
261 this.reset = function() {
266 this.pi(settings
.xmldecl
|| 'xml version="1.0" encoding="UTF-8"');