appium 2.0.0-beta.23 → 2.0.0-beta.26

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.
Files changed (125) hide show
  1. package/README.md +1 -2
  2. package/build/lib/appium-config.schema.json +278 -0
  3. package/build/lib/appium.js +62 -71
  4. package/build/lib/cli/args.js +31 -53
  5. package/build/lib/cli/driver-command.js +5 -9
  6. package/build/lib/cli/extension-command.js +73 -64
  7. package/build/lib/cli/extension.js +10 -23
  8. package/build/lib/cli/parser.js +10 -20
  9. package/build/lib/cli/plugin-command.js +5 -9
  10. package/build/lib/cli/utils.js +2 -4
  11. package/build/lib/config-file.js +5 -10
  12. package/build/lib/config.js +67 -30
  13. package/build/lib/constants.js +60 -0
  14. package/build/lib/extension/driver-config.js +190 -0
  15. package/build/lib/extension/extension-config.js +297 -0
  16. package/build/lib/extension/index.js +77 -0
  17. package/build/lib/extension/manifest.js +246 -0
  18. package/build/lib/extension/package-changed.js +68 -0
  19. package/build/lib/extension/plugin-config.js +87 -0
  20. package/build/lib/grid-register.js +2 -4
  21. package/build/lib/logger.js +2 -4
  22. package/build/lib/logsink.js +2 -4
  23. package/build/lib/main.js +64 -92
  24. package/build/lib/schema/appium-config-schema.js +2 -4
  25. package/build/lib/schema/arg-spec.js +14 -15
  26. package/build/lib/schema/cli-args.js +8 -16
  27. package/build/lib/schema/cli-transformers.js +2 -4
  28. package/build/lib/schema/index.js +2 -4
  29. package/build/lib/schema/keywords.js +2 -4
  30. package/build/lib/schema/schema.js +136 -41
  31. package/build/lib/utils.js +13 -64
  32. package/lib/appium.js +74 -55
  33. package/lib/cli/args.js +36 -37
  34. package/lib/cli/driver-command.js +10 -2
  35. package/lib/cli/extension-command.js +216 -135
  36. package/lib/cli/extension.js +7 -15
  37. package/lib/cli/parser.js +7 -15
  38. package/lib/cli/plugin-command.js +1 -2
  39. package/lib/config-file.js +12 -15
  40. package/lib/config.js +111 -36
  41. package/lib/constants.js +79 -0
  42. package/lib/extension/driver-config.js +230 -0
  43. package/lib/extension/extension-config.js +459 -0
  44. package/lib/extension/index.js +103 -0
  45. package/lib/extension/manifest.js +590 -0
  46. package/lib/extension/package-changed.js +64 -0
  47. package/lib/extension/plugin-config.js +111 -0
  48. package/lib/grid-register.js +4 -4
  49. package/lib/main.js +110 -96
  50. package/lib/schema/arg-spec.js +11 -5
  51. package/lib/schema/cli-args.js +7 -30
  52. package/lib/schema/keywords.js +1 -1
  53. package/lib/schema/schema.js +206 -48
  54. package/lib/utils.js +27 -58
  55. package/package.json +29 -21
  56. package/{postinstall.js → scripts/postinstall.js} +1 -1
  57. package/types/types.d.ts +72 -28
  58. package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
  59. package/build/check-npm-pack-files.js +0 -23
  60. package/build/commands-yml/parse.js +0 -319
  61. package/build/commands-yml/validator.js +0 -130
  62. package/build/index.js +0 -19
  63. package/build/lib/cli/npm.js +0 -220
  64. package/build/lib/driver-config.js +0 -100
  65. package/build/lib/drivers.js +0 -100
  66. package/build/lib/ext-config-io.js +0 -165
  67. package/build/lib/extension-config.js +0 -320
  68. package/build/lib/plugin-config.js +0 -69
  69. package/build/lib/plugins.js +0 -16
  70. package/build/postinstall.js +0 -90
  71. package/build/test/cli/cli-e2e-specs.js +0 -221
  72. package/build/test/cli/cli-helpers.js +0 -86
  73. package/build/test/cli/cli-specs.js +0 -71
  74. package/build/test/cli/fixtures/test-driver/package.json +0 -27
  75. package/build/test/cli/schema-args-specs.js +0 -48
  76. package/build/test/cli/schema-e2e-specs.js +0 -47
  77. package/build/test/config-e2e-specs.js +0 -112
  78. package/build/test/config-file-e2e-specs.js +0 -209
  79. package/build/test/config-file-specs.js +0 -281
  80. package/build/test/config-specs.js +0 -159
  81. package/build/test/driver-e2e-specs.js +0 -435
  82. package/build/test/driver-specs.js +0 -321
  83. package/build/test/ext-config-io-specs.js +0 -181
  84. package/build/test/extension-config-specs.js +0 -365
  85. package/build/test/fixtures/allow-feat.txt +0 -5
  86. package/build/test/fixtures/caps.json +0 -3
  87. package/build/test/fixtures/config/allow-insecure.txt +0 -3
  88. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +0 -5
  89. package/build/test/fixtures/config/appium.config.bad.json +0 -32
  90. package/build/test/fixtures/config/appium.config.ext-good.json +0 -9
  91. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +0 -10
  92. package/build/test/fixtures/config/appium.config.good.js +0 -40
  93. package/build/test/fixtures/config/appium.config.good.json +0 -33
  94. package/build/test/fixtures/config/appium.config.good.yaml +0 -30
  95. package/build/test/fixtures/config/appium.config.invalid.json +0 -31
  96. package/build/test/fixtures/config/appium.config.security-array.json +0 -5
  97. package/build/test/fixtures/config/appium.config.security-delimited.json +0 -5
  98. package/build/test/fixtures/config/appium.config.security-path.json +0 -5
  99. package/build/test/fixtures/config/driver-fake.config.json +0 -8
  100. package/build/test/fixtures/config/nodeconfig.json +0 -3
  101. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  102. package/build/test/fixtures/default-args.js +0 -35
  103. package/build/test/fixtures/deny-feat.txt +0 -5
  104. package/build/test/fixtures/driver.schema.js +0 -20
  105. package/build/test/fixtures/extensions.yaml +0 -27
  106. package/build/test/fixtures/flattened-schema.js +0 -504
  107. package/build/test/fixtures/plugin.schema.js +0 -20
  108. package/build/test/fixtures/schema-with-extensions.js +0 -28
  109. package/build/test/grid-register-specs.js +0 -74
  110. package/build/test/helpers.js +0 -75
  111. package/build/test/logger-specs.js +0 -76
  112. package/build/test/npm-specs.js +0 -20
  113. package/build/test/parser-specs.js +0 -314
  114. package/build/test/plugin-e2e-specs.js +0 -316
  115. package/build/test/schema/arg-spec-specs.js +0 -70
  116. package/build/test/schema/cli-args-specs.js +0 -431
  117. package/build/test/schema/schema-specs.js +0 -389
  118. package/build/test/utils-specs.js +0 -266
  119. package/lib/cli/npm.js +0 -251
  120. package/lib/driver-config.js +0 -101
  121. package/lib/drivers.js +0 -84
  122. package/lib/ext-config-io.js +0 -287
  123. package/lib/extension-config.js +0 -366
  124. package/lib/plugin-config.js +0 -63
  125. package/lib/plugins.js +0 -11
