|
| 1 | +/* |
| 2 | + * This is the junit reporter provided in the jasmine-reporters project |
| 3 | + * available at https://github.com/larrymyers/jasmine-reporters |
| 4 | + */ |
| 5 | +(function() { |
| 6 | + |
| 7 | + if (typeof jasmine == 'undefined') { |
| 8 | + throw new Error("jasmine library does not exist in global namespace!"); |
| 9 | + } |
| 10 | + |
| 11 | + function elapsed(startTime, endTime) { |
| 12 | + return (endTime - startTime)/1000; |
| 13 | + } |
| 14 | + |
| 15 | + function ISODateString(d) { |
| 16 | + function pad(n) { return n < 10 ? '0'+n : n; } |
| 17 | + |
| 18 | + return d.getFullYear() + '-' + |
| 19 | + pad(d.getMonth()+1) + '-' + |
| 20 | + pad(d.getDate()) + 'T' + |
| 21 | + pad(d.getHours()) + ':' + |
| 22 | + pad(d.getMinutes()) + ':' + |
| 23 | + pad(d.getSeconds()); |
| 24 | + } |
| 25 | + |
| 26 | + function trim(str) { |
| 27 | + return str.replace(/^\s+/, "" ).replace(/\s+$/, "" ); |
| 28 | + } |
| 29 | + |
| 30 | + function escapeInvalidXmlChars(str) { |
| 31 | + return str.replace(/\&/g, "&") |
| 32 | + .replace(/</g, "<") |
| 33 | + .replace(/\>/g, ">") |
| 34 | + .replace(/\"/g, """) |
| 35 | + .replace(/\'/g, "'"); |
| 36 | + } |
| 37 | + |
| 38 | + var JUnitXmlReporter = function() { |
| 39 | + this.useDotNotation = true; |
| 40 | + }; |
| 41 | + |
| 42 | + JUnitXmlReporter.prototype = { |
| 43 | + reportSpecStarting: function(spec) { |
| 44 | + spec.startTime = new Date(); |
| 45 | + |
| 46 | + if (!spec.suite.startTime) { |
| 47 | + spec.suite.startTime = spec.startTime; |
| 48 | + } |
| 49 | + }, |
| 50 | + |
| 51 | + reportSpecResults: function(spec) { |
| 52 | + var results = spec.results(); |
| 53 | + spec.didFail = !results.passed(); |
| 54 | + spec.duration = elapsed(spec.startTime, new Date()); |
| 55 | + spec.output = '<testcase classname="' + this.getFullName(spec.suite) + |
| 56 | + '" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + spec.duration + '">'; |
| 57 | + if(results.skipped) { |
| 58 | + spec.output = spec.output + "<skipped />"; |
| 59 | + } |
| 60 | + |
| 61 | + var failure = ""; |
| 62 | + var failures = 0; |
| 63 | + var resultItems = results.getItems(); |
| 64 | + for (var i = 0; i < resultItems.length; i++) { |
| 65 | + var result = resultItems[i]; |
| 66 | + |
| 67 | + if (result.type == 'expect' && result.passed && !result.passed()) { |
| 68 | + failures += 1; |
| 69 | + failure += '<failure type="' + result.type + '" message="' + trim(escapeInvalidXmlChars(result.message)) + '">'; |
| 70 | + failure += escapeInvalidXmlChars(result.trace.stack || result.message); |
| 71 | + failure += "</failure>"; |
| 72 | + } |
| 73 | + } |
| 74 | + if (failure) { |
| 75 | + spec.output += failure; |
| 76 | + } |
| 77 | + spec.output += "</testcase>"; |
| 78 | + }, |
| 79 | + |
| 80 | + reportSuiteResults: function(suite) { |
| 81 | + var results = suite.results(); |
| 82 | + var specs = suite.specs(); |
| 83 | + var specOutput = ""; |
| 84 | + // for JUnit results, let's only include directly failed tests (not nested suites') |
| 85 | + var failedCount = 0; |
| 86 | + |
| 87 | + suite.status = results.passed() ? 'Passed.' : 'Failed.'; |
| 88 | + if (results.totalCount === 0) { // todo: change this to check results.skipped |
| 89 | + suite.status = 'Skipped.'; |
| 90 | + } |
| 91 | + |
| 92 | + // if a suite has no (active?) specs, reportSpecStarting is never called |
| 93 | + // and thus the suite has no startTime -- account for that here |
| 94 | + suite.startTime = suite.startTime || new Date(); |
| 95 | + suite.duration = elapsed(suite.startTime, new Date()); |
| 96 | + |
| 97 | + for (var i = 0; i < specs.length; i++) { |
| 98 | + failedCount += specs[i].didFail ? 1 : 0; |
| 99 | + specOutput += "\n " + specs[i].output; |
| 100 | + } |
| 101 | + suite.output = '\n<testsuite name="' + this.getFullName(suite) + |
| 102 | + '" errors="0" tests="' + specs.length + '" failures="' + failedCount + |
| 103 | + '" time="' + suite.duration + '" timestamp="' + ISODateString(suite.startTime) + '">'; |
| 104 | + suite.output += specOutput; |
| 105 | + suite.output += "\n</testsuite>"; |
| 106 | + }, |
| 107 | + |
| 108 | + reportRunnerResults: function(runner) { |
| 109 | + var suites = runner.suites(); |
| 110 | + for (var i = 0; i < suites.length; i++) { |
| 111 | + var suite = suites[i]; |
| 112 | + var output = '<?xml version="1.0" encoding="UTF-8" ?>'; |
| 113 | + // if we are consolidating, only write out top-level suites |
| 114 | + if (suite.parentSuite) { |
| 115 | + continue; |
| 116 | + } |
| 117 | + else { |
| 118 | + output += "\n<testsuites>"; |
| 119 | + output += this.getNestedOutput(suite); |
| 120 | + output += "\n</testsuites>"; |
| 121 | + this.print(output); |
| 122 | + } |
| 123 | + } |
| 124 | + this.signalCapybaraTestsFinishedRunning(); |
| 125 | + }, |
| 126 | + |
| 127 | + signalCapybaraTestsFinishedRunning: function() { |
| 128 | + var div = document.createElement('div'); |
| 129 | + div.id = 'testscomplete'; |
| 130 | + document.body.appendChild(div); |
| 131 | + }, |
| 132 | + |
| 133 | + getNestedOutput: function(suite) { |
| 134 | + var output = suite.output; |
| 135 | + for (var i = 0; i < suite.suites().length; i++) { |
| 136 | + output += this.getNestedOutput(suite.suites()[i]); |
| 137 | + } |
| 138 | + return output; |
| 139 | + }, |
| 140 | + |
| 141 | + getFullName: function(suite, isFilename) { |
| 142 | + var fullName; |
| 143 | + if (this.useDotNotation) { |
| 144 | + fullName = suite.description; |
| 145 | + for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { |
| 146 | + fullName = parentSuite.description + '.' + fullName; |
| 147 | + } |
| 148 | + } |
| 149 | + else { |
| 150 | + fullName = suite.getFullName(); |
| 151 | + } |
| 152 | + |
| 153 | + // Either remove or escape invalid XML characters |
| 154 | + if (isFilename) { |
| 155 | + return fullName.replace(/[^\w]/g, ""); |
| 156 | + } |
| 157 | + return escapeInvalidXmlChars(fullName); |
| 158 | + }, |
| 159 | + |
| 160 | + print: function(str) { |
| 161 | + var console = jasmine.getGlobal().console; |
| 162 | + |
| 163 | + if (console && console.log) { |
| 164 | + console.log(str); |
| 165 | + } |
| 166 | + } |
| 167 | + }; |
| 168 | + |
| 169 | + // export public |
| 170 | + jasmine.SnapdragonJUnitReporter = JUnitXmlReporter; |
| 171 | +})(); |
0 commit comments