1 | import fs from 'fs';
|
2 | import path from 'path';
|
3 | import _ from 'lodash';
|
4 | import { ArgumentParser } from 'argparse';
|
5 | import { rootDir } from './utils';
|
6 | import { DEFAULT_BASE_PATH } from 'appium-base-driver';
|
7 |
|
8 | const args = [
|
9 | [['--shell'], {
|
10 | required: false,
|
11 | defaultValue: null,
|
12 | help: 'Enter REPL mode',
|
13 | nargs: 0,
|
14 | dest: 'shell',
|
15 | }],
|
16 |
|
17 | [['--allow-cors'], {
|
18 | required: false,
|
19 | defaultValue: false,
|
20 | action: 'storeTrue',
|
21 | help: 'Whether the Appium server should allow web browser connections from any host',
|
22 | nargs: 0,
|
23 | dest: 'allowCors',
|
24 | }],
|
25 |
|
26 | [['--reboot'], {
|
27 | defaultValue: false,
|
28 | dest: 'reboot',
|
29 | action: 'storeTrue',
|
30 | required: false,
|
31 | help: '(Android-only) reboot emulator after each session and kill it at the end',
|
32 | nargs: 0,
|
33 | }],
|
34 |
|
35 | [['--ipa'], {
|
36 | required: false,
|
37 | defaultValue: null,
|
38 | help: '(IOS-only) abs path to compiled .ipa file',
|
39 | example: '/abs/path/to/my.ipa',
|
40 | dest: 'ipa',
|
41 | }],
|
42 |
|
43 | [['-a', '--address'], {
|
44 | defaultValue: '0.0.0.0',
|
45 | required: false,
|
46 | example: '0.0.0.0',
|
47 | help: 'IP Address to listen on',
|
48 | dest: 'address',
|
49 | }],
|
50 |
|
51 | [['-p', '--port'], {
|
52 | defaultValue: 4723,
|
53 | required: false,
|
54 | type: 'int',
|
55 | example: '4723',
|
56 | help: 'port to listen on',
|
57 | dest: 'port',
|
58 | }],
|
59 |
|
60 | [['-pa', '--base-path'], {
|
61 | required: false,
|
62 | defaultValue: DEFAULT_BASE_PATH,
|
63 | dest: 'basePath',
|
64 | example: '/path/prefix',
|
65 | help: 'Base path to use as the prefix for all webdriver routes running' +
|
66 | `on this server (default: ${DEFAULT_BASE_PATH})`
|
67 | }],
|
68 |
|
69 | [['-ca', '--callback-address'], {
|
70 | required: false,
|
71 | dest: 'callbackAddress',
|
72 | defaultValue: null,
|
73 | example: '127.0.0.1',
|
74 | help: 'callback IP Address (default: same as --address)',
|
75 | }],
|
76 |
|
77 | [['-cp', '--callback-port'], {
|
78 | required: false,
|
79 | dest: 'callbackPort',
|
80 | defaultValue: null,
|
81 | type: 'int',
|
82 | example: '4723',
|
83 | help: 'callback port (default: same as port)',
|
84 | }],
|
85 |
|
86 | [['-bp', '--bootstrap-port'], {
|
87 | defaultValue: 4724,
|
88 | dest: 'bootstrapPort',
|
89 | required: false,
|
90 | type: 'int',
|
91 | example: '4724',
|
92 | help: '(Android-only) port to use on device to talk to Appium',
|
93 | }],
|
94 |
|
95 | [['-r', '--backend-retries'], {
|
96 | defaultValue: 3,
|
97 | dest: 'backendRetries',
|
98 | required: false,
|
99 | type: 'int',
|
100 | example: '3',
|
101 | help: '(iOS-only) How many times to retry launching Instruments ' +
|
102 | 'before saying it crashed or timed out',
|
103 | }],
|
104 |
|
105 | [['--session-override'], {
|
106 | defaultValue: false,
|
107 | dest: 'sessionOverride',
|
108 | action: 'storeTrue',
|
109 | required: false,
|
110 | help: 'Enables session override (clobbering)',
|
111 | nargs: 0,
|
112 | }],
|
113 |
|
114 | [['-l', '--pre-launch'], {
|
115 | defaultValue: false,
|
116 | dest: 'launch',
|
117 | action: 'storeTrue',
|
118 | required: false,
|
119 | help: 'Pre-launch the application before allowing the first session ' +
|
120 | '(Requires --app and, for Android, --app-pkg and --app-activity)',
|
121 | nargs: 0,
|
122 | }],
|
123 |
|
124 | [['-g', '--log'], {
|
125 | defaultValue: null,
|
126 | dest: 'logFile',
|
127 | required: false,
|
128 | example: '/path/to/appium.log',
|
129 | help: 'Also send log output to this file',
|
130 | }],
|
131 |
|
132 | [['--log-level'], {
|
133 | choices: [
|
134 | 'info', 'info:debug', 'info:info', 'info:warn', 'info:error',
|
135 | 'warn', 'warn:debug', 'warn:info', 'warn:warn', 'warn:error',
|
136 | 'error', 'error:debug', 'error:info', 'error:warn', 'error:error',
|
137 | 'debug', 'debug:debug', 'debug:info', 'debug:warn', 'debug:error',
|
138 | ],
|
139 | defaultValue: 'debug',
|
140 | dest: 'loglevel',
|
141 | required: false,
|
142 | example: 'debug',
|
143 | help: 'log level; default (console[:file]): debug[:debug]',
|
144 | }],
|
145 |
|
146 | [['--log-timestamp'], {
|
147 | defaultValue: false,
|
148 | required: false,
|
149 | help: 'Show timestamps in console output',
|
150 | nargs: 0,
|
151 | action: 'storeTrue',
|
152 | dest: 'logTimestamp',
|
153 | }],
|
154 |
|
155 | [['--local-timezone'], {
|
156 | defaultValue: false,
|
157 | required: false,
|
158 | help: 'Use local timezone for timestamps',
|
159 | nargs: 0,
|
160 | action: 'storeTrue',
|
161 | dest: 'localTimezone',
|
162 | }],
|
163 |
|
164 | [['--log-no-colors'], {
|
165 | defaultValue: false,
|
166 | required: false,
|
167 | help: 'Do not use colors in console output',
|
168 | nargs: 0,
|
169 | action: 'storeTrue',
|
170 | dest: 'logNoColors',
|
171 | }],
|
172 |
|
173 | [['-G', '--webhook'], {
|
174 | defaultValue: null,
|
175 | required: false,
|
176 | example: 'localhost:9876',
|
177 | dest: 'webhook',
|
178 | help: 'Also send log output to this HTTP listener',
|
179 | }],
|
180 |
|
181 | [['--safari'], {
|
182 | defaultValue: false,
|
183 | action: 'storeTrue',
|
184 | dest: 'safari',
|
185 | required: false,
|
186 | help: '(IOS-Only) Use the safari app',
|
187 | nargs: 0,
|
188 | }],
|
189 |
|
190 | [['--default-device', '-dd'], {
|
191 | dest: 'defaultDevice',
|
192 | defaultValue: false,
|
193 | action: 'storeTrue',
|
194 | required: false,
|
195 | help: '(IOS-Simulator-only) use the default simulator that instruments ' +
|
196 | 'launches on its own',
|
197 | }],
|
198 |
|
199 | [['--force-iphone'], {
|
200 | defaultValue: false,
|
201 | dest: 'forceIphone',
|
202 | action: 'storeTrue',
|
203 | required: false,
|
204 | help: '(IOS-only) Use the iPhone Simulator no matter what the app wants',
|
205 | nargs: 0,
|
206 | }],
|
207 |
|
208 | [['--force-ipad'], {
|
209 | defaultValue: false,
|
210 | dest: 'forceIpad',
|
211 | action: 'storeTrue',
|
212 | required: false,
|
213 | help: '(IOS-only) Use the iPad Simulator no matter what the app wants',
|
214 | nargs: 0,
|
215 | }],
|
216 |
|
217 | [['--tracetemplate'], {
|
218 | defaultValue: null,
|
219 | dest: 'automationTraceTemplatePath',
|
220 | required: false,
|
221 | example: '/Users/me/Automation.tracetemplate',
|
222 | help: '(IOS-only) .tracetemplate file to use with Instruments',
|
223 | }],
|
224 |
|
225 | [['--instruments'], {
|
226 | defaultValue: null,
|
227 | dest: 'instrumentsPath',
|
228 | require: false,
|
229 | example: '/path/to/instruments',
|
230 | help: '(IOS-only) path to instruments binary',
|
231 | }],
|
232 |
|
233 | [['--nodeconfig'], {
|
234 | required: false,
|
235 | defaultValue: null,
|
236 | dest: 'nodeconfig',
|
237 | help: 'Configuration JSON file to register appium with selenium grid',
|
238 | example: '/abs/path/to/nodeconfig.json',
|
239 | }],
|
240 |
|
241 | [['-ra', '--robot-address'], {
|
242 | defaultValue: '0.0.0.0',
|
243 | dest: 'robotAddress',
|
244 | required: false,
|
245 | example: '0.0.0.0',
|
246 | help: 'IP Address of robot',
|
247 | }],
|
248 |
|
249 | [['-rp', '--robot-port'], {
|
250 | defaultValue: -1,
|
251 | dest: 'robotPort',
|
252 | required: false,
|
253 | type: 'int',
|
254 | example: '4242',
|
255 | help: 'port for robot',
|
256 | }],
|
257 |
|
258 | [['--chromedriver-port'], {
|
259 | defaultValue: null,
|
260 | dest: 'chromeDriverPort',
|
261 | required: false,
|
262 | type: 'int',
|
263 | example: '9515',
|
264 | help: 'Port upon which ChromeDriver will run. If not given, Android driver will pick a random available port.',
|
265 | }],
|
266 |
|
267 | [['--chromedriver-executable'], {
|
268 | defaultValue: null,
|
269 | dest: 'chromedriverExecutable',
|
270 | required: false,
|
271 | help: 'ChromeDriver executable full path',
|
272 | }],
|
273 |
|
274 | [['--show-config'], {
|
275 | defaultValue: false,
|
276 | dest: 'showConfig',
|
277 | action: 'storeTrue',
|
278 | required: false,
|
279 | help: 'Show info about the appium server configuration and exit',
|
280 | }],
|
281 |
|
282 | [['--no-perms-check'], {
|
283 | defaultValue: false,
|
284 | dest: 'noPermsCheck',
|
285 | action: 'storeTrue',
|
286 | required: false,
|
287 | help: 'Bypass Appium\'s checks to ensure we can read/write necessary files',
|
288 | }],
|
289 |
|
290 | [['--strict-caps'], {
|
291 | defaultValue: false,
|
292 | dest: 'enforceStrictCaps',
|
293 | action: 'storeTrue',
|
294 | required: false,
|
295 | help: 'Cause sessions to fail if desired caps are sent in that Appium ' +
|
296 | 'does not recognize as valid for the selected device',
|
297 | nargs: 0,
|
298 | }],
|
299 |
|
300 | [['--isolate-sim-device'], {
|
301 | defaultValue: false,
|
302 | dest: 'isolateSimDevice',
|
303 | action: 'storeTrue',
|
304 | required: false,
|
305 | help: 'Xcode 6 has a bug on some platforms where a certain simulator ' +
|
306 | 'can only be launched without error if all other simulator devices ' +
|
307 | 'are first deleted. This option causes Appium to delete all ' +
|
308 | 'devices other than the one being used by Appium. Note that this ' +
|
309 | 'is a permanent deletion, and you are responsible for using simctl ' +
|
310 | 'or xcode to manage the categories of devices used with Appium.',
|
311 | nargs: 0,
|
312 | }],
|
313 |
|
314 | [['--tmp'], {
|
315 | defaultValue: null,
|
316 | dest: 'tmpDir',
|
317 | required: false,
|
318 | help: 'Absolute path to directory Appium can use to manage temporary ' +
|
319 | 'files, like built-in iOS apps it needs to move around. On *nix/Mac ' +
|
320 | 'defaults to /tmp, on Windows defaults to C:\\Windows\\Temp',
|
321 | }],
|
322 |
|
323 | [['--trace-dir'], {
|
324 | defaultValue: null,
|
325 | dest: 'traceDir',
|
326 | required: false,
|
327 | help: 'Absolute path to directory Appium use to save ios instruments ' +
|
328 | 'traces, defaults to <tmp dir>/appium-instruments',
|
329 | }],
|
330 |
|
331 | [['--debug-log-spacing'], {
|
332 | dest: 'debugLogSpacing',
|
333 | defaultValue: false,
|
334 | action: 'storeTrue',
|
335 | required: false,
|
336 | help: 'Add exaggerated spacing in logs to help with visual inspection',
|
337 | }],
|
338 |
|
339 | [['--suppress-adb-kill-server'], {
|
340 | dest: 'suppressKillServer',
|
341 | defaultValue: false,
|
342 | action: 'storeTrue',
|
343 | required: false,
|
344 | help: '(Android-only) If set, prevents Appium from killing the adb server instance',
|
345 | nargs: 0,
|
346 | }],
|
347 |
|
348 | [['--long-stacktrace'], {
|
349 | dest: 'longStacktrace',
|
350 | defaultValue: false,
|
351 | required: false,
|
352 | action: 'storeTrue',
|
353 | help: 'Add long stack traces to log entries. Recommended for debugging only.',
|
354 | }],
|
355 |
|
356 | [['--webkit-debug-proxy-port'], {
|
357 | defaultValue: 27753,
|
358 | dest: 'webkitDebugProxyPort',
|
359 | required: false,
|
360 | type: 'int',
|
361 | example: '27753',
|
362 | help: '(IOS-only) Local port used for communication with ios-webkit-debug-proxy'
|
363 | }],
|
364 |
|
365 | [['--webdriveragent-port'], {
|
366 | defaultValue: 8100,
|
367 | dest: 'wdaLocalPort',
|
368 | required: false,
|
369 | type: 'int',
|
370 | example: '8100',
|
371 | help: '(IOS-only, XCUITest-only) Local port used for communication with WebDriverAgent'
|
372 | }],
|
373 |
|
374 | [['-dc', '--default-capabilities'], {
|
375 | dest: 'defaultCapabilities',
|
376 | defaultValue: {},
|
377 | type: parseDefaultCaps,
|
378 | required: false,
|
379 | example: '[ \'{"app": "myapp.app", "deviceName": "iPhone Simulator"}\' ' +
|
380 | '| /path/to/caps.json ]',
|
381 | help: 'Set the default desired capabilities, which will be set on each ' +
|
382 | 'session unless overridden by received capabilities.'
|
383 | }],
|
384 |
|
385 | [['--relaxed-security'], {
|
386 | defaultValue: false,
|
387 | dest: 'relaxedSecurityEnabled',
|
388 | action: 'storeTrue',
|
389 | required: false,
|
390 | help: 'Disable additional security checks, so it is possible to use some advanced features, provided ' +
|
391 | 'by drivers supporting this option. Only enable it if all the ' +
|
392 | 'clients are in the trusted network and it\'s not the case if a client could potentially ' +
|
393 | 'break out of the session sandbox. Specific features can be overridden by ' +
|
394 | 'using the --deny-insecure flag',
|
395 | nargs: 0
|
396 | }],
|
397 |
|
398 | [['--allow-insecure'], {
|
399 | dest: 'allowInsecure',
|
400 | defaultValue: [],
|
401 | type: parseSecurityFeatures,
|
402 | required: false,
|
403 | example: 'execute_driver_script,adb_shell',
|
404 | help: 'Set which insecure features are allowed to run in this server\'s sessions. ' +
|
405 | 'Features are defined on a driver level; see documentation for more details. ' +
|
406 | 'This should be either a comma-separated list of feature names, or a path to ' +
|
407 | 'a file where each feature name is on a line. Note that features defined via ' +
|
408 | '--deny-insecure will be disabled, even if also listed here.',
|
409 | }],
|
410 |
|
411 | [['--deny-insecure'], {
|
412 | dest: 'denyInsecure',
|
413 | defaultValue: [],
|
414 | type: parseSecurityFeatures,
|
415 | required: false,
|
416 | example: 'execute_driver_script,adb_shell',
|
417 | help: 'Set which insecure features are not allowed to run in this server\'s sessions. ' +
|
418 | 'Features are defined on a driver level; see documentation for more details. ' +
|
419 | 'This should be either a comma-separated list of feature names, or a path to ' +
|
420 | 'a file where each feature name is on a line. Features listed here will not be ' +
|
421 | 'enabled even if also listed in --allow-insecure, and even if --relaxed-security ' +
|
422 | 'is turned on.',
|
423 | }],
|
424 | ];
|
425 |
|
426 | const deprecatedArgs = [
|
427 | [['--command-timeout'], {
|
428 | defaultValue: 60,
|
429 | dest: 'defaultCommandTimeout',
|
430 | type: 'int',
|
431 | required: false,
|
432 | help: '[DEPRECATED] No effect. This used to be the default command ' +
|
433 | 'timeout for the server to use for all sessions (in seconds and ' +
|
434 | 'should be less than 2147483). Use newCommandTimeout cap instead'
|
435 | }],
|
436 |
|
437 | [['-k', '--keep-artifacts'], {
|
438 | defaultValue: false,
|
439 | dest: 'keepArtifacts',
|
440 | action: 'storeTrue',
|
441 | required: false,
|
442 | help: '[DEPRECATED] - no effect, trace is now in tmp dir by default and is ' +
|
443 | 'cleared before each run. Please also refer to the --trace-dir flag.',
|
444 | nargs: 0,
|
445 | }],
|
446 |
|
447 | [['--platform-name'], {
|
448 | dest: 'platformName',
|
449 | defaultValue: null,
|
450 | required: false,
|
451 | deprecatedFor: '--default-capabilities',
|
452 | example: 'iOS',
|
453 | help: '[DEPRECATED] - Name of the mobile platform: iOS, Android, or FirefoxOS',
|
454 | }],
|
455 |
|
456 | [['--platform-version'], {
|
457 | dest: 'platformVersion',
|
458 | defaultValue: null,
|
459 | required: false,
|
460 | deprecatedFor: '--default-capabilities',
|
461 | example: '7.1',
|
462 | help: '[DEPRECATED] - Version of the mobile platform',
|
463 | }],
|
464 |
|
465 | [['--automation-name'], {
|
466 | dest: 'automationName',
|
467 | defaultValue: null,
|
468 | required: false,
|
469 | deprecatedFor: '--default-capabilities',
|
470 | example: 'Appium',
|
471 | help: '[DEPRECATED] - Name of the automation tool: Appium, XCUITest, etc.',
|
472 | }],
|
473 |
|
474 | [['--device-name'], {
|
475 | dest: 'deviceName',
|
476 | defaultValue: null,
|
477 | required: false,
|
478 | deprecatedFor: '--default-capabilities',
|
479 | example: 'iPhone Retina (4-inch), Android Emulator',
|
480 | help: '[DEPRECATED] - Name of the mobile device to use',
|
481 | }],
|
482 |
|
483 | [['--browser-name'], {
|
484 | dest: 'browserName',
|
485 | defaultValue: null,
|
486 | required: false,
|
487 | deprecatedFor: '--default-capabilities',
|
488 | example: 'Safari',
|
489 | help: '[DEPRECATED] - Name of the mobile browser: Safari or Chrome',
|
490 | }],
|
491 |
|
492 | [['--app'], {
|
493 | dest: 'app',
|
494 | required: false,
|
495 | defaultValue: null,
|
496 | deprecatedFor: '--default-capabilities',
|
497 | help: '[DEPRECATED] - IOS: abs path to simulator-compiled .app file or the bundle_id of the desired target on device; Android: abs path to .apk file',
|
498 | example: '/abs/path/to/my.app',
|
499 | }],
|
500 |
|
501 | [['-lt', '--launch-timeout'], {
|
502 | defaultValue: 90000,
|
503 | dest: 'launchTimeout',
|
504 | type: 'int',
|
505 | required: false,
|
506 | deprecatedFor: '--default-capabilities',
|
507 | help: '[DEPRECATED] - (iOS-only) how long in ms to wait for Instruments to launch',
|
508 | }],
|
509 |
|
510 | [['--language'], {
|
511 | defaultValue: null,
|
512 | dest: 'language',
|
513 | required: false,
|
514 | example: 'en',
|
515 | deprecatedFor: '--default-capabilities',
|
516 | help: '[DEPRECATED] - Language for the iOS simulator / Android Emulator',
|
517 | }],
|
518 |
|
519 | [['--locale'], {
|
520 | defaultValue: null,
|
521 | dest: 'locale',
|
522 | required: false,
|
523 | example: 'en_US',
|
524 | deprecatedFor: '--default-capabilities',
|
525 | help: '[DEPRECATED] - Locale for the iOS simulator / Android Emulator',
|
526 | }],
|
527 |
|
528 | [['-U', '--udid'], {
|
529 | dest: 'udid',
|
530 | required: false,
|
531 | defaultValue: null,
|
532 | example: '1adsf-sdfas-asdf-123sdf',
|
533 | deprecatedFor: '--default-capabilities',
|
534 | help: '[DEPRECATED] - Unique device identifier of the connected physical device',
|
535 | }],
|
536 |
|
537 | [['--orientation'], {
|
538 | dest: 'orientation',
|
539 | defaultValue: null,
|
540 | required: false,
|
541 | example: 'LANDSCAPE',
|
542 | deprecatedFor: '--default-capabilities',
|
543 | help: '[DEPRECATED] - (IOS-only) use LANDSCAPE or PORTRAIT to initialize all requests ' +
|
544 | 'to this orientation',
|
545 | }],
|
546 |
|
547 | [['--no-reset'], {
|
548 | defaultValue: false,
|
549 | dest: 'noReset',
|
550 | action: 'storeTrue',
|
551 | required: false,
|
552 | deprecatedFor: '--default-capabilities',
|
553 | help: '[DEPRECATED] - Do not reset app state between sessions (IOS: do not delete app ' +
|
554 | 'plist files; Android: do not uninstall app before new session)',
|
555 | nargs: 0,
|
556 | }],
|
557 |
|
558 | [['--full-reset'], {
|
559 | defaultValue: false,
|
560 | dest: 'fullReset',
|
561 | action: 'storeTrue',
|
562 | required: false,
|
563 | deprecatedFor: '--default-capabilities',
|
564 | help: '[DEPRECATED] - (iOS) Delete the entire simulator folder. (Android) Reset app ' +
|
565 | 'state by uninstalling app instead of clearing app data. On ' +
|
566 | 'Android, this will also remove the app after the session is complete.',
|
567 | nargs: 0,
|
568 | }],
|
569 |
|
570 | [['--app-pkg'], {
|
571 | dest: 'appPackage',
|
572 | defaultValue: null,
|
573 | required: false,
|
574 | deprecatedFor: '--default-capabilities',
|
575 | example: 'com.example.android.myApp',
|
576 | help: '[DEPRECATED] - (Android-only) Java package of the Android app you want to run ' +
|
577 | '(e.g., com.example.android.myApp)',
|
578 | }],
|
579 |
|
580 | [['--app-activity'], {
|
581 | dest: 'appActivity',
|
582 | defaultValue: null,
|
583 | required: false,
|
584 | example: 'MainActivity',
|
585 | deprecatedFor: '--default-capabilities',
|
586 | help: '[DEPRECATED] - (Android-only) Activity name for the Android activity you want ' +
|
587 | 'to launch from your package (e.g., MainActivity)',
|
588 | }],
|
589 |
|
590 | [['--app-wait-package'], {
|
591 | dest: 'appWaitPackage',
|
592 | defaultValue: false,
|
593 | required: false,
|
594 | example: 'com.example.android.myApp',
|
595 | deprecatedFor: '--default-capabilities',
|
596 | help: '[DEPRECATED] - (Android-only) Package name for the Android activity you want ' +
|
597 | 'to wait for (e.g., com.example.android.myApp)',
|
598 | }],
|
599 |
|
600 | [['--app-wait-activity'], {
|
601 | dest: 'appWaitActivity',
|
602 | defaultValue: false,
|
603 | required: false,
|
604 | example: 'SplashActivity',
|
605 | deprecatedFor: '--default-capabilities',
|
606 | help: '[DEPRECATED] - (Android-only) Activity name for the Android activity you want ' +
|
607 | 'to wait for (e.g., SplashActivity)',
|
608 | }],
|
609 |
|
610 | [['--device-ready-timeout'], {
|
611 | dest: 'deviceReadyTimeout',
|
612 | defaultValue: 5,
|
613 | required: false,
|
614 | type: 'int',
|
615 | example: '5',
|
616 | deprecatedFor: '--default-capabilities',
|
617 | help: '[DEPRECATED] - (Android-only) Timeout in seconds while waiting for device to become ready',
|
618 | }],
|
619 |
|
620 | [['--android-coverage'], {
|
621 | dest: 'androidCoverage',
|
622 | defaultValue: false,
|
623 | required: false,
|
624 | example: 'com.my.Pkg/com.my.Pkg.instrumentation.MyInstrumentation',
|
625 | deprecatedFor: '--default-capabilities',
|
626 | help: '[DEPRECATED] - (Android-only) Fully qualified instrumentation class. Passed to -w in ' +
|
627 | 'adb shell am instrument -e coverage true -w ',
|
628 | }],
|
629 |
|
630 | [['--avd'], {
|
631 | dest: 'avd',
|
632 | defaultValue: null,
|
633 | required: false,
|
634 | example: '@default',
|
635 | deprecatedFor: '--default-capabilities',
|
636 | help: '[DEPRECATED] - (Android-only) Name of the avd to launch',
|
637 | }],
|
638 |
|
639 | [['--avd-args'], {
|
640 | dest: 'avdArgs',
|
641 | defaultValue: null,
|
642 | required: false,
|
643 | example: '-no-snapshot-load',
|
644 | deprecatedFor: '--default-capabilities',
|
645 | help: '[DEPRECATED] - (Android-only) Additional emulator arguments to launch the avd',
|
646 | }],
|
647 |
|
648 | [['--use-keystore'], {
|
649 | defaultValue: false,
|
650 | dest: 'useKeystore',
|
651 | action: 'storeTrue',
|
652 | required: false,
|
653 | deprecatedFor: '--default-capabilities',
|
654 | help: '[DEPRECATED] - (Android-only) When set the keystore will be used to sign apks.',
|
655 | }],
|
656 |
|
657 | [['--keystore-path'], {
|
658 | defaultValue: path.resolve(process.env.HOME || process.env.USERPROFILE || '', '.android', 'debug.keystore'),
|
659 | dest: 'keystorePath',
|
660 | required: false,
|
661 | deprecatedFor: '--default-capabilities',
|
662 | help: '[DEPRECATED] - (Android-only) Path to keystore',
|
663 | }],
|
664 |
|
665 | [['--keystore-password'], {
|
666 | defaultValue: 'android',
|
667 | dest: 'keystorePassword',
|
668 | required: false,
|
669 | deprecatedFor: '--default-capabilities',
|
670 | help: '[DEPRECATED] - (Android-only) Password to keystore',
|
671 | }],
|
672 |
|
673 | [['--key-alias'], {
|
674 | defaultValue: 'androiddebugkey',
|
675 | dest: 'keyAlias',
|
676 | required: false,
|
677 | deprecatedFor: '--default-capabilities',
|
678 | help: '[DEPRECATED] - (Android-only) Key alias',
|
679 | }],
|
680 |
|
681 | [['--key-password'], {
|
682 | defaultValue: 'android',
|
683 | dest: 'keyPassword',
|
684 | required: false,
|
685 | deprecatedFor: '--default-capabilities',
|
686 | help: '[DEPRECATED] - (Android-only) Key password',
|
687 | }],
|
688 |
|
689 | [['--intent-action'], {
|
690 | dest: 'intentAction',
|
691 | defaultValue: 'android.intent.action.MAIN',
|
692 | required: false,
|
693 | example: 'android.intent.action.MAIN',
|
694 | deprecatedFor: '--default-capabilities',
|
695 | help: '[DEPRECATED] - (Android-only) Intent action which will be used to start activity',
|
696 | }],
|
697 |
|
698 | [['--intent-category'], {
|
699 | dest: 'intentCategory',
|
700 | defaultValue: 'android.intent.category.LAUNCHER',
|
701 | required: false,
|
702 | example: 'android.intent.category.APP_CONTACTS',
|
703 | deprecatedFor: '--default-capabilities',
|
704 | help: '[DEPRECATED] - (Android-only) Intent category which will be used to start activity',
|
705 | }],
|
706 |
|
707 | [['--intent-flags'], {
|
708 | dest: 'intentFlags',
|
709 | defaultValue: '0x10200000',
|
710 | required: false,
|
711 | example: '0x10200000',
|
712 | deprecatedFor: '--default-capabilities',
|
713 | help: '[DEPRECATED] - (Android-only) Flags that will be used to start activity',
|
714 | }],
|
715 |
|
716 | [['--intent-args'], {
|
717 | dest: 'optionalIntentArguments',
|
718 | defaultValue: null,
|
719 | required: false,
|
720 | example: '0x10200000',
|
721 | deprecatedFor: '--default-capabilities',
|
722 | help: '[DEPRECATED] - (Android-only) Additional intent arguments that will be used to ' +
|
723 | 'start activity',
|
724 | }],
|
725 |
|
726 | [['--dont-stop-app-on-reset'], {
|
727 | dest: 'dontStopAppOnReset',
|
728 | defaultValue: false,
|
729 | action: 'storeTrue',
|
730 | required: false,
|
731 | deprecatedFor: '--default-capabilities',
|
732 | help: '[DEPRECATED] - (Android-only) When included, refrains from stopping the app before restart',
|
733 | }],
|
734 |
|
735 | [['--calendar-format'], {
|
736 | defaultValue: null,
|
737 | dest: 'calendarFormat',
|
738 | required: false,
|
739 | example: 'gregorian',
|
740 | deprecatedFor: '--default-capabilities',
|
741 | help: '[DEPRECATED] - (IOS-only) calendar format for the iOS simulator',
|
742 | }],
|
743 |
|
744 | [['--native-instruments-lib'], {
|
745 | defaultValue: false,
|
746 | dest: 'nativeInstrumentsLib',
|
747 | action: 'storeTrue',
|
748 | required: false,
|
749 | deprecatedFor: '--default-capabilities',
|
750 | help: '[DEPRECATED] - (IOS-only) IOS has a weird built-in unavoidable ' +
|
751 | 'delay. We patch this in appium. If you do not want it patched, ' +
|
752 | 'pass in this flag.',
|
753 | nargs: 0,
|
754 | }],
|
755 |
|
756 | [['--keep-keychains'], {
|
757 | defaultValue: false,
|
758 | dest: 'keepKeyChains',
|
759 | action: 'storeTrue',
|
760 | required: false,
|
761 | deprecatedFor: '--default-capabilities',
|
762 | help: '[DEPRECATED] - (iOS-only) Whether to keep keychains (Library/Keychains) when reset app between sessions',
|
763 | nargs: 0,
|
764 | }],
|
765 |
|
766 | [['--localizable-strings-dir'], {
|
767 | required: false,
|
768 | dest: 'localizableStringsDir',
|
769 | defaultValue: 'en.lproj',
|
770 | deprecatedFor: '--default-capabilities',
|
771 | help: '[DEPRECATED] - (IOS-only) the relative path of the dir where Localizable.strings file resides ',
|
772 | example: 'en.lproj',
|
773 | }],
|
774 |
|
775 | [['--show-ios-log'], {
|
776 | defaultValue: false,
|
777 | dest: 'showIOSLog',
|
778 | action: 'storeTrue',
|
779 | required: false,
|
780 | deprecatedFor: '--default-capabilities',
|
781 | help: '[DEPRECATED] - (IOS-only) if set, the iOS system log will be written to the console',
|
782 | nargs: 0,
|
783 | }],
|
784 |
|
785 | [['--async-trace'], {
|
786 | dest: 'longStacktrace',
|
787 | defaultValue: false,
|
788 | required: false,
|
789 | action: 'storeTrue',
|
790 | deprecatedFor: '--long-stacktrace',
|
791 | help: '[DEPRECATED] - Add long stack traces to log entries. Recommended for debugging only.',
|
792 | }],
|
793 | ];
|
794 |
|
795 | function updateParseArgsForDefaultCapabilities (parser) {
|
796 |
|
797 |
|
798 |
|
799 |
|
800 |
|
801 | parser._parseArgs = parser.parseArgs;
|
802 | parser.parseArgs = function parseArgs (args) {
|
803 | let parsedArgs = parser._parseArgs(args);
|
804 | parsedArgs.defaultCapabilities = parsedArgs.defaultCapabilities || {};
|
805 | for (let argEntry of deprecatedArgs) {
|
806 | let arg = argEntry[1].dest;
|
807 | if (argEntry[1].deprecatedFor === '--default-capabilities') {
|
808 | if (arg in parsedArgs && parsedArgs[arg] !== argEntry[1].defaultValue) {
|
809 | parsedArgs.defaultCapabilities[arg] = parsedArgs[arg];
|
810 |
|
811 | let capDict = {[arg]: parsedArgs[arg]};
|
812 | argEntry[1].deprecatedFor = `--default-capabilities ` +
|
813 | `'${JSON.stringify(capDict)}'`;
|
814 | }
|
815 | }
|
816 | }
|
817 | return parsedArgs;
|
818 | };
|
819 | }
|
820 |
|
821 | function parseSecurityFeatures (features) {
|
822 | const splitter = (splitOn, str) => `${str}`.split(splitOn).map(s => s.trim()).filter(Boolean);
|
823 | let parsedFeatures;
|
824 | try {
|
825 | parsedFeatures = splitter(',', features);
|
826 | } catch (err) {
|
827 | throw new Error('Could not parse value of --allow/deny-insecure. Should be ' +
|
828 | 'a list of strings separated by commas, or a path to a file ' +
|
829 | 'listing one feature name per line.');
|
830 | }
|
831 |
|
832 | if (parsedFeatures.length === 1 && fs.existsSync(parsedFeatures[0])) {
|
833 |
|
834 | try {
|
835 | const fileFeatures = fs.readFileSync(parsedFeatures[0], 'utf8');
|
836 | parsedFeatures = splitter('\n', fileFeatures);
|
837 | } catch (err) {
|
838 | throw new Error(`Attempted to read --allow/deny-insecure feature names ` +
|
839 | `from file ${parsedFeatures[0]} but got error: ${err.message}`);
|
840 | }
|
841 | }
|
842 |
|
843 | return parsedFeatures;
|
844 | }
|
845 |
|
846 | function parseDefaultCaps (caps) {
|
847 | try {
|
848 |
|
849 |
|
850 |
|
851 |
|
852 |
|
853 | if (fs.statSync(caps).isFile()) {
|
854 | caps = fs.readFileSync(caps, 'utf8');
|
855 | }
|
856 | } catch (err) {
|
857 |
|
858 | }
|
859 | caps = JSON.parse(caps);
|
860 | if (!_.isPlainObject(caps)) {
|
861 | throw 'Invalid format for default capabilities';
|
862 | }
|
863 | return caps;
|
864 | }
|
865 |
|
866 | function getParser () {
|
867 | let parser = new ArgumentParser({
|
868 | version: require(path.resolve(rootDir, 'package.json')).version,
|
869 | addHelp: true,
|
870 | description: 'A webdriver-compatible server for use with native and hybrid iOS and Android applications.',
|
871 | prog: process.argv[1] || 'Appium'
|
872 | });
|
873 | let allArgs = _.union(args, deprecatedArgs);
|
874 | parser.rawArgs = allArgs;
|
875 | for (let arg of allArgs) {
|
876 | parser.addArgument(arg[0], arg[1]);
|
877 | }
|
878 | updateParseArgsForDefaultCapabilities(parser);
|
879 |
|
880 | return parser;
|
881 | }
|
882 |
|
883 | function getDefaultArgs () {
|
884 | let defaults = {};
|
885 | for (let [, arg] of args) {
|
886 | defaults[arg.dest] = arg.defaultValue;
|
887 | }
|
888 | return defaults;
|
889 | }
|
890 |
|
891 | export default getParser;
|
892 | export { getDefaultArgs, getParser };
|