konacha 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -57,23 +57,24 @@ module.exports = function(type){
57
57
  }); // module: browser/debug.js
58
58
 
59
59
  require.register("browser/diff.js", function(module, exports, require){
60
- /* See license.txt for terms of usage */
60
+ /* See LICENSE file for terms of use */
61
61
 
62
62
  /*
63
63
  * Text diff implementation.
64
- *
64
+ *
65
65
  * This library supports the following APIS:
66
66
  * JsDiff.diffChars: Character by character diff
67
67
  * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
68
68
  * JsDiff.diffLines: Line based diff
69
- *
69
+ *
70
70
  * JsDiff.diffCss: Diff targeted at CSS content
71
- *
71
+ *
72
72
  * These methods are based on the implementation proposed in
73
73
  * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
74
74
  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
75
75
  */
76
76
  var JsDiff = (function() {
77
+ /*jshint maxparams: 5*/
77
78
  function clonePath(path) {
78
79
  return { newPos: path.newPos, components: path.components.slice(0) };
79
80
  }
@@ -88,22 +89,21 @@ var JsDiff = (function() {
88
89
  }
89
90
  function escapeHTML(s) {
90
91
  var n = s;
91
- n = n.replace(/&/g, "&");
92
- n = n.replace(/</g, "&lt;");
93
- n = n.replace(/>/g, "&gt;");
94
- n = n.replace(/"/g, "&quot;");
92
+ n = n.replace(/&/g, '&amp;');
93
+ n = n.replace(/</g, '&lt;');
94
+ n = n.replace(/>/g, '&gt;');
95
+ n = n.replace(/"/g, '&quot;');
95
96
 
96
97
  return n;
97
98
  }
98
99
 
99
-
100
- var fbDiff = function(ignoreWhitespace) {
100
+ var Diff = function(ignoreWhitespace) {
101
101
  this.ignoreWhitespace = ignoreWhitespace;
102
102
  };
103
- fbDiff.prototype = {
103
+ Diff.prototype = {
104
104
  diff: function(oldString, newString) {
105
105
  // Handle the identity case (this is due to unrolling editLength == 0
106
- if (newString == oldString) {
106
+ if (newString === oldString) {
107
107
  return [{ value: newString }];
108
108
  }
109
109
  if (!newString) {
@@ -186,7 +186,7 @@ var JsDiff = (function() {
186
186
  while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
187
187
  newPos++;
188
188
  oldPos++;
189
-
189
+
190
190
  this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
191
191
  }
192
192
  basePath.newPos = newPos;
@@ -198,7 +198,7 @@ var JsDiff = (function() {
198
198
  if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
199
199
  return true;
200
200
  } else {
201
- return left == right;
201
+ return left === right;
202
202
  }
203
203
  },
204
204
  join: function(left, right) {
@@ -208,27 +208,31 @@ var JsDiff = (function() {
208
208
  return value;
209
209
  }
210
210
  };
211
-
212
- var CharDiff = new fbDiff();
213
-
214
- var WordDiff = new fbDiff(true);
215
- WordDiff.tokenize = function(value) {
211
+
212
+ var CharDiff = new Diff();
213
+
214
+ var WordDiff = new Diff(true);
215
+ var WordWithSpaceDiff = new Diff();
216
+ WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
216
217
  return removeEmpty(value.split(/(\s+|\b)/));
217
218
  };
218
-
219
- var CssDiff = new fbDiff(true);
219
+
220
+ var CssDiff = new Diff(true);
220
221
  CssDiff.tokenize = function(value) {
221
222
  return removeEmpty(value.split(/([{}:;,]|\s+)/));
222
223
  };
223
-
224
- var LineDiff = new fbDiff();
224
+
225
+ var LineDiff = new Diff();
225
226
  LineDiff.tokenize = function(value) {
226
227
  return value.split(/^/m);
227
228
  };
228
-
229
+
229
230
  return {
231
+ Diff: Diff,
232
+
230
233
  diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
231
234
  diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
235
+ diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
232
236
  diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
233
237
 
234
238
  diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
@@ -236,16 +240,16 @@ var JsDiff = (function() {
236
240
  createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
237
241
  var ret = [];
238
242
 
239
- ret.push("Index: " + fileName);
240
- ret.push("===================================================================");
241
- ret.push("--- " + fileName + (typeof oldHeader === "undefined" ? "" : "\t" + oldHeader));
242
- ret.push("+++ " + fileName + (typeof newHeader === "undefined" ? "" : "\t" + newHeader));
243
+ ret.push('Index: ' + fileName);
244
+ ret.push('===================================================================');
245
+ ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
246
+ ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
243
247
 
244
248
  var diff = LineDiff.diff(oldStr, newStr);
245
249
  if (!diff[diff.length-1].value) {
246
250
  diff.pop(); // Remove trailing newline add
247
251
  }
248
- diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier
252
+ diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
249
253
 
250
254
  function contextLines(lines) {
251
255
  return lines.map(function(entry) { return ' ' + entry; });
@@ -253,7 +257,7 @@ var JsDiff = (function() {
253
257
  function eofNL(curRange, i, current) {
254
258
  var last = diff[diff.length-2],
255
259
  isLast = i === diff.length-2,
256
- isLastOfType = i === diff.length-3 && (current.added === !last.added || current.removed === !last.removed);
260
+ isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
257
261
 
258
262
  // Figure out if this is the last line for the given file and missing NL
259
263
  if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
@@ -265,7 +269,7 @@ var JsDiff = (function() {
265
269
  oldLine = 1, newLine = 1;
266
270
  for (var i = 0; i < diff.length; i++) {
267
271
  var current = diff[i],
268
- lines = current.lines || current.value.replace(/\n$/, "").split("\n");
272
+ lines = current.lines || current.value.replace(/\n$/, '').split('\n');
269
273
  current.lines = lines;
270
274
 
271
275
  if (current.added || current.removed) {
@@ -273,14 +277,14 @@ var JsDiff = (function() {
273
277
  var prev = diff[i-1];
274
278
  oldRangeStart = oldLine;
275
279
  newRangeStart = newLine;
276
-
280
+
277
281
  if (prev) {
278
282
  curRange = contextLines(prev.lines.slice(-4));
279
283
  oldRangeStart -= curRange.length;
280
284
  newRangeStart -= curRange.length;
281
285
  }
282
286
  }
283
- curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; }));
287
+ curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
284
288
  eofNL(curRange, i, current);
285
289
 
286
290
  if (current.added) {
@@ -298,9 +302,9 @@ var JsDiff = (function() {
298
302
  // end the range and output
299
303
  var contextSize = Math.min(lines.length, 4);
300
304
  ret.push(
301
- "@@ -" + oldRangeStart + "," + (oldLine-oldRangeStart+contextSize)
302
- + " +" + newRangeStart + "," + (newLine-newRangeStart+contextSize)
303
- + " @@");
305
+ '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
306
+ + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
307
+ + ' @@');
304
308
  ret.push.apply(ret, curRange);
305
309
  ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
306
310
  if (lines.length <= 4) {
@@ -318,30 +322,93 @@ var JsDiff = (function() {
318
322
  return ret.join('\n') + '\n';
319
323
  },
320
324
 
325
+ applyPatch: function(oldStr, uniDiff) {
326
+ var diffstr = uniDiff.split('\n');
327
+ var diff = [];
328
+ var remEOFNL = false,
329
+ addEOFNL = false;
330
+
331
+ for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
332
+ if(diffstr[i][0] === '@') {
333
+ var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
334
+ diff.unshift({
335
+ start:meh[3],
336
+ oldlength:meh[2],
337
+ oldlines:[],
338
+ newlength:meh[4],
339
+ newlines:[]
340
+ });
341
+ } else if(diffstr[i][0] === '+') {
342
+ diff[0].newlines.push(diffstr[i].substr(1));
343
+ } else if(diffstr[i][0] === '-') {
344
+ diff[0].oldlines.push(diffstr[i].substr(1));
345
+ } else if(diffstr[i][0] === ' ') {
346
+ diff[0].newlines.push(diffstr[i].substr(1));
347
+ diff[0].oldlines.push(diffstr[i].substr(1));
348
+ } else if(diffstr[i][0] === '\\') {
349
+ if (diffstr[i-1][0] === '+') {
350
+ remEOFNL = true;
351
+ } else if(diffstr[i-1][0] === '-') {
352
+ addEOFNL = true;
353
+ }
354
+ }
355
+ }
356
+
357
+ var str = oldStr.split('\n');
358
+ for (var i = diff.length - 1; i >= 0; i--) {
359
+ var d = diff[i];
360
+ for (var j = 0; j < d.oldlength; j++) {
361
+ if(str[d.start-1+j] !== d.oldlines[j]) {
362
+ return false;
363
+ }
364
+ }
365
+ Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
366
+ }
367
+
368
+ if (remEOFNL) {
369
+ while (!str[str.length-1]) {
370
+ str.pop();
371
+ }
372
+ } else if (addEOFNL) {
373
+ str.push('');
374
+ }
375
+ return str.join('\n');
376
+ },
377
+
321
378
  convertChangesToXML: function(changes){
322
379
  var ret = [];
323
380
  for ( var i = 0; i < changes.length; i++) {
324
381
  var change = changes[i];
325
382
  if (change.added) {
326
- ret.push("<ins>");
383
+ ret.push('<ins>');
327
384
  } else if (change.removed) {
328
- ret.push("<del>");
385
+ ret.push('<del>');
329
386
  }
330
387
 
331
388
  ret.push(escapeHTML(change.value));
332
389
 
333
390
  if (change.added) {
334
- ret.push("</ins>");
391
+ ret.push('</ins>');
335
392
  } else if (change.removed) {
336
- ret.push("</del>");
393
+ ret.push('</del>');
337
394
  }
338
395
  }
339
- return ret.join("");
396
+ return ret.join('');
397
+ },
398
+
399
+ // See: http://code.google.com/p/google-diff-match-patch/wiki/API
400
+ convertChangesToDMP: function(changes){
401
+ var ret = [], change;
402
+ for ( var i = 0; i < changes.length; i++) {
403
+ change = changes[i];
404
+ ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
405
+ }
406
+ return ret;
340
407
  }
341
408
  };
342
409
  })();
343
410
 
344
- if (typeof module !== "undefined") {
411
+ if (typeof module !== 'undefined') {
345
412
  module.exports = JsDiff;
346
413
  }
347
414
 
@@ -537,7 +604,6 @@ require.register("browser/path.js", function(module, exports, require){
537
604
  }); // module: browser/path.js
538
605
 
539
606
  require.register("browser/progress.js", function(module, exports, require){
540
-
541
607
  /**
542
608
  * Expose `Progress`.
543
609
  */
@@ -626,40 +692,41 @@ Progress.prototype.update = function(n){
626
692
  */
627
693
 
628
694
  Progress.prototype.draw = function(ctx){
629
- var percent = Math.min(this.percent, 100)
630
- , size = this._size
631
- , half = size / 2
632
- , x = half
633
- , y = half
634
- , rad = half - 1
635
- , fontSize = this._fontSize;
636
-
637
- ctx.font = fontSize + 'px ' + this._font;
638
-
639
- var angle = Math.PI * 2 * (percent / 100);
640
- ctx.clearRect(0, 0, size, size);
641
-
642
- // outer circle
643
- ctx.strokeStyle = '#9f9f9f';
644
- ctx.beginPath();
645
- ctx.arc(x, y, rad, 0, angle, false);
646
- ctx.stroke();
647
-
648
- // inner circle
649
- ctx.strokeStyle = '#eee';
650
- ctx.beginPath();
651
- ctx.arc(x, y, rad - 1, 0, angle, true);
652
- ctx.stroke();
653
-
654
- // text
655
- var text = this._text || (percent | 0) + '%'
656
- , w = ctx.measureText(text).width;
657
-
658
- ctx.fillText(
659
- text
660
- , x - w / 2 + 1
661
- , y + fontSize / 2 - 1);
662
-
695
+ try {
696
+ var percent = Math.min(this.percent, 100)
697
+ , size = this._size
698
+ , half = size / 2
699
+ , x = half
700
+ , y = half
701
+ , rad = half - 1
702
+ , fontSize = this._fontSize;
703
+
704
+ ctx.font = fontSize + 'px ' + this._font;
705
+
706
+ var angle = Math.PI * 2 * (percent / 100);
707
+ ctx.clearRect(0, 0, size, size);
708
+
709
+ // outer circle
710
+ ctx.strokeStyle = '#9f9f9f';
711
+ ctx.beginPath();
712
+ ctx.arc(x, y, rad, 0, angle, false);
713
+ ctx.stroke();
714
+
715
+ // inner circle
716
+ ctx.strokeStyle = '#eee';
717
+ ctx.beginPath();
718
+ ctx.arc(x, y, rad - 1, 0, angle, true);
719
+ ctx.stroke();
720
+
721
+ // text
722
+ var text = this._text || (percent | 0) + '%'
723
+ , w = ctx.measureText(text).width;
724
+
725
+ ctx.fillText(
726
+ text
727
+ , x - w / 2 + 1
728
+ , y + fontSize / 2 - 1);
729
+ } catch (ex) {} //don't fail if we can't render progress
663
730
  return this;
664
731
  };
665
732
 
@@ -672,8 +739,14 @@ exports.isatty = function(){
672
739
  };
673
740
 
674
741
  exports.getWindowSize = function(){
675
- return [window.innerHeight, window.innerWidth];
742
+ if ('innerHeight' in global) {
743
+ return [global.innerHeight, global.innerWidth];
744
+ } else {
745
+ // In a Web Worker, the DOM Window is not available.
746
+ return [640, 480];
747
+ }
676
748
  };
749
+
677
750
  }); // module: browser/tty.js
678
751
 
679
752
  require.register("context.js", function(module, exports, require){
@@ -813,7 +886,8 @@ require.register("interfaces/bdd.js", function(module, exports, require){
813
886
  */
814
887
 
815
888
  var Suite = require('../suite')
816
- , Test = require('../test');
889
+ , Test = require('../test')
890
+ , utils = require('../utils');
817
891
 
818
892
  /**
819
893
  * BDD-style interface:
@@ -904,6 +978,7 @@ module.exports = function(suite){
904
978
  context.describe.only = function(title, fn){
905
979
  var suite = context.describe(title, fn);
906
980
  mocha.grep(suite.fullTitle());
981
+ return suite;
907
982
  };
908
983
 
909
984
  /**
@@ -926,7 +1001,9 @@ module.exports = function(suite){
926
1001
 
927
1002
  context.it.only = function(title, fn){
928
1003
  var test = context.it(title, fn);
929
- mocha.grep(test.fullTitle());
1004
+ var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1005
+ mocha.grep(new RegExp(reString));
1006
+ return test;
930
1007
  };
931
1008
 
932
1009
  /**
@@ -1023,7 +1100,8 @@ require.register("interfaces/qunit.js", function(module, exports, require){
1023
1100
  */
1024
1101
 
1025
1102
  var Suite = require('../suite')
1026
- , Test = require('../test');
1103
+ , Test = require('../test')
1104
+ , utils = require('../utils');
1027
1105
 
1028
1106
  /**
1029
1107
  * QUnit-style interface:
@@ -1125,7 +1203,8 @@ module.exports = function(suite){
1125
1203
 
1126
1204
  context.test.only = function(title, fn){
1127
1205
  var test = context.test(title, fn);
1128
- mocha.grep(test.fullTitle());
1206
+ var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1207
+ mocha.grep(new RegExp(reString));
1129
1208
  };
1130
1209
 
1131
1210
  /**
@@ -1147,7 +1226,8 @@ require.register("interfaces/tdd.js", function(module, exports, require){
1147
1226
  */
1148
1227
 
1149
1228
  var Suite = require('../suite')
1150
- , Test = require('../test');
1229
+ , Test = require('../test')
1230
+ , utils = require('../utils');;
1151
1231
 
1152
1232
  /**
1153
1233
  * TDD-style interface:
@@ -1225,6 +1305,17 @@ module.exports = function(suite){
1225
1305
  return suite;
1226
1306
  };
1227
1307
 
1308
+ /**
1309
+ * Pending suite.
1310
+ */
1311
+ context.suite.skip = function(title, fn) {
1312
+ var suite = Suite.create(suites[0], title);
1313
+ suite.pending = true;
1314
+ suites.unshift(suite);
1315
+ fn.call(suite);
1316
+ suites.shift();
1317
+ };
1318
+
1228
1319
  /**
1229
1320
  * Exclusive test-case.
1230
1321
  */
@@ -1241,8 +1332,10 @@ module.exports = function(suite){
1241
1332
  */
1242
1333
 
1243
1334
  context.test = function(title, fn){
1335
+ var suite = suites[0];
1336
+ if (suite.pending) var fn = null;
1244
1337
  var test = new Test(title, fn);
1245
- suites[0].addTest(test);
1338
+ suite.addTest(test);
1246
1339
  return test;
1247
1340
  };
1248
1341
 
@@ -1252,7 +1345,8 @@ module.exports = function(suite){
1252
1345
 
1253
1346
  context.test.only = function(title, fn){
1254
1347
  var test = context.test(title, fn);
1255
- mocha.grep(test.fullTitle());
1348
+ var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1349
+ mocha.grep(new RegExp(reString));
1256
1350
  };
1257
1351
 
1258
1352
  /**
@@ -1340,8 +1434,24 @@ function Mocha(options) {
1340
1434
  this.ui(options.ui);
1341
1435
  this.bail(options.bail);
1342
1436
  this.reporter(options.reporter);
1343
- if (options.timeout) this.timeout(options.timeout);
1437
+ if (null != options.timeout) this.timeout(options.timeout);
1438
+ this.useColors(options.useColors)
1344
1439
  if (options.slow) this.slow(options.slow);
1440
+
1441
+ this.suite.on('pre-require', function (context) {
1442
+ exports.afterEach = context.afterEach || context.teardown;
1443
+ exports.after = context.after || context.suiteTeardown;
1444
+ exports.beforeEach = context.beforeEach || context.setup;
1445
+ exports.before = context.before || context.suiteSetup;
1446
+ exports.describe = context.describe || context.suite;
1447
+ exports.it = context.it || context.test;
1448
+ exports.setup = context.setup || context.beforeEach;
1449
+ exports.suiteSetup = context.suiteSetup || context.before;
1450
+ exports.suiteTeardown = context.suiteTeardown || context.after;
1451
+ exports.suite = context.suite || context.describe;
1452
+ exports.teardown = context.teardown || context.afterEach;
1453
+ exports.test = context.test || context.it;
1454
+ });
1345
1455
  }
1346
1456
 
1347
1457
  /**
@@ -1381,12 +1491,15 @@ Mocha.prototype.reporter = function(reporter){
1381
1491
  this._reporter = reporter;
1382
1492
  } else {
1383
1493
  reporter = reporter || 'dot';
1384
- try {
1385
- this._reporter = require('./reporters/' + reporter);
1386
- } catch (err) {
1387
- this._reporter = require(reporter);
1388
- }
1389
- if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"');
1494
+ var _reporter;
1495
+ try { _reporter = require('./reporters/' + reporter); } catch (err) {};
1496
+ if (!_reporter) try { _reporter = require(reporter); } catch (err) {};
1497
+ if (!_reporter && reporter === 'teamcity')
1498
+ console.warn('The Teamcity reporter was moved to a package named ' +
1499
+ 'mocha-teamcity-reporter ' +
1500
+ '(https://npmjs.org/package/mocha-teamcity-reporter).');
1501
+ if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
1502
+ this._reporter = _reporter;
1390
1503
  }
1391
1504
  return this;
1392
1505
  };
@@ -1401,6 +1514,7 @@ Mocha.prototype.reporter = function(reporter){
1401
1514
  Mocha.prototype.ui = function(name){
1402
1515
  name = name || 'bdd';
1403
1516
  this._ui = exports.interfaces[name];
1517
+ if (!this._ui) try { this._ui = require(name); } catch (err) {};
1404
1518
  if (!this._ui) throw new Error('invalid interface "' + name + '"');
1405
1519
  this._ui = this._ui(this.suite);
1406
1520
  return this;
@@ -1479,12 +1593,13 @@ Mocha.prototype.invert = function(){
1479
1593
  /**
1480
1594
  * Ignore global leaks.
1481
1595
  *
1596
+ * @param {Boolean} ignore
1482
1597
  * @return {Mocha}
1483
1598
  * @api public
1484
1599
  */
1485
1600
 
1486
- Mocha.prototype.ignoreLeaks = function(){
1487
- this.options.ignoreLeaks = true;
1601
+ Mocha.prototype.ignoreLeaks = function(ignore){
1602
+ this.options.ignoreLeaks = !!ignore;
1488
1603
  return this;
1489
1604
  };
1490
1605
 
@@ -1525,6 +1640,36 @@ Mocha.prototype.globals = function(globals){
1525
1640
  return this;
1526
1641
  };
1527
1642
 
1643
+ /**
1644
+ * Emit color output.
1645
+ *
1646
+ * @param {Boolean} colors
1647
+ * @return {Mocha}
1648
+ * @api public
1649
+ */
1650
+
1651
+ Mocha.prototype.useColors = function(colors){
1652
+ this.options.useColors = arguments.length && colors != undefined
1653
+ ? colors
1654
+ : true;
1655
+ return this;
1656
+ };
1657
+
1658
+ /**
1659
+ * Use inline diffs rather than +/-.
1660
+ *
1661
+ * @param {Boolean} inlineDiffs
1662
+ * @return {Mocha}
1663
+ * @api public
1664
+ */
1665
+
1666
+ Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
1667
+ this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined
1668
+ ? inlineDiffs
1669
+ : false;
1670
+ return this;
1671
+ };
1672
+
1528
1673
  /**
1529
1674
  * Set the timeout in milliseconds.
1530
1675
  *
@@ -1582,13 +1727,14 @@ Mocha.prototype.run = function(fn){
1582
1727
  if (options.grep) runner.grep(options.grep, options.invert);
1583
1728
  if (options.globals) runner.globals(options.globals);
1584
1729
  if (options.growl) this._growl(runner, reporter);
1730
+ exports.reporters.Base.useColors = options.useColors;
1731
+ exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
1585
1732
  return runner.run(fn);
1586
1733
  };
1587
1734
 
1588
1735
  }); // module: mocha.js
1589
1736
 
1590
1737
  require.register("ms.js", function(module, exports, require){
1591
-
1592
1738
  /**
1593
1739
  * Helpers.
1594
1740
  */
@@ -1597,19 +1743,26 @@ var s = 1000;
1597
1743
  var m = s * 60;
1598
1744
  var h = m * 60;
1599
1745
  var d = h * 24;
1746
+ var y = d * 365.25;
1600
1747
 
1601
1748
  /**
1602
1749
  * Parse or format the given `val`.
1603
1750
  *
1751
+ * Options:
1752
+ *
1753
+ * - `long` verbose formatting [false]
1754
+ *
1604
1755
  * @param {String|Number} val
1756
+ * @param {Object} options
1605
1757
  * @return {String|Number}
1606
1758
  * @api public
1607
1759
  */
1608
1760
 
1609
- module.exports = function(val){
1761
+ module.exports = function(val, options){
1762
+ options = options || {};
1610
1763
  if ('string' == typeof val) return parse(val);
1611
- return format(val);
1612
- }
1764
+ return options.long ? longFormat(val) : shortFormat(val);
1765
+ };
1613
1766
 
1614
1767
  /**
1615
1768
  * Parse the given `str` and return milliseconds.
@@ -1620,55 +1773,78 @@ module.exports = function(val){
1620
1773
  */
1621
1774
 
1622
1775
  function parse(str) {
1623
- var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
1624
- if (!m) return;
1625
- var n = parseFloat(m[1]);
1626
- var type = (m[2] || 'ms').toLowerCase();
1776
+ var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
1777
+ if (!match) return;
1778
+ var n = parseFloat(match[1]);
1779
+ var type = (match[2] || 'ms').toLowerCase();
1627
1780
  switch (type) {
1628
1781
  case 'years':
1629
1782
  case 'year':
1630
1783
  case 'y':
1631
- return n * 31557600000;
1784
+ return n * y;
1632
1785
  case 'days':
1633
1786
  case 'day':
1634
1787
  case 'd':
1635
- return n * 86400000;
1788
+ return n * d;
1636
1789
  case 'hours':
1637
1790
  case 'hour':
1638
1791
  case 'h':
1639
- return n * 3600000;
1792
+ return n * h;
1640
1793
  case 'minutes':
1641
1794
  case 'minute':
1642
1795
  case 'm':
1643
- return n * 60000;
1796
+ return n * m;
1644
1797
  case 'seconds':
1645
1798
  case 'second':
1646
1799
  case 's':
1647
- return n * 1000;
1800
+ return n * s;
1648
1801
  case 'ms':
1649
1802
  return n;
1650
1803
  }
1651
1804
  }
1652
1805
 
1653
1806
  /**
1654
- * Format the given `ms`.
1807
+ * Short format for `ms`.
1655
1808
  *
1656
1809
  * @param {Number} ms
1657
1810
  * @return {String}
1658
- * @api public
1811
+ * @api private
1812
+ */
1813
+
1814
+ function shortFormat(ms) {
1815
+ if (ms >= d) return Math.round(ms / d) + 'd';
1816
+ if (ms >= h) return Math.round(ms / h) + 'h';
1817
+ if (ms >= m) return Math.round(ms / m) + 'm';
1818
+ if (ms >= s) return Math.round(ms / s) + 's';
1819
+ return ms + 'ms';
1820
+ }
1821
+
1822
+ /**
1823
+ * Long format for `ms`.
1824
+ *
1825
+ * @param {Number} ms
1826
+ * @return {String}
1827
+ * @api private
1828
+ */
1829
+
1830
+ function longFormat(ms) {
1831
+ return plural(ms, d, 'day')
1832
+ || plural(ms, h, 'hour')
1833
+ || plural(ms, m, 'minute')
1834
+ || plural(ms, s, 'second')
1835
+ || ms + ' ms';
1836
+ }
1837
+
1838
+ /**
1839
+ * Pluralization helper.
1659
1840
  */
1660
1841
 
1661
- function format(ms) {
1662
- if (ms == d) return Math.round(ms / d) + ' day';
1663
- if (ms > d) return Math.round(ms / d) + ' days';
1664
- if (ms == h) return Math.round(ms / h) + ' hour';
1665
- if (ms > h) return Math.round(ms / h) + ' hours';
1666
- if (ms == m) return Math.round(ms / m) + ' minute';
1667
- if (ms > m) return Math.round(ms / m) + ' minutes';
1668
- if (ms == s) return Math.round(ms / s) + ' second';
1669
- if (ms > s) return Math.round(ms / s) + ' seconds';
1670
- return ms + ' ms';
1842
+ function plural(ms, n, name) {
1843
+ if (ms < n) return;
1844
+ if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
1845
+ return Math.ceil(ms / n) + ' ' + name + 's';
1671
1846
  }
1847
+
1672
1848
  }); // module: ms.js
1673
1849
 
1674
1850
  require.register("reporters/base.js", function(module, exports, require){
@@ -1679,7 +1855,8 @@ require.register("reporters/base.js", function(module, exports, require){
1679
1855
 
1680
1856
  var tty = require('browser/tty')
1681
1857
  , diff = require('browser/diff')
1682
- , ms = require('../ms');
1858
+ , ms = require('../ms')
1859
+ , utils = require('../utils');
1683
1860
 
1684
1861
  /**
1685
1862
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -1707,7 +1884,13 @@ exports = module.exports = Base;
1707
1884
  * Enable coloring by default.
1708
1885
  */
1709
1886
 
1710
- exports.useColors = isatty;
1887
+ exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);
1888
+
1889
+ /**
1890
+ * Inline diffs instead of +/-
1891
+ */
1892
+
1893
+ exports.inlineDiffs = false;
1711
1894
 
1712
1895
  /**
1713
1896
  * Default color map.
@@ -1789,24 +1972,28 @@ exports.window = {
1789
1972
 
1790
1973
  exports.cursor = {
1791
1974
  hide: function(){
1792
- process.stdout.write('\u001b[?25l');
1975
+ isatty && process.stdout.write('\u001b[?25l');
1793
1976
  },
1794
1977
 
1795
1978
  show: function(){
1796
- process.stdout.write('\u001b[?25h');
1979
+ isatty && process.stdout.write('\u001b[?25h');
1797
1980
  },
1798
1981
 
1799
1982
  deleteLine: function(){
1800
- process.stdout.write('\u001b[2K');
1983
+ isatty && process.stdout.write('\u001b[2K');
1801
1984
  },
1802
1985
 
1803
1986
  beginningOfLine: function(){
1804
- process.stdout.write('\u001b[0G');
1987
+ isatty && process.stdout.write('\u001b[0G');
1805
1988
  },
1806
1989
 
1807
1990
  CR: function(){
1808
- exports.cursor.deleteLine();
1809
- exports.cursor.beginningOfLine();
1991
+ if (isatty) {
1992
+ exports.cursor.deleteLine();
1993
+ exports.cursor.beginningOfLine();
1994
+ } else {
1995
+ process.stdout.write('\r');
1996
+ }
1810
1997
  }
1811
1998
  };
1812
1999
 
@@ -1835,40 +2022,29 @@ exports.list = function(failures){
1835
2022
  , expected = err.expected
1836
2023
  , escape = true;
1837
2024
 
2025
+ // uncaught
2026
+ if (err.uncaught) {
2027
+ msg = 'Uncaught ' + msg;
2028
+ }
2029
+
1838
2030
  // explicitly show diff
1839
- if (err.showDiff) {
2031
+ if (err.showDiff && sameType(actual, expected)) {
1840
2032
  escape = false;
1841
- err.actual = actual = JSON.stringify(actual, null, 2);
1842
- err.expected = expected = JSON.stringify(expected, null, 2);
2033
+ err.actual = actual = stringify(canonicalize(actual));
2034
+ err.expected = expected = stringify(canonicalize(expected));
1843
2035
  }
1844
2036
 
1845
2037
  // actual / expected diff
1846
2038
  if ('string' == typeof actual && 'string' == typeof expected) {
1847
- msg = errorDiff(err, 'Words', escape);
1848
-
1849
- // linenos
1850
- var lines = msg.split('\n');
1851
- if (lines.length > 4) {
1852
- var width = String(lines.length).length;
1853
- msg = lines.map(function(str, i){
1854
- return pad(++i, width) + ' |' + ' ' + str;
1855
- }).join('\n');
1856
- }
2039
+ fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
2040
+ var match = message.match(/^([^:]+): expected/);
2041
+ msg = '\n ' + color('error message', match ? match[1] : msg);
1857
2042
 
1858
- // legend
1859
- msg = '\n'
1860
- + color('diff removed', 'actual')
1861
- + ' '
1862
- + color('diff added', 'expected')
1863
- + '\n\n'
1864
- + msg
1865
- + '\n';
1866
-
1867
- // indent
1868
- msg = msg.replace(/^/gm, ' ');
1869
-
1870
- fmt = color('error title', ' %s) %s:\n%s')
1871
- + color('error stack', '\n%s\n');
2043
+ if (exports.inlineDiffs) {
2044
+ msg += inlineDiff(err, escape);
2045
+ } else {
2046
+ msg += unifiedDiff(err, escape);
2047
+ }
1872
2048
  }
1873
2049
 
1874
2050
  // indent stack trace without msg
@@ -1953,48 +2129,38 @@ function Base(runner) {
1953
2129
  */
1954
2130
 
1955
2131
  Base.prototype.epilogue = function(){
1956
- var stats = this.stats
1957
- , fmt
1958
- , tests;
2132
+ var stats = this.stats;
2133
+ var tests;
2134
+ var fmt;
1959
2135
 
1960
2136
  console.log();
1961
2137
 
1962
- function pluralize(n) {
1963
- return 1 == n ? 'test' : 'tests';
1964
- }
1965
-
1966
- // failure
1967
- if (stats.failures) {
1968
- fmt = color('bright fail', ' ' + exports.symbols.err)
1969
- + color('fail', ' %d of %d %s failed')
1970
- + color('light', ':')
1971
-
1972
- console.error(fmt,
1973
- stats.failures,
1974
- this.runner.total,
1975
- pluralize(this.runner.total));
1976
-
1977
- Base.list(this.failures);
1978
- console.error();
1979
- return;
1980
- }
1981
-
1982
- // pass
2138
+ // passes
1983
2139
  fmt = color('bright pass', ' ')
1984
- + color('green', ' %d %s complete')
2140
+ + color('green', ' %d passing')
1985
2141
  + color('light', ' (%s)');
1986
2142
 
1987
2143
  console.log(fmt,
1988
- stats.tests || 0,
1989
- pluralize(stats.tests),
2144
+ stats.passes || 0,
1990
2145
  ms(stats.duration));
1991
2146
 
1992
2147
  // pending
1993
2148
  if (stats.pending) {
1994
2149
  fmt = color('pending', ' ')
1995
- + color('pending', ' %d %s pending');
2150
+ + color('pending', ' %d pending');
1996
2151
 
1997
- console.log(fmt, stats.pending, pluralize(stats.pending));
2152
+ console.log(fmt, stats.pending);
2153
+ }
2154
+
2155
+ // failures
2156
+ if (stats.failures) {
2157
+ fmt = color('fail', ' %d failing');
2158
+
2159
+ console.error(fmt,
2160
+ stats.failures);
2161
+
2162
+ Base.list(this.failures);
2163
+ console.error();
1998
2164
  }
1999
2165
 
2000
2166
  console.log();
@@ -2014,6 +2180,73 @@ function pad(str, len) {
2014
2180
  return Array(len - str.length + 1).join(' ') + str;
2015
2181
  }
2016
2182
 
2183
+
2184
+ /**
2185
+ * Returns an inline diff between 2 strings with coloured ANSI output
2186
+ *
2187
+ * @param {Error} Error with actual/expected
2188
+ * @return {String} Diff
2189
+ * @api private
2190
+ */
2191
+
2192
+ function inlineDiff(err, escape) {
2193
+ var msg = errorDiff(err, 'WordsWithSpace', escape);
2194
+
2195
+ // linenos
2196
+ var lines = msg.split('\n');
2197
+ if (lines.length > 4) {
2198
+ var width = String(lines.length).length;
2199
+ msg = lines.map(function(str, i){
2200
+ return pad(++i, width) + ' |' + ' ' + str;
2201
+ }).join('\n');
2202
+ }
2203
+
2204
+ // legend
2205
+ msg = '\n'
2206
+ + color('diff removed', 'actual')
2207
+ + ' '
2208
+ + color('diff added', 'expected')
2209
+ + '\n\n'
2210
+ + msg
2211
+ + '\n';
2212
+
2213
+ // indent
2214
+ msg = msg.replace(/^/gm, ' ');
2215
+ return msg;
2216
+ }
2217
+
2218
+ /**
2219
+ * Returns a unified diff between 2 strings
2220
+ *
2221
+ * @param {Error} Error with actual/expected
2222
+ * @return {String} Diff
2223
+ * @api private
2224
+ */
2225
+
2226
+ function unifiedDiff(err, escape) {
2227
+ var indent = ' ';
2228
+ function cleanUp(line) {
2229
+ if (escape) {
2230
+ line = escapeInvisibles(line);
2231
+ }
2232
+ if (line[0] === '+') return indent + colorLines('diff added', line);
2233
+ if (line[0] === '-') return indent + colorLines('diff removed', line);
2234
+ if (line.match(/\@\@/)) return null;
2235
+ if (line.match(/\\ No newline/)) return null;
2236
+ else return indent + line;
2237
+ }
2238
+ function notBlank(line) {
2239
+ return line != null;
2240
+ }
2241
+ msg = diff.createPatch('string', err.actual, err.expected);
2242
+ var lines = msg.split('\n').splice(4);
2243
+ return '\n '
2244
+ + colorLines('diff added', '+ expected') + ' '
2245
+ + colorLines('diff removed', '- actual')
2246
+ + '\n\n'
2247
+ + lines.map(cleanUp).filter(notBlank).join('\n');
2248
+ }
2249
+
2017
2250
  /**
2018
2251
  * Return a character diff for `err`.
2019
2252
  *
@@ -2023,19 +2256,28 @@ function pad(str, len) {
2023
2256
  */
2024
2257
 
2025
2258
  function errorDiff(err, type, escape) {
2026
- return diff['diff' + type](err.actual, err.expected).map(function(str){
2027
- if (escape) {
2028
- str.value = str.value
2029
- .replace(/\t/g, '<tab>')
2030
- .replace(/\r/g, '<CR>')
2031
- .replace(/\n/g, '<LF>\n');
2032
- }
2259
+ var actual = escape ? escapeInvisibles(err.actual) : err.actual;
2260
+ var expected = escape ? escapeInvisibles(err.expected) : err.expected;
2261
+ return diff['diff' + type](actual, expected).map(function(str){
2033
2262
  if (str.added) return colorLines('diff added', str.value);
2034
2263
  if (str.removed) return colorLines('diff removed', str.value);
2035
2264
  return str.value;
2036
2265
  }).join('');
2037
2266
  }
2038
2267
 
2268
+ /**
2269
+ * Returns a string with all invisible characters in plain text
2270
+ *
2271
+ * @param {String} line
2272
+ * @return {String}
2273
+ * @api private
2274
+ */
2275
+ function escapeInvisibles(line) {
2276
+ return line.replace(/\t/g, '<tab>')
2277
+ .replace(/\r/g, '<CR>')
2278
+ .replace(/\n/g, '<LF>\n');
2279
+ }
2280
+
2039
2281
  /**
2040
2282
  * Color lines for `str`, using the color `name`.
2041
2283
  *
@@ -2051,6 +2293,69 @@ function colorLines(name, str) {
2051
2293
  }).join('\n');
2052
2294
  }
2053
2295
 
2296
+ /**
2297
+ * Stringify `obj`.
2298
+ *
2299
+ * @param {Object} obj
2300
+ * @return {String}
2301
+ * @api private
2302
+ */
2303
+
2304
+ function stringify(obj) {
2305
+ if (obj instanceof RegExp) return obj.toString();
2306
+ return JSON.stringify(obj, null, 2);
2307
+ }
2308
+
2309
+ /**
2310
+ * Return a new object that has the keys in sorted order.
2311
+ * @param {Object} obj
2312
+ * @return {Object}
2313
+ * @api private
2314
+ */
2315
+
2316
+ function canonicalize(obj, stack) {
2317
+ stack = stack || [];
2318
+
2319
+ if (utils.indexOf(stack, obj) !== -1) return obj;
2320
+
2321
+ var canonicalizedObj;
2322
+
2323
+ if ('[object Array]' == {}.toString.call(obj)) {
2324
+ stack.push(obj);
2325
+ canonicalizedObj = utils.map(obj, function(item) {
2326
+ return canonicalize(item, stack);
2327
+ });
2328
+ stack.pop();
2329
+ } else if (typeof obj === 'object' && obj !== null) {
2330
+ stack.push(obj);
2331
+ canonicalizedObj = {};
2332
+ utils.forEach(utils.keys(obj).sort(), function(key) {
2333
+ canonicalizedObj[key] = canonicalize(obj[key], stack);
2334
+ });
2335
+ stack.pop();
2336
+ } else {
2337
+ canonicalizedObj = obj;
2338
+ }
2339
+
2340
+ return canonicalizedObj;
2341
+ }
2342
+
2343
+ /**
2344
+ * Check that a / b have the same type.
2345
+ *
2346
+ * @param {Object} a
2347
+ * @param {Object} b
2348
+ * @return {Boolean}
2349
+ * @api private
2350
+ */
2351
+
2352
+ function sameType(a, b) {
2353
+ a = Object.prototype.toString.call(a);
2354
+ b = Object.prototype.toString.call(b);
2355
+ return a == b;
2356
+ }
2357
+
2358
+
2054
2359
  }); // module: reporters/base.js
2055
2360
 
2056
2361
  require.register("reporters/doc.js", function(module, exports, require){
@@ -2258,7 +2563,7 @@ var Date = global.Date
2258
2563
  , clearInterval = global.clearInterval;
2259
2564
 
2260
2565
  /**
2261
- * Expose `Doc`.
2566
+ * Expose `HTML`.
2262
2567
  */
2263
2568
 
2264
2569
  exports = module.exports = HTML;
@@ -2275,7 +2580,7 @@ var statsTemplate = '<ul id="mocha-stats">'
2275
2580
  + '</ul>';
2276
2581
 
2277
2582
  /**
2278
- * Initialize a new `Doc` reporter.
2583
+ * Initialize a new `HTML` reporter.
2279
2584
  *
2280
2585
  * @param {Runner} runner
2281
2586
  * @api public
@@ -2340,7 +2645,7 @@ function HTML(runner, root) {
2340
2645
  if (suite.root) return;
2341
2646
 
2342
2647
  // suite
2343
- var url = '?grep=' + encodeURIComponent(suite.fullTitle());
2648
+ var url = self.suiteURL(suite);
2344
2649
  var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
2345
2650
 
2346
2651
  // container
@@ -2371,7 +2676,8 @@ function HTML(runner, root) {
2371
2676
 
2372
2677
  // test
2373
2678
  if ('passed' == test.state) {
2374
- var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="?grep=%e" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle()));
2679
+ var url = self.testURL(test);
2680
+ var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
2375
2681
  } else if (test.pending) {
2376
2682
  var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
2377
2683
  } else {
@@ -2416,6 +2722,26 @@ function HTML(runner, root) {
2416
2722
  });
2417
2723
  }
2418
2724
 
2725
+ /**
2726
+ * Provide suite URL
2727
+ *
2728
+ * @param {Object} [suite]
2729
+ */
2730
+
2731
+ HTML.prototype.suiteURL = function(suite){
2732
+ return '?grep=' + encodeURIComponent(suite.fullTitle());
2733
+ };
2734
+
2735
+ /**
2736
+ * Provide test URL
2737
+ *
2738
+ * @param {Object} [test]
2739
+ */
2740
+
2741
+ HTML.prototype.testURL = function(test){
2742
+ return '?grep=' + encodeURIComponent(test.fullTitle());
2743
+ };
2744
+
2419
2745
  /**
2420
2746
  * Display error `msg`.
2421
2747
  */
@@ -2512,7 +2838,6 @@ exports.Landing = require('./landing');
2512
2838
  exports.JSONCov = require('./json-cov');
2513
2839
  exports.HTMLCov = require('./html-cov');
2514
2840
  exports.JSONStream = require('./json-stream');
2515
- exports.Teamcity = require('./teamcity');
2516
2841
 
2517
2842
  }); // module: reporters/index.js
2518
2843
 
@@ -3149,7 +3474,6 @@ exports = module.exports = NyanCat;
3149
3474
 
3150
3475
  function NyanCat(runner) {
3151
3476
  Base.call(this, runner);
3152
-
3153
3477
  var self = this
3154
3478
  , stats = this.stats
3155
3479
  , width = Base.window.width * .75 | 0
@@ -3165,19 +3489,19 @@ function NyanCat(runner) {
3165
3489
 
3166
3490
  runner.on('start', function(){
3167
3491
  Base.cursor.hide();
3168
- self.draw('start');
3492
+ self.draw();
3169
3493
  });
3170
3494
 
3171
3495
  runner.on('pending', function(test){
3172
- self.draw('pending');
3496
+ self.draw();
3173
3497
  });
3174
3498
 
3175
3499
  runner.on('pass', function(test){
3176
- self.draw('pass');
3500
+ self.draw();
3177
3501
  });
3178
3502
 
3179
3503
  runner.on('fail', function(test, err){
3180
- self.draw('fail');
3504
+ self.draw();
3181
3505
  });
3182
3506
 
3183
3507
  runner.on('end', function(){
@@ -3188,17 +3512,16 @@ function NyanCat(runner) {
3188
3512
  }
3189
3513
 
3190
3514
  /**
3191
- * Draw the nyan cat with runner `status`.
3515
+ * Draw the nyan cat
3192
3516
  *
3193
- * @param {String} status
3194
3517
  * @api private
3195
3518
  */
3196
3519
 
3197
- NyanCat.prototype.draw = function(status){
3520
+ NyanCat.prototype.draw = function(){
3198
3521
  this.appendRainbow();
3199
3522
  this.drawScoreboard();
3200
3523
  this.drawRainbow();
3201
- this.drawNyanCat(status);
3524
+ this.drawNyanCat();
3202
3525
  this.tick = !this.tick;
3203
3526
  };
3204
3527
 
@@ -3263,44 +3586,33 @@ NyanCat.prototype.drawRainbow = function(){
3263
3586
  };
3264
3587
 
3265
3588
  /**
3266
- * Draw the nyan cat with `status`.
3589
+ * Draw the nyan cat
3267
3590
  *
3268
- * @param {String} status
3269
3591
  * @api private
3270
3592
  */
3271
3593
 
3272
- NyanCat.prototype.drawNyanCat = function(status) {
3594
+ NyanCat.prototype.drawNyanCat = function() {
3273
3595
  var self = this;
3274
3596
  var startWidth = this.scoreboardWidth + this.trajectories[0].length;
3275
3597
  var color = '\u001b[' + startWidth + 'C';
3276
3598
  var padding = '';
3277
-
3599
+
3278
3600
  write(color);
3279
3601
  write('_,------,');
3280
3602
  write('\n');
3281
-
3603
+
3282
3604
  write(color);
3283
3605
  padding = self.tick ? ' ' : ' ';
3284
3606
  write('_|' + padding + '/\\_/\\ ');
3285
3607
  write('\n');
3286
-
3608
+
3287
3609
  write(color);
3288
3610
  padding = self.tick ? '_' : '__';
3289
3611
  var tail = self.tick ? '~' : '^';
3290
3612
  var face;
3291
- switch (status) {
3292
- case 'pass':
3293
- face = '( ^ .^)';
3294
- break;
3295
- case 'fail':
3296
- face = '( o .o)';
3297
- break;
3298
- default:
3299
- face = '( - .-)';
3300
- }
3301
- write(tail + '|' + padding + face + ' ');
3613
+ write(tail + '|' + padding + this.face() + ' ');
3302
3614
  write('\n');
3303
-
3615
+
3304
3616
  write(color);
3305
3617
  padding = self.tick ? ' ' : ' ';
3306
3618
  write(padding + '"" "" ');
@@ -3309,6 +3621,26 @@ NyanCat.prototype.drawNyanCat = function(status) {
3309
3621
  this.cursorUp(this.numberOfLines);
3310
3622
  };
3311
3623
 
3624
+ /**
3625
+ * Draw nyan cat face.
3626
+ *
3627
+ * @return {String}
3628
+ * @api private
3629
+ */
3630
+
3631
+ NyanCat.prototype.face = function() {
3632
+ var stats = this.stats;
3633
+ if (stats.failures) {
3634
+ return '( x .x)';
3635
+ } else if (stats.pending) {
3636
+ return '( o .o)';
3637
+ } else if(stats.passes) {
3638
+ return '( ^ .^)';
3639
+ } else {
3640
+ return '( - .-)';
3641
+ }
3642
+ }
3643
+
3312
3644
  /**
3313
3645
  * Move cursor up `n`.
3314
3646
  *
@@ -3530,10 +3862,6 @@ function Spec(runner) {
3530
3862
  if (1 == indents) console.log();
3531
3863
  });
3532
3864
 
3533
- runner.on('test', function(test){
3534
- process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
3535
- });
3536
-
3537
3865
  runner.on('pending', function(test){
3538
3866
  var fmt = indent() + color('pending', ' - %s');
3539
3867
  console.log(fmt, test.title);
@@ -3653,75 +3981,6 @@ function title(test) {
3653
3981
 
3654
3982
  }); // module: reporters/tap.js
3655
3983
 
3656
- require.register("reporters/teamcity.js", function(module, exports, require){
3657
-
3658
- /**
3659
- * Module dependencies.
3660
- */
3661
-
3662
- var Base = require('./base');
3663
-
3664
- /**
3665
- * Expose `Teamcity`.
3666
- */
3667
-
3668
- exports = module.exports = Teamcity;
3669
-
3670
- /**
3671
- * Initialize a new `Teamcity` reporter.
3672
- *
3673
- * @param {Runner} runner
3674
- * @api public
3675
- */
3676
-
3677
- function Teamcity(runner) {
3678
- Base.call(this, runner);
3679
- var stats = this.stats;
3680
-
3681
- runner.on('start', function() {
3682
- console.log("##teamcity[testSuiteStarted name='mocha.suite']");
3683
- });
3684
-
3685
- runner.on('test', function(test) {
3686
- console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']");
3687
- });
3688
-
3689
- runner.on('fail', function(test, err) {
3690
- console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']");
3691
- });
3692
-
3693
- runner.on('pending', function(test) {
3694
- console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']");
3695
- });
3696
-
3697
- runner.on('test end', function(test) {
3698
- console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']");
3699
- });
3700
-
3701
- runner.on('end', function() {
3702
- console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']");
3703
- });
3704
- }
3705
-
3706
- /**
3707
- * Escape the given `str`.
3708
- */
3709
-
3710
- function escape(str) {
3711
- return str
3712
- .replace(/\|/g, "||")
3713
- .replace(/\n/g, "|n")
3714
- .replace(/\r/g, "|r")
3715
- .replace(/\[/g, "|[")
3716
- .replace(/\]/g, "|]")
3717
- .replace(/\u0085/g, "|x")
3718
- .replace(/\u2028/g, "|l")
3719
- .replace(/\u2029/g, "|p")
3720
- .replace(/'/g, "|'");
3721
- }
3722
-
3723
- }); // module: reporters/teamcity.js
3724
-
3725
3984
  require.register("reporters/xunit.js", function(module, exports, require){
3726
3985
 
3727
3986
  /**
@@ -3761,6 +4020,10 @@ function XUnit(runner) {
3761
4020
  , tests = []
3762
4021
  , self = this;
3763
4022
 
4023
+ runner.on('pending', function(test){
4024
+ tests.push(test);
4025
+ });
4026
+
3764
4027
  runner.on('pass', function(test){
3765
4028
  tests.push(test);
3766
4029
  });
@@ -3775,9 +4038,9 @@ function XUnit(runner) {
3775
4038
  , tests: stats.tests
3776
4039
  , failures: stats.failures
3777
4040
  , errors: stats.failures
3778
- , skip: stats.tests - stats.failures - stats.passes
4041
+ , skipped: stats.tests - stats.failures - stats.passes
3779
4042
  , timestamp: (new Date).toUTCString()
3780
- , time: stats.duration / 1000
4043
+ , time: (stats.duration / 1000) || 0
3781
4044
  }, false));
3782
4045
 
3783
4046
  tests.forEach(test);
@@ -3803,7 +4066,7 @@ function test(test) {
3803
4066
  var attrs = {
3804
4067
  classname: test.parent.fullTitle()
3805
4068
  , name: test.title
3806
- , time: test.duration / 1000
4069
+ , time: (test.duration / 1000) || 0
3807
4070
  };
3808
4071
 
3809
4072
  if ('failed' == test.state) {
@@ -3983,16 +4246,24 @@ Runnable.prototype.inspect = function(){
3983
4246
  */
3984
4247
 
3985
4248
  Runnable.prototype.resetTimeout = function(){
3986
- var self = this
3987
- , ms = this.timeout();
4249
+ var self = this;
4250
+ var ms = this.timeout() || 1e9;
3988
4251
 
3989
4252
  this.clearTimeout();
3990
- if (ms) {
3991
- this.timer = setTimeout(function(){
3992
- self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
3993
- self.timedOut = true;
3994
- }, ms);
3995
- }
4253
+ this.timer = setTimeout(function(){
4254
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
4255
+ self.timedOut = true;
4256
+ }, ms);
4257
+ };
4258
+
4259
+ /**
4260
+ * Whitelist these globals for this test run
4261
+ *
4262
+ * @api private
4263
+ */
4264
+ Runnable.prototype.globals = function(arr){
4265
+ var self = this;
4266
+ this._allowedGlobals = arr;
3996
4267
  };
3997
4268
 
3998
4269
  /**
@@ -4073,7 +4344,6 @@ Runnable.prototype.run = function(fn){
4073
4344
  }); // module: runnable.js
4074
4345
 
4075
4346
  require.register("runner.js", function(module, exports, require){
4076
-
4077
4347
  /**
4078
4348
  * Module dependencies.
4079
4349
  */
@@ -4119,6 +4389,7 @@ module.exports = Runner;
4119
4389
  * - `hook end` (hook) hook complete
4120
4390
  * - `pass` (test) test passed
4121
4391
  * - `fail` (test, err) test failed
4392
+ * - `pending` (test) test pending
4122
4393
  *
4123
4394
  * @api public
4124
4395
  */
@@ -4126,13 +4397,14 @@ module.exports = Runner;
4126
4397
  function Runner(suite) {
4127
4398
  var self = this;
4128
4399
  this._globals = [];
4400
+ this._abort = false;
4129
4401
  this.suite = suite;
4130
4402
  this.total = suite.total();
4131
4403
  this.failures = 0;
4132
4404
  this.on('test end', function(test){ self.checkGlobals(test); });
4133
4405
  this.on('hook end', function(hook){ self.checkGlobals(hook); });
4134
4406
  this.grep(/.*/);
4135
- this.globals(this.globalProps().concat(['errno']));
4407
+ this.globals(this.globalProps().concat(extraGlobals()));
4136
4408
  }
4137
4409
 
4138
4410
  /**
@@ -4224,9 +4496,7 @@ Runner.prototype.globalProps = function() {
4224
4496
  Runner.prototype.globals = function(arr){
4225
4497
  if (0 == arguments.length) return this._globals;
4226
4498
  debug('globals %j', arr);
4227
- utils.forEach(arr, function(arr){
4228
- this._globals.push(arr);
4229
- }, this);
4499
+ this._globals = this._globals.concat(arr);
4230
4500
  return this;
4231
4501
  };
4232
4502
 
@@ -4239,13 +4509,17 @@ Runner.prototype.globals = function(arr){
4239
4509
  Runner.prototype.checkGlobals = function(test){
4240
4510
  if (this.ignoreLeaks) return;
4241
4511
  var ok = this._globals;
4512
+
4242
4513
  var globals = this.globalProps();
4243
4514
  var isNode = process.kill;
4244
4515
  var leaks;
4245
4516
 
4246
- // check length - 2 ('errno' and 'location' globals)
4247
- if (isNode && 1 == ok.length - globals.length) return
4248
- else if (2 == ok.length - globals.length) return;
4517
+ if (test) {
4518
+ ok = ok.concat(test._allowedGlobals || []);
4519
+ }
4520
+
4521
+ if(this.prevGlobalsLength == globals.length) return;
4522
+ this.prevGlobalsLength = globals.length;
4249
4523
 
4250
4524
  leaks = filterLeaks(ok, globals);
4251
4525
  this._globals = this._globals.concat(leaks);
@@ -4279,10 +4553,18 @@ Runner.prototype.fail = function(test, err){
4279
4553
  /**
4280
4554
  * Fail the given `hook` with `err`.
4281
4555
  *
4282
- * Hook failures (currently) hard-end due
4283
- * to that fact that a failing hook will
4284
- * surely cause subsequent tests to fail,
4285
- * causing jumbled reporting.
4556
+ * Hook failures work in the following pattern:
4557
+ * - If bail, then exit
4558
+ * - Failed `before` hook skips all tests in a suite and subsuites,
4559
+ * but jumps to corresponding `after` hook
4560
+ * - Failed `before each` hook skips remaining tests in a
4561
+ * suite and jumps to corresponding `after each` hook,
4562
+ * which is run only once
4563
+ * - Failed `after` hook does not alter
4564
+ * execution order
4565
+ * - Failed `after each` hook skips remaining tests in a
4566
+ * suite and subsuites, but executes other `after each`
4567
+ * hooks
4286
4568
  *
4287
4569
  * @param {Hook} hook
4288
4570
  * @param {Error} err
@@ -4291,7 +4573,9 @@ Runner.prototype.fail = function(test, err){
4291
4573
 
4292
4574
  Runner.prototype.failHook = function(hook, err){
4293
4575
  this.fail(hook, err);
4294
- this.emit('end');
4576
+ if (this.suite.bail()) {
4577
+ this.emit('end');
4578
+ }
4295
4579
  };
4296
4580
 
4297
4581
  /**
@@ -4311,8 +4595,11 @@ Runner.prototype.hook = function(name, fn){
4311
4595
  function next(i) {
4312
4596
  var hook = hooks[i];
4313
4597
  if (!hook) return fn();
4598
+ if (self.failures && suite.bail()) return fn();
4314
4599
  self.currentRunnable = hook;
4315
4600
 
4601
+ hook.ctx.currentTest = self.test;
4602
+
4316
4603
  self.emit('hook', hook);
4317
4604
 
4318
4605
  hook.on('error', function(err){
@@ -4323,8 +4610,14 @@ Runner.prototype.hook = function(name, fn){
4323
4610
  hook.removeAllListeners('error');
4324
4611
  var testError = hook.error();
4325
4612
  if (testError) self.fail(self.test, testError);
4326
- if (err) return self.failHook(hook, err);
4613
+ if (err) {
4614
+ self.failHook(hook, err);
4615
+
4616
+ // stop executing hooks, notify callee of hook err
4617
+ return fn(err);
4618
+ }
4327
4619
  self.emit('hook end', hook);
4620
+ delete hook.ctx.currentTest;
4328
4621
  next(++i);
4329
4622
  });
4330
4623
  }
@@ -4336,7 +4629,7 @@ Runner.prototype.hook = function(name, fn){
4336
4629
 
4337
4630
  /**
4338
4631
  * Run hook `name` for the given array of `suites`
4339
- * in order, and callback `fn(err)`.
4632
+ * in order, and callback `fn(err, errSuite)`.
4340
4633
  *
4341
4634
  * @param {String} name
4342
4635
  * @param {Array} suites
@@ -4358,8 +4651,9 @@ Runner.prototype.hooks = function(name, suites, fn){
4358
4651
 
4359
4652
  self.hook(name, function(err){
4360
4653
  if (err) {
4654
+ var errSuite = self.suite;
4361
4655
  self.suite = orig;
4362
- return fn(err);
4656
+ return fn(err, errSuite);
4363
4657
  }
4364
4658
 
4365
4659
  next(suites.pop());
@@ -4447,10 +4741,39 @@ Runner.prototype.runTests = function(suite, fn){
4447
4741
  , tests = suite.tests.slice()
4448
4742
  , test;
4449
4743
 
4450
- function next(err) {
4744
+
4745
+ function hookErr(err, errSuite, after) {
4746
+ // before/after Each hook for errSuite failed:
4747
+ var orig = self.suite;
4748
+
4749
+ // for failed 'after each' hook start from errSuite parent,
4750
+ // otherwise start from errSuite itself
4751
+ self.suite = after ? errSuite.parent : errSuite;
4752
+
4753
+ if (self.suite) {
4754
+ // call hookUp afterEach
4755
+ self.hookUp('afterEach', function(err2, errSuite2) {
4756
+ self.suite = orig;
4757
+ // some hooks may fail even now
4758
+ if (err2) return hookErr(err2, errSuite2, true);
4759
+ // report error suite
4760
+ fn(errSuite);
4761
+ });
4762
+ } else {
4763
+ // there is no need calling other 'after each' hooks
4764
+ self.suite = orig;
4765
+ fn(errSuite);
4766
+ }
4767
+ }
4768
+
4769
+ function next(err, errSuite) {
4451
4770
  // if we bail after first err
4452
4771
  if (self.failures && suite._bail) return fn();
4453
4772
 
4773
+ if (self._abort) return fn();
4774
+
4775
+ if (err) return hookErr(err, errSuite, true);
4776
+
4454
4777
  // next test
4455
4778
  test = tests.shift();
4456
4779
 
@@ -4471,7 +4794,10 @@ Runner.prototype.runTests = function(suite, fn){
4471
4794
 
4472
4795
  // execute test and hook(s)
4473
4796
  self.emit('test', self.test = test);
4474
- self.hookDown('beforeEach', function(){
4797
+ self.hookDown('beforeEach', function(err, errSuite){
4798
+
4799
+ if (err) return hookErr(err, errSuite, false);
4800
+
4475
4801
  self.currentRunnable = self.test;
4476
4802
  self.runTest(function(err){
4477
4803
  test = self.test;
@@ -4514,21 +4840,37 @@ Runner.prototype.runSuite = function(suite, fn){
4514
4840
 
4515
4841
  this.emit('suite', this.suite = suite);
4516
4842
 
4517
- function next() {
4843
+ function next(errSuite) {
4844
+ if (errSuite) {
4845
+ // current suite failed on a hook from errSuite
4846
+ if (errSuite == suite) {
4847
+ // if errSuite is current suite
4848
+ // continue to the next sibling suite
4849
+ return done();
4850
+ } else {
4851
+ // errSuite is among the parents of current suite
4852
+ // stop execution of errSuite and all sub-suites
4853
+ return done(errSuite);
4854
+ }
4855
+ }
4856
+
4857
+ if (self._abort) return done();
4858
+
4518
4859
  var curr = suite.suites[i++];
4519
4860
  if (!curr) return done();
4520
4861
  self.runSuite(curr, next);
4521
4862
  }
4522
4863
 
4523
- function done() {
4864
+ function done(errSuite) {
4524
4865
  self.suite = suite;
4525
4866
  self.hook('afterAll', function(){
4526
4867
  self.emit('suite end', suite);
4527
- fn();
4868
+ fn(errSuite);
4528
4869
  });
4529
4870
  }
4530
4871
 
4531
- this.hook('beforeAll', function(){
4872
+ this.hook('beforeAll', function(err){
4873
+ if (err) return done();
4532
4874
  self.runTests(suite, next);
4533
4875
  });
4534
4876
  };
@@ -4598,6 +4940,17 @@ Runner.prototype.run = function(fn){
4598
4940
  return this;
4599
4941
  };
4600
4942
 
4943
+ /**
4944
+ * Cleanly abort execution
4945
+ *
4946
+ * @return {Runner} for chaining
4947
+ * @api public
4948
+ */
4949
+ Runner.prototype.abort = function(){
4950
+ debug('aborting');
4951
+ this._abort = true;
4952
+ }
4953
+
4601
4954
  /**
4602
4955
  * Filter leaks with the given globals flagged as `ok`.
4603
4956
  *
@@ -4611,16 +4964,52 @@ function filterLeaks(ok, globals) {
4611
4964
  return filter(globals, function(key){
4612
4965
  // Firefox and Chrome exposes iframes as index inside the window object
4613
4966
  if (/^d+/.test(key)) return false;
4967
+
4968
+ // in firefox
4969
+ // if runner runs in an iframe, this iframe's window.getInterface method not init at first
4970
+ // it is assigned in some seconds
4971
+ if (global.navigator && /^getInterface/.test(key)) return false;
4972
+
4973
+ // an iframe could be approached by window[iframeIndex]
4974
+ // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
4975
+ if (global.navigator && /^\d+/.test(key)) return false;
4976
+
4977
+ // Opera and IE expose global variables for HTML element IDs (issue #243)
4978
+ if (/^mocha-/.test(key)) return false;
4979
+
4614
4980
  var matched = filter(ok, function(ok){
4615
4981
  if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
4616
- // Opera and IE expose global variables for HTML element IDs (issue #243)
4617
- if (/^mocha-/.test(key)) return true;
4618
4982
  return key == ok;
4619
4983
  });
4620
4984
  return matched.length == 0 && (!global.navigator || 'onerror' !== key);
4621
4985
  });
4622
4986
  }
4623
4987
 
4988
+ /**
4989
+ * Array of globals dependent on the environment.
4990
+ *
4991
+ * @return {Array}
4992
+ * @api private
4993
+ */
4994
+
4995
+ function extraGlobals() {
4996
+ if (typeof(process) === 'object' &&
4997
+ typeof(process.version) === 'string') {
4998
+
4999
+ var nodeVersion = process.version.split('.').reduce(function(a, v) {
5000
+ return a << 8 | v;
5001
+ });
5002
+
5003
+ // 'errno' was renamed to process._errno in v0.9.11.
5004
+
5005
+ if (nodeVersion < 0x00090B) {
5006
+ return ['errno'];
5007
+ }
5008
+ }
5009
+
5010
+ return [];
5011
+ }
5012
+
4624
5013
  }); // module: runner.js
4625
5014
 
4626
5015
  require.register("suite.js", function(module, exports, require){
@@ -4968,7 +5357,6 @@ Test.prototype.constructor = Test;
4968
5357
  }); // module: test.js
4969
5358
 
4970
5359
  require.register("utils.js", function(module, exports, require){
4971
-
4972
5360
  /**
4973
5361
  * Module dependencies.
4974
5362
  */
@@ -5014,6 +5402,22 @@ exports.forEach = function(arr, fn, scope){
5014
5402
  fn.call(scope, arr[i], i);
5015
5403
  };
5016
5404
 
5405
+ /**
5406
+ * Array#map (<=IE8)
5407
+ *
5408
+ * @param {Array} array
5409
+ * @param {Function} fn
5410
+ * @param {Object} scope
5411
+ * @api private
5412
+ */
5413
+
5414
+ exports.map = function(arr, fn, scope){
5415
+ var result = [];
5416
+ for (var i = 0, l = arr.length; i < l; i++)
5417
+ result.push(fn.call(scope, arr[i], i));
5418
+ return result;
5419
+ };
5420
+
5017
5421
  /**
5018
5422
  * Array#indexOf (<=IE8)
5019
5423
  *
@@ -5133,7 +5537,7 @@ exports.files = function(dir, ret){
5133
5537
  path = join(dir, path);
5134
5538
  if (fs.statSync(path).isDirectory()) {
5135
5539
  exports.files(path, ret);
5136
- } else if (path.match(/\.(js|coffee)$/)) {
5540
+ } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) {
5137
5541
  ret.push(path);
5138
5542
  }
5139
5543
  });
@@ -5163,11 +5567,13 @@ exports.slug = function(str){
5163
5567
 
5164
5568
  exports.clean = function(str) {
5165
5569
  str = str
5570
+ .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
5166
5571
  .replace(/^function *\(.*\) *{/, '')
5167
5572
  .replace(/\s+\}$/, '');
5168
5573
 
5169
5574
  var spaces = str.match(/^\n?( *)/)[1].length
5170
- , re = new RegExp('^ {' + spaces + '}', 'gm');
5575
+ , tabs = str.match(/^\n?(\t*)/)[1].length
5576
+ , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
5171
5577
 
5172
5578
  str = str.replace(re, '');
5173
5579
 
@@ -5252,16 +5658,18 @@ exports.highlightTags = function(name) {
5252
5658
  };
5253
5659
 
5254
5660
  }); // module: utils.js
5661
+ // The global object is "self" in Web Workers.
5662
+ global = (function() { return this; })();
5255
5663
 
5256
5664
  /**
5257
5665
  * Save timer references to avoid Sinon interfering (see GH-237).
5258
5666
  */
5259
5667
 
5260
- var Date = window.Date;
5261
- var setTimeout = window.setTimeout;
5262
- var setInterval = window.setInterval;
5263
- var clearTimeout = window.clearTimeout;
5264
- var clearInterval = window.clearInterval;
5668
+ var Date = global.Date;
5669
+ var setTimeout = global.setTimeout;
5670
+ var setInterval = global.setInterval;
5671
+ var clearTimeout = global.clearTimeout;
5672
+ var clearInterval = global.clearInterval;
5265
5673
 
5266
5674
  /**
5267
5675
  * Node shims.
@@ -5275,15 +5683,18 @@ var clearInterval = window.clearInterval;
5275
5683
  var process = {};
5276
5684
  process.exit = function(status){};
5277
5685
  process.stdout = {};
5278
- global = window;
5686
+
5687
+ var uncaughtExceptionHandlers = [];
5279
5688
 
5280
5689
  /**
5281
5690
  * Remove uncaughtException listener.
5282
5691
  */
5283
5692
 
5284
- process.removeListener = function(e){
5693
+ process.removeListener = function(e, fn){
5285
5694
  if ('uncaughtException' == e) {
5286
- window.onerror = null;
5695
+ global.onerror = function() {};
5696
+ var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
5697
+ if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }
5287
5698
  }
5288
5699
  };
5289
5700
 
@@ -5293,9 +5704,11 @@ process.removeListener = function(e){
5293
5704
 
5294
5705
  process.on = function(e, fn){
5295
5706
  if ('uncaughtException' == e) {
5296
- window.onerror = function(err, url, line){
5707
+ global.onerror = function(err, url, line){
5297
5708
  fn(new Error(err + ' (' + url + ':' + line + ')'));
5709
+ return true;
5298
5710
  };
5711
+ uncaughtExceptionHandlers.push(fn);
5299
5712
  }
5300
5713
  };
5301
5714
 
@@ -5303,8 +5716,13 @@ process.on = function(e, fn){
5303
5716
  * Expose mocha.
5304
5717
  */
5305
5718
 
5306
- var Mocha = window.Mocha = require('mocha'),
5307
- mocha = window.mocha = new Mocha({ reporter: 'html' });
5719
+ var Mocha = global.Mocha = require('mocha'),
5720
+ mocha = global.mocha = new Mocha({ reporter: 'html' });
5721
+
5722
+ // The BDD UI is registered by default, but no UI will be functional in the
5723
+ // browser without an explicit call to the overridden `mocha.ui` (see below).
5724
+ // Ensure that this default UI does not expose its methods to the global scope.
5725
+ mocha.suite.removeAllListeners('pre-require');
5308
5726
 
5309
5727
  var immediateQueue = []
5310
5728
  , immediateTimeout;
@@ -5332,6 +5750,18 @@ Mocha.Runner.immediately = function(callback) {
5332
5750
  }
5333
5751
  };
5334
5752
 
5753
+ /**
5754
+ * Function to allow assertion libraries to throw errors directly into mocha.
5755
+ * This is useful when running tests in a browser because window.onerror will
5756
+ * only receive the 'message' attribute of the Error.
5757
+ */
5758
+ mocha.throwError = function(err) {
5759
+ Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
5760
+ fn(err);
5761
+ });
5762
+ throw err;
5763
+ };
5764
+
5335
5765
  /**
5336
5766
  * Override ui to ensure that the ui functions are initialized.
5337
5767
  * Normally this would happen in Mocha.prototype.loadFiles.
@@ -5339,7 +5769,7 @@ Mocha.Runner.immediately = function(callback) {
5339
5769
 
5340
5770
  mocha.ui = function(ui){
5341
5771
  Mocha.prototype.ui.call(this, ui);
5342
- this.suite.emit('pre-require', window, null, this);
5772
+ this.suite.emit('pre-require', global, null, this);
5343
5773
  return this;
5344
5774
  };
5345
5775
 
@@ -5361,13 +5791,22 @@ mocha.run = function(fn){
5361
5791
  var options = mocha.options;
5362
5792
  mocha.globals('location');
5363
5793
 
5364
- var query = Mocha.utils.parseQuery(window.location.search || '');
5794
+ var query = Mocha.utils.parseQuery(global.location.search || '');
5365
5795
  if (query.grep) mocha.grep(query.grep);
5366
5796
  if (query.invert) mocha.invert();
5367
5797
 
5368
5798
  return Mocha.prototype.run.call(mocha, function(){
5369
- Mocha.utils.highlightTags('code');
5799
+ // The DOM Document is not available in Web Workers.
5800
+ if (global.document) {
5801
+ Mocha.utils.highlightTags('code');
5802
+ }
5370
5803
  if (fn) fn();
5371
5804
  });
5372
5805
  };
5806
+
5807
+ /**
5808
+ * Expose the process shim.
5809
+ */
5810
+
5811
+ Mocha.process = process;
5373
5812
  })();