appium 2.0.0-beta.25 → 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 (124) hide show
  1. package/build/lib/appium-config.schema.json +278 -0
  2. package/build/lib/appium.js +45 -66
  3. package/build/lib/cli/args.js +19 -39
  4. package/build/lib/cli/driver-command.js +5 -9
  5. package/build/lib/cli/extension-command.js +73 -64
  6. package/build/lib/cli/extension.js +10 -23
  7. package/build/lib/cli/parser.js +9 -19
  8. package/build/lib/cli/plugin-command.js +5 -9
  9. package/build/lib/cli/utils.js +2 -4
  10. package/build/lib/config-file.js +2 -4
  11. package/build/lib/config.js +7 -6
  12. package/build/lib/constants.js +60 -0
  13. package/build/lib/extension/driver-config.js +190 -0
  14. package/build/lib/extension/extension-config.js +297 -0
  15. package/build/lib/extension/index.js +77 -0
  16. package/build/lib/extension/manifest.js +246 -0
  17. package/build/lib/extension/package-changed.js +68 -0
  18. package/build/lib/extension/plugin-config.js +87 -0
  19. package/build/lib/grid-register.js +2 -4
  20. package/build/lib/logger.js +2 -4
  21. package/build/lib/logsink.js +2 -4
  22. package/build/lib/main.js +40 -68
  23. package/build/lib/schema/appium-config-schema.js +2 -4
  24. package/build/lib/schema/arg-spec.js +11 -14
  25. package/build/lib/schema/cli-args.js +2 -4
  26. package/build/lib/schema/cli-transformers.js +2 -4
  27. package/build/lib/schema/index.js +2 -4
  28. package/build/lib/schema/keywords.js +2 -4
  29. package/build/lib/schema/schema.js +55 -37
  30. package/build/lib/utils.js +1 -32
  31. package/lib/appium.js +50 -68
  32. package/lib/cli/args.js +19 -23
  33. package/lib/cli/driver-command.js +10 -2
  34. package/lib/cli/extension-command.js +216 -135
  35. package/lib/cli/extension.js +7 -15
  36. package/lib/cli/parser.js +6 -14
  37. package/lib/cli/plugin-command.js +1 -2
  38. package/lib/config-file.js +3 -3
  39. package/lib/config.js +5 -4
  40. package/lib/constants.js +79 -0
  41. package/lib/extension/driver-config.js +230 -0
  42. package/lib/extension/extension-config.js +459 -0
  43. package/lib/extension/index.js +103 -0
  44. package/lib/extension/manifest.js +590 -0
  45. package/lib/extension/package-changed.js +64 -0
  46. package/lib/extension/plugin-config.js +111 -0
  47. package/lib/grid-register.js +4 -4
  48. package/lib/main.js +51 -88
  49. package/lib/schema/arg-spec.js +2 -2
  50. package/lib/schema/cli-args.js +1 -0
  51. package/lib/schema/keywords.js +1 -1
  52. package/lib/schema/schema.js +60 -28
  53. package/lib/utils.js +2 -32
  54. package/package.json +29 -21
  55. package/{postinstall.js → scripts/postinstall.js} +1 -1
  56. package/types/types.d.ts +70 -31
  57. package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
  58. package/build/check-npm-pack-files.js +0 -23
  59. package/build/commands-yml/parse.js +0 -319
  60. package/build/commands-yml/validator.js +0 -130
  61. package/build/index.js +0 -19
  62. package/build/lib/cli/npm.js +0 -220
  63. package/build/lib/driver-config.js +0 -100
  64. package/build/lib/drivers.js +0 -100
  65. package/build/lib/ext-config-io.js +0 -165
  66. package/build/lib/extension-config.js +0 -320
  67. package/build/lib/plugin-config.js +0 -69
  68. package/build/lib/plugins.js +0 -18
  69. package/build/postinstall.js +0 -90
  70. package/build/test/cli/cli-e2e-specs.js +0 -221
  71. package/build/test/cli/cli-helpers.js +0 -86
  72. package/build/test/cli/cli-specs.js +0 -71
  73. package/build/test/cli/fixtures/test-driver/package.json +0 -27
  74. package/build/test/cli/schema-args-specs.js +0 -48
  75. package/build/test/cli/schema-e2e-specs.js +0 -47
  76. package/build/test/config-e2e-specs.js +0 -112
  77. package/build/test/config-file-e2e-specs.js +0 -191
  78. package/build/test/config-file-specs.js +0 -281
  79. package/build/test/config-specs.js +0 -258
  80. package/build/test/driver-e2e-specs.js +0 -435
  81. package/build/test/driver-specs.js +0 -386
  82. package/build/test/ext-config-io-specs.js +0 -181
  83. package/build/test/extension-config-specs.js +0 -365
  84. package/build/test/fixtures/allow-feat.txt +0 -5
  85. package/build/test/fixtures/caps.json +0 -3
  86. package/build/test/fixtures/config/allow-insecure.txt +0 -3
  87. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +0 -5
  88. package/build/test/fixtures/config/appium.config.bad.json +0 -32
  89. package/build/test/fixtures/config/appium.config.ext-good.json +0 -9
  90. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +0 -10
  91. package/build/test/fixtures/config/appium.config.good.js +0 -40
  92. package/build/test/fixtures/config/appium.config.good.json +0 -33
  93. package/build/test/fixtures/config/appium.config.good.yaml +0 -30
  94. package/build/test/fixtures/config/appium.config.invalid.json +0 -31
  95. package/build/test/fixtures/config/appium.config.security-array.json +0 -5
  96. package/build/test/fixtures/config/appium.config.security-delimited.json +0 -5
  97. package/build/test/fixtures/config/appium.config.security-path.json +0 -5
  98. package/build/test/fixtures/config/driver-fake.config.json +0 -8
  99. package/build/test/fixtures/config/nodeconfig.json +0 -3
  100. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  101. package/build/test/fixtures/default-args.js +0 -35
  102. package/build/test/fixtures/deny-feat.txt +0 -5
  103. package/build/test/fixtures/driver.schema.js +0 -20
  104. package/build/test/fixtures/extensions.yaml +0 -27
  105. package/build/test/fixtures/flattened-schema.js +0 -532
  106. package/build/test/fixtures/plugin.schema.js +0 -20
  107. package/build/test/fixtures/schema-with-extensions.js +0 -28
  108. package/build/test/grid-register-specs.js +0 -74
  109. package/build/test/helpers.js +0 -75
  110. package/build/test/logger-specs.js +0 -76
  111. package/build/test/npm-specs.js +0 -20
  112. package/build/test/parser-specs.js +0 -319
  113. package/build/test/plugin-e2e-specs.js +0 -316
  114. package/build/test/schema/arg-spec-specs.js +0 -70
  115. package/build/test/schema/cli-args-specs.js +0 -408
  116. package/build/test/schema/schema-specs.js +0 -407
  117. package/build/test/utils-specs.js +0 -288
  118. package/lib/cli/npm.js +0 -251
  119. package/lib/driver-config.js +0 -101
  120. package/lib/drivers.js +0 -84
  121. package/lib/ext-config-io.js +0 -287
  122. package/lib/extension-config.js +0 -366
  123. package/lib/plugin-config.js +0 -63
  124. package/lib/plugins.js +0 -13
