Skip to content

Commit 5a201ec

Browse files
authored
Add getOptionValueSourceWithGlobals for completeness. (#1832)
1 parent 0ae5b2f commit 5a201ec

File tree

4 files changed

+136
-57
lines changed

4 files changed

+136
-57
lines changed

lib/command.js

+19
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,25 @@ Expecting one of '${allowedValues.join("', '")}'`);
814814
return this._optionValueSources[key];
815815
}
816816

817+
/**
818+
* Get source of option value. See also .optsWithGlobals().
819+
* Expected values are default | config | env | cli | implied
820+
*
821+
* @param {string} key
822+
* @return {string}
823+
*/
824+
825+
getOptionValueSourceWithGlobals(key) {
826+
// global overwrites local, like optsWithGlobals
827+
let source;
828+
getCommandAndParents(this).forEach((cmd) => {
829+
if (cmd.getOptionValueSource(key) !== undefined) {
830+
source = cmd.getOptionValueSource(key);
831+
}
832+
});
833+
return source;
834+
}
835+
817836
/**
818837
* Get user arguments from implied or explicit arguments.
819838
* Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.

tests/options.optsWithGlobals.test.js

+108-56
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,115 @@
11
const commander = require('../');
22

3-
test('when variety of options used with program then opts is same as optsWithGlobals', () => {
4-
const program = new commander.Command();
5-
program
6-
.option('-b, --boolean')
7-
.option('-r, --require-value <value)')
8-
.option('-f, --float <value>', 'description', parseFloat)
9-
.option('-d, --default-value <value)', 'description', 'default value')
10-
.option('-n, --no-something');
11-
12-
program.parse(['-b', '-r', 'req', '-f', '1e2'], { from: 'user' });
13-
expect(program.opts()).toEqual(program.optsWithGlobals());
14-
});
3+
// Testing optsWithGlobals and getOptionValueSourceWithGlobals with focus on globals.
154

16-
test('when options in sub and program then optsWithGlobals includes both', () => {
17-
const program = new commander.Command();
18-
let mergedOptions;
19-
program
20-
.option('-g, --global <value>');
21-
program
22-
.command('sub')
23-
.option('-l, --local <value)')
24-
.action((options, cmd) => {
25-
mergedOptions = cmd.optsWithGlobals();
26-
});
27-
28-
program.parse(['-g', 'GGG', 'sub', '-l', 'LLL'], { from: 'user' });
29-
expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });
30-
});
5+
describe('optsWithGlobals', () => {
6+
test('when variety of options used with program then opts is same as optsWithGlobals', () => {
7+
const program = new commander.Command();
8+
program
9+
.option('-b, --boolean')
10+
.option('-r, --require-value <value)')
11+
.option('-f, --float <value>', 'description', parseFloat)
12+
.option('-d, --default-value <value)', 'description', 'default value')
13+
.option('-n, --no-something');
14+
15+
program.parse(['-b', '-r', 'req', '-f', '1e2'], { from: 'user' });
16+
expect(program.opts()).toEqual(program.optsWithGlobals());
17+
});
18+
19+
test('when options in sub and program then optsWithGlobals includes both', () => {
20+
const program = new commander.Command();
21+
let mergedOptions;
22+
program
23+
.option('-g, --global <value>');
24+
program
25+
.command('sub')
26+
.option('-l, --local <value)')
27+
.action((options, cmd) => {
28+
mergedOptions = cmd.optsWithGlobals();
29+
});
30+
31+
program.parse(['-g', 'GGG', 'sub', '-l', 'LLL'], { from: 'user' });
32+
expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });
33+
});
34+
35+
test('when options in sub and subsub then optsWithGlobals includes both', () => {
36+
const program = new commander.Command();
37+
let mergedOptions;
38+
program
39+
.command('sub')
40+
.option('-g, --global <value)')
41+
.command('subsub')
42+
.option('-l, --local <value)')
43+
.action((options, cmd) => {
44+
mergedOptions = cmd.optsWithGlobals();
45+
});
46+
47+
program.parse(['sub', '-g', 'GGG', 'subsub', '-l', 'LLL'], { from: 'user' });
48+
expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });
49+
});
50+
51+
test('when same named option in sub and program then optsWithGlobals includes global', () => {
52+
const program = new commander.Command();
53+
let mergedOptions;
54+
program
55+
.option('-c, --common <value>')
56+
.enablePositionalOptions();
57+
program
58+
.command('sub')
59+
.option('-c, --common <value)')
60+
.action((options, cmd) => {
61+
mergedOptions = cmd.optsWithGlobals();
62+
});
3163

32-
test('when options in sub and subsub then optsWithGlobals includes both', () => {
33-
const program = new commander.Command();
34-
let mergedOptions;
35-
program
36-
.command('sub')
37-
.option('-g, --global <value)')
38-
.command('subsub')
39-
.option('-l, --local <value)')
40-
.action((options, cmd) => {
41-
mergedOptions = cmd.optsWithGlobals();
42-
});
43-
44-
program.parse(['sub', '-g', 'GGG', 'subsub', '-l', 'LLL'], { from: 'user' });
45-
expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });
64+
program.parse(['-c', 'GGG', 'sub', '-c', 'LLL'], { from: 'user' });
65+
expect(mergedOptions).toEqual({ common: 'GGG' });
66+
});
4667
});
4768

48-
test('when same named option in sub and program then optsWithGlobals includes global', () => {
49-
const program = new commander.Command();
50-
let mergedOptions;
51-
program
52-
.option('-c, --common <value>')
53-
.enablePositionalOptions();
54-
program
55-
.command('sub')
56-
.option('-c, --common <value)')
57-
.action((options, cmd) => {
58-
mergedOptions = cmd.optsWithGlobals();
59-
});
60-
61-
program.parse(['-c', 'GGG', 'sub', '-c', 'LLL'], { from: 'user' });
62-
expect(mergedOptions).toEqual({ common: 'GGG' });
69+
describe('getOptionValueSourceWithGlobals', () => {
70+
test('when option used with simple command then source is defined', () => {
71+
const program = new commander.Command();
72+
program
73+
.option('-g, --global');
74+
75+
program.parse(['-g'], { from: 'user' });
76+
expect(program.getOptionValueSourceWithGlobals('global')).toEqual('cli');
77+
});
78+
79+
test('when option used with program then source is defined', () => {
80+
const program = new commander.Command();
81+
program
82+
.option('-g, --global');
83+
const sub = program.command('sub')
84+
.option('-l, --local')
85+
.action(() => {});
86+
87+
program.parse(['sub', '-g'], { from: 'user' });
88+
expect(sub.getOptionValueSourceWithGlobals('global')).toEqual('cli');
89+
});
90+
91+
test('when option used with subcommand then source is defined', () => {
92+
const program = new commander.Command();
93+
program
94+
.option('-g, --global');
95+
const sub = program.command('sub')
96+
.option('-l, --local')
97+
.action(() => {});
98+
99+
program.parse(['sub', '-l'], { from: 'user' });
100+
expect(sub.getOptionValueSourceWithGlobals('local')).toEqual('cli');
101+
});
102+
103+
test('when same named option in sub and program then source is defined by global', () => {
104+
const program = new commander.Command();
105+
program
106+
.enablePositionalOptions()
107+
.option('-c, --common <value>', 'description', 'default value');
108+
const sub = program.command('sub')
109+
.option('-c, --common <value>')
110+
.action(() => {});
111+
112+
program.parse(['sub', '--common', 'value'], { from: 'user' });
113+
expect(sub.getOptionValueSourceWithGlobals('common')).toEqual('default');
114+
});
63115
});

typings/index.d.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -600,10 +600,15 @@ export class Command {
600600
setOptionValueWithSource(key: string, value: unknown, source: OptionValueSource): this;
601601

602602
/**
603-
* Retrieve option value source.
603+
* Get source of option value.
604604
*/
605605
getOptionValueSource(key: string): OptionValueSource | undefined;
606606

607+
/**
608+
* Get source of option value. See also .optsWithGlobals().
609+
*/
610+
getOptionValueSourceWithGlobals(key: string): OptionValueSource | undefined;
611+
607612
/**
608613
* Alter parsing of short flags with optional values.
609614
*

typings/index.test-d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ expectType<commander.Command>(program.setOptionValueWithSource('example', [], 'c
174174
// getOptionValueSource
175175
expectType<commander.OptionValueSource | undefined>(program.getOptionValueSource('example'));
176176

177+
// getOptionValueSourceWithGlobals
178+
expectType<commander.OptionValueSource | undefined>(program.getOptionValueSourceWithGlobals('example'));
179+
177180
// combineFlagAndOptionalValue
178181
expectType<commander.Command>(program.combineFlagAndOptionalValue());
179182
expectType<commander.Command>(program.combineFlagAndOptionalValue(false));

0 commit comments

Comments
 (0)