mocha 1.2.1 → 1.3.2

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.
Files changed (39) hide show
  1. package/.npmignore +2 -0
  2. package/.travis.yml +1 -1
  3. package/History.md +38 -0
  4. package/Makefile +9 -2
  5. package/_mocha.js +160 -63
  6. package/bin/_mocha +66 -61
  7. package/bin/mocha +5 -1
  8. package/lib/interfaces/bdd.js +23 -6
  9. package/lib/mocha.js +55 -10
  10. package/lib/reporters/base.js +5 -5
  11. package/lib/reporters/dot.js +5 -4
  12. package/lib/reporters/html.js +28 -13
  13. package/lib/reporters/index.js +3 -2
  14. package/lib/reporters/landing.js +2 -2
  15. package/lib/reporters/min.js +3 -2
  16. package/lib/reporters/nyan.js +6 -6
  17. package/lib/reporters/progress.js +1 -1
  18. package/lib/reporters/xunit.js +5 -1
  19. package/lib/runnable.js +4 -4
  20. package/lib/runner.js +12 -6
  21. package/lib/suite.js +7 -1
  22. package/lib/utils.js +1 -1
  23. package/mocha.css +18 -1
  24. package/mocha.js +160 -63
  25. package/my-reporter.js +23 -0
  26. package/package.json +2 -2
  27. package/test.js +5 -11
  28. package/editors/JavaScript mocha.tmbundle/Snippets/bdd - after each.tmSnippet +0 -16
  29. package/editors/JavaScript mocha.tmbundle/Snippets/bdd - after.tmSnippet +0 -16
  30. package/editors/JavaScript mocha.tmbundle/Snippets/bdd - before each.tmSnippet +0 -16
  31. package/editors/JavaScript mocha.tmbundle/Snippets/bdd - before.tmSnippet +0 -16
  32. package/editors/JavaScript mocha.tmbundle/Snippets/bdd - it.tmSnippet +0 -16
  33. package/editors/JavaScript mocha.tmbundle/Snippets/untitled.tmSnippet +0 -16
  34. package/editors/JavaScript mocha.tmbundle/info.plist +0 -19
  35. package/support/compile.js +0 -154
  36. package/support/foot.js +0 -1
  37. package/support/head.js +0 -2
  38. package/support/tail.js +0 -150
  39. package/support/template.html +0 -16
package/.npmignore CHANGED
@@ -2,3 +2,5 @@ test
2
2
  examples
3
3
  *.sock
4
4
  lib-cov
5
+ editors
6
+ support
package/.travis.yml CHANGED
@@ -2,4 +2,4 @@ language: node_js
2
2
  node_js:
3
3
  - 0.4
4
4
  - 0.6
5
- #- 0.7
5
+ - 0.8
package/History.md CHANGED
@@ -1,4 +1,42 @@
1
1
 
2
+ 1.3.2 / 2012-08-01
3
+ ==================
4
+
5
+ * fix exports double-execution regression. Closes #531
6
+
7
+ 1.3.1 / 2012-08-01
8
+ ==================
9
+
10
+ * add passes/failures toggling to HTML reporter
11
+ * add pending state to `xit()` and `xdescribe()` [Brian Moore]
12
+ * add the @charset "UTF-8"; to fix #522 with FireFox. [Jonathan Creamer]
13
+ * add border-bottom to #stats links
14
+ * add check for runnable in `Runner#uncaught()`. Closes #494
15
+ * add 0.4 and 0.6 back to travis.yml
16
+ * add `-E, --growl-errors` to growl on failures only
17
+ * add prefixes to debug() names. Closes #497
18
+ * add `Mocha#invert()` to js api
19
+ * change dot reporter to use sexy unicode dots
20
+ * fix error when clicking pending test in HTML reporter
21
+ * fix `make tm`
22
+
23
+ 1.3.0 / 2012-07-05
24
+ ==================
25
+
26
+ * add window scrolling to `HTML` reporter
27
+ * add v8 `--trace-*` option support
28
+ * add support for custom reports via `--reporter MODULE`
29
+ * add `--invert` switch to invert `--grep` matches
30
+ * fix export of `Nyan` reporter. Closes #495
31
+ * fix escaping of `HTML` suite titles. Closes #486
32
+ * fix `done()` called multiple times with an error test
33
+ * change `--grep` - regexp escape the input
34
+
35
+ 1.2.2 / 2012-06-28
36
+ ==================
37
+
38
+ * Added 0.8.0 support
39
+
2
40
  1.2.1 / 2012-06-25
