qunit-clib.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*!
  2. * QUnit CLI Boilerplate v1.0.0
  3. * Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
  4. * Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
  5. * Available under MIT license <http://mths.be/mit>
  6. */
  7. ;(function(global) {
  8. 'use strict';
  9. /** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
  10. global.console || (global.console = { 'log': global.print });
  11. /** Reduce global.QUnit.QUnit -> global.QUnit */
  12. global.QUnit && (QUnit = QUnit.QUnit || QUnit);
  13. /*--------------------------------------------------------------------------*/
  14. /** Used as a horizontal rule in console output */
  15. var hr = '----------------------------------------';
  16. /** Shortcut used to convert array-like objects to arrays */
  17. var slice = [].slice;
  18. /** Used to resolve a value's internal [[Class]] */
  19. var toString = {}.toString;
  20. /** Used by timer methods */
  21. var doneCalled,
  22. timer,
  23. counter = 0,
  24. ids = {};
  25. /*--------------------------------------------------------------------------*/
  26. /**
  27. * An iteration utility for arrays.
  28. *
  29. * @private
  30. * @param {Array} array The array to iterate over.
  31. * @param {Function} callback The function called per iteration.
  32. */
  33. function each(array, callback) {
  34. var index = -1,
  35. length = array.length;
  36. while (++index < length) {
  37. callback(array[index], index, array);
  38. }
  39. }
  40. /**
  41. * Checks if the specified `value` is a function.
  42. *
  43. * @private
  44. * @param {Mixed} value The value to check.
  45. * @returns {Boolean} Returns `true` if `value` is a function, else `false`.
  46. */
  47. function isFunction(value) {
  48. return toString.call(value) == '[object Function]';
  49. }
  50. /*--------------------------------------------------------------------------*/
  51. /**
  52. * Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
  53. * https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
  54. * http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
  55. */
  56. /**
  57. * Clears the delay set by `setInterval` or `setTimeout`.
  58. *
  59. * @memberOf global
  60. * @param {Number} id The ID of the timeout to be cleared.
  61. */
  62. function clearTimer(id) {
  63. if (ids[id]) {
  64. ids[id].cancel();
  65. timer.purge();
  66. delete ids[id];
  67. }
  68. }
  69. /**
  70. * Schedules timer-based callbacks.
  71. *
  72. * @private
  73. * @param {Function} fn The function to call.
  74. * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
  75. * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
  76. * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
  77. * @returns {Number} The the ID of the timeout.
  78. */
  79. function schedule(fn, delay, args, repeated) {
  80. // Rhino 1.7RC4 will error assigning `task` below
  81. // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
  82. var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
  83. 'run': function() {
  84. fn.apply(global, args);
  85. }
  86. });
  87. // support non-functions
  88. if (!isFunction(fn)) {
  89. fn = (function(code) {
  90. code = String(code);
  91. return function() { eval(code); };
  92. }(fn));
  93. }
  94. // used by setInterval
  95. if (repeated) {
  96. timer.schedule(task, delay, delay);
  97. }
  98. // used by setTimeout
  99. else {
  100. timer.schedule(task, delay);
  101. }
  102. return counter;
  103. }
  104. /**
  105. * Executes a code snippet or function repeatedly, with a delay between each call.
  106. *
  107. * @memberOf global
  108. * @param {Function|String} fn The function to call or string to evaluate.
  109. * @oaram {Number} delay The number of milliseconds to delay each `fn` call.
  110. * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
  111. * @returns {Number} The the ID of the timeout.
  112. */
  113. function setInterval(fn, delay) {
  114. return schedule(fn, delay, slice.call(arguments, 2), true);
  115. }
  116. /**
  117. * Executes a code snippet or a function after specified delay.
  118. *
  119. * @memberOf global
  120. * @param {Function|String} fn The function to call or string to evaluate.
  121. * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
  122. * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
  123. * @returns {Number} The the ID of the timeout.
  124. */
  125. function setTimeout(fn, delay) {
  126. return schedule(fn, delay, slice.call(arguments, 2));
  127. }
  128. /*--------------------------------------------------------------------------*/
  129. /**
  130. * A logging callback triggered when all testing is completed.
  131. *
  132. * @memberOf QUnit
  133. * @param {Object} details An object with properties `failed`, `passed`,
  134. * `runtime`, and `total`.
  135. */
  136. function done(details) {
  137. // stop `asyncTest()` from erroneously calling `done()` twice in
  138. // environments w/o timeouts
  139. if (doneCalled) {
  140. return;
  141. }
  142. doneCalled = true;
  143. console.log(hr);
  144. console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
  145. console.log(' Finished in ' + details.runtime + ' milliseconds.');
  146. console.log(hr);
  147. // exit out of Rhino
  148. try {
  149. quit();
  150. } catch(e) { }
  151. // exit out of Node.js
  152. try {
  153. process.exit();
  154. } catch(e) { }
  155. }
  156. /**
  157. * A logging callback triggered after every assertion.
  158. *
  159. * @memberOf QUnit
  160. * @param {Object} details An object with properties `actual`, `expected`,
  161. * `message`, and `result`.
  162. */
  163. function log(details) {
  164. var expected = details.expected,
  165. result = details.result,
  166. type = typeof expected != 'undefined' ? 'EQ' : 'OK';
  167. var assertion = [
  168. result ? 'PASS' : 'FAIL',
  169. type,
  170. details.message || 'ok'
  171. ];
  172. if (!result && type == 'EQ') {
  173. assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
  174. }
  175. QUnit.config.testStats.assertions.push(assertion.join(' | '));
  176. }
  177. /**
  178. * A logging callback triggered at the start of every test module.
  179. *
  180. * @memberOf QUnit
  181. * @param {Object} details An object with property `name`.
  182. */
  183. function moduleStart(details) {
  184. console.log(hr);
  185. console.log(details.name);
  186. console.log(hr);
  187. }
  188. /**
  189. * Converts an object into a string representation.
  190. *
  191. * @memberOf QUnit
  192. * @type Function
  193. * @param {Object} object The object to stringify.
  194. * @returns {String} The result string.
  195. */
  196. var parseObject = (function() {
  197. var func = QUnit.jsDump.parsers.object;
  198. return function(object) {
  199. // fork to support Rhino's error objects
  200. if (typeof object.rhinoException == 'object') {
  201. return object.name +
  202. ' { message: "' + object.message +
  203. '", fileName: "' + object.fileName +
  204. '", lineNumber: ' + object.lineNumber + ' }';
  205. }
  206. return func(object);
  207. };
  208. }());
  209. /**
  210. * A logging callback triggered after a test is completed.
  211. *
  212. * @memberOf QUnit
  213. * @param {Object} details An object with properties `failed`, `name`,
  214. * `passed`, and `total`.
  215. */
  216. function testDone(details) {
  217. var assertions = QUnit.config.testStats.assertions,
  218. testName = details.name;
  219. if (details.failed > 0) {
  220. console.log(' FAIL - '+ testName);
  221. each(assertions, function(value) {
  222. console.log(' ' + value);
  223. });
  224. }
  225. else {
  226. console.log(' PASS - ' + testName);
  227. }
  228. assertions.length = 0;
  229. }
  230. /*--------------------------------------------------------------------------*/
  231. /**
  232. * An object used to hold information about the current running test.
  233. *
  234. * @memberOf QUnit.config
  235. * @type Object
  236. */
  237. QUnit.config.testStats = {
  238. /**
  239. * An array of test summaries (pipe separated).
  240. *
  241. * @memberOf QUnit.config.testStats
  242. * @type Array
  243. */
  244. 'assertions': []
  245. };
  246. // add shortcuts to the global
  247. // exclude `module` because some environments have it as a built-in object
  248. each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
  249. 'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
  250. 'strictEqual', 'test', 'throws'], function(funcName) {
  251. var func = QUnit[funcName];
  252. if (func) {
  253. global[funcName] = func;
  254. }
  255. });
  256. // expose timer methods to global
  257. try {
  258. timer = new java.util.Timer;
  259. if (!isFunction(global.clearInterval)) {
  260. global.clearInterval = clearTimer;
  261. }
  262. if (!isFunction(global.clearTimeout)) {
  263. global.clearTimeout = clearTimer;
  264. }
  265. if (!isFunction(global.setInterval)) {
  266. global.setInterval = setInterval;
  267. }
  268. if (!isFunction(global.setTimeout)) {
  269. global.setTimeout = setTimeout;
  270. }
  271. } catch(e) { }
  272. // add callbacks
  273. QUnit.done(done);
  274. QUnit.log(log);
  275. QUnit.moduleStart(moduleStart);
  276. QUnit.testDone(testDone);
  277. // add wrapped function
  278. QUnit.jsDump.parsers.object = parseObject;
  279. // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
  280. // Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
  281. QUnit.init();
  282. }(typeof global == 'object' && global || this));