mocha 3.0.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/LICENSE +1 -1
  3. package/README.md +2 -2
  4. package/bin/_mocha +170 -104
  5. package/bin/mocha +22 -13
  6. package/bin/options.js +7 -5
  7. package/browser-entry.js +43 -22
  8. package/lib/browser/.eslintrc.yaml +4 -0
  9. package/lib/browser/debug.js +6 -3
  10. package/lib/browser/events.js +11 -9
  11. package/lib/browser/progress.js +9 -7
  12. package/lib/browser/tty.js +4 -2
  13. package/lib/context.js +11 -9
  14. package/lib/hook.js +4 -2
  15. package/lib/interfaces/bdd.js +11 -9
  16. package/lib/interfaces/common.js +16 -14
  17. package/lib/interfaces/exports.js +4 -2
  18. package/lib/interfaces/index.js +2 -0
  19. package/lib/interfaces/qunit.js +12 -8
  20. package/lib/interfaces/tdd.js +9 -7
  21. package/lib/mocha.js +36 -34
  22. package/lib/ms.js +12 -10
  23. package/lib/pending.js +2 -1
  24. package/lib/reporters/base.js +52 -50
  25. package/lib/reporters/doc.js +8 -6
  26. package/lib/reporters/dot.js +9 -7
  27. package/lib/reporters/html.js +32 -30
  28. package/lib/reporters/index.js +2 -0
  29. package/lib/reporters/json-stream.js +8 -6
  30. package/lib/reporters/json.js +11 -9
  31. package/lib/reporters/landing.js +8 -6
  32. package/lib/reporters/list.js +13 -11
  33. package/lib/reporters/markdown.js +12 -10
  34. package/lib/reporters/min.js +4 -2
  35. package/lib/reporters/nyan.js +22 -20
  36. package/lib/reporters/progress.js +7 -5
  37. package/lib/reporters/spec.js +17 -15
  38. package/lib/reporters/tap.js +10 -8
  39. package/lib/reporters/xunit.js +14 -12
  40. package/lib/runnable.js +43 -32
  41. package/lib/runner.js +78 -63
  42. package/lib/suite.js +24 -22
  43. package/lib/test.js +4 -2
  44. package/lib/utils.js +115 -90
  45. package/mocha.js +1185 -800
  46. package/package.json +9 -2
  47. package/lib/interfaces/bdd.js.orig +0 -118
  48. package/lib/mocha.js.orig +0 -532
  49. package/lib/runnable.js.orig +0 -378
  50. package/lib/runner.js.orig +0 -934
  51. package/lib/suite.js.orig +0 -418
  52. package/lib/test.js.orig +0 -52
  53. package/lib/utils.js.orig +0 -758
