Skip to content

Commit 8d06106

Browse files
committed
fix --inspect and its ilk; closes #3681
- upgrade `node-environment-flags` - add some tests - use `mocha:cli:mocha` in `bin/mocha` as unique `DEBUG` identifier (`DEBUG=mocha:cli:mocha bin/mocha ...`) - add some handiness to the integration test helpers - update docstrings in integration test helpers
1 parent c91b325 commit 8d06106

File tree

7 files changed

+164
-10
lines changed

7 files changed

+164
-10
lines changed

bin/mocha

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
const {deprecate, warn} = require('../lib/utils');
1313
const {spawn} = require('child_process');
1414
const {loadOptions} = require('../lib/cli/options');
15-
const {isNodeFlag, impliesNoTimeouts} = require('../lib/cli/node-flags');
15+
const {
16+
unparseNodeFlags,
17+
isNodeFlag,
18+
impliesNoTimeouts
19+
} = require('../lib/cli/node-flags');
1620
const unparse = require('yargs-unparser');
17-
const debug = require('debug')('mocha:cli');
21+
const debug = require('debug')('mocha:cli:mocha');
1822
const {aliases} = require('../lib/cli/run-option-metadata');
1923

2024
const mochaPath = require.resolve('./_mocha');
@@ -115,8 +119,10 @@ if (nodeArgs.gc) {
115119
delete nodeArgs.gc;
116120
}
117121

122+
debug('final node args', nodeArgs);
123+
118124
const args = [].concat(
119-
unparse(nodeArgs),
125+
unparseNodeFlags(nodeArgs),
120126
mochaPath,
121127
unparse(mochaArgs, {alias: aliases})
122128
);

lib/cli/node-flags.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
const nodeFlags = require('node-environment-flags');
10+
const unparse = require('yargs-unparser');
1011

1112
/**
1213
* These flags are considered "debug" flags.
@@ -46,3 +47,22 @@ exports.isNodeFlag = flag =>
4647
* @private
4748
*/
4849
exports.impliesNoTimeouts = flag => debugFlags.has(flag);
50+
51+
/**
52+
* All non-strictly-boolean arguments to node--those with values--must specify those values using `=`, e.g., `--inspect=0.0.0.0`.
53+
* Unparse these arguments using `yargs-unparser` (which would result in `--inspect 0.0.0.0`), then supply `=` where we have values.
54+
* There's probably an easier or more robust way to do this; fixes welcome
55+
* @param {Object} opts - Arguments object
56+
* @returns {string[]} Unparsed arguments using `=` to specify values
57+
* @private
58+
*/
59+
exports.unparseNodeFlags = opts => {
60+
var args = unparse(opts);
61+
return args.length
62+
? args
63+
.join(' ')
64+
.split(/\b/)
65+
.map(arg => (arg === ' ' ? '=' : arg))
66+
.join('')
67+
: [];
68+
};