@@ -1,366 +0,0 @@
1
- // @ts-check
2
-
3
- import _ from 'lodash';
4
- import os from 'os';
5
- import path from 'path';
6
- import resolveFrom from 'resolve-from';
7
- import { getExtConfigIOInstance } from './ext-config-io';
8
- import log from './logger';
9
- import { ALLOWED_SCHEMA_EXTENSIONS, isAllowedSchemaFileExtension, registerSchema } from './schema/schema';
10
-
11
- const DEFAULT_APPIUM_HOME = path.resolve(os.homedir(), '.appium');
12
- const APPIUM_HOME = process.env.APPIUM_HOME || DEFAULT_APPIUM_HOME;
13
-
14
- const INSTALL_TYPE_NPM = 'npm';
15
- const INSTALL_TYPE_LOCAL = 'local';
16
- const INSTALL_TYPE_GITHUB = 'github';
17
- const INSTALL_TYPE_GIT = 'git';
18
- const INSTALL_TYPES = [
19
- INSTALL_TYPE_GIT,
20
- INSTALL_TYPE_GITHUB,
21
- INSTALL_TYPE_LOCAL,
22
- INSTALL_TYPE_NPM
23
- ];
24
-
25
- export default class ExtensionConfig {
26
- /**
27
- *
28
- * @param {string} appiumHome - `APPIUM_HOME`
29
- * @param {ExtensionType} extensionType - Type of extension
30
- * @param {(...args: any[]) => void} [logFn]
31
- */
32
- constructor (appiumHome, extensionType, logFn) {
33
- const logger = _.isFunction(logFn) ? logFn : log.error.bind(log);
34
- /** @type {string} */
35
- this.appiumHome = appiumHome;
36
- /** @type {Record<string,object>} */
37
- this.installedExtensions = {};
38
- /** @type {import('./ext-config-io').ExtensionConfigIO} */
39
- this.io = getExtConfigIOInstance(appiumHome);
40
- /** @type {ExtensionType} */
41
- this.extensionType = extensionType;
42
- /** @type {'drivers'|'plugins'} */
43
- this.configKey = `${extensionType}s`; // todo use template type
44
- /**
45
- * @type {(...args: any[])=>void}
46
- */
47
- this.log = logger;
48
- }
49
-
50
- /**
51
- * Checks extensions for problems
52
- * @template ExtData
53
- * @param {ExtData[]} exts - Array of extData objects
54
- * @returns {ExtData[]}
55
- */
56
- validate (exts) {
57
- const foundProblems = {};
58
- for (const [extName, extData] of _.toPairs(exts)) {
59
- foundProblems[extName] = [
60
- ...this.getGenericConfigProblems(extData, extName),
61
- ...this.getConfigProblems(extData, extName),
62
- ...this.getSchemaProblems(extData, extName)
63
- ];
64
- }
65
-
66
- const problemSummaries = [];
67
- for (const [extName, problems] of _.toPairs(foundProblems)) {
68
- if (_.isEmpty(problems)) {
69
- continue;
70
- }
71
- // remove this extension from the list since it's not valid
72
- delete exts[extName];
73
- problemSummaries.push(`${this.extensionType} ${extName} had errors and will not ` +
74
- `be available. Errors:`);
75
- for (const problem of problems) {
76
- problemSummaries.push(` - ${problem.err} (Actual value: ` +
77
- `${JSON.stringify(problem.val)})`);
78
- }
79
- }
80
-
81
- if (!_.isEmpty(problemSummaries)) {
82
- this.log(`Appium encountered one or more errors while validating ` +
83
- `the ${this.configKey} extension file (${this.io.filepath}):`);
84
- for (const summary of problemSummaries) {
85
- this.log(summary);
86
- }
87
- }
88
-
89
- return exts;
90
- }
91
-
92
- /**
93
- * @param {object} extData
94
- * @param {string} extName
95
- * @returns {Problem[]}
96
- */
97
- getSchemaProblems (extData, extName) {
98
- const problems = [];
99
- const {schema: argSchemaPath} = extData;
100
- if (argSchemaPath) {
101
- if (_.isString(argSchemaPath)) {
102
- if (isAllowedSchemaFileExtension(argSchemaPath)) {
103
- try {
104
- this.readExtensionSchema(extName, extData);
105
- } catch (err) {
106
- problems.push({err: `Unable to register schema at path ${argSchemaPath}; ${err.message}`, val: argSchemaPath});
107
- }
108
- } else {
109
- problems.push({
110
- err: `Schema file has unsupported extension. Allowed: ${[...ALLOWED_SCHEMA_EXTENSIONS].join(', ')}`,
111
- val: argSchemaPath
112
- });
113
- }
114
- } else if (_.isPlainObject(argSchemaPath)) {
115
- try {
116
- this.readExtensionSchema(extName, extData);
117
- } catch (err) {
118
- problems.push({err: `Unable to register embedded schema; ${err.message}`, val: argSchemaPath});
119
- }
120
- } else {
121
- problems.push({
122
- err: 'Incorrectly formatted schema field; must be a path to a schema file or a schema object.',
123
- val: argSchemaPath
124
- });
125
- }
126
- }
127
- return problems;
128
- }
129
-
130
- /**
131
- * @param {object} extData
132
- * @param {string} extName
133
- * @returns {Problem[]}
134
- */
135
- // eslint-disable-next-line no-unused-vars
136
- getGenericConfigProblems (extData, extName) {
137
- const {version, pkgName, installSpec, installType, installPath, mainClass} = extData;
138
- const problems = [];
139
-
140
- if (!_.isString(version)) {
141
- problems.push({err: 'Missing or incorrect version', val: version});
142
- }
143
-
144
- if (!_.isString(pkgName)) {
145
- problems.push({err: 'Missing or incorrect NPM package name', val: pkgName});
146
- }
147
-
148
- if (!_.isString(installSpec)) {
149
- problems.push({err: 'Missing or incorrect installation spec', val: installSpec});
150
- }
151
-
152
- if (!_.includes(INSTALL_TYPES, installType)) {
153
- problems.push({err: 'Missing or incorrect install type', val: installType});
154
- }
155
-
156
- if (!_.isString(installPath)) {
157
- problems.push({err: 'Missing or incorrect installation path', val: installPath});
158
- }
159
-
160
- if (!_.isString(mainClass)) {
161
- problems.push({err: 'Missing or incorrect driver class name', val: mainClass});
162
- }
163
-
164
- return problems;
165
- }
166
-
167
- /**
168
- * @param {object} extData
169
- * @param {string} extName
170
- * @returns {Problem[]}
171
- */
172
- // eslint-disable-next-line no-unused-vars
173
- getConfigProblems (extData, extName) {
174
- // shoud override this method if special validation is necessary for this extension type
175
- return [];
176
- }
177
-
178
- /**
179
- * @returns {Promise<typeof this.installedExtensions>}
180
- */
181
- async read () {
182
- const extensions = await this.io.read(this.extensionType);
183
- this.installedExtensions = this.validate(extensions);
184
- return this.installedExtensions;
185
- }
186
-
187
- /**
188
- * @returns {Promise<boolean>}
189
- */
190
- async write () {
191
- return await this.io.write();
192
- }
193
-
194
- /**
195
- * @param {string} extName
196
- * @param {object} extData
197
- * @returns {Promise<void>}
198
- */
199
- async addExtension (extName, extData) {
200
- this.installedExtensions[extName] = extData;
201
- await this.write();
202
- }
203
-
204
- /**
205
- * @param {string} extName
206
- * @param {object} extData
207
- * @returns {Promise<void>}
208
- */
209
- async updateExtension (extName, extData) {
210
- this.installedExtensions[extName] = {
211
- ...this.installedExtensions[extName],
212
- ...extData,
213
- };
214
- await this.write();
215
- }
216
-
217
- /**
218
- * @param {string} extName
219
- * @returns {Promise<void>}
220
- */
221
- async removeExtension (extName) {
222
- delete this.installedExtensions[extName];
223
- await this.write();
224
- }
225
-
226
- print () {
227
- const extNames = Object.keys(this.installedExtensions);
228
- if (_.isEmpty(extNames)) {
229
- log.info(`No ${this.configKey} have been installed. Use the "appium ${this.extensionType}" ` +
230
- 'command to install the one(s) you want to use.');
231
- return;
232
- }
233
-
234
- log.info(`Available ${this.configKey}:`);
235
- for (const [extName, extData] of _.toPairs(this.installedExtensions)) {
236
- log.info(` - ${this.extensionDesc(extName, extData)}`);
237
- }
238
- }
239
-
240
- /**
241
- * Returns a string describing the extension. Subclasses must implement.
242
- * @param {string} extName - Extension name
243
- * @param {object} extData - Extension data
244
- * @returns {string}
245
- * @abstract
246
- */
247
- // eslint-disable-next-line no-unused-vars
248
- extensionDesc (extName, extData) {
249
- throw new Error('This must be implemented in a subclass');
250
- }
251
-
252
- /**
253
- * @param {string} extName
254
- * @returns {string}
255
- */
256
- getExtensionRequirePath (extName) {
257
- const {pkgName, installPath} = this.installedExtensions[extName];
258
- return path.resolve(this.appiumHome, installPath, 'node_modules', pkgName);
259
- }
260
-
261
- /**
262
- * @param {string} extName
263
- * @returns {string}
264
- */
265
- getInstallPath (extName) {
266
- const {installPath} = this.installedExtensions[extName];
267
- return path.resolve(this.appiumHome, installPath);
268
- }
269
-
270
- /**
271
- * Loads extension and returns its main class
272
- * @param {string} extName
273
- * @returns {(...args: any[]) => object }
274
- */
275
- require (extName) {
276
- const {mainClass} = this.installedExtensions[extName];
277
- const reqPath = this.getExtensionRequirePath(extName);
278
- const reqResolved = require.resolve(reqPath);
279
- if (process.env.APPIUM_RELOAD_EXTENSIONS && require.cache[reqResolved]) {
280
- log.debug(`Removing ${reqResolved} from require cache`);
281
- delete require.cache[reqResolved];
282
- }
283
- return require(reqPath)[mainClass];
284
- }
285
-
286
- /**
287
- * @param {string} extName
288
- * @returns {boolean}
289
- */
290
- isInstalled (extName) {
291
- return _.includes(Object.keys(this.installedExtensions), extName);
292
- }
293
-
294
- /**
295
- * Intended to be called by corresponding instance methods of subclass.
296
- * @private
297
- * @param {string} appiumHome
298
- * @param {ExtensionType} extType
299
- * @param {string} extName - Extension name (unique to its type)
300
- * @param {ExtData} extData - Extension config
301
- * @returns {import('ajv').SchemaObject|undefined}
302
- */
303
- static _readExtensionSchema (appiumHome, extType, extName, extData) {
304
- const {installPath, pkgName, schema: argSchemaPath} = extData;
305
- if (!argSchemaPath) {
306
- throw new TypeError(
307
- `No \`schema\` property found in config for ${extType} ${pkgName} -- why is this function being called?`,
308
- );
309
- }
310
- let moduleObject;
311
- if (_.isString(argSchemaPath)) {
312
- const schemaPath = resolveFrom(
313
- path.resolve(appiumHome, installPath),
314
- // this path sep is fine because `resolveFrom` uses Node's module resolution
315
- path.normalize(`${pkgName}/${argSchemaPath}`),
316
- );
317
- moduleObject = require(schemaPath);
318
- } else {
319
- moduleObject = argSchemaPath;
320
- }
321
- // this sucks. default exports should be destroyed
322
- const schema = moduleObject.__esModule
323
- ? moduleObject.default
324
- : moduleObject;
325
- registerSchema(extType, extName, schema);
326
- return schema;
327
- }
328
-
329
- /**
330
- * If an extension provides a schema, this will load the schema and attempt to
331
- * register it with the schema registrar.
332
- * @param {string} extName - Name of extension
333
- * @param {ExtData} extData - Extension data
334
- * @returns {import('ajv').SchemaObject|undefined}
335
- */
336
- readExtensionSchema (extName, extData) {
337
- return ExtensionConfig._readExtensionSchema(this.appiumHome, this.extensionType, extName, extData);
338
- }
339
- }
340
-
341
- export { DRIVER_TYPE, PLUGIN_TYPE } from './ext-config-io';
342
- export {
343
- INSTALL_TYPE_NPM, INSTALL_TYPE_GIT, INSTALL_TYPE_LOCAL, INSTALL_TYPE_GITHUB,
344
- INSTALL_TYPES, DEFAULT_APPIUM_HOME, APPIUM_HOME
345
- };
346
-
347
- /**
348
- * Config problem
349
- * @typedef {Object} Problem
350
- * @property {string} err - Error message
351
- * @property {any} val - Associated value
352
- */
353
-
354
- /**
355
- * Alias
356
- * @typedef {import('./ext-config-io').ExtensionType} ExtensionType
357
- */
358
-
359
- /**
360
- * Extension data (pulled from config YAML)
361
- * @typedef {Object} ExtData
362
- * @property {string|import('ajv').SchemaObject} [schema] - Optional schema path if the ext defined it
363
- * @property {string} pkgName - Package name
364
- * @property {string} installPath - Actually looks more like a module identifier? Resolved from `APPIUM_HOME`
365
- */
366
-
@@ -1,63 +0,0 @@
1
- import _ from 'lodash';
2
- import ExtensionConfig from './extension-config';
3
- import { PLUGIN_TYPE } from './ext-config-io';
4
- import log from './logger';
5
-
6
- export default class PluginConfig extends ExtensionConfig {
7
-
8
- /**
9
- * A mapping of `APPIUM_HOME` values to {@link PluginConfig} instances.
10
- * Each `APPIUM_HOME` should only have one associated `PluginConfig` instance.
11
- * @type {Record<string,PluginConfig>}
12
- * @private
13
- */
14
- static _instances = {};
15
-
16
- /**
17
- * Call {@link PluginConfig.getInstance} instead.
18
- *
19
- * Just calls the superclass' constructor with the correct extension type
20
- * @private
21
- * @param {string} appiumHome - `APPIUM_HOME` path
22
- * @param {(...args: any[]) => void)} [logFn] - Optional logging function
23
- */
24
- constructor (appiumHome, logFn) {
25
- super(appiumHome, PLUGIN_TYPE, logFn);
26
- }
27
-
28
- /**
29
- * Creates or gets an instance of {@link PluginConfig} based value of `appiumHome`
30
- * @param {string} appiumHome - `APPIUM_HOME` path
31
- * @param {(...args: any[]) => void} [logFn] - Optional logging function
32
- * @returns {PluginConfig}
33
- */
34
- static getInstance (appiumHome, logFn) {
35
- const instance = PluginConfig._instances[appiumHome] ?? new PluginConfig(appiumHome, logFn);
36
- PluginConfig._instances[appiumHome] = instance;
37
- return instance;
38
- }
39
-
40
- extensionDesc (pluginName, {version}) {
41
- return `${pluginName}@${version}`;
42
- }
43
-
44
- print (activeNames) {
45
- const pluginNames = Object.keys(this.installedExtensions);
46
-
47
- if (_.isEmpty(pluginNames)) {
48
- log.info(`No plugins have been installed. Use the "appium plugin" ` +
49
- 'command to install the one(s) you want to use.');
50
- return;
51
- }
52
-
53
- log.info(`Available plugins:`);
54
- for (const [pluginName, pluginData] of _.toPairs(this.installedExtensions)) {
55
- const activeTxt = _.includes(activeNames, pluginName) ? ' (ACTIVE)' : '';
56
- log.info(` - ${this.extensionDesc(pluginName, pluginData)}${activeTxt}`);
57
- }
58
-
59
- if (_.isEmpty(activeNames)) {
60
- log.info('No plugins activated. Use the --use-plugins flag with names of plugins to activate');
61
- }
62
- }
63
- }
package/lib/plugins.js DELETED
@@ -1,11 +0,0 @@
1
- // This is a map of plugin names to npm packages representing those plugins.
2
- // The plugins in this list will be available to the CLI so users can just
3
- // type 'appium plugin install 'name'', rather than having to specify the full
4
- // npm package. I.e., these are the officially recognized plugins.
5
- const KNOWN_PLUGINS = {
6
- images: '@appium/images-plugin',
7
- };
8
-
9
- export {
10
- KNOWN_PLUGINS,
11
- };