mocha 1.16.0 → 1.17.1

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/Readme.md CHANGED
@@ -9,112 +9,160 @@
9
9
  ```
10
10
 
11
11
  project : mocha
12
- repo age : 1 year, 7 months
13
- active : 272 days
14
- commits : 1116
15
- files : 123
12
+ repo age : 2 years, 4 months ago
13
+ commits : 1314
14
+ active : 372 days
15
+ files : 141
16
16
  authors :
17
- 504 TJ Holowaychuk 45.2%
18
- 389 Tj Holowaychuk 34.9%
19
- 31 Guillermo Rauch 2.8%
20
- 13 Attila Domokos 1.2%
21
- 9 John Firebaugh 0.8%
22
- 8 Jo Liss 0.7%
23
- 7 Nathan Rajlich 0.6%
24
- 6 James Carr 0.5%
25
- 6 Brendan Nee 0.5%
26
- 5 Aaron Heckmann 0.4%
27
- 4 hokaccha 0.4%
28
- 4 Xavier Antoviaque 0.4%
29
- 4 Joshua Krall 0.4%
30
- 3 Wil Moore III 0.3%
31
- 3 Jesse Dailey 0.3%
32
- 3 Nathan Bowser 0.3%
33
- 3 Tyson Tate 0.3%
34
- 3 Cory Thomas 0.3%
35
- 3 Ryunosuke SATO 0.3%
36
- 3 Paul Miller 0.3%
37
- 3 Ben Lindsey 0.3%
38
- 2 Forbes Lindesay 0.2%
39
- 2 Konstantin Käfer 0.2%
40
- 2 Brian Beck 0.2%
41
- 2 Merrick Christensen 0.2%
42
- 2 Michael Riley 0.2%
43
- 2 David Henderson 0.2%
44
- 2 Nathan Alderson 0.2%
45
- 2 Paul Armstrong 0.2%
46
- 2 Pete Hawkins 0.2%
47
- 2 Quang Van 0.2%
48
- 2 Raynos 0.2%
49
- 2 Jonas Westerlund 0.2%
50
- 2 Domenic Denicola 0.2%
51
- 2 Shawn Krisman 0.2%
52
- 2 Simon Gaeremynck 0.2%
53
- 2 FARKAS Máté 0.2%
54
- 2 Timo Tijhof 0.2%
55
- 2 Justin DuJardin 0.2%
56
- 2 Juzer Ali 0.2%
57
- 2 Ian Storm Taylor 0.2%
58
- 2 Arian Stolwijk 0.2%
59
- 2 domenic 0.2%
60
- 1 Richard Dingwall 0.1%
61
- 1 Russ Bradberry 0.1%
62
- 1 Sasha Koss 0.1%
63
- 1 Seiya Konno 0.1%
64
- 1 Standa Opichal 0.1%
65
- 1 Steve Mason 0.1%
66
- 1 Will Langstroth 0.1%
67
- 1 Yanis Wang 0.1%
68
- 1 Yuest Wang 0.1%
69
- 1 abrkn 0.1%
70
- 1 airportyh 0.1%
71
- 1 fengmk2 0.1%
72
- 1 tgautier@yahoo.com 0.1%
73
- 1 traleig1 0.1%
74
- 1 vlad 0.1%
75
- 1 yuitest 0.1%
76
- 1 Adam Crabtree 0.1%
77
- 1 Andreas Brekken 0.1%
78
- 1 Atsuya Takagi 0.1%
79
- 1 Austin Birch 0.1%
80
- 1 Bjørge Næss 0.1%
81
- 1 Brian Moore 0.1%
82
- 1 Bryan Donovan 0.1%
83
- 1 Casey Foster 0.1%
84
- 1 Corey Butler 0.1%
85
- 1 Dave McKenna 0.1%
86
- 1 Fedor Indutny 0.1%
87
- 1 Florian Margaine 0.1%
88
- 1 Frederico Silva 0.1%
89
- 1 Fredrik Lindin 0.1%
90
- 1 Gareth Murphy 0.1%
91
- 1 Gavin Mogan 0.1%
92
- 1 Greg Perkins 0.1%
93
- 1 Harry Brundage 0.1%
94
- 1 Herman Junge 0.1%
95
- 1 Ian Young 0.1%
96
- 1 Ivan 0.1%
97
- 1 Jaakko Salonen 0.1%
98
- 1 Jakub Nešetřil 0.1%
99
- 1 James Bowes 0.1%
100
- 1 James Lal 0.1%
101
- 1 Jason Barry 0.1%
102
- 1 Javier Aranda 0.1%
103
- 1 Jeff Kunkle 0.1%
104
- 1 Jonathan Creamer 0.1%
105
- 1 Jussi Virtanen 0.1%
106
- 1 Katie Gengler 0.1%
107
- 1 Kazuhito Hokamura 0.1%
108
- 1 Koen Punt 0.1%
109
- 1 Laszlo Bacsi 0.1%
110
- 1 László Bácsi 0.1%
111
- 1 Maciej Małecki 0.1%
112
- 1 Matt Robenolt 0.1%
113
- 1 Matt Smith 0.1%
114
- 1 Matthew Shanley 0.1%
115
- 1 Michael Schoonmaker 0.1%
116
- 1 Phil Sung 0.1%
117
- 1 R56 0.1%
17
+ 582 TJ Holowaychuk 44.3%
18
+ 389 Tj Holowaychuk 29.6%
19
+ 46 Travis Jeffery 3.5%
20
+ 31 Guillermo Rauch 2.4%
21
+ 13 Attila Domokos 1.0%
22
+ 10 John Firebaugh 0.8%
23
+ 8 Jo Liss 0.6%
24
+ 7 Nathan Rajlich 0.5%
25
+ 6 Mike Pennisi 0.5%
26
+ 6 James Carr 0.5%
27
+ 6 Brendan Nee 0.5%
28
+ 5 Aaron Heckmann 0.4%
29
+ 5 Ryunosuke SATO 0.4%
30
+ 4 hokaccha 0.3%
31
+ 4 Joshua Krall 0.3%
32
+ 4 Xavier Antoviaque 0.3%
33
+ 3 Jesse Dailey 0.2%
34
+ 3 Forbes Lindesay 0.2%
35
+ 3 Sindre Sorhus 0.2%
36
+ 3 Cory Thomas 0.2%
37
+ 3 Fredrik Enestad 0.2%
38
+ 3 Ben Lindsey 0.2%
39
+ 3 Tyson Tate 0.2%
40
+ 3 Mathieu Desvé 0.2%
41
+ 3 Valentin Agachi 0.2%
42
+ 3 Wil Moore III 0.2%
43
+ 3 Merrick Christensen 0.2%
44
+ 3 eiji.ienaga 0.2%
45
+ 3 fool2fish 0.2%
46
+ 3 Nathan Bowser 0.2%
47
+ 3 Paul Miller 0.2%
48
+ 2 Juzer Ali 0.2%
49
+ 2 Pete Hawkins 0.2%
50
+ 2 Jonas Westerlund 0.2%
51
+ 2 Arian Stolwijk 0.2%
52
+ 2 Quang Van 0.2%
53
+ 2 Glen Mailer 0.2%
54
+ 2 Justin DuJardin 0.2%
55
+ 2 FARKAS Máté 0.2%
56
+ 2 Raynos 0.2%
57
+ 2 Michael Riley 0.2%
58
+ 2 Michael Schoonmaker 0.2%
59
+ 2 Domenic Denicola 0.2%
60
+ 2 Simon Gaeremynck 0.2%
61
+ 2 Konstantin Käfer 0.2%
62
+ 2 domenic 0.2%
63
+ 2 Paul Armstrong 0.2%
64
+ 2 fcrisci 0.2%
65
+ 2 Alexander Early 0.2%
66
+ 2 Shawn Krisman 0.2%
67
+ 2 Brian Beck 0.2%
68
+ 2 Nathan Alderson 0.2%
69
+ 2 David Henderson 0.2%
70
+ 2 Timo Tijhof 0.2%
71
+ 2 Ian Storm Taylor 0.2%
72
+ 2 travis jeffery 0.2%
73
+ 1 Matt Smith 0.1%
74
+ 1 Matthew Shanley 0.1%
75
+ 1 Nathan Black 0.1%
76
+ 1 Phil Sung 0.1%
77
+ 1 R56 0.1%
78
+ 1 Refael Ackermann 0.1%
79
+ 1 Richard Dingwall 0.1%
80
+ 1 Romain Prieto 0.1%
81
+ 1 Roman Neuhauser 0.1%
82
+ 1 Roman Shtylman 0.1%
83
+ 1 Russ Bradberry 0.1%
84
+ 1 Russell Munson 0.1%
85
+ 1 Rustem Mustafin 0.1%
86
+ 1 Salehen Shovon Rahman 0.1%
87
+ 1 Sasha Koss 0.1%
88
+ 1 Seiya Konno 0.1%
89
+ 1 Simon Goumaz 0.1%
90
+ 1 Standa Opichal 0.1%
91
+ 1 Stephen Mathieson 0.1%
92
+ 1 Steve Mason 0.1%
93
+ 1 Tapiwa Kelvin 0.1%
94
+ 1 Teddy Zeenny 0.1%
95
+ 1 Tim Ehat 0.1%
96
+ 1 Vadim Nikitin 0.1%
97
+ 1 Victor Costan 0.1%
98
+ 1 Will Langstroth 0.1%
99
+ 1 Yanis Wang 0.1%
100
+ 1 Yuest Wang 0.1%
101
+ 1 abrkn 0.1%
102
+ 1 airportyh 0.1%
103
+ 1 badunk 0.1%
104
+ 1 fengmk2 0.1%
105
+ 1 grasGendarme 0.1%
106
+ 1 lodr 0.1%
107
+ 1 tgautier@yahoo.com 0.1%
108
+ 1 traleig1 0.1%
109
+ 1 vlad 0.1%
110
+ 1 yuitest 0.1%
111
+ 1 Adam Crabtree 0.1%
112
+ 1 Andreas Brekken 0.1%
113
+ 1 Andreas Lind Petersen 0.1%
114
+ 1 Andrew Nesbitt 0.1%
115
+ 1 Andrey Popp 0.1%
116
+ 1 Arnaud Brousseau 0.1%
117
+ 1 Atsuya Takagi 0.1%
118
+ 1 Austin Birch 0.1%
119
+ 1 Bjørge Næss 0.1%
120
+ 1 Brian Lalor 0.1%
121
+ 1 Brian M. Carlson 0.1%
122
+ 1 Brian Moore 0.1%
123
+ 1 Bryan Donovan 0.1%
124
+ 1 Casey Foster 0.1%
125
+ 1 ChrisWren 0.1%
126
+ 1 Corey Butler 0.1%
127
+ 1 Daniel Stockman 0.1%
128
+ 1 Dave McKenna 0.1%
129
+ 1 Di Wu 0.1%
130
+ 1 Dmitry Shirokov 0.1%
131
+ 1 Fedor Indutny 0.1%
132
+ 1 Florian Margaine 0.1%
133
+ 1 Frederico Silva 0.1%
134
+ 1 Fredrik Lindin 0.1%
135
+ 1 Gareth Murphy 0.1%
136
+ 1 Gavin Mogan 0.1%
137
+ 1 Glen Huang 0.1%
138
+ 1 Greg Perkins 0.1%
139
+ 1 Harry Brundage 0.1%
140
+ 1 Herman Junge 0.1%
141
+ 1 Ian Young 0.1%
142
+ 1 Ivan 0.1%
143
+ 1 JP Bochi 0.1%
144
+ 1 Jaakko Salonen 0.1%
145
+ 1 Jakub Nešetřil 0.1%
146
+ 1 James Bowes 0.1%
147
+ 1 James Lal 0.1%
148
+ 1 Jason Barry 0.1%
149
+ 1 Javier Aranda 0.1%
150
+ 1 Jeff Kunkle 0.1%
151
+ 1 Jeremy Martin 0.1%
152
+ 1 Jimmy Cuadra 0.1%
153
+ 1 Jonathan Creamer 0.1%
154
+ 1 Jussi Virtanen 0.1%
155
+ 1 Katie Gengler 0.1%
156
+ 1 Kazuhito Hokamura 0.1%
157
+ 1 Kirill Korolyov 0.1%
158
+ 1 Koen Punt 0.1%
159
+ 1 Laszlo Bacsi 0.1%
160
+ 1 Liam Newman 0.1%
161
+ 1 László Bácsi 0.1%
162
+ 1 Maciej Małecki 0.1%
163
+ 1 Mal Graty 0.1%
164
+ 1 Marc Kuo 0.1%
165
+ 1 Matt Robenolt 0.1%
118
166
  ```