lib/cli/options.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ module.exports.loadPkgRc = loadPkgRc;
259259
* @returns {external:yargsParser.Arguments} Parsed args from everything
260260
*/
261261
const loadOptions = (argv = []) => {
262+
// save node-specific args containing a '=' to reapply below
263+
const nodeArgOptionalValues = new Map(
264+
(Array.isArray(argv) ? argv : argv.split(' '))
265+
.filter(arg => arg.includes('='))
266+
.map(arg => arg.substring(2).split('='))
267+
);
268+
262269
let args = parse(argv);
263270
// short-circuit: look for a flag that would abort loading of mocha.opts
264271
if (
@@ -299,6 +306,11 @@ const loadOptions = (argv = []) => {
299306
delete args.spec;
300307
}
301308

309+
// reapply "=" arg values from above
310+
nodeArgOptionalValues.forEach((value, key) => {
311+
args[key] = value;
312+
});
313+
302314
return args;
303315
};
304316

lib/cli/run-option-metadata.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,15 @@ exports.types = {
4242
'recursive',
4343
'reporters',
4444
'sort',
45-
'watch'
45+
'watch',
46+
47+
// these are special-cased args for node which have optional values.
48+
// if we don't treat them as boolean, they get greedy and might eat subsequent positional arguments.
49+
// instead, we will save their "real" values before parsing via yargs-parser.
50+
'debug',
51+
'debug-brk',
52+
'inspect',
53+
'inspect-brk'
4654
],
4755
number: ['retries', 'slow', 'timeout'],
4856
string: ['fgrep', 'grep', 'package', 'reporter', 'ui']

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@
498498
"minimatch": "3.0.4",
499499
"mkdirp": "0.5.1",
500500
"ms": "2.1.1",
501-
"node-environment-flags": "1.0.2",
501+
"node-environment-flags": "1.0.4",
502502
"object.assign": "4.1.0",
503503
"strip-json-comments": "2.0.1",
504504
"supports-color": "6.0.0",

test/integration/options/debug.spec.js

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('--debug', function() {
1414

1515
it('should invoke --inspect', function(done) {
1616
invokeMocha(
17-
['--debug', '--file', DEFAULT_FIXTURE],
17+
['--debug', DEFAULT_FIXTURE],
1818
function(err, res) {
1919
if (err) {
2020
return done(err);
@@ -25,8 +25,116 @@ describe('--debug', function() {
2525
);
2626
done();
2727
},
28-
{stdio: 'pipe'}
28+
'pipe'
2929
);
3030
});
31+
32+
it('should invoke --inspect-brk', function(done) {
33+
var proc = invokeMocha(
34+
['--debug-brk', DEFAULT_FIXTURE],
35+
function(err, res) {
36+
if (err) {
37+
return done(err);
38+
}
39+
expect(res, 'to have passed').and(
40+
'to contain output',
41+
/Debugger listening/i
42+
);
43+
done();
44+
},
45+
'pipe'
46+
);
47+
48+
// debugger must be manually killed
49+
setTimeout(function() {
50+
proc.kill('SIGINT');
51+
}, 1000);
52+
});
53+
54+
it('should respect custom host/port', function(done) {
55+
invokeMocha(
56+
['--debug=127.0.0.1:9229', DEFAULT_FIXTURE],
57+
function(err, res) {
58+
if (err) {
59+
return done(err);
60+
}
61+
expect(res, 'to have passed').and(
62+
'to contain output',
63+
/Debugger listening on .*127.0.0.1:9229/i
64+
);
65+
done();
66+
},
67+
'pipe'
68+
);
69+
});
70+
71+
it('should warn about incorrect usage for version', function(done) {
72+
invokeMocha(
73+
['--debug=127.0.0.1:9229', DEFAULT_FIXTURE],
74+
function(err, res) {
75+
if (err) {
76+
return done(err);
77+
}
78+
expect(res, 'to have passed').and(
79+
'to contain output',
80+
/"--debug" is not available/i
81+
);
82+
done();
83+
},
84+
'pipe'
85+
);
86+
});
87+
});
88+
89+
describe('Node.js v6', function() {
90+
// note that v6.3.0 and newer supports --inspect but still supports --debug.
91+
before(function() {
92+
if (process.version.substring(0, 2) !== 'v6') {
93+
this.skip();
94+
}
95+
});
96+
97+
it('should start debugger', function(done) {
98+
var proc = invokeMocha(
99+
['--debug', DEFAULT_FIXTURE],
100+
function(err, res) {
101+
if (err) {
102+
return done(err);
103+
}
104+
expect(res, 'to have passed').and(
105+
'to contain output',
106+
/Debugger listening/i
107+
);
108+
done();
109+
},
110+
'pipe'
111+
);
112+
113+
// debugger must be manually killed
114+
setTimeout(function() {
115+
proc.kill('SIGINT');
116+
}, 1000);
117+
});
118+
119+
it('should respect custom host/port', function(done) {
120+
var proc = invokeMocha(
121+
['--debug=127.0.0.1:9229', DEFAULT_FIXTURE],
122+
function(err, res) {
123+
if (err) {
124+
return done(err);
125+
}
126+
expect(res, 'to have passed').and(
127+
'to contain output',
128+
/Debugger listening on .*127.0.0.1:9229/i
129+
);
130+
done();
131+
},
132+
'pipe'
133+
);
134+
135+
setTimeout(function() {
136+
proc.kill('SIGINT');
137+
}, 1000);
138+
});
31139
});
32140
});

0 commit comments

Comments
 (0)