jasmine-html.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // Object.toQueryString from MooTools Core
  2. jasmine.toQueryString = function(object, base){
  3. var queryString = [];
  4. for (var i in object) (function(value, key){
  5. if (base) key = base + '[' + key + ']';
  6. var result;
  7. if (jasmine.isArray_(value)){
  8. var qs = {};
  9. for (var j = 0; j < value.length; j++)
  10. qs[j] = value[j];
  11. result = jasmine.toQueryString(qs, key);
  12. } else if (typeof value == 'object'){
  13. result = jasmine.toQueryString(value, key);
  14. } else {
  15. result = key + '=' + encodeURIComponent(value);
  16. }
  17. if (value != undefined) queryString.push(result);
  18. })(object[i], i);
  19. return queryString.join('&');
  20. };
  21. // String.parseQueryString from MooTools More
  22. jasmine.parseQueryString = function(string){
  23. var vars = string.split(/[&;]/),
  24. object = {};
  25. if (!vars.length) return object;
  26. for(var i = 0; i < vars.length; i++) (function(val){
  27. var index = val.indexOf('='),
  28. keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g),
  29. value = decodeURIComponent(val.substr(index + 1));
  30. for(var j = 0; j < keys.length; j++) (function(key, i){
  31. var current = object[key];
  32. if(i < keys.length - 1)
  33. object = object[key] = current || {};
  34. else if(current != null && typeof current.length == 'number')
  35. current.push(value);
  36. else
  37. object[key] = current != null ? [current, value] : value;
  38. })(keys[j], j);
  39. })(vars[i]);
  40. return object;
  41. };
  42. jasmine.TrivialReporter = function(doc, appendTo) {
  43. this.document = doc || document;
  44. this.suiteDivs = {};
  45. this.logRunningSpecs = false;
  46. this.appendTo = appendTo || this.document.body;
  47. };
  48. jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
  49. var el = document.createElement(type);
  50. for (var i = 2; i < arguments.length; i++) {
  51. var child = arguments[i];
  52. if (typeof child === 'string') {
  53. el.appendChild(document.createTextNode(child));
  54. } else {
  55. if (child) {el.appendChild(child);}
  56. }
  57. }
  58. for (var attr in attrs) {
  59. if (attr == "className") {
  60. el[attr] = attrs[attr];
  61. } else {
  62. el.setAttribute(attr, attrs[attr]);
  63. }
  64. }
  65. return el;
  66. };
  67. jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
  68. var showPassed, showSkipped;
  69. var query = jasmine.parseQueryString(document.location.search.substr(1));
  70. delete query.spec;
  71. this.outerDiv = this.createDom('div', {className: 'jasmine_reporter'},
  72. this.createDom('div', {className: 'banner'},
  73. this.createDom('div', {className: 'logo'},
  74. "Jasmine",
  75. this.createDom('span', {className: 'version'}, runner.env.versionString())),
  76. this.createDom('div', {className: 'options'},
  77. "Show ",
  78. showPassed = this.createDom('input', {id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox'}),
  79. this.createDom('label', {"for": "__jasmine_TrivialReporter_showPassed__"}, " passed "),
  80. showSkipped = this.createDom('input', {id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox'}),
  81. this.createDom('label', {"for": "__jasmine_TrivialReporter_showSkipped__"}, " skipped")
  82. )
  83. ),
  84. this.runnerDiv = this.createDom('div', {className: 'runner running'},
  85. this.createDom('a', {className: 'run_spec', href: '?' + jasmine.toQueryString(query)}, "run all"),
  86. this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
  87. this.finishedAtSpan = this.createDom('span', {className: 'finished-at'}, ""))
  88. );
  89. this.appendTo.appendChild(this.outerDiv);
  90. var suites = runner.suites();
  91. for (var i = 0; i < suites.length; i++) {
  92. var suite = suites[i];
  93. query.spec = suite.getFullName();
  94. var suiteDiv = this.createDom('div', {className: 'suite'},
  95. this.createDom('a', {className: 'run_spec', href: '?' + jasmine.toQueryString(query)}, "run"),
  96. this.createDom('a', {className: 'description', href: '?' + jasmine.toQueryString(query)}, suite.description));
  97. this.suiteDivs[suite.id] = suiteDiv;
  98. var parentDiv = this.outerDiv;
  99. if (suite.parentSuite) {
  100. parentDiv = this.suiteDivs[suite.parentSuite.id];
  101. }
  102. parentDiv.appendChild(suiteDiv);
  103. }
  104. this.startedAt = new Date();
  105. var self = this;
  106. showPassed.onchange = function(evt) {
  107. if (evt.target.checked) {
  108. self.outerDiv.className += ' show-passed';
  109. } else {
  110. self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
  111. }
  112. };
  113. showSkipped.onchange = function(evt) {
  114. if (evt.target.checked) {
  115. self.outerDiv.className += ' show-skipped';
  116. } else {
  117. self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
  118. }
  119. };
  120. runner.env.specFilter = this.specFilter;
  121. };
  122. jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
  123. var results = runner.results();
  124. var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
  125. this.runnerDiv.setAttribute("class", className);
  126. //do it twice for IE
  127. this.runnerDiv.setAttribute("className", className);
  128. var specs = runner.specs();
  129. var specCount = 0;
  130. for (var i = 0; i < specs.length; i++) {
  131. if (this.specFilter(specs[i])) {
  132. specCount++;
  133. }
  134. }
  135. var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.totalCount + " assertion" + (results.totalCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
  136. message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
  137. this.runnerMessageSpan.replaceChild(this.createDom('a', {className: 'description', href: '#'}, message), this.runnerMessageSpan.firstChild);
  138. this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
  139. };
  140. jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
  141. var results = suite.results();
  142. var status = results.passed() ? 'passed' : 'failed';
  143. if (results.totalCount == 0) { // todo: change this to check results.skipped
  144. status = 'skipped';
  145. }
  146. this.suiteDivs[suite.id].className += " " + status;
  147. };
  148. jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
  149. if (this.logRunningSpecs) {
  150. this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
  151. }
  152. };
  153. jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
  154. var results = spec.results();
  155. var status = results.passed() ? 'passed' : 'failed';
  156. if (results.skipped) {
  157. status = 'skipped';
  158. }
  159. var query = jasmine.parseQueryString(document.location.search.substr(1));
  160. query.spec = spec.getFullName();
  161. var specDiv = this.createDom('div', {className: 'spec ' + status},
  162. this.createDom('a', {className: 'run_spec', href: '?' + jasmine.toQueryString(query)}, "run"),
  163. this.createDom('a', {
  164. className: 'description',
  165. href: '?' + jasmine.toQueryString(query),
  166. title: spec.getFullName()
  167. }, spec.description));
  168. var resultItems = results.getItems();
  169. var messagesDiv = this.createDom('div', {className: 'messages'});
  170. for (var i = 0; i < resultItems.length; i++) {
  171. var result = resultItems[i];
  172. if (result.type == 'log') {
  173. messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
  174. } else if (result.type == 'expect' && result.passed && !result.passed()) {
  175. messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
  176. var fn = spec.queue && spec.queue.blocks && spec.queue.blocks[1] ? spec.queue.blocks[1].func : null;
  177. if (fn){
  178. var pre = this.createDom('pre', {className: 'examples-code'});
  179. pre.appendChild(this.createDom('code', null, fn.toString().replace(/</img, '&lt;').replace(/>/img, '&gt;')));
  180. messagesDiv.appendChild(pre);
  181. }
  182. }
  183. }
  184. if (messagesDiv.childNodes.length > 0) {
  185. specDiv.appendChild(messagesDiv);
  186. }
  187. this.suiteDivs[spec.suite.id].appendChild(specDiv);
  188. };
  189. jasmine.TrivialReporter.prototype.log = function() {
  190. var console = jasmine.getGlobal().console;
  191. if (console && console.log){
  192. if (console.log.apply) console.log.apply(console, arguments);
  193. else console.log(Array.prototype.join.call(arguments, ', '));
  194. }
  195. };
  196. jasmine.TrivialReporter.prototype.getLocation = function() {
  197. return this.document.location;
  198. };
  199. (function(){
  200. var query = jasmine.parseQueryString(document.location.search.substr(1));
  201. jasmine.TrivialReporter.prototype.specFilter = function(spec) {
  202. if (!query.spec) return true;
  203. return spec.getFullName().indexOf(query.spec) == 0;
  204. };
  205. })();