3
41
  ==================
4
42
 
package/Makefile CHANGED
@@ -78,6 +78,13 @@ test-grep:
78
78
  --grep fast \
79
79
  test/acceptance/misc/grep
80
80
 
81
+ test-invert:
82
+ @./bin/mocha \
83
+ --reporter $(REPORTER) \
84
+ --grep slow \
85
+ --invert \
86
+ test/acceptance/misc/grep
87
+
81
88
  test-bail:
82
89
  @./bin/mocha \
83
90
  --reporter $(REPORTER) \
@@ -107,7 +114,7 @@ non-tty:
107
114
  @cat /tmp/spec.out
108
115
 
109
116
  tm:
110
- mkdir -p $(TM_DEST)/$(TM_BUNDLE)
111
- cp -fr editors/$(TM_BUNDLE) $(TM_DEST)/$(TM_BUNDLE)
117
+ mkdir -p $(TM_DEST)
118
+ cp -fr editors/$(TM_BUNDLE) $(TM_DEST)
112
119
 
113
120
  .PHONY: test-cov test-jsapi test-compilers watch test test-all test-bdd test-tdd test-qunit test-exports test-unit non-tty test-grep tm clean
package/_mocha.js CHANGED
@@ -535,11 +535,6 @@ module.exports = function(suite){
535
535
 
536
536
  suite.on('pre-require', function(context){
537
537
 
538
- // noop variants
539
-
540
- context.xdescribe = function(){};
541
- context.xit = function(){};
542
-
543
538
  /**
544
539
  * Execute before running tests.
545
540
  */
@@ -572,6 +567,18 @@ module.exports = function(suite){
572
567
  suites[0].afterEach(fn);
573
568
  };
574
569
 
570
+ /**
571
+ * Pending describe.
572
+ */
573
+
574
+ context.xdescribe = context.xcontext = function(title, fn){
575
+ var suite = Suite.create(suites[0], title);
576
+ suite.pending = true;
577
+ suites.unshift(suite);
578
+ fn();
579
+ suites.shift();
580
+ };
581
+
575
582
  /**
576
583
  * Describe a "suite" with the given `title`
577
584
  * and callback `fn` containing nested suites
@@ -592,7 +599,17 @@ module.exports = function(suite){
592
599
  */
593
600
 
594
601
  context.it = context.specify = function(title, fn){
595
- suites[0].addTest(new Test(title, fn));
602
+ var suite = suites[0];
603
+ if (suite.pending) var fn = null;
604
+ suite.addTest(new Test(title, fn));
605
+ };
606
+
607
+ /**
608
+ * Pending test case.
609
+ */
610
+
611
+ context.xit = context.xspecify = function(title){
612
+ context.it(title);
596
613
  };
597
614
  });
598
615
  };
@@ -883,12 +900,6 @@ var path = require('browser/path');
883
900
 
884
901
  exports = module.exports = Mocha;
885
902
 
886
- /**
887
- * Library version.
888
- */
889
-
890
- exports.version = '1.2.1';
891
-
892
903
  /**
893
904
  * Expose internals.
894
905
  */
