browser-entry.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. 'use strict';
  2. /* eslint no-unused-vars: off */
  3. /* eslint-env commonjs */
  4. /**
  5. * Shim process.stdout.
  6. */
  7. process.stdout = require('browser-stdout')({label: false});
  8. var parseQuery = require('./lib/browser/parse-query');
  9. var highlightTags = require('./lib/browser/highlight-tags');
  10. var Mocha = require('./lib/mocha');
  11. /**
  12. * Create a Mocha instance.
  13. *
  14. * @return {undefined}
  15. */
  16. var mocha = new Mocha({reporter: 'html'});
  17. /**
  18. * Save timer references to avoid Sinon interfering (see GH-237).
  19. */
  20. var Date = global.Date;
  21. var setTimeout = global.setTimeout;
  22. var setInterval = global.setInterval;
  23. var clearTimeout = global.clearTimeout;
  24. var clearInterval = global.clearInterval;
  25. var uncaughtExceptionHandlers = [];
  26. var originalOnerrorHandler = global.onerror;
  27. /**
  28. * Remove uncaughtException listener.
  29. * Revert to original onerror handler if previously defined.
  30. */
  31. process.removeListener = function (e, fn) {
  32. if (e === 'uncaughtException') {
  33. if (originalOnerrorHandler) {
  34. global.onerror = originalOnerrorHandler;
  35. } else {
  36. global.onerror = function () {};
  37. }
  38. var i = uncaughtExceptionHandlers.indexOf(fn);
  39. if (i !== -1) {
  40. uncaughtExceptionHandlers.splice(i, 1);
  41. }
  42. }
  43. };
  44. /**
  45. * Implements listenerCount for 'uncaughtException'.
  46. */
  47. process.listenerCount = function (name) {
  48. if (name === 'uncaughtException') {
  49. return uncaughtExceptionHandlers.length;
  50. }
  51. return 0;
  52. };
  53. /**
  54. * Implements uncaughtException listener.
  55. */
  56. process.on = function (e, fn) {
  57. if (e === 'uncaughtException') {
  58. global.onerror = function (msg, url, line, col, err) {
  59. fn(err || new Error(msg + ' (' + url + ':' + line + ':' + col + ')'));
  60. return !mocha.options.allowUncaught;
  61. };
  62. uncaughtExceptionHandlers.push(fn);
  63. }
  64. };
  65. process.listeners = function (err) {
  66. if (err === 'uncaughtException') {
  67. return uncaughtExceptionHandlers;
  68. }
  69. return [];
  70. };
  71. // The BDD UI is registered by default, but no UI will be functional in the
  72. // browser without an explicit call to the overridden `mocha.ui` (see below).
  73. // Ensure that this default UI does not expose its methods to the global scope.
  74. mocha.suite.removeAllListeners('pre-require');
  75. var immediateQueue = [];
  76. var immediateTimeout;
  77. function timeslice() {
  78. var immediateStart = new Date().getTime();
  79. while (immediateQueue.length && new Date().getTime() - immediateStart < 100) {
  80. immediateQueue.shift()();
  81. }
  82. if (immediateQueue.length) {
  83. immediateTimeout = setTimeout(timeslice, 0);
  84. } else {
  85. immediateTimeout = null;
  86. }
  87. }
  88. /**
  89. * High-performance override of Runner.immediately.
  90. */
  91. Mocha.Runner.immediately = function (callback) {
  92. immediateQueue.push(callback);
  93. if (!immediateTimeout) {
  94. immediateTimeout = setTimeout(timeslice, 0);
  95. }
  96. };
  97. /**
  98. * Function to allow assertion libraries to throw errors directly into mocha.
  99. * This is useful when running tests in a browser because window.onerror will
  100. * only receive the 'message' attribute of the Error.
  101. */
  102. mocha.throwError = function (err) {
  103. uncaughtExceptionHandlers.forEach(function (fn) {
  104. fn(err);
  105. });
  106. throw err;
  107. };
  108. /**
  109. * Override ui to ensure that the ui functions are initialized.
  110. * Normally this would happen in Mocha.prototype.loadFiles.
  111. */
  112. mocha.ui = function (ui) {
  113. Mocha.prototype.ui.call(this, ui);
  114. this.suite.emit('pre-require', global, null, this);
  115. return this;
  116. };
  117. /**
  118. * Setup mocha with the given setting options.
  119. */
  120. mocha.setup = function (opts) {
  121. if (typeof opts === 'string') {
  122. opts = {ui: opts};
  123. }
  124. if (opts.delay === true) {
  125. this.delay();
  126. }
  127. var self = this;
  128. Object.keys(opts)
  129. .filter(function (opt) {
  130. return opt !== 'delay';
  131. })
  132. .forEach(function (opt) {
  133. if (Object.prototype.hasOwnProperty.call(opts, opt)) {
  134. self[opt](opts[opt]);
  135. }
  136. });
  137. return this;
  138. };
  139. /**
  140. * Run mocha, returning the Runner.
  141. */
  142. mocha.run = function (fn) {
  143. var options = mocha.options;
  144. mocha.globals('location');
  145. var query = parseQuery(global.location.search || '');
  146. if (query.grep) {
  147. mocha.grep(query.grep);
  148. }
  149. if (query.fgrep) {
  150. mocha.fgrep(query.fgrep);
  151. }
  152. if (query.invert) {
  153. mocha.invert();
  154. }
  155. return Mocha.prototype.run.call(mocha, function (err) {
  156. // The DOM Document is not available in Web Workers.
  157. var document = global.document;
  158. if (
  159. document &&
  160. document.getElementById('mocha') &&
  161. options.noHighlighting !== true
  162. ) {
  163. highlightTags('code');
  164. }
  165. if (fn) {
  166. fn(err);
  167. }
  168. });
  169. };
  170. /**
  171. * Expose the process shim.
  172. * https://github.com/mochajs/mocha/pull/916
  173. */
  174. Mocha.process = process;
  175. /**
  176. * Expose mocha.
  177. */
  178. global.Mocha = Mocha;
  179. global.mocha = mocha;
  180. // for bundlers: enable `import {describe, it} from 'mocha'`
  181. // `bdd` interface only
  182. // prettier-ignore
  183. [
  184. 'describe', 'context', 'it', 'specify',
  185. 'xdescribe', 'xcontext', 'xit', 'xspecify',
  186. 'before', 'beforeEach', 'afterEach', 'after'
  187. ].forEach(function(key) {
  188. mocha[key] = global[key];
  189. });
  190. module.exports = mocha;