konacha 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  })();