Skip to content

Commit 352fdc2

Browse files
committed
chore(cli): throw errors on unknown flags
clsoes angular#3216
1 parent c194af8 commit 352fdc2

File tree

2 files changed

+135
-40
lines changed

2 files changed

+135
-40
lines changed

lib/cli.ts

Lines changed: 129 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -31,49 +31,138 @@ process.argv.slice(2).forEach(function(arg: string) {
3131
}
3232
});
3333

34-
optimist
35-
.usage(
36-
'Usage: protractor [configFile] [options]\n' +
37-
'configFile defaults to protractor.conf.js\n' +
38-
'The [options] object will override values from the config file.\n' +
39-
'See the reference config for a full list of options.')
40-
.describe('help', 'Print Protractor help menu')
41-
.describe('version', 'Print Protractor version')
42-
.describe('browser', 'Browsername, e.g. chrome or firefox')
43-
.describe('seleniumAddress', 'A running selenium address to use')
44-
.describe('seleniumSessionId', 'Attaching an existing session id')
45-
.describe('seleniumServerJar', 'Location of the standalone selenium jar file')
46-
.describe('seleniumPort', 'Optional port for the selenium standalone server')
47-
.describe('baseUrl', 'URL to prepend to all relative paths')
48-
.describe('rootElement', 'Element housing ng-app, if not html or body')
49-
.describe('specs', 'Comma-separated list of files to test')
50-
.describe('exclude', 'Comma-separated list of files to exclude')
51-
.describe('verbose', 'Print full spec names')
52-
.describe('stackTrace', 'Print stack trace on error')
53-
.describe('params', 'Param object to be passed to the tests')
54-
.describe('framework', 'Test framework to use: jasmine, mocha, or custom')
55-
.describe('resultJsonOutputFile', 'Path to save JSON test result')
56-
.describe('troubleshoot', 'Turn on troubleshooting output')
57-
.describe('elementExplorer', 'Interactively test Protractor commands')
58-
.describe('debuggerServerPort', 'Start a debugger server at specified port instead of repl')
59-
.alias('browser', 'capabilities.browserName')
60-
.alias('name', 'capabilities.name')
61-
.alias('platform', 'capabilities.platform')
62-
.alias('platform-version', 'capabilities.version')
63-
.alias('tags', 'capabilities.tags')
64-
.alias('build', 'capabilities.build')
65-
.alias('grep', 'jasmineNodeOpts.grep')
66-
.alias('invert-grep', 'jasmineNodeOpts.invertGrep')
67-
.alias('explorer', 'elementExplorer')
68-
.string('capabilities.tunnel-identifier')
69-
.check(function(arg: any) {
70-
if (arg._.length > 1) {
71-
throw new Error('Error: more than one config file specified');
72-
}
73-
});
34+
// TODO(cnishina): Make cli checks better.
35+
let allowedNames = [
36+
'seleniumServerJar',
37+
'seleniumServerStartTimeout',
38+
'localSeleniumStandaloneOpts',
39+
'chromeDriver',
40+
'seleniumAddress',
41+
'seleniumSessionId',
42+
'webDriverProxy',
43+
'useBlockingProxy',
44+
'sauceUser',
45+
'sauceKey',
46+
'sauceAgent',
47+
'sauceBuild',
48+
'sauceSeleniumAddress',
49+
'browserstackUser',
50+
'browserstackKey',
51+
'directConnect',
52+
'firefoxPath',
53+
'noGlobals',
54+
'specs',
55+
'exclude',
56+
'suites',
57+
'suite',
58+
'capabilities',
59+
'multiCapabilities',
60+
'getMultiCapabilities',
61+
'maxSessions',
62+
'verboseMultiSessions',
63+
'baseUrl',
64+
'rootElement',
65+
'allScriptsTimeout',
66+
'getPageTimeout',
67+
'beforeLaunch',
68+
'onPrepare',
69+
'onComplete',
70+
'onCleanUp',
71+
'afterLaunch',
72+
'params',
73+
'resultJsonOutputFile',
74+
'restartBrowserBetweenTests',
75+
'untrackOutstandingTimeouts',
76+
'ignoreUncaughtExceptions',
77+
'framework',
78+
'jasmineNodeOpts',
79+
'mochaOpts',
80+
'plugins',
81+
'skipSourceMapSupport',
82+
'disableEnvironmentOverrides',
83+
'ng12Hybrid',
84+
'seleniumArgs',
85+
'jvmArgs',
86+
'configDir',
87+
'troubleshoot',
88+
'seleniumPort',
89+
'mockSelenium',
90+
'v8Debug',
91+
'nodeDebug',
92+
'debuggerServerPort',
93+
'useAllAngular2AppRoots',
94+
'frameworkPath',
95+
'elementExplorer',
96+
'debug'
97+
];
98+
99+
let optimistOptions: any = {
100+
describes: {
101+
help: 'Print Protractor help menu',
102+
version: 'Print Protractor version',
103+
browser: 'Browsername, e.g. chrome or firefox',
104+
seleniumAddress: 'A running selenium address to use',
105+
seleniumSessionId: 'Attaching an existing session id',
106+
seleniumServerJar: 'Location of the standalone selenium jar file',
107+
seleniumPort: 'Optional port for the selenium standalone server',
108+
baseUrl: 'URL to prepend to all relative paths',
109+
rootElement: 'Element housing ng-app, if not html or body',
110+
specs: 'Comma-separated list of files to test',
111+
exclude: 'Comma-separated list of files to exclude',
112+
verbose: 'Print full spec names',
113+
stackTrace: 'Print stack trace on error',
114+
params: 'Param object to be passed to the tests',
115+
framework: 'Test framework to use: jasmine, mocha, or custom',
116+
resultJsonOutputFile: 'Path to save JSON test result',
117+
troubleshoot: 'Turn on troubleshooting output',
118+
elementExplorer: 'Interactively test Protractor commands',
119+
debuggerServerPort: 'Start a debugger server at specified port instead of repl'
120+
},
121+
aliases: {
122+
browser: 'capabilities.browserName',
123+
name: 'capabilities.name',
124+
platform: 'capabilities.platform',
125+
'platform-version': 'capabilities.version',
126+
tags: 'capabilities.tags',
127+
build: 'capabilities.build',
128+
grep: 'jasmineNodeOpts.grep',
129+
'invert-grep': 'jasmineNodeOpts.invertGrep',
130+
explorer: 'elementExplorer'
131+
},
132+
strings: {'capabilities.tunnel-identifier': ''}
133+
};
134+
135+
optimist.usage(
136+
'Usage: protractor [configFile] [options]\n' +
137+
'configFile defaults to protractor.conf.js\n' +
138+
'The [options] object will override values from the config file.\n' +
139+
'See the reference config for a full list of options.');
140+
for (let key of Object.keys(optimistOptions.describes)) {
141+
optimist.describe(key, optimistOptions.describes[key]);
142+
}
143+
for (let key of Object.keys(optimistOptions.aliases)) {
144+
optimist.alias(key, optimistOptions.aliases[key]);
145+
}
146+
for (let key of Object.keys(optimistOptions.strings)) {
147+
optimist.string(key);
148+
}
149+
optimist.check(function(arg: any) {
150+
if (arg._.length > 1) {
151+
throw new Error('Error: more than one config file specified');
152+
}
153+
});
74154

75155
let argv: any = optimist.parse(args);
76156

157+
// Check to see if additional flags were used.
158+
let unknownKeys: string[] = Object.keys(argv).slice(2).filter((element: string) => {
159+
return element !== '$0' && allowedNames.indexOf(element) === -1;
160+
});
161+
162+
if (unknownKeys.length > 0) {
163+
throw new Error('Found extra flags: ' + unknownKeys.join(', '));
164+
}
165+
77166
if (argv.help) {
78167
optimist.showHelp();
79168
process.exit(0);

scripts/errorTest.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ var checkLogs = function(output, messages) {
1919
*Below are exit failure tests*
2020
******************************/
2121

22+
runProtractor = spawn('node',
23+
['bin/protractor', '--help', '--foobar', 'foobar']);
24+
output = runProtractor.stderr.toString();
25+
messages = ['Error: Found extra flags: foobar'];
26+
checkLogs(output, messages);
27+
2228
// assert authentication error for sauce labs
2329
runProtractor = spawn('node',
2430
['bin/protractor', 'spec/errorTest/sauceLabsAuthentication.js']);

0 commit comments

Comments
 (0)