package/lib/drivers.js DELETED
@@ -1,84 +0,0 @@
1
- import _ from 'lodash';
2
- import log from './logger';
3
-
4
-
5
- // This is a map of driver names to npm packages representing those drivers.
6
- // The drivers in this list will be available to the CLI so users can just
7
- // type 'appium driver install 'name'', rather than having to specify the full
8
- // npm package. I.e., these are the officially recognized drivers.
9
- const KNOWN_DRIVERS = {
10
- uiautomator2: 'appium-uiautomator2-driver',
11
- xcuitest: 'appium-xcuitest-driver',
12
- youiengine: 'appium-youiengine-driver',
13
- windows: 'appium-windows-driver',
14
- mac: 'appium-mac-driver',
15
- mac2: 'appium-mac2-driver',
16
- espresso: 'appium-espresso-driver',
17
- tizen: 'appium-tizen-driver',
18
- flutter: 'appium-flutter-driver',
19
- safari: 'appium-safari-driver',
20
- gecko: 'appium-geckodriver',
21
- };
22
-
23
- function getDriverBySupport (drivers, matchAutomationName, matchPlatformName) {
24
- for (const [driverName, driverData] of _.toPairs(drivers)) {
25
- const {automationName, platformNames} = driverData;
26
- const aNameMatches = automationName.toLowerCase() === matchAutomationName.toLowerCase();
27
- const pNameMatches = _.includes(platformNames.map(_.toLower),
28
- matchPlatformName.toLowerCase());
29
-
30
- if (aNameMatches && pNameMatches) {
31
- return {driverName, ...driverData};
32
- }
33
-
34
- if (aNameMatches) {
35
- throw new Error(`Driver '${driverName}' supports automationName ` +
36
- `'${automationName}', but Appium could not find ` +
37
- `support for platformName '${matchPlatformName}'. Supported ` +
38
- `platformNames are: ` +
39
- JSON.stringify(platformNames));
40
- }
41
- }
42
-
43
- throw new Error(`Could not find installed driver to support given caps`);
44
- }
45
-
46
- function findMatchingDriver (config, {automationName, platformName}) {
47
- if (!_.isString(platformName)) {
48
- throw new Error('You must include a platformName capability');
49
- }
50
-
51
- if (!_.isString(automationName)) {
52
- throw new Error('You must include an automationName capability');
53
- }
54
-
55
- log.info(`Attempting to find matching driver for automationName ` +
56
- `'${automationName}' and platformName '${platformName}'`);
57
-
58
- try {
59
- const {
60
- driverName,
61
- mainClass,
62
- version,
63
- } = getDriverBySupport(config.installedExtensions, automationName, platformName);
64
- log.info(`The '${driverName}' driver was installed and matched caps.`);
65
- log.info(`Will require it at ${config.getExtensionRequirePath(driverName)}`);
66
- const driver = config.require(driverName);
67
- if (!driver) {
68
- throw new Error(`MainClass ${mainClass} did not result in a driver object`);
69
- }
70
- return {driver, version, driverName};
71
- } catch (err) {
72
- const msg = `Could not find a driver for automationName ` +
73
- `'${automationName}' and platformName ${platformName}'. ` +
74
- `Have you installed a driver that supports those ` +
75
- `capabilities? Run 'appium driver list --installed' to see. ` +
76
- `(Lower-level error: ${err.message})`;
77
- throw new Error(msg);
78
- }
79
- }
80
-
81
- export {
82
- findMatchingDriver,
83
- KNOWN_DRIVERS,
84
- };
@@ -1,287 +0,0 @@
1
- // @ts-check
2
-
3
- /**
4
- * Module containing {@link ExtConfigIO} which handles reading & writing of extension config files.
5
- */
6
-
7
- import { fs, mkdirp } from '@appium/support';
8
- import _ from 'lodash';
9
- import path from 'path';
10
- import YAML from 'yaml';
11
-
12
- const CONFIG_FILE_NAME = 'extensions.yaml';
13
-
14
- /**
15
- * Current configuration schema revision!
16
- */
17
- const CONFIG_SCHEMA_REV = 2;
18
-
19
- export const DRIVER_TYPE = 'driver';
20
- export const PLUGIN_TYPE = 'plugin';
21
-
22
- /**
23
- * Set of valid extension types.
24
- * @type {Readonly<Set<ExtensionType>>}
25
- */
26
- const VALID_EXT_TYPES = new Set([DRIVER_TYPE, PLUGIN_TYPE]);
27
-
28
- const CONFIG_DATA_DRIVER_KEY = `${DRIVER_TYPE}s`;
29
- const CONFIG_DATA_PLUGIN_KEY = `${PLUGIN_TYPE}s`;
30
-
31
- /**
32
- * Handles reading & writing of extension config files.
33
- *
34
- * Only one instance of this class exists per value of `APPIUM_HOME`.
35
- */
36
- class ExtConfigIO {
37
- /**
38
- * "Dirty" flag. If true, the data has changed since the last write.
39
- * @type {boolean}
40
- * @private
41
- */
42
- _dirty;
43
-
44
- /**
45
- * The entire contents of a parsed YAML extension config file.
46
- * @type {object?}
47
- * @private
48
- */
49
- _data;
50
-
51
- /**
52
- * A mapping of extension type to configuration data. Configuration data is
53
- * keyed on extension name.
54
- *
55
- * Consumers get the values of this `Map` (corresponding to the
56
- * `extensionType` of the consumer, which will be a subclass of
57
- * `ExtensionConfig`) and do not have access to the entire data object.
58
- * @private
59
- * @type {Map<ExtensionType,object>}
60
- */
61
- _extDataByType = new Map();
62
-
63
- /**
64
- * Path to config file.
65
- * @private
66
- * @type {Readonly<string>}
67
- */
68
- _filepath;
69
-
70
- /**
71
- * Path to `APPIUM_HOME`
72
- * @private
73
- * @type {Readonly<string>}
74
- */
75
- _appiumHome;
76
-
77
- /**
78
- * Helps avoid writing multiple times.
79
- *
80
- * If this is `null`, calling {@link ExtConfigIO.write} will cause it to be
81
- * set to a `Promise`. When the call to `write()` is complete, the `Promise`
82
- * will resolve and then this value will be set to `null`. Concurrent calls
83
- * made while this value is a `Promise` will return the `Promise` itself.
84
- * @private
85
- * @type {Promise<boolean>?}
86
- */
87
- _writing = null;
88
-
89
- /**
90
- * Helps avoid reading multiple times.
91
- *
92
- * If this is `null`, calling {@link ExtConfigIO.read} will cause it to be
93
- * set to a `Promise`. When the call to `read()` is complete, the `Promise`
94
- * will resolve and then this value will be set to `null`. Concurrent calls
95
- * made while this value is a `Promise` will return the `Promise` itself.
96
- * @private
97
- * @type {Promise<void>?}
98
- */
99
- _reading = null;
100
-
101
- /**
102
- * @param {string} appiumHome
103
- */
104
- constructor (appiumHome) {
105
- this._filepath = path.resolve(appiumHome, CONFIG_FILE_NAME);
106
- this._appiumHome = appiumHome;
107
- }
108
-
109
- /**
110
- * Creaes a `Proxy` which watches for changes to the extension-type-specific
111
- * config data.
112
- *
113
- * When changes are detected, it sets a `_dirty` flag. The next call to
114
- * {@link ExtConfigIO.write} will check if this flag is `true` before
115
- * proceeding.
116
- * @param {ExtensionType} extensionType
117
- * @param {Record<string,object>} data - Extension config data, keyed by name
118
- * @private
119
- * @returns {Record<string,object>}
120
- */
121
- _createProxy (extensionType, data) {
122
- return new Proxy(data[`${extensionType}s`], {
123
- set: (target, prop, value) => {
124
- if (value !== target[prop]) {
125
- this._dirty = true;
126
- }
127
- target[prop] = value;
128
- return Reflect.set(target, prop, value);
129
- },
130
- deleteProperty: (target, prop) => {
131
- if (prop in target) {
132
- this._dirty = true;
133
- }
134
- return Reflect.deleteProperty(target, prop);
135
- },
136
- });
137
- }
138
-
139
- /**
140
- * Returns the path to the config file.
141
- */
142
- get filepath () {
143
- return this._filepath;
144
- }
145
-
146
- /**
147
- * Gets data for an extension type. Reads the config file if necessary.
148
- *
149
- * Force-reading is _not_ supported, as it's likely to be a source of
150
- * bugs--it's easy to mutate the data and then overwrite memory with the file
151
- * contents
152
- *
153
- * Ideally this will only ever read the file _once_.
154
- * @param {ExtensionType} extensionType - Which bit of the config data we
155
- * want
156
- * @returns {Promise<object>} The data
157
- */
158
- async read (extensionType) {
159
- if (this._reading) {
160
- await this._reading;
161
- return this._extDataByType.get(extensionType);
162
- }
163
-
164
- this._reading = (async () => {
165
- if (!VALID_EXT_TYPES.has(extensionType)) {
166
- throw new TypeError(
167
- `Invalid extension type: ${extensionType}. Valid values are: ${[
168
- ...VALID_EXT_TYPES,
169
- ].join(', ')}`,
170
- );
171
- }
172
- if (this._extDataByType.has(extensionType)) {
173
- return;
174
- }
175
-
176
- let data;
177
- let isNewFile = false;
178
- try {
179
- await mkdirp(this._appiumHome);
180
- const yaml = await fs.readFile(this.filepath, 'utf8');
181
- data = YAML.parse(yaml);
182
- } catch (err) {
183
- if (err.code === 'ENOENT') {
184
- data = {
185
- [CONFIG_DATA_DRIVER_KEY]: {},
186
- [CONFIG_DATA_PLUGIN_KEY]: {},
187
- schemaRev: CONFIG_SCHEMA_REV,
188
- };
189
- isNewFile = true;
190
- } else {
191
- throw new Error(
192
- `Appium had trouble loading the extension installation ` +
193
- `cache file (${this.filepath}). Ensure it exists and is ` +
194
- `readable. Specific error: ${err.message}`,
195
- );
196
- }
197
- }
198
-
199
- this._data = data;
200
- this._extDataByType.set(
201
- DRIVER_TYPE,
202
- this._createProxy(DRIVER_TYPE, data),
203
- );
204
- this._extDataByType.set(
205
- PLUGIN_TYPE,
206
- this._createProxy(PLUGIN_TYPE, data),
207
- );
208
-
209
- if (isNewFile) {
210
- await this.write(true);
211
- }
212
- })();
213
- try {
214
- await this._reading;
215
- return this._extDataByType.get(extensionType);
216
- } finally {
217
- this._reading = null;
218
- }
219
- }
220
-
221
- /**
222
- * Writes the data if it needs writing.
223
- *
224
- * If the `schemaRev` prop needs updating, the file will be written.
225
- * @param {boolean} [force=false] - Whether to force a write even if the data is clean
226
- * @returns {Promise<boolean>} Whether the data was written
227
- */
228
- async write (force = false) {
229
- if (this._writing) {
230
- return this._writing;
231
- }
232
- this._writing = (async () => {
233
- try {
234
- if (!this._dirty && !force) {
235
- return false;
236
- }
237
-
238
- if (!this._data) {
239
- throw new ReferenceError('No data to write. Call `read()` first');
240
- }
241
-
242
- const dataToWrite = {
243
- ...this._data,
244
- [CONFIG_DATA_DRIVER_KEY]: this._extDataByType.get(DRIVER_TYPE),
245
- [CONFIG_DATA_PLUGIN_KEY]: this._extDataByType.get(PLUGIN_TYPE),
246
- };
247
-
248
- try {
249
- await fs.writeFile(
250
- this.filepath,
251
- YAML.stringify(dataToWrite),
252
- 'utf8',
253
- );
254
- this._dirty = false;
255
- return true;
256
- } catch {
257
- throw new Error(
258
- `Appium could not parse or write from the Appium Home directory ` +
259
- `(${this._appiumHome}). Please ensure it is writable.`,
260
- );
261
- }
262
- } finally {
263
- this._writing = null;
264
- }
265
- })();
266
- return await this._writing;
267
- }
268
- }
269
-
270
- /**
271
- * Factory function for {@link ExtConfigIO}.
272
- *
273
- * Maintains one instance per value of `APPIUM_HOME`.
274
- * @param {string} appiumHome - `APPIUM_HOME`
275
- * @returns {ExtConfigIO}
276
- */
277
- export const getExtConfigIOInstance = _.memoize(
278
- (appiumHome) => new ExtConfigIO(appiumHome),
279
- );
280
-
281
- /**
282
- * @typedef {ExtConfigIO} ExtensionConfigIO
283
- */
284
-
285
- /**
286
- * @typedef {typeof DRIVER_TYPE | typeof PLUGIN_TYPE} ExtensionType
287
- */