1 (function(){ 2 3 var APOS = "'"; QUOTE = '"'; 4 var ESCAPED_QUOTE = { }; 5 ESCAPED_QUOTE[QUOTE] = '"'; 6 ESCAPED_QUOTE[APOS] = '''; 7 8 function formatAttributes(attributes) { 9 var att_value; 10 var apos_pos, quot_pos; 11 var use_quote, escape, quote_to_escape; 12 var att_str; 13 var re; 14 var result = ''; 15 16 for (var att in attributes) { 17 att_value = attributes[att]; 18 19 att_value = att_value.replace(/&/g, "&"); 20 21 // Find first quote marks if any 22 apos_pos = att_value.indexOf(APOS); 23 quot_pos = att_value.indexOf(QUOTE); 24 25 // Determine which quote type to use around 26 // the attribute value 27 if (apos_pos == -1 && quot_pos == -1) { 28 att_str = ' ' + att + "='" + att_value + "'"; 29 result += att_str; 30 continue; 31 } 32 33 // Prefer the single quote unless forced to use double 34 if (quot_pos != -1 && quot_pos < apos_pos) { 35 use_quote = APOS; 36 } 37 else { 38 use_quote = QUOTE; 39 } 40 41 // Figure out which kind of quote to escape 42 // Use nice dictionary instead of yucky if-else nests 43 escape = ESCAPED_QUOTE[use_quote]; 44 45 // Escape only the right kind of quote 46 re = new RegExp(use_quote,'g'); 47 att_str = ' ' + att + '=' + use_quote + 48 att_value.replace(re, escape) + use_quote; 49 result += att_str; 50 } 51 return result; 52 }; 53 54 55 /** JavaScript API reporter. 56 * 57 * @constructor 58 */ 59 jasmine.XMLReporter = function() { 60 this.started = false; 61 this.finished = false; 62 this.suites_ = []; 63 this.results_ = {}; 64 }; 65 66 jasmine.XMLReporter.prototype.reportRunnerStarting = function(runner) { 67 this.started = true; 68 var suites = runner.suites(); 69 for (var i = 0; i < suites.length; i++) { 70 var suite = suites[i]; 71 this.suites_.push(this.summarize_(suite)); 72 } 73 this.startedAt = new Date(); 74 puts("<testsuites>") 75 }; 76 77 jasmine.XMLReporter.prototype.suites = function() { 78 return this.suites_; 79 }; 80 81 jasmine.XMLReporter.prototype.summarize_ = function(suiteOrSpec) { 82 var isSuite = suiteOrSpec instanceof jasmine.Suite 83 var summary = { 84 id: suiteOrSpec.id, 85 name: suiteOrSpec.description, 86 type: isSuite ? 'suite' : 'spec', 87 children: [] 88 }; 89 if (isSuite) { 90 var specs = suiteOrSpec.specs(); 91 for (var i = 0; i < specs.length; i++) { 92 summary.children.push(this.summarize_(specs[i])); 93 } 94 } 95 return summary; 96 }; 97 98 jasmine.XMLReporter.prototype.results = function() { 99 return this.results_; 100 }; 101 102 jasmine.XMLReporter.prototype.resultsForSpec = function(specId) { 103 return this.results_[specId]; 104 }; 105 106 //noinspection JSUnusedLocalSymbols 107 jasmine.XMLReporter.prototype.reportRunnerResults = function(runner) { 108 this.finished = true; 109 var results = runner.results(); 110 var specs = runner.specs(); 111 var specCount = specs.length; 112 if(jasmine.XMLReporter.current_suite){ 113 puts(" </testsuite>"); 114 } 115 // puts(" <tests>"+specCount+"</tests>"); 116 // puts(" <errors>"+results.failedCount+"</errors>"); 117 // puts(" <skipped>0</skipped>"); 118 // puts(" <failures>0</failures>"); 119 // puts(" <time>"+((new Date().getTime() - this.startedAt.getTime()) / 1000)+"</time>"); 120 puts("</testsuites>"); 121 }; 122 123 //noinspection JSUnusedLocalSymbols 124 jasmine.XMLReporter.prototype.reportSuiteResults = function(suite) { 125 }; 126 127 //noinspection JSUnusedLocalSymbols 128 jasmine.XMLReporter.prototype.reportSpecResults = function(spec) { 129 var suite = spec.suite; 130 if(jasmine.XMLReporter.current_suite != suite){ 131 if(jasmine.XMLReporter.current_suite){ 132 puts(" </testsuite>"); 133 } 134 var name = [ spec.description ]; 135 while(suite){ 136 name.unshift( suite.description ); 137 suite = suite.parentSuite; 138 } 139 puts(" <testsuite"+formatAttributes({name:name.join(" : ")}) +">"); 140 jasmine.XMLReporter.current_suite = spec.suite; 141 } 142 this.results_[spec.id] = { 143 spec: spec, 144 messages: spec.results().getItems(), 145 result: spec.results().failedCount > 0 ? "failed" : "passed" 146 }; 147 var results = spec.results().getItems(); 148 for(var i in results) { 149 var result = results[i]; 150 puts(" <testcase"+formatAttributes({name:(1+parseInt(i))+ ": " + result.matcherName})+">"); 151 if(!result.passed()){ 152 puts(" <failure"+formatAttributes({type:result.matcherName, 153 message:result.message})+">"); 154 puts("<![CDATA["); 155 print_exception_trace(result.trace); 156 puts("]]>"); 157 puts(" </failure>"); 158 } 159 puts(" </testcase>"); 160 } 161 }; 162 163 //noinspection JSUnusedLocalSymbols 164 jasmine.XMLReporter.prototype.log = function(str) { 165 // print(str); 166 }; 167 168 jasmine.XMLReporter.prototype.resultsForSpecs = function(specIds){ 169 var results = {}; 170 for (var i = 0; i < specIds.length; i++) { 171 var specId = specIds[i]; 172 results[specId] = this.summarizeResult_(this.results_[specId]); 173 } 174 return results; 175 }; 176 177 jasmine.XMLReporter.prototype.summarizeResult_ = function(result){ 178 var summaryMessages = []; 179 for (var messageIndex in result.messages) { 180 var resultMessage = result.messages[messageIndex]; 181 summaryMessages.push({ 182 text: resultMessage.text, 183 passed: resultMessage.passed ? resultMessage.passed() : true, 184 type: resultMessage.type, 185 message: resultMessage.message, 186 trace: { 187 stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : undefined 188 } 189 }); 190 }; 191 192 var summaryResult = { 193 result : result.result, 194 messages : summaryMessages 195 }; 196 197 return summaryResult; 198 }; 199 200 })(); 201