appium 2.0.0-beta.25 → 2.0.0-beta.28
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.
- package/build/lib/appium.d.ts +215 -0
- package/build/lib/appium.d.ts.map +1 -0
- package/build/lib/appium.js +94 -101
- package/build/lib/cli/args.d.ts +20 -0
- package/build/lib/cli/args.d.ts.map +1 -0
- package/build/lib/cli/args.js +19 -39
- package/build/lib/cli/driver-command.d.ts +36 -0
- package/build/lib/cli/driver-command.d.ts.map +1 -0
- package/build/lib/cli/driver-command.js +10 -13
- package/build/lib/cli/extension-command.d.ts +345 -0
- package/build/lib/cli/extension-command.d.ts.map +1 -0
- package/build/lib/cli/extension-command.js +117 -94
- package/build/lib/cli/extension.d.ts +14 -0
- package/build/lib/cli/extension.d.ts.map +1 -0
- package/build/lib/cli/extension.js +14 -22
- package/build/lib/cli/parser.d.ts +79 -0
- package/build/lib/cli/parser.d.ts.map +1 -0
- package/build/lib/cli/parser.js +9 -19
- package/build/lib/cli/plugin-command.d.ts +39 -0
- package/build/lib/cli/plugin-command.d.ts.map +1 -0
- package/build/lib/cli/plugin-command.js +9 -14
- package/build/lib/cli/utils.d.ts +29 -0
- package/build/lib/cli/utils.d.ts.map +1 -0
- package/build/lib/cli/utils.js +2 -4
- package/build/lib/config-file.d.ts +100 -0
- package/build/lib/config-file.d.ts.map +1 -0
- package/build/lib/config-file.js +2 -4
- package/build/lib/config.d.ts +40 -0
- package/build/lib/config.d.ts.map +1 -0
- package/build/lib/config.js +8 -7
- package/build/lib/constants.d.ts +48 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +60 -0
- package/build/lib/extension/driver-config.d.ts +84 -0
- package/build/lib/extension/driver-config.d.ts.map +1 -0
- package/build/lib/extension/driver-config.js +190 -0
- package/build/lib/extension/extension-config.d.ts +170 -0
- package/build/lib/extension/extension-config.d.ts.map +1 -0
- package/build/lib/extension/extension-config.js +297 -0
- package/build/lib/extension/index.d.ts +39 -0
- package/build/lib/extension/index.d.ts.map +1 -0
- package/build/lib/extension/index.js +77 -0
- package/build/lib/extension/manifest.d.ts +174 -0
- package/build/lib/extension/manifest.d.ts.map +1 -0
- package/build/lib/extension/manifest.js +246 -0
- package/build/lib/extension/package-changed.d.ts +11 -0
- package/build/lib/extension/package-changed.d.ts.map +1 -0
- package/build/lib/extension/package-changed.js +68 -0
- package/build/lib/extension/plugin-config.d.ts +62 -0
- package/build/lib/extension/plugin-config.d.ts.map +1 -0
- package/build/lib/extension/plugin-config.js +87 -0
- package/build/lib/grid-register.d.ts +10 -0
- package/build/lib/grid-register.d.ts.map +1 -0
- package/build/lib/grid-register.js +2 -4
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +2 -4
- package/build/lib/logsink.d.ts +4 -0
- package/build/lib/logsink.d.ts.map +1 -0
- package/build/lib/logsink.js +2 -4
- package/build/lib/main.d.ts +51 -0
- package/build/lib/main.d.ts.map +1 -0
- package/build/lib/main.js +40 -68
- package/build/lib/schema/arg-spec.d.ts +143 -0
- package/build/lib/schema/arg-spec.d.ts.map +1 -0
- package/build/lib/schema/arg-spec.js +11 -14
- package/build/lib/schema/cli-args.d.ts +19 -0
- package/build/lib/schema/cli-args.d.ts.map +1 -0
- package/build/lib/schema/cli-args.js +2 -4
- package/build/lib/schema/cli-transformers.d.ts +5 -0
- package/build/lib/schema/cli-transformers.d.ts.map +1 -0
- package/build/lib/schema/cli-transformers.js +2 -4
- package/build/lib/schema/index.d.ts +3 -0
- package/build/lib/schema/index.d.ts.map +1 -0
- package/build/lib/schema/index.js +2 -4
- package/build/lib/schema/keywords.d.ts +24 -0
- package/build/lib/schema/keywords.d.ts.map +1 -0
- package/build/lib/schema/keywords.js +2 -4
- package/build/lib/schema/schema.d.ts +259 -0
- package/build/lib/schema/schema.d.ts.map +1 -0
- package/build/lib/schema/schema.js +57 -39
- package/build/lib/utils.d.ts +66 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +6 -35
- package/build/tsconfig.tsbuildinfo +1 -0
- package/lib/appium.js +188 -117
- package/lib/cli/args.js +19 -24
- package/lib/cli/driver-command.js +19 -8
- package/lib/cli/extension-command.js +314 -184
- package/lib/cli/extension.js +18 -16
- package/lib/cli/parser.js +7 -16
- package/lib/cli/plugin-command.js +16 -7
- package/lib/cli/utils.js +1 -1
- package/lib/config-file.js +6 -7
- package/lib/config.js +17 -12
- package/lib/constants.js +78 -0
- package/lib/extension/driver-config.js +249 -0
- package/lib/extension/extension-config.js +458 -0
- package/lib/extension/index.js +102 -0
- package/lib/extension/manifest.js +486 -0
- package/lib/extension/package-changed.js +63 -0
- package/lib/extension/plugin-config.js +113 -0
- package/lib/grid-register.js +4 -4
- package/lib/logsink.js +4 -0
- package/lib/main.js +54 -92
- package/lib/schema/arg-spec.js +11 -7
- package/lib/schema/cli-args.js +1 -1
- package/lib/schema/cli-transformers.js +0 -1
- package/lib/schema/keywords.js +1 -2
- package/lib/schema/schema.js +62 -31
- package/lib/utils.js +48 -45
- package/package.json +30 -24
- package/{postinstall.js → scripts/postinstall.js} +1 -1
- package/types/appium-manifest.d.ts +61 -0
- package/types/cli.d.ts +134 -0
- package/types/extension.d.ts +56 -0
- package/types/external-manifest.d.ts +58 -0
- package/types/index.d.ts +7 -0
- package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
- package/build/check-npm-pack-files.js +0 -23
- package/build/commands-yml/parse.js +0 -319
- package/build/commands-yml/validator.js +0 -130
- package/build/index.js +0 -19
- package/build/lib/appium-config.schema.json +0 -0
- package/build/lib/cli/npm.js +0 -220
- package/build/lib/driver-config.js +0 -100
- package/build/lib/drivers.js +0 -100
- package/build/lib/ext-config-io.js +0 -165
- package/build/lib/extension-config.js +0 -320
- package/build/lib/plugin-config.js +0 -69
- package/build/lib/plugins.js +0 -18
- package/build/lib/schema/appium-config-schema.js +0 -253
- package/build/postinstall.js +0 -90
- package/build/test/cli/cli-e2e-specs.js +0 -221
- package/build/test/cli/cli-helpers.js +0 -86
- package/build/test/cli/cli-specs.js +0 -71
- package/build/test/cli/fixtures/test-driver/package.json +0 -27
- package/build/test/cli/schema-args-specs.js +0 -48
- package/build/test/cli/schema-e2e-specs.js +0 -47
- package/build/test/config-e2e-specs.js +0 -112
- package/build/test/config-file-e2e-specs.js +0 -191
- package/build/test/config-file-specs.js +0 -281
- package/build/test/config-specs.js +0 -258
- package/build/test/driver-e2e-specs.js +0 -435
- package/build/test/driver-specs.js +0 -386
- package/build/test/ext-config-io-specs.js +0 -181
- package/build/test/extension-config-specs.js +0 -365
- package/build/test/fixtures/allow-feat.txt +0 -5
- package/build/test/fixtures/caps.json +0 -3
- package/build/test/fixtures/config/allow-insecure.txt +0 -3
- package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +0 -5
- package/build/test/fixtures/config/appium.config.bad.json +0 -32
- package/build/test/fixtures/config/appium.config.ext-good.json +0 -9
- package/build/test/fixtures/config/appium.config.ext-unknown-props.json +0 -10
- package/build/test/fixtures/config/appium.config.good.js +0 -40
- package/build/test/fixtures/config/appium.config.good.json +0 -33
- package/build/test/fixtures/config/appium.config.good.yaml +0 -30
- package/build/test/fixtures/config/appium.config.invalid.json +0 -31
- package/build/test/fixtures/config/appium.config.security-array.json +0 -5
- package/build/test/fixtures/config/appium.config.security-delimited.json +0 -5
- package/build/test/fixtures/config/appium.config.security-path.json +0 -5
- package/build/test/fixtures/config/driver-fake.config.json +0 -8
- package/build/test/fixtures/config/nodeconfig.json +0 -3
- package/build/test/fixtures/config/plugin-fake.config.json +0 -0
- package/build/test/fixtures/default-args.js +0 -35
- package/build/test/fixtures/deny-feat.txt +0 -5
- package/build/test/fixtures/driver.schema.js +0 -20
- package/build/test/fixtures/extensions.yaml +0 -27
- package/build/test/fixtures/flattened-schema.js +0 -532
- package/build/test/fixtures/plugin.schema.js +0 -20
- package/build/test/fixtures/schema-with-extensions.js +0 -28
- package/build/test/grid-register-specs.js +0 -74
- package/build/test/helpers.js +0 -75
- package/build/test/logger-specs.js +0 -76
- package/build/test/npm-specs.js +0 -20
- package/build/test/parser-specs.js +0 -319
- package/build/test/plugin-e2e-specs.js +0 -316
- package/build/test/schema/arg-spec-specs.js +0 -70
- package/build/test/schema/cli-args-specs.js +0 -408
- package/build/test/schema/schema-specs.js +0 -407
- package/build/test/utils-specs.js +0 -288
- package/lib/cli/npm.js +0 -251
- package/lib/driver-config.js +0 -101
- package/lib/drivers.js +0 -84
- package/lib/ext-config-io.js +0 -287
- package/lib/extension-config.js +0 -366
- package/lib/plugin-config.js +0 -63
- package/lib/plugins.js +0 -13
- package/lib/schema/appium-config-schema.js +0 -287
- package/types/appium-config.d.ts +0 -197
- package/types/types.d.ts +0 -206
package/lib/cli/extension.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import DriverCommand from './driver-command';
|
|
4
4
|
import PluginCommand from './plugin-command';
|
|
5
|
-
import
|
|
6
|
-
import PluginConfig from '../plugin-config';
|
|
7
|
-
import { DRIVER_TYPE } from '../extension-config';
|
|
5
|
+
import { DRIVER_TYPE, PLUGIN_TYPE } from '../constants';
|
|
8
6
|
import { errAndQuit, log, JSON_SPACES } from './utils';
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
const commandClasses = Object.freeze(/** @type {const} */({
|
|
9
|
+
[DRIVER_TYPE]: DriverCommand,
|
|
10
|
+
[PLUGIN_TYPE]: PluginCommand
|
|
11
|
+
}));
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Run a subcommand of the 'appium driver' type. Each subcommand has its own set of arguments which
|
|
@@ -14,13 +16,14 @@ import { APPIUM_HOME } from './args';
|
|
|
14
16
|
*
|
|
15
17
|
* @param {Object} args - JS object where the key is the parameter name (as defined in
|
|
16
18
|
* driver-parser.js)
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
19
|
+
* @template {import('../extension/manifest').ExtensionType} ExtType
|
|
20
|
+
* @param {import('../extension/extension-config').ExtensionConfig<ExtType>} configObject - Extension config object
|
|
19
21
|
*/
|
|
20
|
-
async function runExtensionCommand (args,
|
|
22
|
+
async function runExtensionCommand (args, configObject) {
|
|
21
23
|
// TODO driver config file should be locked while any of these commands are
|
|
22
24
|
// running to prevent weird situations
|
|
23
25
|
let jsonResult = null;
|
|
26
|
+
const {extensionType: type} = configObject;
|
|
24
27
|
const extCmd = args[`${type}Command`];
|
|
25
28
|
if (!extCmd) {
|
|
26
29
|
throw new TypeError(`Cannot call ${type} command without a subcommand like 'install'`);
|
|
@@ -30,17 +33,11 @@ async function runExtensionCommand (args, type, configObject) {
|
|
|
30
33
|
json = true;
|
|
31
34
|
}
|
|
32
35
|
const logFn = (msg) => log(json, msg);
|
|
33
|
-
let config;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
config.log = logFn;
|
|
37
|
-
} else {
|
|
38
|
-
config = (type === DRIVER_TYPE ? DriverConfig : PluginConfig).getInstance(APPIUM_HOME, logFn);
|
|
39
|
-
}
|
|
40
|
-
const CommandClass = type === DRIVER_TYPE ? DriverCommand : PluginCommand;
|
|
36
|
+
let config = configObject;
|
|
37
|
+
config.log = logFn;
|
|
38
|
+
const CommandClass = /** @type {ExtCommand<ExtType>} */(commandClasses[type]);
|
|
41
39
|
const cmd = new CommandClass({config, json});
|
|
42
40
|
try {
|
|
43
|
-
await config.read();
|
|
44
41
|
jsonResult = await cmd.execute(args);
|
|
45
42
|
} catch (err) {
|
|
46
43
|
// in the suppress output case, we are calling this function internally and should
|
|
@@ -61,3 +58,8 @@ async function runExtensionCommand (args, type, configObject) {
|
|
|
61
58
|
export {
|
|
62
59
|
runExtensionCommand,
|
|
63
60
|
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @template {import('../../types').ExtensionType} ExtType
|
|
64
|
+
* @typedef {ExtType extends import('../../types').DriverType ? import('@appium/types').Class<DriverCommand> : ExtType extends import('../../types').PluginType ? import('@appium/types').Class<PluginCommand> : never} ExtCommand
|
|
65
|
+
*/
|
package/lib/cli/parser.js
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
|
|
3
2
|
import { fs } from '@appium/support';
|
|
4
3
|
import { ArgumentParser } from 'argparse';
|
|
5
|
-
import B from 'bluebird';
|
|
6
4
|
import _ from 'lodash';
|
|
7
5
|
import path from 'path';
|
|
8
|
-
import { DRIVER_TYPE, PLUGIN_TYPE } from '../
|
|
6
|
+
import { DRIVER_TYPE, PLUGIN_TYPE, SERVER_SUBCOMMAND } from '../constants';
|
|
9
7
|
import { finalizeSchema, getArgSpec, hasArgSpec } from '../schema';
|
|
10
|
-
import { rootDir } from '../
|
|
8
|
+
import { rootDir } from '../config';
|
|
11
9
|
import {
|
|
12
|
-
driverConfig,
|
|
13
10
|
getExtensionArgs,
|
|
14
|
-
getServerArgs
|
|
15
|
-
pluginConfig
|
|
11
|
+
getServerArgs
|
|
16
12
|
} from './args';
|
|
17
13
|
|
|
18
|
-
export const SERVER_SUBCOMMAND = 'server';
|
|
19
|
-
|
|
20
14
|
/**
|
|
21
15
|
* If the parsed args do not contain any of these values, then we
|
|
22
16
|
* will automatially inject the `server` subcommand.
|
|
@@ -106,7 +100,7 @@ class ArgParser {
|
|
|
106
100
|
*
|
|
107
101
|
* `ArgParser.prototype.parse_args` is an alias of this method.
|
|
108
102
|
* @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
|
|
109
|
-
* @returns {import('../../types/
|
|
103
|
+
* @returns {import('../../types/cli').ParsedArgs} - The parsed arguments
|
|
110
104
|
*/
|
|
111
105
|
parseArgs (args = process.argv.slice(2)) {
|
|
112
106
|
if (!NON_SERVER_ARGS.has(args[0])) {
|
|
@@ -258,19 +252,16 @@ class ArgParser {
|
|
|
258
252
|
}
|
|
259
253
|
|
|
260
254
|
/**
|
|
261
|
-
* Creates a {@link ArgParser} instance
|
|
262
|
-
* beforehand, and finalizes the config schema.
|
|
255
|
+
* Creates a {@link ArgParser} instance; finalizes the config schema.
|
|
263
256
|
*
|
|
264
257
|
* @constructs ArgParser
|
|
265
258
|
* @param {boolean} [debug] - If `true`, throw instead of exit upon parsing error
|
|
266
|
-
* @returns {
|
|
259
|
+
* @returns {ArgParser}
|
|
267
260
|
*/
|
|
268
|
-
|
|
269
|
-
await B.all([driverConfig.read(), pluginConfig.read()]);
|
|
261
|
+
function getParser (debug) {
|
|
270
262
|
finalizeSchema();
|
|
271
263
|
|
|
272
264
|
return new ArgParser(debug);
|
|
273
265
|
}
|
|
274
266
|
|
|
275
|
-
export default getParser;
|
|
276
267
|
export { getParser, ArgParser };
|
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import ExtensionCommand from './extension-command';
|
|
3
|
-
import {
|
|
4
|
-
import { KNOWN_PLUGINS } from '../plugins';
|
|
3
|
+
import { KNOWN_PLUGINS } from '../constants';
|
|
5
4
|
|
|
6
5
|
const REQ_PLUGIN_FIELDS = ['pluginName', 'mainClass'];
|
|
7
6
|
|
|
8
7
|
export default class PluginCommand extends ExtensionCommand {
|
|
9
8
|
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {PluginCommandOptions} opts
|
|
12
|
+
*/
|
|
10
13
|
constructor ({config, json}) {
|
|
11
|
-
super({config, json
|
|
14
|
+
super({config, json});
|
|
12
15
|
this.knownExtensions = KNOWN_PLUGINS;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
async install ({plugin, installType, packageName}) {
|
|
16
|
-
return await super.
|
|
19
|
+
return await super._install({ext: plugin, installType, packageName});
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
async uninstall ({plugin}) {
|
|
20
|
-
return await super.
|
|
23
|
+
return await super._uninstall({ext: plugin});
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
async update ({plugin, unsafe}) {
|
|
24
|
-
return await super.
|
|
27
|
+
return await super._update({ext: plugin, unsafe});
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
async run ({plugin, scriptName}) {
|
|
28
|
-
return await super.
|
|
31
|
+
return await super._run({ext: plugin, scriptName});
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
getPostInstallText ({extName, extData}) {
|
|
@@ -45,3 +48,9 @@ export default class PluginCommand extends ExtensionCommand {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @typedef PluginCommandOptions
|
|
54
|
+
* @property {import('../extension/extension-config').ExtensionConfig<import('../extension/manifest').PluginType>} config
|
|
55
|
+
* @property {boolean} json
|
|
56
|
+
*/
|
package/lib/cli/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ const JSON_SPACES = 4;
|
|
|
7
7
|
/***
|
|
8
8
|
* Log an error to the console and exit the process.
|
|
9
9
|
* @param {boolean} json - whether we should log json or text
|
|
10
|
-
* @param {
|
|
10
|
+
* @param {any} msg - error message, object, Error instance, etc.
|
|
11
11
|
*/
|
|
12
12
|
function errAndQuit (json, msg) {
|
|
13
13
|
if (json) {
|
package/lib/config-file.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
|
|
3
2
|
import betterAjvErrors from '@sidvind/better-ajv-errors';
|
|
4
3
|
import { lilconfig } from 'lilconfig';
|
|
@@ -181,17 +180,17 @@ export function normalizeConfig (config) {
|
|
|
181
180
|
|
|
182
181
|
/**
|
|
183
182
|
* Result of calling {@link readConfigFile}.
|
|
184
|
-
* @typedef
|
|
183
|
+
* @typedef ReadConfigFileResult
|
|
185
184
|
* @property {import('ajv').ErrorObject[]} [errors] - Validation errors
|
|
186
185
|
* @property {string} [filepath] - The path to the config file, if found
|
|
187
186
|
* @property {boolean} [isEmpty] - If `true`, the config file exists but is empty
|
|
188
187
|
* @property {NormalizedAppiumConfig} [config] - The parsed configuration
|
|
189
|
-
* @property {string|
|
|
188
|
+
* @property {string|import('@sidvind/better-ajv-errors').IOutputError[]} [reason] - Human-readable error messages and suggestions. If the `pretty` option is `true`, this will be a nice string to print.
|
|
190
189
|
*/
|
|
191
190
|
|
|
192
191
|
/**
|
|
193
192
|
* Options for {@link readConfigFile}.
|
|
194
|
-
* @typedef
|
|
193
|
+
* @typedef ReadConfigFileOptions
|
|
195
194
|
* @property {boolean} [pretty=true] If `false`, do not use color and fancy formatting in the `reason` property of the {@link ReadConfigFileResult}. The value of `reason` is then suitable for machine-reading.
|
|
196
195
|
*/
|
|
197
196
|
|
|
@@ -202,12 +201,12 @@ export function normalizeConfig (config) {
|
|
|
202
201
|
|
|
203
202
|
/**
|
|
204
203
|
* The contents of an Appium config file. Generated from schema
|
|
205
|
-
* @typedef {import('
|
|
204
|
+
* @typedef {import('@appium/types').AppiumConfig} AppiumConfig
|
|
206
205
|
*/
|
|
207
206
|
|
|
208
207
|
/**
|
|
209
208
|
* The contents of an Appium config file with camelcased property names (and using `appiumCliDest` value if present). Generated from {@link AppiumConfig}
|
|
210
|
-
* @typedef {import('
|
|
209
|
+
* @typedef {import('@appium/types').NormalizedAppiumConfig} NormalizedAppiumConfig
|
|
211
210
|
*/
|
|
212
211
|
|
|
213
212
|
/**
|
|
@@ -217,7 +216,7 @@ export function normalizeConfig (config) {
|
|
|
217
216
|
|
|
218
217
|
/**
|
|
219
218
|
* Options for {@link formatErrors}.
|
|
220
|
-
* @typedef
|
|
219
|
+
* @typedef FormatConfigErrorsOptions
|
|
221
220
|
* @property {import('./config-file').RawJson} [json] - Raw JSON config (as string)
|
|
222
221
|
* @property {boolean} [pretty=true] - Whether to format errors as a CLI-friendly string
|
|
223
222
|
* @property {string} [schemaId] - Specific ID of a prop; otherwise entire schema
|
package/lib/config.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
1
|
/* eslint-disable no-console */
|
|
4
2
|
import _ from 'lodash';
|
|
5
|
-
import {
|
|
3
|
+
import { system, fs } from '@appium/support';
|
|
6
4
|
import axios from 'axios';
|
|
7
5
|
import { exec } from 'teen_process';
|
|
8
|
-
import { rootDir } from './utils';
|
|
9
6
|
import logger from './logger';
|
|
10
7
|
import semver from 'semver';
|
|
11
8
|
import findUp from 'find-up';
|
|
@@ -20,6 +17,9 @@ const GIT_META_ROOT = '.git';
|
|
|
20
17
|
const GIT_BINARY = `git${system.isWindows() ? '.exe' : ''}`;
|
|
21
18
|
const GITHUB_API = 'https://api.github.com/repos/appium/appium';
|
|
22
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @type {import('../types/cli').BuildInfo}
|
|
22
|
+
*/
|
|
23
23
|
const BUILD_INFO = {
|
|
24
24
|
version: APPIUM_VER,
|
|
25
25
|
};
|
|
@@ -35,7 +35,7 @@ async function updateBuildInfo (useGithubApiFallback = false) {
|
|
|
35
35
|
}
|
|
36
36
|
BUILD_INFO['git-sha'] = sha;
|
|
37
37
|
const built = await getGitTimestamp(sha, useGithubApiFallback);
|
|
38
|
-
if (
|
|
38
|
+
if (built) {
|
|
39
39
|
BUILD_INFO.built = built;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -86,7 +86,7 @@ async function getGitRev (useGithubApiFallback = false) {
|
|
|
86
86
|
/**
|
|
87
87
|
* @param {string} commitSha
|
|
88
88
|
* @param {boolean} [useGithubApiFallback]
|
|
89
|
-
* @returns {Promise<
|
|
89
|
+
* @returns {Promise<string?>}
|
|
90
90
|
*/
|
|
91
91
|
async function getGitTimestamp (commitSha, useGithubApiFallback = false) {
|
|
92
92
|
const gitRoot = await findGitRoot();
|
|
@@ -122,10 +122,11 @@ async function getGitTimestamp (commitSha, useGithubApiFallback = false) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
125
|
+
* Mutable object containing Appium build information. By default it
|
|
126
126
|
* only contains the Appium version, but is updated with the build timestamp
|
|
127
127
|
* and git commit hash asynchronously as soon as `updateBuildInfo` is called
|
|
128
128
|
* and succeeds.
|
|
129
|
+
* @returns {import('../types/cli').BuildInfo}
|
|
129
130
|
*/
|
|
130
131
|
function getBuildInfo () {
|
|
131
132
|
return BUILD_INFO;
|
|
@@ -167,7 +168,7 @@ function getNonDefaultServerArgs (parsedArgs) {
|
|
|
167
168
|
* Flattens parsed args into a single level object for comparison with
|
|
168
169
|
* flattened defaults across server args and extension args.
|
|
169
170
|
* @param {ParsedArgs} args
|
|
170
|
-
* @returns {Record<string, { value: any, argSpec:
|
|
171
|
+
* @returns {Record<string, { value: any, argSpec: ArgSpec }>}
|
|
171
172
|
*/
|
|
172
173
|
const flatten = (args) => {
|
|
173
174
|
const argSpecs = getAllArgSpecs();
|
|
@@ -176,7 +177,7 @@ function getNonDefaultServerArgs (parsedArgs) {
|
|
|
176
177
|
acc[argSpec.dest] = {value: _.get(args, argSpec.dest), argSpec};
|
|
177
178
|
}
|
|
178
179
|
return acc;
|
|
179
|
-
}, /** @type {Record<string, { value: any, argSpec:
|
|
180
|
+
}, /** @type {Record<string, { value: any, argSpec: ArgSpec }>} */({}));
|
|
180
181
|
|
|
181
182
|
return flattened;
|
|
182
183
|
};
|
|
@@ -289,19 +290,23 @@ function showConfig (nonDefaultPreConfigParsedArgs, configResult, defaults, pars
|
|
|
289
290
|
*/
|
|
290
291
|
async function validateTmpDir (tmpDir) {
|
|
291
292
|
try {
|
|
292
|
-
await mkdirp(tmpDir);
|
|
293
|
+
await fs.mkdirp(tmpDir);
|
|
293
294
|
} catch (e) {
|
|
294
295
|
throw new Error(`We could not ensure that the temp dir you specified ` +
|
|
295
296
|
`(${tmpDir}) exists. Please make sure it's writeable.`);
|
|
296
297
|
}
|
|
297
298
|
}
|
|
298
299
|
|
|
300
|
+
const rootDir = fs.findRoot(__dirname);
|
|
301
|
+
|
|
299
302
|
export {
|
|
300
303
|
getBuildInfo, checkNodeOk, showBuildInfo,
|
|
301
304
|
warnNodeDeprecations, validateTmpDir, getNonDefaultServerArgs,
|
|
302
|
-
getGitRev, APPIUM_VER, updateBuildInfo, showConfig
|
|
305
|
+
getGitRev, APPIUM_VER, updateBuildInfo, showConfig, rootDir
|
|
303
306
|
};
|
|
304
307
|
|
|
305
308
|
/**
|
|
306
|
-
* @typedef {import('../types/
|
|
309
|
+
* @typedef {import('../types/cli').ParsedArgs} ParsedArgs
|
|
310
|
+
* @typedef {import('./schema/arg-spec').ArgSpec} ArgSpec
|
|
307
311
|
*/
|
|
312
|
+
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The name of the extension type for drivers
|
|
6
|
+
*/
|
|
7
|
+
export const DRIVER_TYPE = 'driver';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The name of the extension type for plugins
|
|
11
|
+
*/
|
|
12
|
+
export const PLUGIN_TYPE = 'plugin';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The `server` command of the `appium` CLI
|
|
16
|
+
*/
|
|
17
|
+
export const SERVER_SUBCOMMAND = 'server';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The value of `--use-plugins` if _all_ plugins should be loaded
|
|
21
|
+
*/
|
|
22
|
+
export const USE_ALL_PLUGINS = 'all';
|
|
23
|
+
|
|
24
|
+
// This is a map of plugin names to npm packages representing those plugins.
|
|
25
|
+
// The plugins in this list will be available to the CLI so users can just
|
|
26
|
+
// type 'appium plugin install 'name'', rather than having to specify the full
|
|
27
|
+
// npm package. I.e., these are the officially recognized plugins.
|
|
28
|
+
export const KNOWN_PLUGINS = Object.freeze(
|
|
29
|
+
/** @type {const} */ ({
|
|
30
|
+
images: '@appium/images-plugin',
|
|
31
|
+
'execute-driver': '@appium/execute-driver-plugin',
|
|
32
|
+
'relaxed-caps': '@appium/relaxed-caps-plugin',
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// This is a map of driver names to npm packages representing those drivers.
|
|
37
|
+
// The drivers in this list will be available to the CLI so users can just
|
|
38
|
+
// type 'appium driver install 'name'', rather than having to specify the full
|
|
39
|
+
// npm package. I.e., these are the officially recognized drivers.
|
|
40
|
+
export const KNOWN_DRIVERS = Object.freeze(
|
|
41
|
+
/** @type {const} */ ({
|
|
42
|
+
uiautomator2: 'appium-uiautomator2-driver',
|
|
43
|
+
xcuitest: 'appium-xcuitest-driver',
|
|
44
|
+
youiengine: 'appium-youiengine-driver',
|
|
45
|
+
windows: 'appium-windows-driver',
|
|
46
|
+
mac: 'appium-mac-driver',
|
|
47
|
+
mac2: 'appium-mac2-driver',
|
|
48
|
+
espresso: 'appium-espresso-driver',
|
|
49
|
+
tizen: 'appium-tizen-driver',
|
|
50
|
+
flutter: 'appium-flutter-driver',
|
|
51
|
+
safari: 'appium-safari-driver',
|
|
52
|
+
gecko: 'appium-geckodriver',
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Relative path to directory containing any Appium internal files
|
|
58
|
+
*/
|
|
59
|
+
export const CACHE_DIR_RELATIVE_PATH = path.join(
|
|
60
|
+
'node_modules',
|
|
61
|
+
'.cache',
|
|
62
|
+
'appium',
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Relative path to hashfile (from `APPIUM_HOME`) of consuming project's `package.json` (if it exists)
|
|
67
|
+
*/
|
|
68
|
+
export const PKG_HASHFILE_RELATIVE_PATH = path.join(
|
|
69
|
+
CACHE_DIR_RELATIVE_PATH,
|
|
70
|
+
'package.hash',
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
export const EXT_SUBCOMMAND_LIST = 'list';
|
|
75
|
+
export const EXT_SUBCOMMAND_INSTALL = 'install';
|
|
76
|
+
export const EXT_SUBCOMMAND_UNINSTALL = 'uninstall';
|
|
77
|
+
export const EXT_SUBCOMMAND_UPDATE = 'update';
|
|
78
|
+
export const EXT_SUBCOMMAND_RUN = 'run';
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { DRIVER_TYPE } from '../constants';
|
|
4
|
+
import log from '../logger';
|
|
5
|
+
import { ExtensionConfig } from './extension-config';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @extends {ExtensionConfig<DriverType>}
|
|
9
|
+
*/
|
|
10
|
+
export class DriverConfig extends ExtensionConfig {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A set of unique automation names used by drivers.
|
|
14
|
+
* @type {Set<string>}
|
|
15
|
+
*/
|
|
16
|
+
knownAutomationNames;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A mapping of {@link Manifest} instances to {@link DriverConfig} instances.
|
|
20
|
+
*
|
|
21
|
+
* `Manifest` and `ExtensionConfig` have a one-to-many relationship; each `Manifest` should be associated with a `DriverConfig` and a `PluginConfig`; no more, no less.
|
|
22
|
+
*
|
|
23
|
+
* This variable tracks the `Manifest`-to-`DriverConfig` portion.
|
|
24
|
+
*
|
|
25
|
+
* @type {WeakMap<Manifest,DriverConfig>}
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
static _instances = new WeakMap();
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Call {@link DriverConfig.create} instead.
|
|
32
|
+
* @private
|
|
33
|
+
* @param {import('./manifest').Manifest} manifest - Manifest instance
|
|
34
|
+
* @param {DriverConfigOptions} [opts]
|
|
35
|
+
*/
|
|
36
|
+
constructor (manifest, {logFn, extData} = {}) {
|
|
37
|
+
super(DRIVER_TYPE, manifest, logFn);
|
|
38
|
+
|
|
39
|
+
this.knownAutomationNames = new Set();
|
|
40
|
+
|
|
41
|
+
if (extData) {
|
|
42
|
+
this.validate(extData);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a new {@link DriverConfig} instance for a {@link Manifest} instance.
|
|
48
|
+
*
|
|
49
|
+
* @param {Manifest} manifest
|
|
50
|
+
* @param {DriverConfigOptions} [opts]
|
|
51
|
+
* @throws If `manifest` already associated with a `DriverConfig`
|
|
52
|
+
* @returns {DriverConfig}
|
|
53
|
+
*/
|
|
54
|
+
static create (manifest, {extData, logFn} = {}) {
|
|
55
|
+
const instance = new DriverConfig(manifest, {logFn, extData});
|
|
56
|
+
if (DriverConfig.getInstance(manifest)) {
|
|
57
|
+
throw new Error(`Manifest with APPIUM_HOME ${manifest.appiumHome} already has a DriverConfig; use DriverConfig.getInstance() to retrieve it.`);
|
|
58
|
+
}
|
|
59
|
+
DriverConfig._instances.set(manifest, instance);
|
|
60
|
+
return instance;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Returns a DriverConfig associated with a Manifest
|
|
65
|
+
* @param {Manifest} manifest
|
|
66
|
+
* @returns {DriverConfig|undefined}
|
|
67
|
+
*/
|
|
68
|
+
static getInstance (manifest) {
|
|
69
|
+
return DriverConfig._instances.get(manifest);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Checks extensions for problems
|
|
74
|
+
* @param {ExtRecord<DriverType>} exts
|
|
75
|
+
*/
|
|
76
|
+
validate (exts) {
|
|
77
|
+
this.knownAutomationNames.clear();
|
|
78
|
+
return super.validate(exts);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {ExtManifest<DriverType>} extData
|
|
83
|
+
* @returns {import('./extension-config').Problem[]}
|
|
84
|
+
*/
|
|
85
|
+
getConfigProblems (extData) {
|
|
86
|
+
const problems = [];
|
|
87
|
+
const {platformNames, automationName} = extData;
|
|
88
|
+
|
|
89
|
+
if (!_.isArray(platformNames)) {
|
|
90
|
+
problems.push({
|
|
91
|
+
err: 'Missing or incorrect supported platformNames list.',
|
|
92
|
+
val: platformNames
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
if (_.isEmpty(platformNames)) {
|
|
96
|
+
problems.push({
|
|
97
|
+
err: 'Empty platformNames list.',
|
|
98
|
+
val: platformNames
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
for (const pName of platformNames) {
|
|
102
|
+
if (!_.isString(pName)) {
|
|
103
|
+
problems.push({err: 'Incorrectly formatted platformName.', val: pName});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!_.isString(automationName)) {
|
|
110
|
+
problems.push({err: 'Missing or incorrect automationName', val: automationName});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (this.knownAutomationNames.has(automationName)) {
|
|
114
|
+
problems.push({
|
|
115
|
+
err: 'Multiple drivers claim support for the same automationName',
|
|
116
|
+
val: automationName
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// should we retain the name at the end of this function, once we've checked there are no problems?
|
|
121
|
+
this.knownAutomationNames.add(automationName);
|
|
122
|
+
|
|
123
|
+
return problems;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {ExtName<DriverType>} driverName
|
|
128
|
+
* @param {ExtManifest<DriverType>} extData
|
|
129
|
+
* @returns {string}
|
|
130
|
+
*/
|
|
131
|
+
extensionDesc (driverName, {version, automationName}) {
|
|
132
|
+
return `${driverName}@${version} (automationName '${automationName}')`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Given capabilities, find a matching driver within the config. Load its class and return it along with version and driver name.
|
|
137
|
+
* @param {Capabilities} caps
|
|
138
|
+
* @returns {MatchedDriver}
|
|
139
|
+
*/
|
|
140
|
+
findMatchingDriver ({automationName, platformName}) {
|
|
141
|
+
if (!_.isString(platformName)) {
|
|
142
|
+
throw new Error('You must include a platformName capability');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!_.isString(automationName)) {
|
|
146
|
+
throw new Error('You must include an automationName capability');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
log.info(`Attempting to find matching driver for automationName ` +
|
|
150
|
+
`'${automationName}' and platformName '${platformName}'`);
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const {
|
|
154
|
+
driverName,
|
|
155
|
+
mainClass,
|
|
156
|
+
version,
|
|
157
|
+
} = this._getDriverBySupport(automationName, platformName);
|
|
158
|
+
log.info(`The '${driverName}' driver was installed and matched caps.`);
|
|
159
|
+
log.info(`Will require it at ${this.getInstallPath(driverName)}`);
|
|
160
|
+
const driver = this.require(driverName);
|
|
161
|
+
if (!driver) {
|
|
162
|
+
throw new Error(`Driver '${driverName}' did not export a class with name '${mainClass}'. Contact the author of the driver!`);
|
|
163
|
+
}
|
|
164
|
+
return {driver, version, driverName};
|
|
165
|
+
} catch (err) {
|
|
166
|
+
const msg = `Could not find a driver for automationName ` +
|
|
167
|
+
`'${automationName}' and platformName ${platformName}'. ` +
|
|
168
|
+
`Have you installed a driver that supports those ` +
|
|
169
|
+
`capabilities? Run 'appium driver list --installed' to see. ` +
|
|
170
|
+
`(Lower-level error: ${err.message})`;
|
|
171
|
+
throw new Error(msg);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Given an automation name and platform name, find a suitable driver and return its extension data.
|
|
177
|
+
* @param {string} matchAutomationName
|
|
178
|
+
* @param {string} matchPlatformName
|
|
179
|
+
* @returns {ExtMetadata<DriverType> & import('../../types/appium-manifest').InternalMetadata & import('../../types/external-manifest').CommonMetadata}
|
|
180
|
+
*/
|
|
181
|
+
_getDriverBySupport (matchAutomationName, matchPlatformName) {
|
|
182
|
+
const drivers = this.installedExtensions;
|
|
183
|
+
for (const [driverName, driverData] of _.toPairs(drivers)) {
|
|
184
|
+
const {automationName, platformNames} = driverData;
|
|
185
|
+
const aNameMatches = automationName.toLowerCase() === matchAutomationName.toLowerCase();
|
|
186
|
+
const pNameMatches = _.includes(platformNames.map(_.toLower),
|
|
187
|
+
matchPlatformName.toLowerCase());
|
|
188
|
+
|
|
189
|
+
if (aNameMatches && pNameMatches) {
|
|
190
|
+
return {driverName, ...driverData};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (aNameMatches) {
|
|
194
|
+
throw new Error(`Driver '${driverName}' supports automationName ` +
|
|
195
|
+
`'${automationName}', but Appium could not find ` +
|
|
196
|
+
`support for platformName '${matchPlatformName}'. Supported ` +
|
|
197
|
+
`platformNames are: ` +
|
|
198
|
+
JSON.stringify(platformNames));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
throw new Error(`Could not find installed driver to support given caps`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @typedef DriverConfigOptions
|
|
208
|
+
* @property {import('./extension-config').ExtensionLogFn} [logFn] - Optional logging function
|
|
209
|
+
* @property {ManifestData['drivers']} [extData] - Extension data
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @template T
|
|
214
|
+
* @typedef {import('../../types').ExtMetadata<T>} ExtMetadata
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @template T
|
|
219
|
+
* @typedef {import('../../types').ExtManifest<T>} ExtManifest
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @typedef {import('../../types').ManifestData} ManifestData
|
|
224
|
+
* @typedef {import('../../types').DriverType} DriverType
|
|
225
|
+
* @typedef {import('./manifest').Manifest} Manifest
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @template T
|
|
230
|
+
* @typedef {import('../../types').ExtRecord<T>} ExtRecord
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @template T
|
|
235
|
+
* @typedef {import('../../types').ExtName<T>} ExtName
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Return value of {@linkcode DriverConfig.findMatchingDriver}
|
|
241
|
+
* @typedef MatchedDriver
|
|
242
|
+
* @property {import('../../types/extension').DriverClass} driver
|
|
243
|
+
* @property {string} version
|
|
244
|
+
* @property {string} driverName
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @typedef {import('@appium/types').Capabilities} Capabilities
|
|
249
|
+
*/
|