@@ -989,13 +1000,15 @@ Mocha.prototype.ui = function(name){
989
1000
  * @api private
990
1001
  */
991
1002
 
992
- Mocha.prototype.loadFiles = function(){
1003
+ Mocha.prototype.loadFiles = function(fn){
993
1004
  var suite = this.suite;
1005
+ var pending = this.files.length;
994
1006
  this.files.forEach(function(file){
995
1007
  file = path.resolve(file);
996
1008
  suite.emit('pre-require', global, file);
997
1009
  suite.emit('require', require(file), file);
998
1010
  suite.emit('post-require', global, file);
1011
+ --pending || (fn && fn());
999
1012
  });
1000
1013
  };
1001
1014
 
@@ -1005,7 +1018,7 @@ Mocha.prototype.loadFiles = function(){
1005
1018
  * @api private
1006
1019
  */
1007
1020
 
1008
- Mocha.prototype.growl = function(runner, reporter) {
1021
+ Mocha.prototype._growl = function(runner, reporter) {
1009
1022
  var notify = require('growl');
1010
1023
 
1011
1024
  runner.on('end', function(){
@@ -1038,6 +1051,55 @@ Mocha.prototype.grep = function(re){
1038
1051
  return this;
1039
1052
  };
1040
1053
 
1054
+ /**
1055
+ * Invert `.grep()` matches.
1056
+ *
1057
+ * @return {Mocha}
1058
+ * @api public
1059
+ */
1060
+
1061
+ Mocha.prototype.invert = function(){
1062
+ this.options.invert = true;
1063
+ return this;
1064
+ };
1065
+
1066
+ /**
1067
+ * Ignore global leaks.
1068
+ *
1069
+ * @return {Mocha}
1070
+ * @api public
1071
+ */
1072
+
1073
+ Mocha.prototype.ignoreLeaks = function(){
1074
+ this.options.ignoreLeaks = true;
1075
+ return this;
1076
+ };
1077
+
1078
+ /**
1079
+ * Enable growl support.
1080
+ *
1081
+ * @return {Mocha}
1082
+ * @api public
1083
+ */
1084
+
1085
+ Mocha.prototype.growl = function(){
1086
+ this.options.growl = true;
1087
+ return this;
1088
+ };
1089
+
1090
+ /**
1091
+ * Ignore `globals`.
1092
+ *
1093
+ * @param {Array} globals
1094
+ * @return {Mocha}
1095
+ * @api public
1096
+ */
1097
+
1098
+ Mocha.prototype.globals = function(globals){
1099
+ this.options.globals = globals;
1100
+ return this;
1101
+ };
1102
+
1041
1103
  /**
1042
1104
  * Run tests and invoke `fn()` when complete.
1043
1105
  *
@@ -1053,9 +1115,9 @@ Mocha.prototype.run = function(fn){
1053
1115
  var runner = new exports.Runner(suite);
1054
1116
  var reporter = new this._reporter(runner);
1055
1117
  runner.ignoreLeaks = options.ignoreLeaks;
1056
- if (options.grep) runner.grep(options.grep);
1118
+ if (options.grep) runner.grep(options.grep, options.invert);
1057
1119
  if (options.globals) runner.globals(options.globals);
1058
- if (options.growl) this.growl(runner, reporter);
1120
+ if (options.growl) this._growl(runner, reporter);
1059
1121
  return runner.run(fn);
1060
1122
  };
1061
1123
 
@@ -1138,7 +1200,7 @@ exports.colors = {
1138
1200
 
1139
1201
  var color = exports.color = function(type, str) {
1140
1202
  if (!exports.useColors) return str;
1141
- return '\033[' + exports.colors[type] + 'm' + str + '\033[0m';
1203
+ return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
1142
1204
  };
1143
1205
 
1144
1206
  /**
@@ -1161,19 +1223,19 @@ exports.window = {
1161
1223
 
1162
1224
  exports.cursor = {
1163
1225
  hide: function(){
1164
- process.stdout.write('\033[?25l');
1226
+ process.stdout.write('\u001b[?25l');
1165
1227
  },
1166
1228
 
1167
1229
  show: function(){
1168
- process.stdout.write('\033[?25h');
1230
+ process.stdout.write('\u001b[?25h');
1169
1231
  },
1170
1232
 
1171
1233
  deleteLine: function(){
1172
- process.stdout.write('\033[2K');
1234
+ process.stdout.write('\u001b[2K');
1173
1235
  },
1174
1236
 
1175
1237
  beginningOfLine: function(){
1176
- process.stdout.write('\033[0G');
1238
+ process.stdout.write('\u001b[0G');
1177
1239
  },
1178
1240
 
1179
1241
  CR: function(){
@@ -1508,6 +1570,7 @@ function Dot(runner) {
1508
1570
  var self = this
1509
1571
  , stats = this.stats
1510
1572
  , width = Base.window.width * .75 | 0
1573
+ , c = '․'
1511
1574
  , n = 0;
1512
1575
 
1513
1576
  runner.on('start', function(){
@@ -1515,21 +1578,21 @@ function Dot(runner) {
1515
1578
  });
1516
1579
 
1517
1580
  runner.on('pending', function(test){
1518
- process.stdout.write(color('pending', '.'));
1581
+ process.stdout.write(color('pending', c));
1519
1582
  });
1520
1583
 
1521
1584
  runner.on('pass', function(test){
1522
1585
  if (++n % width == 0) process.stdout.write('\n ');
1523
1586
  if ('slow' == test.speed) {
1524
- process.stdout.write(color('bright yellow', '.'));
1587
+ process.stdout.write(color('bright yellow', c));
1525
1588
  } else {
1526
- process.stdout.write(color(test.speed, '.'));
1589
+ process.stdout.write(color(test.speed, c));
1527
1590
  }
1528
1591
  });
1529
1592
 
1530
1593
  runner.on('fail', function(test, err){
1531
1594
  if (++n % width == 0) process.stdout.write('\n ');
1532
- process.stdout.write(color('fail', '.'));
1595
+ process.stdout.write(color('fail', c));
1533
1596
  });
1534
1597
 
1535
1598
  runner.on('end', function(){
@@ -1634,8 +1697,8 @@ exports = module.exports = HTML;
1634
1697
 
1635
1698
  var statsTemplate = '<ul id="stats">'
1636
1699
  + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
1637
- + '<li class="passes">passes: <em>0</em></li>'
1638
- + '<li class="failures">failures: <em>0</em></li>'
1700
+ + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
1701
+ + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
1639
1702
  + '<li class="duration">duration: <em>0</em>s</li>'
1640
1703
  + '</ul>';
1641
1704
 
@@ -1656,7 +1719,9 @@ function HTML(runner) {
1656
1719
  , stat = fragment(statsTemplate)
1657
1720
  , items = stat.getElementsByTagName('li')
1658
1721
  , passes = items[1].getElementsByTagName('em')[0]
1722
+ , passesLink = items[1].getElementsByTagName('a')[0]
1659
1723
  , failures = items[2].getElementsByTagName('em')[0]
1724
+ , failuresLink = items[2].getElementsByTagName('a')[0]
1660
1725
  , duration = items[3].getElementsByTagName('em')[0]
1661
1726
  , canvas = stat.getElementsByTagName('canvas')[0]
1662
1727
  , report = fragment('<ul id="report"></ul>')
@@ -1671,6 +1736,18 @@ function HTML(runner) {
1671
1736
 
1672
1737
  if (!root) return error('#mocha div missing, add it to your document');
1673
1738
 
1739
+ // pass toggle
1740
+ on(passesLink, 'click', function () {
1741
+ var className = /pass/.test(report.className) ? '' : ' pass';
1742
+ report.className = report.className.replace(/fail|pass/g, '') + className;
1743
+ });
1744
+
1745
+ // failure toggle
1746
+ on(failuresLink, 'click', function () {
1747
+ var className = /fail/.test(report.className) ? '' : ' fail';
1748
+ report.className = report.className.replace(/fail|pass/g, '') + className;
1749
+ });
1750
+
1674
1751
  root.appendChild(stat);
1675
1752
  root.appendChild(report);
1676
1753
 
@@ -1681,7 +1758,7 @@ function HTML(runner) {
1681
1758
 
1682
1759
  // suite
1683
1760
  var url = location.protocol + '//' + location.host + location.pathname + '?grep=^' + utils.escapeRegexp(suite.fullTitle());
1684
- var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, suite.title);
1761
+ var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
1685
1762
 
1686
1763
  // container
1687
1764
  stack[0].appendChild(el);
@@ -1699,6 +1776,8 @@ function HTML(runner) {
1699
1776
  });
1700
1777
 
1701
1778
  runner.on('test end', function(test){
1779
+ window.scrollTo(0, document.body.scrollHeight);
1780
+
1702
1781
  // TODO: add to stats
1703
1782
  var percent = stats.tests / total * 100 | 0;
1704
1783
  if (progress) progress.update(percent).draw(ctx);
@@ -1736,17 +1815,16 @@ function HTML(runner) {
1736
1815
  }
1737
1816
 
1738
1817
  // toggle code
1739
- var h2 = el.getElementsByTagName('h2')[0];
1740
-
1741
- on(h2, 'click', function(){
1742
- pre.style.display = 'none' == pre.style.display
1743
- ? 'block'
1744
- : 'none';
1745
- });
1746
-
1747
- // code
1748
1818
  // TODO: defer
1749
1819
  if (!test.pending) {
1820
+ var h2 = el.getElementsByTagName('h2')[0];
1821
+
1822
+ on(h2, 'click', function(){
1823
+ pre.style.display = 'none' == pre.style.display
1824
+ ? 'inline-block'
1825
+ : 'none';
1826
+ });
1827
+
1750
1828
  var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
1751
1829
  el.appendChild(pre);
1752
1830
  pre.style.display = 'none';
@@ -1806,6 +1884,7 @@ function on(el, event, fn) {
1806
1884
  el.attachEvent('on' + event, fn);
1807
1885
  }
1808
1886
  }
1887
+
1809
1888
  }); // module: reporters/html.js
1810
1889
 
1811
1890
  require.register("reporters/index.js", function(module, exports, require){
@@ -1819,13 +1898,14 @@ exports.HTML = require('./html');
1819
1898
  exports.List = require('./list');
1820
1899
  exports.Min = require('./min');
1821
1900
  exports.Spec = require('./spec');
1901
+ exports.Nyan = require('./nyan');
1902
+ exports.XUnit = require('./xunit');
1822
1903
  exports.Progress = require('./progress');
1823
1904
  exports.Landing = require('./landing');
1824
1905
  exports.JSONCov = require('./json-cov');
1825
1906
  exports.HTMLCov = require('./html-cov');
1826
1907
  exports.JSONStream = require('./json-stream');
1827
- exports.XUnit = require('./xunit')
1828
- exports.Teamcity = require('./teamcity')
1908
+ exports.Teamcity = require('./teamcity');
1829
1909
 
1830
1910
  }); // module: reporters/index.js
1831
1911
 
@@ -2195,14 +2275,14 @@ function Landing(runner) {
2195
2275
  }
2196
2276
 
2197
2277
  // render landing strip
2198
- stream.write('\033[4F\n\n');
2278
+ stream.write('\u001b[4F\n\n');
2199
2279
  stream.write(runway());
2200
2280
  stream.write('\n ');
2201
2281
  stream.write(color('runway', Array(col).join('⋅')));
2202
2282
  stream.write(plane)
2203
2283
  stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
2204
2284
  stream.write(runway());
2205
- stream.write('\033[0m');
2285
+ stream.write('\u001b[0m');
2206
2286
  });
2207
2287
 
2208
2288
  runner.on('end', function(){
@@ -2387,6 +2467,7 @@ function Markdown(runner) {
2387
2467
  }); // module: reporters/markdown.js
2388
2468
 
2389
2469
  require.register("reporters/min.js", function(module, exports, require){
2470
+
2390
2471
  /**
2391
2472
  * Module dependencies.
2392
2473
  */
@@ -2411,9 +2492,9 @@ function Min(runner) {
2411
2492
 
2412
2493
  runner.on('start', function(){
2413
2494
  // clear screen
2414
- process.stdout.write('\033[2J');
2495
+ process.stdout.write('\u001b[2J');
2415
2496
  // set cursor position
2416
- process.stdout.write('\033[1;3H');
2497
+ process.stdout.write('\u001b[1;3H');
2417
2498
  });
2418
2499
 
2419
2500
  runner.on('end', this.epilogue.bind(this));
@@ -2518,7 +2599,7 @@ NyanCat.prototype.drawScoreboard = function(){
2518
2599
 
2519
2600
  function draw(color, n) {
2520
2601
  write(' ');
2521
- write('\033[' + color + 'm' + n + '\033[0m');
2602
+ write('\u001b[' + color + 'm' + n + '\u001b[0m');
2522
2603
  write('\n');
2523
2604
  }
2524
2605
 
@@ -2557,7 +2638,7 @@ NyanCat.prototype.drawRainbow = function(){
2557
2638
  var self = this;
2558
2639
 
2559
2640
  this.trajectories.forEach(function(line, index) {
2560
- write('\033[' + self.scoreboardWidth + 'C');
2641
+ write('\u001b[' + self.scoreboardWidth + 'C');
2561
2642
  write(line.join(''));
2562
2643
  write('\n');
2563
2644
  });
@@ -2577,7 +2658,7 @@ NyanCat.prototype.drawNyanCat = function(status) {
2577
2658
  var startWidth = this.scoreboardWidth + this.trajectories[0].length;
2578
2659
 
2579
2660
  [0, 1, 2, 3].forEach(function(index) {
2580
- write('\033[' + startWidth + 'C');
2661
+ write('\u001b[' + startWidth + 'C');
2581
2662
 
2582
2663
  switch (index) {
2583
2664
  case 0:
@@ -2625,7 +2706,7 @@ NyanCat.prototype.drawNyanCat = function(status) {
2625
2706
  */
2626
2707
 
2627
2708
  NyanCat.prototype.cursorUp = function(n) {
2628
- write('\033[' + n + 'A');
2709
+ write('\u001b[' + n + 'A');
2629
2710
  };
2630
2711
 
2631
2712
  /**
@@ -2636,7 +2717,7 @@ NyanCat.prototype.cursorUp = function(n) {
2636
2717
  */
2637
2718
 
2638
2719
  NyanCat.prototype.cursorDown = function(n) {
2639
- write('\033[' + n + 'B');
2720
+ write('\u001b[' + n + 'B');
2640
2721
  };
2641
2722
 
2642
2723
  /**
@@ -2672,7 +2753,7 @@ NyanCat.prototype.generateColors = function(){
2672
2753
  NyanCat.prototype.rainbowify = function(str){
2673
2754
  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
2674
2755
  this.colorIndex += 1;
2675
- return '\033[38;5;' + color + 'm' + str + '\033[0m';
2756
+ return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
2676
2757
  };
2677
2758
 
2678
2759
  /**
@@ -2756,7 +2837,7 @@ function Progress(runner, options) {
2756
2837
  , i = width - n;
2757
2838
 
2758
2839
  cursor.CR();
2759
- process.stdout.write('\033[J');
2840
+ process.stdout.write('\u001b[J');
2760
2841
  process.stdout.write(color('progress', ' ' + options.open));
2761
2842
  process.stdout.write(Array(n).join(options.complete));
2762
2843
  process.stdout.write(Array(i).join(options.incomplete));
@@ -3053,7 +3134,11 @@ function XUnit(runner) {
3053
3134
  , tests = []
3054
3135
  , self = this;
3055
3136
 
3056
- runner.on('test end', function(test){
3137
+ runner.on('pass', function(test){
3138
+ tests.push(test);
3139
+ });
3140
+
3141
+ runner.on('fail', function(test){
3057
3142
  tests.push(test);
3058
3143
  });
3059
3144
 
@@ -3138,7 +3223,7 @@ require.register("runnable.js", function(module, exports, require){
3138
3223
  */
3139
3224
 
3140
3225
  var EventEmitter = require('browser/events').EventEmitter
3141
- , debug = require('browser/debug')('runnable');
3226
+ , debug = require('browser/debug')('mocha:runnable');
3142
3227
 
3143
3228
  /**
3144
3229
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -3282,16 +3367,16 @@ Runnable.prototype.run = function(fn){
3282
3367
  }
3283
3368
 
3284
3369
  // called multiple times
3285
- function multiple() {
3370
+ function multiple(err) {
3286
3371
  if (emitted) return;
3287
3372
  emitted = true;
3288
- self.emit('error', new Error('done() called multiple times'));
3373
+ self.emit('error', err || new Error('done() called multiple times'));
3289
3374
  }
3290
3375
 
3291
3376
  // finished
3292
3377
  function done(err) {
3293
3378
  if (self.timedOut) return;
3294
- if (finished) return multiple();
3379
+ if (finished) return multiple(err);
3295
3380
  self.clearTimeout();
3296
3381
  self.duration = new Date - start;
3297
3382
  finished = true;
@@ -3334,7 +3419,7 @@ require.register("runner.js", function(module, exports, require){
3334
3419
  */
3335
3420
 
3336
3421
  var EventEmitter = require('browser/events').EventEmitter
3337
- , debug = require('browser/debug')('runner')
3422
+ , debug = require('browser/debug')('mocha:runner')
3338
3423
  , Test = require('./test')
3339
3424
  , utils = require('./utils')
3340
3425
  , filter = utils.filter
@@ -3391,13 +3476,15 @@ Runner.prototype.constructor = Runner;
3391
3476
  * with number of tests matched.
3392
3477
  *
3393
3478
  * @param {RegExp} re
3479
+ * @param {Boolean} invert
3394
3480
  * @return {Runner} for chaining
3395
3481
  * @api public
3396
3482
  */
3397
3483
 
3398
- Runner.prototype.grep = function(re){
3484
+ Runner.prototype.grep = function(re, invert){
3399
3485
  debug('grep %s', re);
3400
3486
  this._grep = re;
3487
+ this._invert = invert;
3401
3488
  this.total = this.grepTotal(this.suite);
3402
3489
  return this;
3403
3490
  };
@@ -3416,7 +3503,9 @@ Runner.prototype.grepTotal = function(suite) {
3416
3503
  var total = 0;
3417
3504
 
3418
3505
  suite.eachTest(function(test){
3419
- if (self._grep.test(test.fullTitle())) total++;
3506
+ var match = self._grep.test(test.fullTitle());
3507
+ if (self._invert) match = !match;
3508
+ if (match) total++;
3420
3509
  });
3421
3510
 
3422
3511
  return total;
@@ -3656,7 +3745,9 @@ Runner.prototype.runTests = function(suite, fn){
3656
3745
  if (!test) return fn();
3657
3746
 
3658
3747
  // grep
3659
- if (!self._grep.test(test.fullTitle())) return next();
3748
+ var match = self._grep.test(test.fullTitle());
3749
+ if (self._invert) match = !match;
3750
+ if (!match) return next();
3660
3751
 
3661
3752
  // pending
3662
3753
  if (test.pending) {
@@ -3737,9 +3828,9 @@ Runner.prototype.runSuite = function(suite, fn){
3737
3828
  */
3738
3829
 
3739
3830
  Runner.prototype.uncaught = function(err){
3740
- debug('uncaught exception');
3831
+ debug('uncaught exception %s', err.message);
3741
3832
  var runnable = this.currentRunnable;
3742
- if ('failed' == runnable.state) return;
3833
+ if (!runnable || 'failed' == runnable.state) return;
3743
3834
  runnable.clearTimeout();
3744
3835
  err.uncaught = true;
3745
3836
  this.fail(runnable, err);
@@ -3821,7 +3912,7 @@ require.register("suite.js", function(module, exports, require){
3821
3912
  */
3822
3913
 
3823
3914
  var EventEmitter = require('browser/events').EventEmitter
3824
- , debug = require('browser/debug')('suite')
3915
+ , debug = require('browser/debug')('mocha:suite')
3825
3916
  , utils = require('./utils')
3826
3917
  , Hook = require('./hook');
3827
3918
 
@@ -3847,6 +3938,7 @@ exports = module.exports = Suite;
3847
3938
  exports.create = function(parent, title){
3848
3939
  var suite = new Suite(title, parent.ctx);
3849
3940
  suite.parent = parent;
3941
+ if (parent.pending) suite.pending = true;
3850
3942
  title = suite.fullTitle();
3851
3943
  parent.addSuite(suite);
3852
3944
  return suite;
@@ -3866,6 +3958,7 @@ function Suite(title, ctx) {
3866
3958
  this.ctx = ctx;
3867
3959
  this.suites = [];
3868
3960
  this.tests = [];
3961
+ this.pending = false;
3869
3962
  this._beforeEach = [];
3870
3963
  this._beforeAll = [];
3871
3964
  this._afterEach = [];
@@ -3939,6 +4032,7 @@ Suite.prototype.bail = function(bail){
3939
4032
  */
3940
4033
 
3941
4034
  Suite.prototype.beforeAll = function(fn){
4035
+ if (this.pending) return this;
3942
4036
  var hook = new Hook('"before all" hook', fn);
3943
4037
  hook.parent = this;
3944
4038
  hook.timeout(this.timeout());
@@ -3957,6 +4051,7 @@ Suite.prototype.beforeAll = function(fn){
3957
4051
  */
3958
4052
 
3959
4053
  Suite.prototype.afterAll = function(fn){
4054
+ if (this.pending) return this;
3960
4055
  var hook = new Hook('"after all" hook', fn);
3961
4056
  hook.parent = this;
3962
4057
  hook.timeout(this.timeout());
@@ -3975,6 +4070,7 @@ Suite.prototype.afterAll = function(fn){
3975
4070
  */
3976
4071
 
3977
4072
  Suite.prototype.beforeEach = function(fn){
4073
+ if (this.pending) return this;
3978
4074
  var hook = new Hook('"before each" hook', fn);
3979
4075
  hook.parent = this;
3980
4076
  hook.timeout(this.timeout());
@@ -3993,6 +4089,7 @@ Suite.prototype.beforeEach = function(fn){
3993
4089
  */
3994
4090
 
3995
4091
  Suite.prototype.afterEach = function(fn){
4092
+ if (this.pending) return this;
3996
4093
  var hook = new Hook('"after each" hook', fn);
3997
4094
  hook.parent = this;
3998
4095
  hook.timeout(this.timeout());
@@ -4132,7 +4229,7 @@ require.register("utils.js", function(module, exports, require){
4132
4229
  var fs = require('browser/fs')
4133
4230
  , path = require('browser/path')
4134
4231
  , join = path.join
4135
- , debug = require('browser/debug')('watch');
4232
+ , debug = require('browser/debug')('mocha:watch');
4136
4233
 
4137
4234
  /**
4138
4235
  * Ignored directories.