browser-entry.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 Mocha = require('./lib/mocha');
  9. /**
  10. * Create a Mocha instance.
  11. *
  12. * @return {undefined}
  13. */
  14. var mocha = new Mocha({reporter: 'html'});
  15. /**
  16. * Save timer references to avoid Sinon interfering (see GH-237).
  17. */
  18. var Date = global.Date;
  19. var setTimeout = global.setTimeout;
  20. var setInterval = global.setInterval;
  21. var clearTimeout = global.clearTimeout;
  22. var clearInterval = global.clearInterval;
  23. var uncaughtExceptionHandlers = [];
  24. var originalOnerrorHandler = global.onerror;
  25. /**
  26. * Remove uncaughtException listener.
  27. * Revert to original onerror handler if previously defined.
  28. */
  29. process.removeListener = function(e, fn) {
  30. if (e === 'uncaughtException') {
  31. if (originalOnerrorHandler) {
  32. global.onerror = originalOnerrorHandler;
  33. } else {
  34. global.onerror = function() {};
  35. }
  36. var i = uncaughtExceptionHandlers.indexOf(fn);
  37. if (i !== -1) {
  38. uncaughtExceptionHandlers.splice(i, 1);
  39. }
  40. }
  41. };
  42. /**
  43. * Implements uncaughtException listener.
  44. */
  45. process.on = function(e, fn) {
  46. if (e === 'uncaughtException') {
  47. global.onerror = function(err, url, line) {
  48. fn(new Error(err + ' (' + url + ':' + line + ')'));
  49. return !mocha.allowUncaught;
  50. };
  51. uncaughtExceptionHandlers.push(fn);
  52. }
  53. };
  54. // The BDD UI is registered by default, but no UI will be functional in the
  55. // browser without an explicit call to the overridden `mocha.ui` (see below).
  56. // Ensure that this default UI does not expose its methods to the global scope.
  57. mocha.suite.removeAllListeners('pre-require');
  58. var immediateQueue = [];
  59. var immediateTimeout;
  60. function timeslice() {
  61. var immediateStart = new Date().getTime();
  62. while (immediateQueue.length && new Date().getTime() - immediateStart < 100) {
  63. immediateQueue.shift()();
  64. }
  65. if (immediateQueue.length) {
  66. immediateTimeout = setTimeout(timeslice, 0);
  67. } else {
  68. immediateTimeout = null;
  69. }
  70. }
  71. /**
  72. * High-performance override of Runner.immediately.
  73. */
  74. Mocha.Runner.immediately = function(callback) {
  75. immediateQueue.push(callback);
  76. if (!immediateTimeout) {
  77. immediateTimeout = setTimeout(timeslice, 0);
  78. }
  79. };
  80. /**
  81. * Function to allow assertion libraries to throw errors directly into mocha.
  82. * This is useful when running tests in a browser because window.onerror will
  83. * only receive the 'message' attribute of the Error.
  84. */
  85. mocha.throwError = function(err) {
  86. uncaughtExceptionHandlers.forEach(function(fn) {
  87. fn(err);
  88. });
  89. throw err;
  90. };
  91. /**
  92. * Override ui to ensure that the ui functions are initialized.
  93. * Normally this would happen in Mocha.prototype.loadFiles.
  94. */
  95. mocha.ui = function(ui) {
  96. Mocha.prototype.ui.call(this, ui);
  97. this.suite.emit('pre-require', global, null, this);
  98. return this;
  99. };
  100. /**
  101. * Setup mocha with the given setting options.
  102. */
  103. mocha.setup = function(opts) {
  104. if (typeof opts === 'string') {
  105. opts = {ui: opts};
  106. }
  107. for (var opt in opts) {
  108. if (opts.hasOwnProperty(opt)) {
  109. this[opt](opts[opt]);
  110. }
  111. }
  112. return this;
  113. };
  114. /**
  115. * Run mocha, returning the Runner.
  116. */
  117. mocha.run = function(fn) {
  118. var options = mocha.options;
  119. mocha.globals('location');
  120. var query = Mocha.utils.parseQuery(global.location.search || '');
  121. if (query.grep) {
  122. mocha.grep(query.grep);
  123. }
  124. if (query.fgrep) {
  125. mocha.fgrep(query.fgrep);
  126. }
  127. if (query.invert) {
  128. mocha.invert();
  129. }
  130. return Mocha.prototype.run.call(mocha, function(err) {
  131. // The DOM Document is not available in Web Workers.
  132. var document = global.document;
  133. if (
  134. document &&
  135. document.getElementById('mocha') &&
  136. options.noHighlighting !== true
  137. ) {
  138. Mocha.utils.highlightTags('code');
  139. }
  140. if (fn) {
  141. fn(err);
  142. }
  143. });
  144. };
  145. /**
  146. * Expose the process shim.
  147. * https://github.com/mochajs/mocha/pull/916
  148. */
  149. Mocha.process = process;
  150. /**
  151. * Expose mocha.
  152. */
  153. global.Mocha = Mocha;
  154. global.mocha = mocha;
  155. // this allows test/acceptance/required-tokens.js to pass; thus,
  156. // you can now do `const describe = require('mocha').describe` in a
  157. // browser context (assuming browserification). should fix #880
  158. module.exports = global;