119
167
 
120
168
  ## Links
package/bin/_mocha CHANGED
@@ -296,6 +296,7 @@ if (program.sort) {
296
296
 
297
297
  // --watch
298
298
 
299
+ var runner;
299
300
  if (program.watch) {
300
301
  console.log();
301
302
  hideCursor();
@@ -306,11 +307,18 @@ if (program.watch) {
306
307
  });
307
308
 
308
309
  var watchFiles = utils.files(cwd);
310
+ var runAgain = false;
309
311
 
310
312
  function loadAndRun() {
311
313
  try {
312
314
  mocha.files = files;
313
- mocha.run(function(){});
315
+ runAgain = false;
316
+ runner = mocha.run(function(){
317
+ runner = null;
318
+ if (runAgain) {
319
+ rerun();
320
+ }
321
+ });
314
322
  } catch(e) {
315
323
  console.log(e.stack);
316
324
  }
@@ -324,12 +332,22 @@ if (program.watch) {
324
332
 
325
333
  loadAndRun();
326
334
 
327
- utils.watch(watchFiles, function(){
335
+ function rerun() {
328
336
  purge();
329
337
  stop()
330
338
  mocha.suite = mocha.suite.clone();
339
+ mocha.suite.ctx = new Mocha.Context;
331
340
  mocha.ui(program.ui);
332
341
  loadAndRun();
342
+ }
343
+
344
+ utils.watch(watchFiles, function(){
345
+ runAgain = true;
346
+ if (runner) {
347
+ runner.abort();
348
+ } else {
349
+ rerun();
350
+ }
333
351
  });
334
352
 
335
353
  return;
@@ -338,7 +356,7 @@ if (program.watch) {
338
356
  // load
339
357
 
340
358
  mocha.files = files;
341
- var runner = mocha.run(program.exit ? process.exit : exitLater);
359
+ runner = mocha.run(program.exit ? process.exit : exitLater);
342
360
 
343
361
  function exitLater(code) {
344
362
  process.on('exit', function() { process.exit(code) })
@@ -410,7 +428,9 @@ function lookupFiles(path, recursive) {
410
428
  if (exists(path + '.js')) {
411
429
  path += '.js'
412
430
  } else {
413
- return glob.sync(path);
431
+ files = glob.sync(path);
432
+ if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
433
+ return files;
414
434
  }
415
435
  }
416
436
 
@@ -1,4 +1,3 @@
1
-
2
1
  /**
3
2
  * Expose `Progress`.
4
3
  */
@@ -87,39 +86,40 @@ Progress.prototype.update = function(n){
87
86
  */
88
87
 
89
88
  Progress.prototype.draw = function(ctx){
90
- var percent = Math.min(this.percent, 100)
91
- , size = this._size
92
- , half = size / 2
93
- , x = half
94
- , y = half
95
- , rad = half - 1
96
- , fontSize = this._fontSize;
97
-
98
- ctx.font = fontSize + 'px ' + this._font;
99
-
100
- var angle = Math.PI * 2 * (percent / 100);
101
- ctx.clearRect(0, 0, size, size);
102
-
103
- // outer circle
104
- ctx.strokeStyle = '#9f9f9f';
105
- ctx.beginPath();
106
- ctx.arc(x, y, rad, 0, angle, false);
107
- ctx.stroke();
108
-
109
- // inner circle
110
- ctx.strokeStyle = '#eee';
111
- ctx.beginPath();
112
- ctx.arc(x, y, rad - 1, 0, angle, true);
113
- ctx.stroke();
114
-
115
- // text
116
- var text = this._text || (percent | 0) + '%'
117
- , w = ctx.measureText(text).width;
118
-
119
- ctx.fillText(
120
- text
121
- , x - w / 2 + 1
122
- , y + fontSize / 2 - 1);
123
-
89
+ try {
90
+ var percent = Math.min(this.percent, 100)
91
+ , size = this._size
92
+ , half = size / 2
93
+ , x = half
94
+ , y = half
95
+ , rad = half - 1
96
+ , fontSize = this._fontSize;
97
+
98
+ ctx.font = fontSize + 'px ' + this._font;
99
+
100
+ var angle = Math.PI * 2 * (percent / 100);
101
+ ctx.clearRect(0, 0, size, size);
102
+
103
+ // outer circle
104
+ ctx.strokeStyle = '#9f9f9f';
105
+ ctx.beginPath();
106
+ ctx.arc(x, y, rad, 0, angle, false);
107
+ ctx.stroke();
108
+
109
+ // inner circle
110
+ ctx.strokeStyle = '#eee';
111
+ ctx.beginPath();
112
+ ctx.arc(x, y, rad - 1, 0, angle, true);
113
+ ctx.stroke();
114
+
115
+ // text
116
+ var text = this._text || (percent | 0) + '%'
117
+ , w = ctx.measureText(text).width;
118
+
119
+ ctx.fillText(
120
+ text
121
+ , x - w / 2 + 1
122
+ , y + fontSize / 2 - 1);
123
+ } catch (ex) {} //don't fail if we can't render progress
124
124
  return this;
125
125
  };
package/lib/mocha.js CHANGED
@@ -73,6 +73,21 @@ function Mocha(options) {
73
73
  if (null != options.timeout) this.timeout(options.timeout);
74
74
  this.useColors(options.useColors)
75
75
  if (options.slow) this.slow(options.slow);
76
+
77
+ this.suite.on('pre-require', function (context) {
78
+ exports.afterEach = context.afterEach || context.teardown;
79
+ exports.after = context.after || context.suiteTeardown;
80
+ exports.beforeEach = context.beforeEach || context.setup;
81
+ exports.before = context.before || context.suiteSetup;
82
+ exports.describe = context.describe || context.suite;
83
+ exports.it = context.it || context.test;
84
+ exports.setup = context.setup || context.beforeEach;
85
+ exports.suiteSetup = context.suiteSetup || context.before;
86
+ exports.suiteTeardown = context.suiteTeardown || context.after;
87
+ exports.suite = context.suite || context.describe;
88
+ exports.teardown = context.teardown || context.afterEach;
89
+ exports.test = context.test || context.it;
90
+ });
76
91
  }
77
92
 
78
93
  /**
@@ -5,7 +5,8 @@
5
5
 
6
6
  var tty = require('tty')
7
7
  , diff = require('diff')
8
- , ms = require('../ms');
8
+ , ms = require('../ms')
9
+ , utils = require('../utils');
9
10
 
10
11
  /**
11
12
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -141,7 +142,7 @@ exports.cursor = {
141
142
  exports.cursor.deleteLine();
142
143
  exports.cursor.beginningOfLine();
143
144
  } else {
144
- process.stdout.write('\n');
145
+ process.stdout.write('\r');
145
146
  }
146
147
  }
147
148
  };
@@ -179,15 +180,15 @@ exports.list = function(failures){
179
180
  // explicitly show diff
180
181
  if (err.showDiff && sameType(actual, expected)) {
181
182
  escape = false;
182
- err.actual = actual = stringify(actual);
183
- err.expected = expected = stringify(expected);
183
+ err.actual = actual = stringify(canonicalize(actual));
184
+ err.expected = expected = stringify(canonicalize(expected));
184
185
  }
185
186
 
186
187
  // actual / expected diff
187
188
  if ('string' == typeof actual && 'string' == typeof expected) {
188
189
  fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
189
190
  var match = message.match(/^([^:]+): expected/);
190
- msg = match ? '\n ' + color('error message', match[1]) : '';
191
+ msg = '\n ' + color('error message', match ? match[1] : msg);
191
192
 
192
193
  if (exports.inlineDiffs) {
193
194
  msg += inlineDiff(err, escape);
@@ -445,7 +446,7 @@ function colorLines(name, str) {
445
446
  /**
446
447
  * Stringify `obj`.
447
448
  *
448
- * @param {Mixed} obj
449
+ * @param {Object} obj
449
450
  * @return {String}
450
451
  * @api private
451
452
  */
@@ -455,6 +456,40 @@ function stringify(obj) {
455
456
  return JSON.stringify(obj, null, 2);
456
457
  }
457
458
 
459
+ /**
460
+ * Return a new object that has the keys in sorted order.
461
+ * @param {Object} obj
462
+ * @return {Object}
463
+ * @api private
464
+ */
465
+
466
+ function canonicalize(obj, stack) {
467
+ stack = stack || [];
468
+
469
+ if (utils.indexOf(stack, obj) !== -1) return obj;
470
+
471
+ var canonicalizedObj;
472
+
473
+ if ('[object Array]' == {}.toString.call(obj)) {
474
+ stack.push(obj);
475
+ canonicalizedObj = utils.map(obj, function(item) {
476
+ return canonicalize(item, stack);
477
+ });
478
+ stack.pop();
479
+ } else if (typeof obj === 'object' && obj !== null) {
480
+ stack.push(obj);
481
+ canonicalizedObj = {};
482
+ utils.forEach(utils.keys(obj).sort(), function(key) {
483
+ canonicalizedObj[key] = canonicalize(obj[key], stack);
484
+ });
485
+ stack.pop();
486
+ } else {
487
+ canonicalizedObj = obj;
488
+ }
489
+
490
+ return canonicalizedObj;
491
+ }
492
+
458
493
  /**
459
494
  * Check that a / b have the same type.
460
495
  *
@@ -470,4 +505,3 @@ function sameType(a, b) {
470
505
  return a == b;
471
506
  }
472
507
 
473
-
@@ -49,7 +49,7 @@ function XUnit(runner) {
49
49
  });
50
50
 
51
51
  runner.on('end', function(){
52
- process.stdout.write(tag('testsuite', {
52
+ console.log(tag('testsuite', {
53
53
  name: 'Mocha Tests'
54
54
  , tests: stats.tests
55
55
  , failures: stats.failures
@@ -60,7 +60,7 @@ function XUnit(runner) {
60
60
  }, false));
61
61
 
62
62
  tests.forEach(test);
63
- process.stdout.write('</testsuite>');
63
+ console.log('</testsuite>');
64
64
  });
65
65
  }
66
66
 
@@ -84,11 +84,11 @@ function test(test) {
84
84
  if ('failed' == test.state) {
85
85
  var err = test.err;
86
86
  attrs.message = escape(err.message);
87
- process.stdout.write(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
87
+ console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
88
88
  } else if (test.pending) {
89
- process.stdout.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
89
+ console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
90
90
  } else {
91
- process.stdout.write(tag('testcase', attrs, true) );
91
+ console.log(tag('testcase', attrs, true) );
92
92
  }
93
93
  }
94
94
 
package/lib/runner.js CHANGED
@@ -58,7 +58,7 @@ function Runner(suite) {
58
58
  this.on('test end', function(test){ self.checkGlobals(test); });
59
59
  this.on('hook end', function(hook){ self.checkGlobals(hook); });
60
60
  this.grep(/.*/);
61
- this.globals(this.globalProps().concat(['errno']));
61
+ this.globals(this.globalProps().concat(extraGlobals()));
62
62
  }
63
63
 
64
64
  /**
@@ -168,10 +168,6 @@ Runner.prototype.checkGlobals = function(test){
168
168
  ok = ok.concat(test._allowedGlobals || []);
169
169
  }
170
170
 
171
- // check length - 2 ('errno' and 'location' globals)
172
- if (isNode && 1 == ok.length - globals.length) return;
173
- else if (2 == ok.length - globals.length) return;
174
-
175
171
  if(this.prevGlobalsLength == globals.length) return;
176
172
  this.prevGlobalsLength = globals.length;
177
173
 
@@ -638,3 +634,28 @@ function filterLeaks(ok, globals) {
638
634
  return matched.length == 0 && (!global.navigator || 'onerror' !== key);
639
635
  });
640
636
  }
637
+
638
+ /**
639
+ * Array of globals dependent on the environment.
640
+ *
641
+ * @return {Array}
642
+ * @api private
643
+ */
644
+
645
+ function extraGlobals() {
646
+ if (typeof(process) === 'object' &&
647
+ typeof(process.version) === 'string') {
648
+
649
+ var nodeVersion = process.version.split('.').reduce(function(a, v) {
650
+ return a << 8 | v;
651
+ });
652
+
653
+ // 'errno' was renamed to process._errno in v0.9.11.
654
+
655
+ if (nodeVersion < 0x00090B) {
656
+ return ['errno'];
657
+ }
658
+ }
659
+
660
+ return [];
661
+ }
package/lib/utils.js CHANGED
@@ -43,6 +43,22 @@ exports.forEach = function(arr, fn, scope){
43
43
  fn.call(scope, arr[i], i);
44
44
  };
45
45
 
46
+ /**
47
+ * Array#map (<=IE8)
48
+ *
49
+ * @param {Array} array
50
+ * @param {Function} fn
51
+ * @param {Object} scope
52
+ * @api private
53
+ */
54
+
55
+ exports.map = function(arr, fn, scope){
56
+ var result = [];
57
+ for (var i = 0, l = arr.length; i < l; i++)
58
+ result.push(fn.call(scope, arr[i], i));
59
+ return result;
60
+ };
61
+
46
62
  /**
47
63
  * Array#indexOf (<=IE8)
48
64
  *
package/mocha.js CHANGED
@@ -604,7 +604,6 @@ require.register("browser/path.js", function(module, exports, require){
604
604
  }); // module: browser/path.js
605
605
 
606
606
  require.register("browser/progress.js", function(module, exports, require){
607
-
608
607
  /**
609
608
  * Expose `Progress`.
610
609
  */
@@ -693,40 +692,41 @@ Progress.prototype.update = function(n){
693
692
  */
694
693
 
695
694
  Progress.prototype.draw = function(ctx){
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
-
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
730
730
  return this;
731
731
  };
732
732
 
@@ -1437,6 +1437,21 @@ function Mocha(options) {
1437
1437
  if (null != options.timeout) this.timeout(options.timeout);
1438
1438
  this.useColors(options.useColors)
1439
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
+ });
1440
1455
  }
1441
1456
 
1442
1457
  /**
@@ -1840,7 +1855,8 @@ require.register("reporters/base.js", function(module, exports, require){
1840
1855
 
1841
1856
  var tty = require('browser/tty')
1842
1857
  , diff = require('browser/diff')
1843
- , ms = require('../ms');
1858
+ , ms = require('../ms')
1859
+ , utils = require('../utils');
1844
1860
 
1845
1861
  /**
1846
1862
  * Save timer references to avoid Sinon interfering (see GH-237).
@@ -1976,7 +1992,7 @@ exports.cursor = {
1976
1992
  exports.cursor.deleteLine();
1977
1993
  exports.cursor.beginningOfLine();
1978
1994
  } else {
1979
- process.stdout.write('\n');
1995
+ process.stdout.write('\r');
1980
1996
  }
1981
1997
  }
1982
1998
  };
@@ -2014,15 +2030,15 @@ exports.list = function(failures){
2014
2030
  // explicitly show diff
2015
2031
  if (err.showDiff && sameType(actual, expected)) {
2016
2032
  escape = false;
2017
- err.actual = actual = stringify(actual);
2018
- err.expected = expected = stringify(expected);
2033
+ err.actual = actual = stringify(canonicalize(actual));
2034
+ err.expected = expected = stringify(canonicalize(expected));
2019
2035
  }
2020
2036
 
2021
2037
  // actual / expected diff
2022
2038
  if ('string' == typeof actual && 'string' == typeof expected) {
2023
2039
  fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
2024
2040
  var match = message.match(/^([^:]+): expected/);
2025
- msg = match ? '\n ' + color('error message', match[1]) : '';
2041
+ msg = '\n ' + color('error message', match ? match[1] : msg);
2026
2042
 
2027
2043
  if (exports.inlineDiffs) {
2028
2044
  msg += inlineDiff(err, escape);
@@ -2280,7 +2296,7 @@ function colorLines(name, str) {
2280
2296
  /**
2281
2297
  * Stringify `obj`.
2282
2298
  *
2283
- * @param {Mixed} obj
2299
+ * @param {Object} obj
2284
2300
  * @return {String}
2285
2301
  * @api private
2286
2302
  */
@@ -2290,6 +2306,40 @@ function stringify(obj) {
2290
2306
  return JSON.stringify(obj, null, 2);
2291
2307
  }
2292
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
+
2293
2343
  /**
2294
2344
  * Check that a / b have the same type.
2295
2345
  *
@@ -2306,7 +2356,6 @@ function sameType(a, b) {
2306
2356
  }
2307
2357
 
2308
2358
 
2309
-
2310
2359
  }); // module: reporters/base.js
2311
2360
 
2312
2361
  require.register("reporters/doc.js", function(module, exports, require){
@@ -3813,10 +3862,6 @@ function Spec(runner) {
3813
3862
  if (1 == indents) console.log();
3814
3863
  });
3815
3864
 
3816
- runner.on('test', function(test){
3817
- process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
3818
- });
3819
-
3820
3865
  runner.on('pending', function(test){
3821
3866
  var fmt = indent() + color('pending', ' - %s');
3822
3867
  console.log(fmt, test.title);
@@ -4021,7 +4066,7 @@ function test(test) {
4021
4066
  var attrs = {
4022
4067
  classname: test.parent.fullTitle()
4023
4068
  , name: test.title
4024
- , time: test.duration / 1000
4069
+ , time: (test.duration / 1000) || 0
4025
4070
  };
4026
4071
 
4027
4072
  if ('failed' == test.state) {
@@ -4211,6 +4256,16 @@ Runnable.prototype.resetTimeout = function(){
4211
4256
  }, ms);
4212
4257
  };
4213
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;
4267
+ };
4268
+
4214
4269
  /**
4215
4270
  * Run the test and invoke `fn(err)`.
4216
4271
  *
@@ -4342,13 +4397,14 @@ module.exports = Runner;
4342
4397
  function Runner(suite) {
4343
4398
  var self = this;
4344
4399
  this._globals = [];
4400
+ this._abort = false;
4345
4401
  this.suite = suite;
4346
4402
  this.total = suite.total();
4347
4403
  this.failures = 0;
4348
4404
  this.on('test end', function(test){ self.checkGlobals(test); });
4349
4405
  this.on('hook end', function(hook){ self.checkGlobals(hook); });
4350
4406
  this.grep(/.*/);
4351
- this.globals(this.globalProps().concat(['errno']));
4407
+ this.globals(this.globalProps().concat(extraGlobals()));
4352
4408
  }
4353
4409
 
4354
4410
  /**
@@ -4453,13 +4509,14 @@ Runner.prototype.globals = function(arr){
4453
4509
  Runner.prototype.checkGlobals = function(test){
4454
4510
  if (this.ignoreLeaks) return;
4455
4511
  var ok = this._globals;
4512
+
4456
4513
  var globals = this.globalProps();
4457
4514
  var isNode = process.kill;
4458
4515
  var leaks;
4459
4516
 
4460
- // check length - 2 ('errno' and 'location' globals)
4461
- if (isNode && 1 == ok.length - globals.length) return;
4462
- else if (2 == ok.length - globals.length) return;
4517
+ if (test) {
4518
+ ok = ok.concat(test._allowedGlobals || []);
4519
+ }
4463
4520
 
4464
4521
  if(this.prevGlobalsLength == globals.length) return;
4465
4522
  this.prevGlobalsLength = globals.length;
@@ -4500,12 +4557,12 @@ Runner.prototype.fail = function(test, err){
4500
4557
  * - If bail, then exit
4501
4558
  * - Failed `before` hook skips all tests in a suite and subsuites,
4502
4559
  * but jumps to corresponding `after` hook
4503
- * - Failed `before each` hook skips remaining tests in a
4560
+ * - Failed `before each` hook skips remaining tests in a
4504
4561
  * suite and jumps to corresponding `after each` hook,
4505
4562
  * which is run only once
4506
4563
  * - Failed `after` hook does not alter
4507
4564
  * execution order
4508
- * - Failed `after each` hook skips remaining tests in a
4565
+ * - Failed `after each` hook skips remaining tests in a
4509
4566
  * suite and subsuites, but executes other `after each`
4510
4567
  * hooks
4511
4568
  *
@@ -4554,7 +4611,7 @@ Runner.prototype.hook = function(name, fn){
4554
4611
  var testError = hook.error();
4555
4612
  if (testError) self.fail(self.test, testError);
4556
4613
  if (err) {
4557
- self.failHook(hook, err);
4614
+ self.failHook(hook, err);
4558
4615
 
4559
4616
  // stop executing hooks, notify callee of hook err
4560
4617
  return fn(err);
@@ -4692,7 +4749,7 @@ Runner.prototype.runTests = function(suite, fn){
4692
4749
  // for failed 'after each' hook start from errSuite parent,
4693
4750
  // otherwise start from errSuite itself
4694
4751
  self.suite = after ? errSuite.parent : errSuite;
4695
-
4752
+
4696
4753
  if (self.suite) {
4697
4754
  // call hookUp afterEach
4698
4755
  self.hookUp('afterEach', function(err2, errSuite2) {
@@ -4703,7 +4760,7 @@ Runner.prototype.runTests = function(suite, fn){
4703
4760
  fn(errSuite);
4704
4761
  });
4705
4762
  } else {
4706
- // there is no need calling other 'after each' hooks
4763
+ // there is no need calling other 'after each' hooks
4707
4764
  self.suite = orig;
4708
4765
  fn(errSuite);
4709
4766
  }
@@ -4713,6 +4770,8 @@ Runner.prototype.runTests = function(suite, fn){
4713
4770
  // if we bail after first err
4714
4771
  if (self.failures && suite._bail) return fn();
4715
4772
 
4773
+ if (self._abort) return fn();
4774
+
4716
4775
  if (err) return hookErr(err, errSuite, true);
4717
4776
 
4718
4777
  // next test
@@ -4795,6 +4854,8 @@ Runner.prototype.runSuite = function(suite, fn){
4795
4854
  }
4796
4855
  }
4797
4856
 
4857
+ if (self._abort) return done();
4858
+
4798
4859
  var curr = suite.suites[i++];
4799
4860
  if (!curr) return done();
4800
4861
  self.runSuite(curr, next);
@@ -4879,6 +4940,17 @@ Runner.prototype.run = function(fn){
4879
4940
  return this;
4880
4941
  };
4881
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
+
4882
4954
  /**
4883
4955
  * Filter leaks with the given globals flagged as `ok`.
4884
4956
  *
@@ -4913,6 +4985,31 @@ function filterLeaks(ok, globals) {
4913
4985
  });
4914
4986
  }
4915
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
+
4916
5013
  }); // module: runner.js
4917
5014
 
4918
5015
  require.register("suite.js", function(module, exports, require){
@@ -5305,6 +5402,22 @@ exports.forEach = function(arr, fn, scope){
5305
5402
  fn.call(scope, arr[i], i);
5306
5403
  };
5307
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
+
5308
5421
  /**
5309
5422
  * Array#indexOf (<=IE8)
5310
5423
  *
@@ -5454,11 +5567,13 @@ exports.slug = function(str){
5454
5567
 
5455
5568
  exports.clean = function(str) {
5456
5569
  str = str
5570
+ .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
5457
5571
  .replace(/^function *\(.*\) *{/, '')
5458
5572
  .replace(/\s+\}$/, '');
5459
5573
 
5460
- var whitespace = str.match(/^\n?(\s*)/)[1]
5461
- , re = new RegExp('^' + whitespace, 'gm');
5574
+ var spaces = str.match(/^\n?( *)/)[1].length
5575
+ , tabs = str.match(/^\n?(\t*)/)[1].length
5576
+ , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
5462
5577
 
5463
5578
  str = str.replace(re, '');
5464
5579
 
@@ -5578,9 +5693,8 @@ var uncaughtExceptionHandlers = [];
5578
5693
  process.removeListener = function(e, fn){
5579
5694
  if ('uncaughtException' == e) {
5580
5695
  global.onerror = function() {};
5581
-
5582
- var indexOfFn = uncaughtExceptionHandlers.indexOf(fn);
5583
- if (indexOfFn != -1) { uncaughtExceptionHandlers.splice(indexOfFn, 1); }
5696
+ var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
5697
+ if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }
5584
5698
  }
5585
5699
  };
5586
5700
 
@@ -5592,6 +5706,7 @@ process.on = function(e, fn){
5592
5706
  if ('uncaughtException' == e) {
5593
5707
  global.onerror = function(err, url, line){
5594
5708
  fn(new Error(err + ' (' + url + ':' + line + ')'));
5709
+ return true;
5595
5710
  };
5596
5711
  uncaughtExceptionHandlers.push(fn);
5597
5712
  }
@@ -5604,6 +5719,11 @@ process.on = function(e, fn){
5604
5719
  var Mocha = global.Mocha = require('mocha'),
5605
5720
  mocha = global.mocha = new Mocha({ reporter: 'html' });
5606
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');
5726
+
5607
5727
  var immediateQueue = []
5608
5728
  , immediateTimeout;
5609
5729
 
@@ -5636,7 +5756,7 @@ Mocha.Runner.immediately = function(callback) {
5636
5756
  * only receive the 'message' attribute of the Error.
5637
5757
  */
5638
5758
  mocha.throwError = function(err) {
5639
- uncaughtExceptionHandlers.forEach(function (fn) {
5759
+ Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
5640
5760
  fn(err);
5641
5761
  });
5642
5762
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocha",
3
- "version": "1.16.0",
3
+ "version": "1.17.1",
4
4
  "description": "simple, flexible, fun test framework",
5
5
  "keywords": [
6
6
  "mocha",