mocha 1.21.4 → 1.21.5

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.
package/bin/_mocha CHANGED
@@ -284,25 +284,22 @@ program.compilers.forEach(function(c) {
284
284
  extensions.push(ext);
285
285
  });
286
286
 
287
- var re = new RegExp('\\.(' + extensions.join('|') + ')$');
288
-
289
287
  // requires
290
288
 
291
289
  requires.forEach(function(mod) {
292
290
  require(mod);
293
291
  });
294
292
 
295
- // files
293
+ //args
296
294
 
297
- var files = []
298
- , args = program.args;
295
+ var args = program.args;
299
296
 
300
297
  // default files to test/*.{js,coffee}
301
298
 
302
299
  if (!args.length) args.push('test');
303
300
 
304
301
  args.forEach(function(arg){
305
- files = files.concat(lookupFiles(arg, program.recursive));
302
+ files = files.concat(utils.lookupFiles(arg, extensions, program.recursive));
306
303
  });
307
304
 
308
305
  // resolve
@@ -357,6 +354,8 @@ if (program.watch) {
357
354
  function rerun() {
358
355
  purge();
359
356
  stop()
357
+ if (!program.grep)
358
+ mocha.grep(null);
360
359
  mocha.suite = mocha.suite.clone();
361
360
  mocha.suite.ctx = new Mocha.Context;
362
361
  mocha.ui(program.ui);
@@ -439,40 +438,6 @@ function stop() {
439
438
  clearInterval(play.timer);
440
439
  }
441
440
 
442
- /**
443
- * Lookup file names at the given `path`.
444
- */
445
-
446
- function lookupFiles(path, recursive) {
447
- var files = [];
448
-
449
- if (!exists(path)) {
450
- if (exists(path + '.js')) {
451
- path += '.js'
452
- } else {
453
- files = glob.sync(path);
454
- if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
455
- return files;
456
- }
457
- }
458
-
459
- var stat = fs.statSync(path);
460
- if (stat.isFile()) return path;
461
-
462
- fs.readdirSync(path).forEach(function(file){
463
- file = join(path, file);
464
- var stat = fs.statSync(file);
465
- if (stat.isDirectory()) {
466
- if (recursive) files = files.concat(lookupFiles(file, recursive));
467
- return
468
- }
469
- if (!stat.isFile() || !re.test(file) || basename(file)[0] == '.') return;
470
- files.push(file);
471
- });
472
-
473
- return files;
474
- }
475
-
476
441
  /**
477
442
  * Play the given array of strings.
478
443
  */
@@ -165,7 +165,22 @@ var JsDiff = (function() {
165
165
 
166
166
  var LineDiff = new Diff();
167
167
  LineDiff.tokenize = function(value) {
168
- return value.split(/^/m);
168
+ var retLines = [],
169
+ lines = value.split(/^/m);
170
+
171
+ for(var i = 0; i < lines.length; i++) {
172
+ var line = lines[i],
173
+ lastLine = lines[i - 1];
174
+
175
+ // Merge lines that may contain windows new lines
176
+ if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
177
+ retLines[retLines.length - 1] += '\n';
178
+ } else if (line) {
179
+ retLines.push(line);
180
+ }
181
+ }
182
+
183
+ return retLines;
169
184
  };
170
185
 
171
186
  return {
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
4
+
5
+ module.exports = function (str) {
6
+ if (typeof str !== 'string') {
7
+ throw new TypeError('Expected a string');
8
+ }
9
+
10
+ return str.replace(matchOperatorsRe, '\\$&');
11
+ };
File without changes
@@ -5,7 +5,8 @@
5
5
 
6
6
  var Suite = require('../suite')
7
7
  , Test = require('../test')
8
- , utils = require('../utils');
8
+ , utils = require('../utils')
9
+ , escapeRe = require('escape-string-regexp');
9
10
 
10
11
  /**
11
12
  * BDD-style interface:
@@ -108,7 +109,7 @@ module.exports = function(suite){
108
109
 
109
110
  context.it = context.specify = function(title, fn){
110
111
  var suite = suites[0];
111
- if (suite.pending) var fn = null;
112
+ if (suite.pending) fn = null;
112
113
  var test = new Test(title, fn);
113
114
  test.file = file;
114
115
  suite.addTest(test);
@@ -121,7 +122,7 @@ module.exports = function(suite){
121
122
 
122
123
  context.it.only = function(title, fn){
123
124
  var test = context.it(title, fn);
124
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
125
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
125
126
  mocha.grep(new RegExp(reString));
126
127
  return test;
127
128
  };
@@ -52,7 +52,7 @@ module.exports = function(suite){
52
52
  suites[0].addTest(test);
53
53
  }
54
54
  } else {
55
- var suite = Suite.create(suites[0], key);
55
+ suite = Suite.create(suites[0], key);
56
56
  suites.unshift(suite);
57
57
  visit(obj[key]);
58
58
  suites.shift();
@@ -5,6 +5,7 @@
5
5
 
6
6
  var Suite = require('../suite')
7
7
  , Test = require('../test')
8
+ , escapeRe = require('escape-string-regexp')
8
9
  , utils = require('../utils');
9
10
 
10
11
  /**
@@ -109,7 +110,7 @@ module.exports = function(suite){
109
110
 
110
111
  context.test.only = function(title, fn){
111
112
  var test = context.test(title, fn);
112
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
113
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
113
114
  mocha.grep(new RegExp(reString));
114
115
  };
115
116
 
@@ -5,7 +5,8 @@
5
5
 
6
6
  var Suite = require('../suite')
7
7
  , Test = require('../test')
8
- , utils = require('../utils');;
8
+ , escapeRe = require('escape-string-regexp')
9
+ , utils = require('../utils');
9
10
 
10
11
  /**
11
12
  * TDD-style interface:
@@ -112,7 +113,7 @@ module.exports = function(suite){
112
113
 
113
114
  context.test = function(title, fn){
114
115
  var suite = suites[0];
115
- if (suite.pending) var fn = null;
116
+ if (suite.pending) fn = null;
116
117
  var test = new Test(title, fn);
117
118
  test.file = file;
118
119
  suite.addTest(test);
@@ -125,7 +126,7 @@ module.exports = function(suite){
125
126
 
126
127
  context.test.only = function(title, fn){
127
128
  var test = context.test(title, fn);
128
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
129
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
129
130
  mocha.grep(new RegExp(reString));
130
131
  };
131
132
 
package/lib/mocha.js CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  var path = require('path')
12
+ , escapeRe = require('escape-string-regexp')
12
13
  , utils = require('./utils');
13
14
 
14
15
  /**
@@ -220,7 +221,7 @@ Mocha.prototype._growl = function(runner, reporter) {
220
221
 
221
222
  Mocha.prototype.grep = function(re){
222
223
  this.options.grep = 'string' == typeof re
223
- ? new RegExp(utils.escapeRegexp(re))
224
+ ? new RegExp(escapeRe(re))
224
225
  : re;
225
226
  return this;
226
227
  };
@@ -370,6 +371,16 @@ Mocha.prototype.asyncOnly = function(){
370
371
  return this;
371
372
  };
372
373
 
374
+ /**
375
+ * Disable syntax highlighting (in browser).
376
+ * @returns {Mocha}
377
+ * @api public
378
+ */
379
+ Mocha.prototype.noHighlighting = function() {
380
+ this.options.noHighlighting = true;
381
+ return this;
382
+ };
383
+
373
384
  /**
374
385
  * Run tests and invoke `fn()` when complete.
375
386
  *
package/lib/ms.js CHANGED
@@ -24,7 +24,7 @@ var y = d * 365.25;
24
24
  module.exports = function(val, options){
25
25
  options = options || {};
26
26
  if ('string' == typeof val) return parse(val);
27
- return options.long ? longFormat(val) : shortFormat(val);
27
+ return options['long'] ? longFormat(val) : shortFormat(val);
28
28
  };
29
29
 
30
30
  /**
@@ -185,7 +185,7 @@ exports.list = function(failures){
185
185
  }
186
186
 
187
187
  // actual / expected diff
188
- if ('string' == typeof actual && 'string' == typeof expected) {
188
+ if (err.showDiff && 'string' == typeof actual && 'string' == typeof expected) {
189
189
  fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
190
190
  var match = message.match(/^([^:]+): expected/);
191
191
  msg = '\n ' + color('error message', match ? match[1] : msg);
@@ -89,7 +89,7 @@ function map(cov) {
89
89
  }
90
90
 
91
91
  return ret;
92
- };
92
+ }
93
93
 
94
94
  /**
95
95
  * Map jscoverage data for a single source file
@@ -25,6 +25,7 @@ function JSONReporter(runner) {
25
25
  Base.call(this, runner);
26
26
 
27
27
  var tests = []
28
+ , pending = []
28
29
  , failures = []
29
30
  , passes = [];
30
31
 
@@ -40,10 +41,15 @@ function JSONReporter(runner) {
40
41
  failures.push(test);
41
42
  });
42
43
 
44
+ runner.on('pending', function(test){
45
+ pending.push(test);
46
+ });
47
+
43
48
  runner.on('end', function(){
44
49
  var obj = {
45
50
  stats: self.stats,
46
51
  tests: tests.map(clean),
52
+ pending: pending.map(clean),
47
53
  failures: failures.map(clean),
48
54
  passes: passes.map(clean)
49
55
  };
@@ -68,7 +74,7 @@ function clean(test) {
68
74
  title: test.title,
69
75
  fullTitle: test.fullTitle(),
70
76
  duration: test.duration,
71
- err: errorJSON(test.err)
77
+ err: errorJSON(test.err || {})
72
78
  }
73
79
  }
74
80
 
@@ -185,7 +185,7 @@ NyanCat.prototype.face = function() {
185
185
  } else {
186
186
  return '( - .-)';
187
187
  }
188
- }
188
+ };
189
189
 
190
190
  /**
191
191
  * Move cursor up `n`.
@@ -1,7 +1,8 @@
1
- !!! 5
1
+ doctype html
2
2
  html
3
3
  head
4
4
  title Coverage
5
+ meta(charset='utf-8')
5
6
  include script.html
6
7
  include style.html
7
8
  body
package/lib/runnable.js CHANGED
@@ -154,6 +154,7 @@ Runnable.prototype.resetTimeout = function(){
154
154
  if (!this._enableTimeouts) return;
155
155
  this.clearTimeout();
156
156
  this.timer = setTimeout(function(){
157
+ if (!self._enableTimeouts) return;
157
158
  self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
158
159
  self.timedOut = true;
159
160
  }, ms);
package/lib/runner.js CHANGED
@@ -533,18 +533,25 @@ Runner.prototype.runSuite = function(suite, fn){
533
533
 
534
534
  Runner.prototype.uncaught = function(err){
535
535
  if (err) {
536
- debug('uncaught exception %s', err.message);
536
+ debug('uncaught exception %s', err !== function () {
537
+ return this;
538
+ }.call(err) ? err : ( err.message || err ));
537
539
  } else {
538
540
  debug('uncaught undefined exception');
539
- err = new Error('Catched undefined error, did you throw without specifying what?');
541
+ err = new Error('Caught undefined error, did you throw without specifying what?');
540
542
  }
541
-
542
- var runnable = this.currentRunnable;
543
- if (!runnable || 'failed' == runnable.state) return;
544
- runnable.clearTimeout();
545
543
  err.uncaught = true;
544
+
545
+ var runnable = this.currentRunnable;
546
+ if (!runnable) return;
547
+
548
+ var wasAlreadyDone = runnable.state;
546
549
  this.fail(runnable, err);
547
550
 
551
+ runnable.clearTimeout();
552
+
553
+ if (wasAlreadyDone) return;
554
+
548
555
  // recover from test
549
556
  if ('test' == runnable.type) {
550
557
  this.emit('test end', runnable);
@@ -604,7 +611,7 @@ Runner.prototype.run = function(fn){
604
611
  Runner.prototype.abort = function(){
605
612
  debug('aborting');
606
613
  this._abort = true;
607
- }
614
+ };
608
615
 
609
616
  /**
610
617
  * Filter leaks with the given globals flagged as `ok`.
package/lib/suite.js CHANGED
@@ -99,6 +99,7 @@ Suite.prototype.clone = function(){
99
99
 
100
100
  Suite.prototype.timeout = function(ms){
101
101
  if (0 == arguments.length) return this._timeout;
102
+ if (ms === 0) this._enableTimeouts = false;
102
103
  if ('string' == typeof ms) ms = milliseconds(ms);
103
104
  debug('timeout %d', ms);
104
105
  this._timeout = parseInt(ms, 10);
@@ -118,7 +119,7 @@ Suite.prototype.enableTimeouts = function(enabled){
118
119
  debug('enableTimeouts %s', enabled);
119
120
  this._enableTimeouts = enabled;
120
121
  return this;
121
- }
122
+ };
122
123
 
123
124
  /**
124
125
  * Set slow `ms` or short-hand such as "2s".
package/lib/utils.js CHANGED
@@ -4,6 +4,9 @@
4
4
 
5
5
  var fs = require('fs')
6
6
  , path = require('path')
7
+ , basename = path.basename
8
+ , exists = fs.existsSync || path.existsSync
9
+ , glob = require('glob')
7
10
  , join = path.join
8
11
  , debug = require('debug')('mocha:watch');
9
12
 
@@ -224,18 +227,6 @@ exports.clean = function(str) {
224
227
  return exports.trim(str);
225
228
  };
226
229
 
227
- /**
228
- * Escape regular expression characters in `str`.
229
- *
230
- * @param {String} str
231
- * @return {String}
232
- * @api private
233
- */
234
-
235
- exports.escapeRegexp = function(str){
236
- return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
237
- };
238
-
239
230
  /**
240
231
  * Trim the given `str`.
241
232
  *
@@ -295,7 +286,7 @@ function highlight(js) {
295
286
  */
296
287
 
297
288
  exports.highlightTags = function(name) {
298
- var code = document.getElementsByTagName(name);
289
+ var code = document.getElementById('mocha').getElementsByTagName(name);
299
290
  for (var i = 0, len = code.length; i < len; ++i) {
300
291
  code[i].innerHTML = highlight(code[i].innerHTML);
301
292
  }
@@ -313,38 +304,85 @@ exports.highlightTags = function(name) {
313
304
  exports.stringify = function(obj) {
314
305
  if (obj instanceof RegExp) return obj.toString();
315
306
  return JSON.stringify(exports.canonicalize(obj), null, 2).replace(/,(\n|$)/g, '$1');
316
- }
307
+ };
317
308
 
318
309
  /**
319
310
  * Return a new object that has the keys in sorted order.
320
311
  * @param {Object} obj
312
+ * @param {Array} [stack]
321
313
  * @return {Object}
322
314
  * @api private
323
315
  */
324
316
 
325
317
  exports.canonicalize = function(obj, stack) {
326
- stack = stack || [];
327
-
328
- if (exports.indexOf(stack, obj) !== -1) return '[Circular]';
329
-
330
- var canonicalizedObj;
331
-
332
- if ({}.toString.call(obj) === '[object Array]') {
333
- stack.push(obj);
334
- canonicalizedObj = exports.map(obj, function(item) {
335
- return exports.canonicalize(item, stack);
336
- });
337
- stack.pop();
338
- } else if (typeof obj === 'object' && obj !== null) {
339
- stack.push(obj);
340
- canonicalizedObj = {};
341
- exports.forEach(exports.keys(obj).sort(), function(key) {
342
- canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
343
- });
344
- stack.pop();
345
- } else {
346
- canonicalizedObj = obj;
347
- }
348
-
349
- return canonicalizedObj;
350
- }
318
+ stack = stack || [];
319
+
320
+ if (exports.indexOf(stack, obj) !== -1) return '[Circular]';
321
+
322
+ var canonicalizedObj;
323
+
324
+ if ({}.toString.call(obj) === '[object Array]') {
325
+ stack.push(obj);
326
+ canonicalizedObj = exports.map(obj, function (item) {
327
+ return exports.canonicalize(item, stack);
328
+ });
329
+ stack.pop();
330
+ } else if (typeof obj === 'object' && obj !== null) {
331
+ stack.push(obj);
332
+ canonicalizedObj = {};
333
+ exports.forEach(exports.keys(obj).sort(), function (key) {
334
+ canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
335
+ });
336
+ stack.pop();
337
+ } else {
338
+ canonicalizedObj = obj;
339
+ }
340
+
341
+ return canonicalizedObj;
342
+ };
343
+
344
+ /**
345
+ * Lookup file names at the given `path`.
346
+ */
347
+ exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
348
+ var files = [];
349
+ var re = new RegExp('\\.(' + extensions.join('|') + ')$');
350
+
351
+ if (!exists(path)) {
352
+ if (exists(path + '.js')) {
353
+ path += '.js';
354
+ } else {
355
+ files = glob.sync(path);
356
+ if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
357
+ return files;
358
+ }
359
+ }
360
+
361
+ try {
362
+ var stat = fs.statSync(path);
363
+ if (stat.isFile()) return path;
364
+ }
365
+ catch (ignored) {
366
+ return;
367
+ }
368
+
369
+ fs.readdirSync(path).forEach(function(file){
370
+ file = join(path, file);
371
+ try {
372
+ var stat = fs.statSync(file);
373
+ if (stat.isDirectory()) {
374
+ if (recursive) {
375
+ files = files.concat(lookupFiles(file, extensions, recursive));
376
+ }
377
+ return;
378
+ }
379
+ }
380
+ catch (ignored) {
381
+ return;
382
+ }
383
+ if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
384
+ files.push(file);
385
+ });
386
+
387
+ return files;
388
+ };
package/mocha.js CHANGED
@@ -224,7 +224,22 @@ var JsDiff = (function() {
224
224
 
225
225
  var LineDiff = new Diff();
226
226
  LineDiff.tokenize = function(value) {
227
- return value.split(/^/m);
227
+ var retLines = [],
228
+ lines = value.split(/^/m);
229
+
230
+ for(var i = 0; i < lines.length; i++) {
231
+ var line = lines[i],
232
+ lastLine = lines[i - 1];
233
+
234
+ // Merge lines that may contain windows new lines
235
+ if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
236
+ retLines[retLines.length - 1] += '\n';
237
+ } else if (line) {
238
+ retLines.push(line);
239
+ }
240
+ }
241
+
242
+ return retLines;
228
243
  };
229
244
 
230
245
  return {
@@ -414,6 +429,21 @@ if (typeof module !== 'undefined') {
414
429
 
415
430
  }); // module: browser/diff.js
416
431
 
432
+ require.register("browser/escape-string-regexp.js", function(module, exports, require){
433
+ 'use strict';
434
+
435
+ var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
436
+
437
+ module.exports = function (str) {
438
+ if (typeof str !== 'string') {
439
+ throw new TypeError('Expected a string');
440
+ }
441
+
442
+ return str.replace(matchOperatorsRe, '\\$&');
443
+ };
444
+
445
+ }); // module: browser/escape-string-regexp.js
446
+
417
447
  require.register("browser/events.js", function(module, exports, require){
418
448
 
419
449
  /**
@@ -599,6 +629,10 @@ require.register("browser/fs.js", function(module, exports, require){
599
629
 
600
630
  }); // module: browser/fs.js
601
631
 
632
+ require.register("browser/glob.js", function(module, exports, require){
633
+
634
+ }); // module: browser/glob.js
635
+
602
636
  require.register("browser/path.js", function(module, exports, require){
603
637
 
604
638
  }); // module: browser/path.js
@@ -902,7 +936,8 @@ require.register("interfaces/bdd.js", function(module, exports, require){
902
936
 
903
937
  var Suite = require('../suite')
904
938
  , Test = require('../test')
905
- , utils = require('../utils');
939
+ , utils = require('../utils')
940
+ , escapeRe = require('browser/escape-string-regexp');
906
941
 
907
942
  /**
908
943
  * BDD-style interface:
@@ -1005,7 +1040,7 @@ module.exports = function(suite){
1005
1040
 
1006
1041
  context.it = context.specify = function(title, fn){
1007
1042
  var suite = suites[0];
1008
- if (suite.pending) var fn = null;
1043
+ if (suite.pending) fn = null;
1009
1044
  var test = new Test(title, fn);
1010
1045
  test.file = file;
1011
1046
  suite.addTest(test);
@@ -1018,7 +1053,7 @@ module.exports = function(suite){
1018
1053
 
1019
1054
  context.it.only = function(title, fn){
1020
1055
  var test = context.it(title, fn);
1021
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1056
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
1022
1057
  mocha.grep(new RegExp(reString));
1023
1058
  return test;
1024
1059
  };
@@ -1092,7 +1127,7 @@ module.exports = function(suite){
1092
1127
  suites[0].addTest(test);
1093
1128
  }
1094
1129
  } else {
1095
- var suite = Suite.create(suites[0], key);
1130
+ suite = Suite.create(suites[0], key);
1096
1131
  suites.unshift(suite);
1097
1132
  visit(obj[key]);
1098
1133
  suites.shift();
@@ -1120,6 +1155,7 @@ require.register("interfaces/qunit.js", function(module, exports, require){
1120
1155
 
1121
1156
  var Suite = require('../suite')
1122
1157
  , Test = require('../test')
1158
+ , escapeRe = require('browser/escape-string-regexp')
1123
1159
  , utils = require('../utils');
1124
1160
 
1125
1161
  /**
@@ -1224,7 +1260,7 @@ module.exports = function(suite){
1224
1260
 
1225
1261
  context.test.only = function(title, fn){
1226
1262
  var test = context.test(title, fn);
1227
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1263
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
1228
1264
  mocha.grep(new RegExp(reString));
1229
1265
  };
1230
1266
 
@@ -1248,7 +1284,8 @@ require.register("interfaces/tdd.js", function(module, exports, require){
1248
1284
 
1249
1285
  var Suite = require('../suite')
1250
1286
  , Test = require('../test')
1251
- , utils = require('../utils');;
1287
+ , escapeRe = require('browser/escape-string-regexp')
1288
+ , utils = require('../utils');
1252
1289
 
1253
1290
  /**
1254
1291
  * TDD-style interface:
@@ -1355,7 +1392,7 @@ module.exports = function(suite){
1355
1392
 
1356
1393
  context.test = function(title, fn){
1357
1394
  var suite = suites[0];
1358
- if (suite.pending) var fn = null;
1395
+ if (suite.pending) fn = null;
1359
1396
  var test = new Test(title, fn);
1360
1397
  test.file = file;
1361
1398
  suite.addTest(test);
@@ -1368,7 +1405,7 @@ module.exports = function(suite){
1368
1405
 
1369
1406
  context.test.only = function(title, fn){
1370
1407
  var test = context.test(title, fn);
1371
- var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
1408
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
1372
1409
  mocha.grep(new RegExp(reString));
1373
1410
  };
1374
1411
 
@@ -1396,6 +1433,7 @@ require.register("mocha.js", function(module, exports, require){
1396
1433
  */
1397
1434
 
1398
1435
  var path = require('browser/path')
1436
+ , escapeRe = require('browser/escape-string-regexp')
1399
1437
  , utils = require('./utils');
1400
1438
 
1401
1439
  /**
@@ -1607,7 +1645,7 @@ Mocha.prototype._growl = function(runner, reporter) {
1607
1645
 
1608
1646
  Mocha.prototype.grep = function(re){
1609
1647
  this.options.grep = 'string' == typeof re
1610
- ? new RegExp(utils.escapeRegexp(re))
1648
+ ? new RegExp(escapeRe(re))
1611
1649
  : re;
1612
1650
  return this;
1613
1651
  };
@@ -1757,6 +1795,16 @@ Mocha.prototype.asyncOnly = function(){
1757
1795
  return this;
1758
1796
  };
1759
1797
 
1798
+ /**
1799
+ * Disable syntax highlighting (in browser).
1800
+ * @returns {Mocha}
1801
+ * @api public
1802
+ */
1803
+ Mocha.prototype.noHighlighting = function() {
1804
+ this.options.noHighlighting = true;
1805
+ return this;
1806
+ };
1807
+
1760
1808
  /**
1761
1809
  * Run tests and invoke `fn()` when complete.
1762
1810
  *
@@ -1811,7 +1859,7 @@ var y = d * 365.25;
1811
1859
  module.exports = function(val, options){
1812
1860
  options = options || {};
1813
1861
  if ('string' == typeof val) return parse(val);
1814
- return options.long ? longFormat(val) : shortFormat(val);
1862
+ return options['long'] ? longFormat(val) : shortFormat(val);
1815
1863
  };
1816
1864
 
1817
1865
  /**
@@ -2085,7 +2133,7 @@ exports.list = function(failures){
2085
2133
  }
2086
2134
 
2087
2135
  // actual / expected diff
2088
- if ('string' == typeof actual && 'string' == typeof expected) {
2136
+ if (err.showDiff && 'string' == typeof actual && 'string' == typeof expected) {
2089
2137
  fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
2090
2138
  var match = message.match(/^([^:]+): expected/);
2091
2139
  msg = '\n ' + color('error message', match ? match[1] : msg);
@@ -2943,7 +2991,7 @@ function map(cov) {
2943
2991
  }
2944
2992
 
2945
2993
  return ret;
2946
- };
2994
+ }
2947
2995
 
2948
2996
  /**
2949
2997
  * Map jscoverage data for a single source file
@@ -3100,6 +3148,7 @@ function JSONReporter(runner) {
3100
3148
  Base.call(this, runner);
3101
3149
 
3102
3150
  var tests = []
3151
+ , pending = []
3103
3152
  , failures = []
3104
3153
  , passes = [];
3105
3154
 
@@ -3111,21 +3160,23 @@ function JSONReporter(runner) {
3111
3160
  passes.push(test);
3112
3161
  });
3113
3162
 
3114
- runner.on('fail', function(test, err){
3163
+ runner.on('fail', function(test){
3115
3164
  failures.push(test);
3116
- if (err === Object(err)) {
3117
- test.errMsg = err.message;
3118
- test.errStack = err.stack;
3119
- }
3165
+ });
3166
+
3167
+ runner.on('pending', function(test){
3168
+ pending.push(test);
3120
3169
  });
3121
3170
 
3122
3171
  runner.on('end', function(){
3123
3172
  var obj = {
3124
3173
  stats: self.stats,
3125
3174
  tests: tests.map(clean),
3175
+ pending: pending.map(clean),
3126
3176
  failures: failures.map(clean),
3127
3177
  passes: passes.map(clean)
3128
3178
  };
3179
+
3129
3180
  runner.testResults = obj;
3130
3181
 
3131
3182
  process.stdout.write(JSON.stringify(obj, null, 2));
@@ -3146,12 +3197,24 @@ function clean(test) {
3146
3197
  title: test.title,
3147
3198
  fullTitle: test.fullTitle(),
3148
3199
  duration: test.duration,
3149
- err: test.err,
3150
- errStack: test.err.stack,
3151
- errMessage: test.err.message
3200
+ err: errorJSON(test.err || {})
3152
3201
  }
3153
3202
  }
3154
3203
 
3204
+ /**
3205
+ * Transform `error` into a JSON object.
3206
+ * @param {Error} err
3207
+ * @return {Object}
3208
+ */
3209
+
3210
+ function errorJSON(err) {
3211
+ var res = {};
3212
+ Object.getOwnPropertyNames(err).forEach(function(key) {
3213
+ res[key] = err[key];
3214
+ }, err);
3215
+ return res;
3216
+ }
3217
+
3155
3218
  }); // module: reporters/json.js
3156
3219
 
3157
3220
  require.register("reporters/landing.js", function(module, exports, require){
@@ -3658,7 +3721,7 @@ NyanCat.prototype.face = function() {
3658
3721
  } else {
3659
3722
  return '( - .-)';
3660
3723
  }
3661
- }
3724
+ };
3662
3725
 
3663
3726
  /**
3664
3727
  * Move cursor up `n`.
@@ -4203,6 +4266,7 @@ Runnable.prototype.constructor = Runnable;
4203
4266
 
4204
4267
  Runnable.prototype.timeout = function(ms){
4205
4268
  if (0 == arguments.length) return this._timeout;
4269
+ if (ms === 0) this._enableTimeouts = false;
4206
4270
  if ('string' == typeof ms) ms = milliseconds(ms);
4207
4271
  debug('timeout %d', ms);
4208
4272
  this._timeout = ms;
@@ -4292,6 +4356,7 @@ Runnable.prototype.resetTimeout = function(){
4292
4356
  if (!this._enableTimeouts) return;
4293
4357
  this.clearTimeout();
4294
4358
  this.timer = setTimeout(function(){
4359
+ if (!self._enableTimeouts) return;
4295
4360
  self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
4296
4361
  self.timedOut = true;
4297
4362
  }, ms);
@@ -4942,18 +5007,25 @@ Runner.prototype.runSuite = function(suite, fn){
4942
5007
 
4943
5008
  Runner.prototype.uncaught = function(err){
4944
5009
  if (err) {
4945
- debug('uncaught exception %s', err.message);
5010
+ debug('uncaught exception %s', err !== function () {
5011
+ return this;
5012
+ }.call(err) ? err : ( err.message || err ));
4946
5013
  } else {
4947
5014
  debug('uncaught undefined exception');
4948
- err = new Error('Catched undefined error, did you throw without specifying what?');
5015
+ err = new Error('Caught undefined error, did you throw without specifying what?');
4949
5016
  }
4950
-
4951
- var runnable = this.currentRunnable;
4952
- if (!runnable || 'failed' == runnable.state) return;
4953
- runnable.clearTimeout();
4954
5017
  err.uncaught = true;
5018
+
5019
+ var runnable = this.currentRunnable;
5020
+ if (!runnable) return;
5021
+
5022
+ var wasAlreadyDone = runnable.state;
4955
5023
  this.fail(runnable, err);
4956
5024
 
5025
+ runnable.clearTimeout();
5026
+
5027
+ if (wasAlreadyDone) return;
5028
+
4957
5029
  // recover from test
4958
5030
  if ('test' == runnable.type) {
4959
5031
  this.emit('test end', runnable);
@@ -5013,7 +5085,7 @@ Runner.prototype.run = function(fn){
5013
5085
  Runner.prototype.abort = function(){
5014
5086
  debug('aborting');
5015
5087
  this._abort = true;
5016
- }
5088
+ };
5017
5089
 
5018
5090
  /**
5019
5091
  * Filter leaks with the given globals flagged as `ok`.
@@ -5182,6 +5254,7 @@ Suite.prototype.clone = function(){
5182
5254
 
5183
5255
  Suite.prototype.timeout = function(ms){
5184
5256
  if (0 == arguments.length) return this._timeout;
5257
+ if (ms === 0) this._enableTimeouts = false;
5185
5258
  if ('string' == typeof ms) ms = milliseconds(ms);
5186
5259
  debug('timeout %d', ms);
5187
5260
  this._timeout = parseInt(ms, 10);
@@ -5201,7 +5274,7 @@ Suite.prototype.enableTimeouts = function(enabled){
5201
5274
  debug('enableTimeouts %s', enabled);
5202
5275
  this._enableTimeouts = enabled;
5203
5276
  return this;
5204
- }
5277
+ };
5205
5278
 
5206
5279
  /**
5207
5280
  * Set slow `ms` or short-hand such as "2s".
@@ -5476,6 +5549,9 @@ require.register("utils.js", function(module, exports, require){
5476
5549
 
5477
5550
  var fs = require('browser/fs')
5478
5551
  , path = require('browser/path')
5552
+ , basename = path.basename
5553
+ , exists = fs.existsSync || path.existsSync
5554
+ , glob = require('browser/glob')
5479
5555
  , join = path.join
5480
5556
  , debug = require('browser/debug')('mocha:watch');
5481
5557
 
@@ -5696,18 +5772,6 @@ exports.clean = function(str) {
5696
5772
  return exports.trim(str);
5697
5773
  };
5698
5774
 
5699
- /**
5700
- * Escape regular expression characters in `str`.
5701
- *
5702
- * @param {String} str
5703
- * @return {String}
5704
- * @api private
5705
- */
5706
-
5707
- exports.escapeRegexp = function(str){
5708
- return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
5709
- };
5710
-
5711
5775
  /**
5712
5776
  * Trim the given `str`.
5713
5777
  *
@@ -5767,7 +5831,7 @@ function highlight(js) {
5767
5831
  */
5768
5832
 
5769
5833
  exports.highlightTags = function(name) {
5770
- var code = document.getElementsByTagName(name);
5834
+ var code = document.getElementById('mocha').getElementsByTagName(name);
5771
5835
  for (var i = 0, len = code.length; i < len; ++i) {
5772
5836
  code[i].innerHTML = highlight(code[i].innerHTML);
5773
5837
  }
@@ -5785,41 +5849,88 @@ exports.highlightTags = function(name) {
5785
5849
  exports.stringify = function(obj) {
5786
5850
  if (obj instanceof RegExp) return obj.toString();
5787
5851
  return JSON.stringify(exports.canonicalize(obj), null, 2).replace(/,(\n|$)/g, '$1');
5788
- }
5852
+ };
5789
5853
 
5790
5854
  /**
5791
5855
  * Return a new object that has the keys in sorted order.
5792
5856
  * @param {Object} obj
5857
+ * @param {Array} [stack]
5793
5858
  * @return {Object}
5794
5859
  * @api private
5795
5860
  */
5796
5861
 
5797
5862
  exports.canonicalize = function(obj, stack) {
5798
- stack = stack || [];
5799
-
5800
- if (exports.indexOf(stack, obj) !== -1) return '[Circular]';
5801
-
5802
- var canonicalizedObj;
5803
-
5804
- if ({}.toString.call(obj) === '[object Array]') {
5805
- stack.push(obj);
5806
- canonicalizedObj = exports.map(obj, function(item) {
5807
- return exports.canonicalize(item, stack);
5808
- });
5809
- stack.pop();
5810
- } else if (typeof obj === 'object' && obj !== null) {
5811
- stack.push(obj);
5812
- canonicalizedObj = {};
5813
- exports.forEach(exports.keys(obj).sort(), function(key) {
5814
- canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
5815
- });
5816
- stack.pop();
5817
- } else {
5818
- canonicalizedObj = obj;
5819
- }
5820
-
5821
- return canonicalizedObj;
5822
- }
5863
+ stack = stack || [];
5864
+
5865
+ if (exports.indexOf(stack, obj) !== -1) return '[Circular]';
5866
+
5867
+ var canonicalizedObj;
5868
+
5869
+ if ({}.toString.call(obj) === '[object Array]') {
5870
+ stack.push(obj);
5871
+ canonicalizedObj = exports.map(obj, function (item) {
5872
+ return exports.canonicalize(item, stack);
5873
+ });
5874
+ stack.pop();
5875
+ } else if (typeof obj === 'object' && obj !== null) {
5876
+ stack.push(obj);
5877
+ canonicalizedObj = {};
5878
+ exports.forEach(exports.keys(obj).sort(), function (key) {
5879
+ canonicalizedObj[key] = exports.canonicalize(obj[key], stack);
5880
+ });
5881
+ stack.pop();
5882
+ } else {
5883
+ canonicalizedObj = obj;
5884
+ }
5885
+
5886
+ return canonicalizedObj;
5887
+ };
5888
+
5889
+ /**
5890
+ * Lookup file names at the given `path`.
5891
+ */
5892
+ exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
5893
+ var files = [];
5894
+ var re = new RegExp('\\.(' + extensions.join('|') + ')$');
5895
+
5896
+ if (!exists(path)) {
5897
+ if (exists(path + '.js')) {
5898
+ path += '.js';
5899
+ } else {
5900
+ files = glob.sync(path);
5901
+ if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
5902
+ return files;
5903
+ }
5904
+ }
5905
+
5906
+ try {
5907
+ var stat = fs.statSync(path);
5908
+ if (stat.isFile()) return path;
5909
+ }
5910
+ catch (ignored) {
5911
+ return;
5912
+ }
5913
+
5914
+ fs.readdirSync(path).forEach(function(file){
5915
+ file = join(path, file);
5916
+ try {
5917
+ var stat = fs.statSync(file);
5918
+ if (stat.isDirectory()) {
5919
+ if (recursive) {
5920
+ files = files.concat(lookupFiles(file, extensions, recursive));
5921
+ }
5922
+ return;
5923
+ }
5924
+ }
5925
+ catch (ignored) {
5926
+ return;
5927
+ }
5928
+ if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
5929
+ files.push(file);
5930
+ });
5931
+
5932
+ return files;
5933
+ };
5823
5934
 
5824
5935
  }); // module: utils.js
5825
5936
  // The global object is "self" in Web Workers.
@@ -5968,7 +6079,8 @@ mocha.run = function(fn){
5968
6079
 
5969
6080
  return Mocha.prototype.run.call(mocha, function(err){
5970
6081
  // The DOM Document is not available in Web Workers.
5971
- if (global.document) {
6082
+ var document = global.document;
6083
+ if (document && document.getElementById('mocha') && options.noHighlighting !== true) {
5972
6084
  Mocha.utils.highlightTags('code');
5973
6085
  }
5974
6086
  if (fn) fn(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocha",
3
- "version": "1.21.4",
3
+ "version": "1.21.5",
4
4
  "description": "simple, flexible, fun test framework",
5
5
  "keywords": [
6
6
  "mocha",
@@ -36,16 +36,17 @@
36
36
  "test": "make test-all"
37
37
  },
38
38
  "dependencies": {
39
- "commander": "2.0.0",
40
- "growl": "1.8.x",
39
+ "commander": "2.3.0",
40
+ "debug": "2.0.0",
41
+ "diff": "1.0.8",
42
+ "escape-string-regexp": "1.0.2",
43
+ "glob": "3.2.3",
44
+ "growl": "1.8.1",
41
45
  "jade": "0.26.3",
42
- "diff": "1.0.7",
43
- "debug": "*",
44
- "mkdirp": "0.3.5",
45
- "glob": "3.2.3"
46
+ "mkdirp": "0.5.0"
46
47
  },
47
48
  "devDependencies": {
48
- "coffee-script": "~1.7.1",
49
+ "coffee-script": "~1.8.0",
49
50
  "should": "~4.0.0"
50
51
  },
51
52
  "files": [