package/CHANGELOG.md CHANGED
@@ -1,3 +1,106 @@
1
+ # 3.2.0 / 2016-11-24
2
+
3
+ ## :newspaper: News
4
+
5
+ ### Mocha is now a JS Foundation Project!
6
+
7
+ Mocha is proud to have joined the [JS Foundation](https://js.foundation). For more information, [read the announcement](https://js.foundation/announcements/2016/10/17/Linux-Foundation-Unites-JavaScript-Community-Open-Web-Development/).
8
+
9
+ ### Contributor License Agreement
10
+
11
+ Under the foundation, all contributors to Mocha must sign the [JS Foundation CLA](https://js.foundation/CLA/) before their code can be merged. When sending a PR--if you have not already signed the CLA--a friendly bot will ask you to do so.
12
+
13
+ Mocha remains licensed under the [MIT license](https://github.com/mochajs/mocha/blob/master/LICENSE).
14
+
15
+ ## :bug: Bug Fix
16
+
17
+ - [#2535]: Fix crash when `--watch` encounters broken symlinks ([@villesau])
18
+ - [#2593]: Fix (old) regression; incorrect symbol shown in `list` reporter ([@Aldaviva])
19
+ - [#2584]: Fix potential error when running XUnit reporter ([@vobujs])
20
+
21
+ ## :tada: Enhancement
22
+
23
+ - [#2294]: Improve timeout error messaging ([@jeversmann], [@boneskull])
24
+ - [#2520]: Add info about `--inspect` flag to CLI help ([@ughitsaaron])
25
+
26
+ ## :nut_and_bolt: Other
27
+
28
+ - [#2570]: Use [karma-mocha](https://npmjs.com/package/karma-mocha) proper ([@boneskull])
29
+ - Licenses updated to reflect new copyright, add link to license and browser matrix to `README.md` ([@boneskull], [@ScottFreeCode], [@dasilvacontin])
30
+
31
+ [#2294]: https://github.com/mochajs/mocha/issues/2294
32
+ [#2535]: https://github.com/mochajs/mocha/issues/2535
33
+ [#2520]: https://github.com/mochajs/mocha/pull/2520
34
+ [#2593]: https://github.com/mochajs/mocha/pull/2593
35
+ [#2584]: https://github.com/mochajs/mocha/issues/2584
36
+ [#2570]: https://github.com/mochajs/mocha/issues/2570
37
+ [@Aldaviva]: https://github.com/Aldaviva
38
+ [@jeversmann]: https://github.com/jeversmann
39
+ [@ughitsaaron]: https://github.com/ughitsaaron
40
+ [@villesau]: https://github.com/villesau
41
+ [@vobujs]: https://github.com/vobujs
42
+
43
+ Thanks to all our contributors, sponsors and backers! Keep on the lookout for a public roadmap and new contribution guide coming soon.
44
+
45
+ # 3.1.2 / 2016-10-10
46
+
47
+ ## :bug: Bug Fix
48
+
49
+ - [#2528]: Recovery gracefully if an `Error`'s `stack` property isn't writable ([@boneskull])
50
+
51
+ [#2528]: https://github.com/mochajs/mocha/issues/2528
52
+
53
+ # 3.1.1 / 2016-10-09
54
+
55
+ ## :bug: Bug Fix
56
+
57
+ - [#1417]: Don't report `done()` was called multiple times when it wasn't ([@frankleonrose])
58
+
59
+ ## :nut_and_bolt: Other
60
+
61
+ - [#2490]: Lint with [semistandard](https://npmjs.com/package/semistandard) config ([@makepanic])
62
+ - [#2525]: Lint all `.js` files ([@boneskull])
63
+ - [#2524]: Provide workaround for developers unable to run browser tests on macOS Sierra ([@boneskull])
64
+
65
+ [#1417]: https://github.com/mochajs/mocha/issues/1417
66
+ [#2490]: https://github.com/mochajs/mocha/issues/2490
67
+ [#2525]: https://github.com/mochajs/mocha/issues/2525
68
+ [#2524]: https://github.com/mochajs/mocha/issues/2524
69
+ [@makepanic]: https://github.com/makepanic
70
+ [@frankleonrose]: https://github.com/frankleonrose
71
+
72
+ # 3.1.0 / 2016-09-27
73
+
74
+ ## :tada: Enhancement
75
+
76
+ - [#2357]: Support `--inspect` on command-line ([@simov])
77
+ - [#2194]: Human-friendly error if no files are matched on command-line ([@Munter])
78
+ - [#1744]: Human-friendly error if a Suite has no callback (BDD/TDD only) ([@anton])
79
+
80
+ ## :bug: Bug Fix
81
+
82
+ - [#2488]: Fix case in which *variables beginning with lowercase "D"* may not have been reported properly as global leaks ([@JustATrick]) :laughing:
83
+ - [#2465]: Always halt execution in async function when `this.skip()` is called ([@boneskull])
84
+ - [#2445]: Exits with expected code 130 when `SIGINT` encountered; exit code can no longer rollover at 256 ([@Munter])
85
+ - [#2315]: Fix uncaught TypeError thrown from callback stack ([@1999])
86
+ - Fix broken `only()`/`skip()` in IE7/IE8 ([@boneskull])
87
+ - [#2502]: Fix broken stack trace filter on Node.js under Windows ([@boneskull])
88
+ - [#2496]: Fix diff output for objects instantiated with `String` constructor ([more](https://youtrack.jetbrains.com/issue/WEB-23383)) ([@boneskull])
89
+
90
+ [#2496]: https://github.com/mochajs/mocha/issues/2496
91
+ [#2502]: https://github.com/mochajs/mocha/issues/2502
92
+ [#2315]: https://github.com/mochajs/mocha/issues/2315
93
+ [#2445]: https://github.com/mochajs/mocha/pull/2445
94
+ [#2465]: https://github.com/mochajs/mocha/issues/2465
95
+ [#2488]: https://github.com/mochajs/mocha/issues/2488
96
+ [#1744]: https://github.com/mochajs/mocha/issues/1744
97
+ [#2194]: https://github.com/mochajs/mocha/issues/2194
98
+ [#2357]: https://github.com/mochajs/mocha/issues/2357
99
+ [@1999]: https://github.com/1999
100
+ [@JustATrick]: https://github.com/JustATrick
101
+ [@anton]: https://github.com/anton
102
+ [@simov]: https://github.com/simov
103
+
1
104
  # 3.0.2 / 2016-08-08
2
105
 
3
106
  ## :bug: Bug Fix
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2011-2016 TJ Holowaychuk <tj@vision-media.ca>
3
+ Copyright (c) 2016 JS Foundation and contributors, https://js.foundation
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
  <p align="center">
3
3
  <img src="https://cldup.com/xFVFxOioAU.svg" alt="Mocha test framework"/>
4
4
  </p>
5
- <br><br>
6
5
 
7
6
  [![Build Status](https://api.travis-ci.org/mochajs/mocha.svg?branch=master)](http://travis-ci.org/mochajs/mocha) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mochajs/mocha?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
7
  [![OpenCollective](https://opencollective.com/mochajs/backers/badge.svg)](#backers)
9
8
  [![OpenCollective](https://opencollective.com/mochajs/sponsors/badge.svg)](#sponsors)
9
+ <br><img alt="Mocha Browser Support h/t SauceLabs" src="https://saucelabs.com/browser-matrix/mochajs.svg" width="354">
10
10
 
11
11
  Mocha is a simple, flexible, fun JavaScript test framework for node.js and the browser. For more information view the [documentation](http://mochajs.org).
12
12
 
@@ -81,4 +81,4 @@ Does your company use Mocha? Ask your manager or marketing team if your company
81
81
 
82
82
  ## License
83
83
 
84
- MIT
84
+ [MIT](LICENSE)
package/bin/_mocha CHANGED
@@ -1,31 +1,34 @@
1
1
  #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /* eslint no-unused-vars: off */
2
5
 
3
6
  /**
4
7
  * Module dependencies.
5
8
  */
6
9
 
7
- var program = require('commander'),
8
- path = require('path'),
9
- fs = require('fs'),
10
- resolve = path.resolve,
11
- exists = fs.existsSync || path.existsSync,
12
- Mocha = require('../'),
13
- utils = Mocha.utils,
14
- interfaceNames = Object.keys(Mocha.interfaces),
15
- join = path.join,
16
- cwd = process.cwd(),
17
- getOptions = require('./options'),
18
- mocha = new Mocha;
10
+ var program = require('commander');
11
+ var path = require('path');
12
+ var fs = require('fs');
13
+ var resolve = path.resolve;
14
+ var exists = fs.existsSync || path.existsSync;
15
+ var Mocha = require('../');
16
+ var utils = Mocha.utils;
17
+ var interfaceNames = Object.keys(Mocha.interfaces);
18
+ var join = path.join;
19
+ var cwd = process.cwd();
20
+ var getOptions = require('./options');
21
+ var mocha = new Mocha();
19
22
 
20
23
  /**
21
24
  * Save timer references to avoid Sinon interfering (see GH-237).
22
25
  */
23
26
 
24
- var Date = global.Date
25
- , setTimeout = global.setTimeout
26
- , setInterval = global.setInterval
27
- , clearTimeout = global.clearTimeout
28
- , clearInterval = global.clearInterval;
27
+ var Date = global.Date;
28
+ var setTimeout = global.setTimeout;
29
+ var setInterval = global.setInterval;
30
+ var clearTimeout = global.clearTimeout;
31
+ var clearInterval = global.clearInterval;
29
32
 
30
33
  /**
31
34
  * Files.
@@ -50,23 +53,23 @@ var requires = [];
50
53
  */
51
54
 
52
55
  var images = {
53
- fail: __dirname + '/../images/error.png'
54
- , pass: __dirname + '/../images/ok.png'
56
+ fail: path.join(__dirname, '..', 'images', 'error.png'),
57
+ pass: path.join(__dirname, '..', 'images', 'ok.png')
55
58
  };
56
59
 
57
60
  // options
58
61
 
59
62
  program
60
- .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version)
63
+ .version(JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')).version)
61
64
  .usage('[debug] [options] [files]')
62
- .option('-A, --async-only', "force all tests to take a callback (async) or return a promise")
65
+ .option('-A, --async-only', 'force all tests to take a callback (async) or return a promise')
63
66
  .option('-c, --colors', 'force enabling of colors')
64
67
  .option('-C, --no-colors', 'force disabling of colors')
65
68
  .option('-G, --growl', 'enable growl notification support')
66
69
  .option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
67
70
  .option('-R, --reporter <name>', 'specify the reporter to use', 'spec')
68
- .option('-S, --sort', "sort test files")
69
- .option('-b, --bail', "bail after first test failure")
71
+ .option('-S, --sort', 'sort test files')
72
+ .option('-b, --bail', 'bail after first test failure')
70
73
  .option('-d, --debug', "enable node's debugger, synonym for node --debug")
71
74
  .option('-g, --grep <pattern>', 'only run tests matching <pattern>')
72
75
  .option('-f, --fgrep <string>', 'only run tests containing <string>')
@@ -87,6 +90,7 @@ program
87
90
  .option('--preserve-symlinks', 'Instructs the module loader to preserve symbolic links when resolving and caching modules')
88
91
  .option('--icu-data-dir', 'include ICU data')
89
92
  .option('--inline-diffs', 'display actual/expected differences inline within each string')
93
+ .option('--inspect', 'activate devtools in chrome')
90
94
  .option('--interfaces', 'display available interfaces')
91
95
  .option('--no-deprecation', 'silence deprecation warnings')
92
96
  .option('--no-exit', 'require a clean shutdown of the event loop: mocha will not call process.exit')
@@ -103,7 +107,7 @@ program
103
107
  .option('--trace-deprecation', 'show stack traces on deprecations')
104
108
  .option('--use_strict', 'enforce strict mode')
105
109
  .option('--watch-extensions <ext>,...', 'additional extensions to monitor with --watch', list, [])
106
- .option('--delay', 'wait for async suite definition')
110
+ .option('--delay', 'wait for async suite definition');
107
111
 
108
112
  program._name = 'mocha';
109
113
 
@@ -112,7 +116,7 @@ program._name = 'mocha';
112
116
  program
113
117
  .command('init <path>')
114
118
  .description('initialize a client-side mocha setup at <path>')
115
- .action(function(path){
119
+ .action(function (path) {
116
120
  var mkdir = require('mkdirp');
117
121
  mkdir.sync(path);
118
122
  var css = fs.readFileSync(join(__dirname, '..', 'mocha.css'));
@@ -127,13 +131,13 @@ program
127
131
 
128
132
  // --globals
129
133
 
130
- program.on('globals', function(val){
134
+ program.on('globals', function (val) {
131
135
  globals = globals.concat(list(val));
132
136
  });
133
137
 
134
138
  // --reporters
135
139
 
136
- program.on('reporters', function(){
140
+ program.on('reporters', function () {
137
141
  console.log();
138
142
  console.log(' dot - dot matrix');
139
143
  console.log(' doc - html documentation');
@@ -154,9 +158,9 @@ program.on('reporters', function(){
154
158
 
155
159
  // --interfaces
156
160
 
157
- program.on('interfaces', function(){
161
+ program.on('interfaces', function () {
158
162
  console.log('');
159
- interfaceNames.forEach(function(interfaceName) {
163
+ interfaceNames.forEach(function (interfaceName) {
160
164
  console.log(' ' + interfaceName);
161
165
  });
162
166
  console.log('');
@@ -167,9 +171,11 @@ program.on('interfaces', function(){
167
171
 
168
172
  module.paths.push(cwd, join(cwd, 'node_modules'));
169
173
 
170
- program.on('require', function(mod){
174
+ program.on('require', function (mod) {
171
175
  var abs = exists(mod) || exists(mod + '.js');
172
- if (abs) mod = resolve(mod);
176
+ if (abs) {
177
+ mod = resolve(mod);
178
+ }
173
179
  requires.push(mod);
174
180
  });
175
181
 
@@ -190,16 +196,16 @@ Error.stackTraceLimit = Infinity; // TODO: config
190
196
 
191
197
  var reporterOptions = {};
192
198
  if (program.reporterOptions !== undefined) {
193
- program.reporterOptions.split(",").forEach(function(opt) {
194
- var L = opt.split("=");
195
- if (L.length > 2 || L.length === 0) {
196
- throw new Error("invalid reporter option '" + opt + "'");
197
- } else if (L.length === 2) {
198
- reporterOptions[L[0]] = L[1];
199
- } else {
200
- reporterOptions[L[0]] = true;
201
- }
202
- });
199
+ program.reporterOptions.split(',').forEach(function (opt) {
200
+ var L = opt.split('=');
201
+ if (L.length > 2 || L.length === 0) {
202
+ throw new Error("invalid reporter option '" + opt + "'");
203
+ } else if (L.length === 2) {
204
+ reporterOptions[L[0]] = L[1];
205
+ } else {
206
+ reporterOptions[L[0]] = true;
207
+ }
208
+ });
203
209
  }
204
210
 
205
211
  // reporter
@@ -214,37 +220,46 @@ try {
214
220
  } catch (err) {
215
221
  try {
216
222
  Reporter = require(program.reporter);
217
- } catch (err) {
223
+ } catch (err2) {
218
224
  throw new Error('reporter "' + program.reporter + '" does not exist');
219
225
  }
220
226
  }
221
227
 
222
228
  // --no-colors
223
229
 
224
- if (!program.colors) mocha.useColors(false);
230
+ if (!program.colors) {
231
+ mocha.useColors(false);
232
+ }
225
233
 
226
234
  // --colors
227
235
 
228
- if (~process.argv.indexOf('--colors') ||
229
- ~process.argv.indexOf('-c')) {
236
+ if (~process.argv.indexOf('--colors') || ~process.argv.indexOf('-c')) {
230
237
  mocha.useColors(true);
231
238
  }
232
239
 
233
240
  // --inline-diffs
234
241
 
235
- if (program.inlineDiffs) mocha.useInlineDiffs(true);
242
+ if (program.inlineDiffs) {
243
+ mocha.useInlineDiffs(true);
244
+ }
236
245
 
237
246
  // --slow <ms>
238
247
 
239
- if (program.slow) mocha.suite.slow(program.slow);
248
+ if (program.slow) {
249
+ mocha.suite.slow(program.slow);
250
+ }
240
251
 
241
252
  // --no-timeouts
242
253
 
243
- if (!program.timeouts) mocha.enableTimeouts(false);
254
+ if (!program.timeouts) {
255
+ mocha.enableTimeouts(false);
256
+ }
244
257
 
245
258
  // --timeout
246
259
 
247
- if (program.timeout) mocha.suite.timeout(program.timeout);
260
+ if (program.timeout) {
261
+ mocha.suite.timeout(program.timeout);
262
+ }
248
263
 
249
264
  // --bail
250
265
 
@@ -252,35 +267,51 @@ mocha.suite.bail(program.bail);
252
267
 
253
268
  // --grep
254
269
 
255
- if (program.grep) mocha.grep(program.grep);
270
+ if (program.grep) {
271
+ mocha.grep(program.grep);
272
+ }
256
273
 
257
274
  // --fgrep
258
275
 
259
- if (program.fgrep) mocha.fgrep(program.fgrep);
276
+ if (program.fgrep) {
277
+ mocha.fgrep(program.fgrep);
278
+ }
260
279
 
261
280
  // --invert
262
281
 
263
- if (program.invert) mocha.invert();
282
+ if (program.invert) {
283
+ mocha.invert();
284
+ }
264
285
 
265
286
  // --check-leaks
266
287
 
267
- if (program.checkLeaks) mocha.checkLeaks();
288
+ if (program.checkLeaks) {
289
+ mocha.checkLeaks();
290
+ }
268
291
 
269
292
  // --stack-trace
270
293
 
271
- if(program.fullTrace) mocha.fullTrace();
294
+ if (program.fullTrace) {
295
+ mocha.fullTrace();
296
+ }
272
297
 
273
298
  // --growl
274
299
 
275
- if (program.growl) mocha.growl();
300
+ if (program.growl) {
301
+ mocha.growl();
302
+ }
276
303
 
277
304
  // --async-only
278
305
 
279
- if (program.asyncOnly) mocha.asyncOnly();
306
+ if (program.asyncOnly) {
307
+ mocha.asyncOnly();
308
+ }
280
309
 
281
310
  // --delay
282
311
 
283
- if (program.delay) mocha.delay();
312
+ if (program.delay) {
313
+ mocha.delay();
314
+ }
284
315
 
285
316
  // --globals
286
317
 
@@ -288,17 +319,21 @@ mocha.globals(globals);
288
319
 
289
320
  // --retries
290
321
 
291
- if (program.retries) mocha.suite.retries(program.retries);
322
+ if (program.retries) {
323
+ mocha.suite.retries(program.retries);
324
+ }
292
325
 
293
326
  // custom compiler support
294
327
 
295
328
  var extensions = ['js'];
296
- program.compilers.forEach(function(c) {
297
- var idx = c.indexOf(':')
298
- , ext = c.slice(0, idx)
299
- , mod = c.slice(idx + 1);
329
+ program.compilers.forEach(function (c) {
330
+ var idx = c.indexOf(':');
331
+ var ext = c.slice(0, idx);
332
+ var mod = c.slice(idx + 1);
300
333
 
301
- if (mod[0] == '.') mod = join(process.cwd(), mod);
334
+ if (mod[0] === '.') {
335
+ mod = join(process.cwd(), mod);
336
+ }
302
337
  require(mod);
303
338
  extensions.push(ext);
304
339
  program.watchExtensions.push(ext);
@@ -306,7 +341,7 @@ program.compilers.forEach(function(c) {
306
341
 
307
342
  // requires
308
343
 
309
- requires.forEach(function(mod) {
344
+ requires.forEach(function (mod) {
310
345
  require(mod);
311
346
  });
312
347
 
@@ -314,21 +349,40 @@ requires.forEach(function(mod) {
314
349
 
315
350
  mocha.ui(program.ui);
316
351
 
317
- //args
352
+ // args
318
353
 
319
354
  var args = program.args;
320
355
 
321
356
  // default files to test/*.{js,coffee}
322
357
 
323
- if (!args.length) args.push('test');
358
+ if (!args.length) {
359
+ args.push('test');
360
+ }
361
+
362
+ args.forEach(function (arg) {
363
+ var newFiles;
364
+ try {
365
+ newFiles = utils.lookupFiles(arg, extensions, program.recursive);
366
+ } catch (err) {
367
+ if (err.message.indexOf('cannot resolve path') === 0) {
368
+ console.error('Warning: Could not find any test files matching pattern: ' + arg);
369
+ return;
370
+ }
324
371
 
325
- args.forEach(function(arg){
326
- files = files.concat(utils.lookupFiles(arg, extensions, program.recursive));
372
+ throw err;
373
+ }
374
+
375
+ files = files.concat(newFiles);
327
376
  });
328
377
 
378
+ if (!files.length) {
379
+ console.error('No test files found');
380
+ process.exit(1);
381
+ }
382
+
329
383
  // resolve
330
384
 
331
- files = files.map(function(path){
385
+ files = files.map(function (path) {
332
386
  return resolve(path);
333
387
  });
334
388
 
@@ -339,54 +393,58 @@ if (program.sort) {
339
393
  // --watch
340
394
 
341
395
  var runner;
396
+ var loadAndRun;
397
+ var purge;
398
+ var rerun;
399
+
342
400
  if (program.watch) {
343
401
  console.log();
344
402
  hideCursor();
345
- process.on('SIGINT', function(){
403
+ process.on('SIGINT', function () {
346
404
  showCursor();
347
405
  console.log('\n');
348
- process.exit();
406
+ process.exit(130);
349
407
  });
350
408
 
351
-
352
409
  var watchFiles = utils.files(cwd, [ 'js' ].concat(program.watchExtensions));
353
410
  var runAgain = false;
354
411
 
355
- function loadAndRun() {
412
+ loadAndRun = function loadAndRun () {
356
413
  try {
357
414
  mocha.files = files;
358
415
  runAgain = false;
359
- runner = mocha.run(function(){
416
+ runner = mocha.run(function () {
360
417
  runner = null;
361
418
  if (runAgain) {
362
419
  rerun();
363
420
  }
364
421
  });
365
- } catch(e) {
422
+ } catch (e) {
366
423
  console.log(e.stack);
367
424
  }
368
- }
425
+ };
369
426
 
370
- function purge() {
371
- watchFiles.forEach(function(file){
427
+ purge = function purge () {
428
+ watchFiles.forEach(function (file) {
372
429
  delete require.cache[file];
373
430
  });
374
- }
431
+ };
375
432
 
376
433
  loadAndRun();
377
434
 
378
- function rerun() {
435
+ rerun = function rerun () {
379
436
  purge();
380
- stop()
381
- if (!program.grep)
437
+ stop();
438
+ if (!program.grep) {
382
439
  mocha.grep(null);
440
+ }
383
441
  mocha.suite = mocha.suite.clone();
384
- mocha.suite.ctx = new Mocha.Context;
442
+ mocha.suite.ctx = new Mocha.Context();
385
443
  mocha.ui(program.ui);
386
444
  loadAndRun();
387
- }
445
+ };
388
446
 
389
- utils.watch(watchFiles, function(){
447
+ utils.watch(watchFiles, function () {
390
448
  runAgain = true;
391
449
  if (runner) {
392
450
  runner.abort();
@@ -394,32 +452,33 @@ if (program.watch) {
394
452
  rerun();
395
453
  }
396
454
  });
397
-
398
455
  } else {
399
-
400
456
  // load
401
457
 
402
458
  mocha.files = files;
403
459
  runner = mocha.run(program.exit ? exit : exitLater);
404
-
405
460
  }
406
461
 
407
- function exitLater(code) {
408
- process.on('exit', function() { process.exit(code) })
462
+ function exitLater (code) {
463
+ process.on('exit', function () {
464
+ process.exit(Math.min(code, 255));
465
+ });
409
466
  }
410
467
 
411
- function exit(code) {
468
+ function exit (code) {
412
469
  // flush output for Node.js Windows pipe bug
413
470
  // https://github.com/joyent/node/issues/6247 is just one bug example
414
471
  // https://github.com/visionmedia/mocha/issues/333 has a good discussion
415
- function done() {
416
- if (!(draining--)) process.exit(code);
472
+ function done () {
473
+ if (!(draining--)) {
474
+ process.exit(Math.min(code, 255));
475
+ }
417
476
  }
418
477
 
419
478
  var draining = 0;
420
479
  var streams = [process.stdout, process.stderr];
421
480
 
422
- streams.forEach(function(stream){
481
+ streams.forEach(function (stream) {
423
482
  // submit empty write request and wait for completion
424
483
  draining += 1;
425
484
  stream.write('', done);
@@ -428,13 +487,20 @@ function exit(code) {
428
487
  done();
429
488
  }
430
489
 
431
- process.on('SIGINT', function() { runner.abort(); })
490
+ process.on('SIGINT', function () {
491
+ runner.abort();
492
+
493
+ // This is a hack:
494
+ // Instead of `process.exit(130)`, set runner.failures to 130 (exit code for SIGINT)
495
+ // The amount of failures will be emitted as error code later
496
+ runner.failures = 130;
497
+ });
432
498
 
433
499
  /**
434
500
  * Parse list.
435
501
  */
436
502
 
437
- function list(str) {
503
+ function list (str) {
438
504
  return str.split(/ *, */);
439
505
  }
440
506
 
@@ -442,7 +508,7 @@ function list(str) {
442
508
  * Hide the cursor.
443
509
  */
444
510
 
445
- function hideCursor(){
511
+ function hideCursor () {
446
512
  process.stdout.write('\u001b[?25l');
447
513
  }
448
514
 
@@ -450,7 +516,7 @@ function hideCursor(){
450
516
  * Show the cursor.
451
517
  */
452
518
 
453
- function showCursor(){
519
+ function showCursor () {
454
520
  process.stdout.write('\u001b[?25h');
455
521
  }
456
522
 
@@ -458,7 +524,7 @@ function showCursor(){
458
524
  * Stop play()ing.
459
525
  */
460
526
 
461
- function stop() {
527
+ function stop () {
462
528
  process.stdout.write('\u001b[2K');
463
529
  clearInterval(play.timer);
464
530
  }
@@ -467,12 +533,12 @@ function stop() {
467
533
  * Play the given array of strings.
468
534
  */
469
535
 
470
- function play(arr, interval) {
471
- var len = arr.length
472
- , interval = interval || 100
473
- , i = 0;
536
+ function play (arr, interval) {
537
+ var len = arr.length;
538
+ interval = interval || 100;
539
+ var i = 0;
474
540
 
475
- play.timer = setInterval(function(){
541
+ play.timer = setInterval(function () {
476
542
  var str = arr[i++ % len];
477
543
  process.stdout.write('\u001b[0G' + str);
478
544
  }, interval);