appium 2.0.0-beta.21 → 2.0.0-beta.25
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/LICENSE +201 -0
- package/README.md +1 -2
- package/build/check-npm-pack-files.js +23 -0
- package/build/commands-yml/parse.js +319 -0
- package/build/commands-yml/validator.js +130 -0
- package/build/index.js +19 -0
- package/build/lib/appium.js +22 -7
- package/build/lib/cli/args.js +13 -15
- package/build/lib/cli/npm.js +27 -16
- package/build/lib/cli/parser.js +7 -3
- package/build/lib/config-file.js +4 -7
- package/build/lib/config.js +57 -48
- package/build/lib/extension-config.js +1 -1
- package/build/lib/main.js +28 -28
- package/build/lib/plugin-config.js +2 -2
- package/build/lib/plugins.js +4 -2
- package/build/lib/schema/appium-config-schema.js +3 -2
- package/build/lib/schema/arg-spec.js +5 -3
- package/build/lib/schema/cli-args.js +25 -16
- package/build/lib/schema/keywords.js +14 -4
- package/build/lib/schema/schema.js +86 -9
- package/build/lib/utils.js +16 -36
- package/build/postinstall.js +90 -0
- package/build/test/cli/cli-e2e-specs.js +221 -0
- package/build/test/cli/cli-helpers.js +86 -0
- package/build/test/cli/cli-specs.js +71 -0
- package/build/test/cli/fixtures/test-driver/package.json +27 -0
- package/build/test/cli/schema-args-specs.js +48 -0
- package/build/test/cli/schema-e2e-specs.js +47 -0
- package/build/test/config-e2e-specs.js +112 -0
- package/build/test/config-file-e2e-specs.js +191 -0
- package/build/test/config-file-specs.js +281 -0
- package/build/test/config-specs.js +258 -0
- package/build/test/driver-e2e-specs.js +435 -0
- package/build/test/driver-specs.js +386 -0
- package/build/test/ext-config-io-specs.js +181 -0
- package/build/test/extension-config-specs.js +365 -0
- package/build/test/fixtures/allow-feat.txt +5 -0
- package/build/test/fixtures/caps.json +3 -0
- package/build/test/fixtures/config/allow-insecure.txt +3 -0
- package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +5 -0
- package/build/test/fixtures/config/appium.config.bad.json +32 -0
- package/build/test/fixtures/config/appium.config.ext-good.json +9 -0
- package/build/test/fixtures/config/appium.config.ext-unknown-props.json +10 -0
- package/build/test/fixtures/config/appium.config.good.js +40 -0
- package/build/test/fixtures/config/appium.config.good.json +33 -0
- package/build/test/fixtures/config/appium.config.good.yaml +30 -0
- package/build/test/fixtures/config/appium.config.invalid.json +31 -0
- package/build/test/fixtures/config/appium.config.security-array.json +5 -0
- package/build/test/fixtures/config/appium.config.security-delimited.json +5 -0
- package/build/test/fixtures/config/appium.config.security-path.json +5 -0
- package/build/test/fixtures/config/driver-fake.config.json +8 -0
- package/build/test/fixtures/config/nodeconfig.json +3 -0
- package/build/test/fixtures/config/plugin-fake.config.json +0 -0
- package/build/test/fixtures/default-args.js +35 -0
- package/build/test/fixtures/deny-feat.txt +5 -0
- package/build/test/fixtures/driver.schema.js +20 -0
- package/build/test/fixtures/extensions.yaml +27 -0
- package/build/test/fixtures/flattened-schema.js +532 -0
- package/build/test/fixtures/plugin.schema.js +20 -0
- package/build/test/fixtures/schema-with-extensions.js +28 -0
- package/build/test/grid-register-specs.js +74 -0
- package/build/test/helpers.js +75 -0
- package/build/test/logger-specs.js +76 -0
- package/build/test/npm-specs.js +20 -0
- package/build/test/parser-specs.js +319 -0
- package/build/test/plugin-e2e-specs.js +316 -0
- package/build/test/schema/arg-spec-specs.js +70 -0
- package/build/test/schema/cli-args-specs.js +408 -0
- package/build/test/schema/schema-specs.js +407 -0
- package/build/test/utils-specs.js +288 -0
- package/index.js +11 -0
- package/lib/appium-config.schema.json +2 -1
- package/lib/appium.js +51 -8
- package/lib/cli/args.js +17 -14
- package/lib/cli/npm.js +68 -6
- package/lib/cli/parser.js +5 -2
- package/lib/config-file.js +9 -12
- package/lib/config.js +104 -56
- package/lib/extension-config.js +1 -1
- package/lib/main.js +94 -40
- package/lib/plugin-config.js +1 -1
- package/lib/plugins.js +2 -0
- package/lib/schema/appium-config-schema.js +1 -0
- package/lib/schema/arg-spec.js +13 -3
- package/lib/schema/cli-args.js +22 -34
- package/lib/schema/keywords.js +20 -4
- package/lib/schema/schema.js +150 -24
- package/lib/utils.js +28 -29
- package/package.json +9 -14
- package/types/types.d.ts +5 -0
- package/build/lib/cli/argparse-actions.js +0 -104
- package/lib/cli/argparse-actions.js +0 -77
package/lib/schema/arg-spec.js
CHANGED
|
@@ -73,6 +73,11 @@ export class ArgSpec {
|
|
|
73
73
|
*/
|
|
74
74
|
dest;
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* The same as {@link ArgSpec.dest} but without the leading `<extType>.<extName>.` prefix.
|
|
78
|
+
*/
|
|
79
|
+
rawDest;
|
|
80
|
+
|
|
76
81
|
/**
|
|
77
82
|
* Whatever the default value of this argument is, as specified by the
|
|
78
83
|
* `default` property of the schema.
|
|
@@ -100,10 +105,10 @@ export class ArgSpec {
|
|
|
100
105
|
|
|
101
106
|
// if no explicit `dest` provided, just camelCase the name to avoid needing
|
|
102
107
|
// to use bracket syntax when accessing props on the parsed args object.
|
|
103
|
-
const
|
|
108
|
+
const rawDest = _.camelCase(dest ?? name);
|
|
104
109
|
|
|
105
110
|
const destKeypath =
|
|
106
|
-
extType && extName ? [extType, extName,
|
|
111
|
+
extType && extName ? [extType, extName, rawDest].join('.') : rawDest;
|
|
107
112
|
|
|
108
113
|
this.defaultValue = defaultValue;
|
|
109
114
|
this.name = name;
|
|
@@ -112,6 +117,7 @@ export class ArgSpec {
|
|
|
112
117
|
this.arg = arg;
|
|
113
118
|
this.dest = destKeypath;
|
|
114
119
|
this.ref = ref;
|
|
120
|
+
this.rawDest = rawDest;
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
/**
|
|
@@ -170,7 +176,7 @@ export class ArgSpec {
|
|
|
170
176
|
/**
|
|
171
177
|
* When given the root ID of a schema for an extension (`<extType>-<normalizedExtName>.json`) Returns an object containing the extension type and the _normalized_ extension name.
|
|
172
178
|
* @param {string} schemaId - Root schema ID
|
|
173
|
-
* @returns {{extType: ExtensionType|undefined, normalizedExtName: string|undefined}}
|
|
179
|
+
* @returns { {extType: ExtensionType|undefined, normalizedExtName: string|undefined} }
|
|
174
180
|
*/
|
|
175
181
|
static extensionInfoFromRootSchemaId (schemaId) {
|
|
176
182
|
const matches = schemaId.match(SCHEMA_ID_REGEXP);
|
|
@@ -216,3 +222,7 @@ export class ArgSpec {
|
|
|
216
222
|
* @property {string} [dest]
|
|
217
223
|
* @property {D} [defaultValue]
|
|
218
224
|
*/
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @typedef {import('../ext-config-io').ExtensionType} ExtensionType
|
|
228
|
+
*/
|
package/lib/schema/cli-args.js
CHANGED
|
@@ -79,26 +79,36 @@ function getSchemaValidator ({ref: schemaId}, coerce = _.identity) {
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Determine the description for display on the CLI, given the schema.
|
|
84
|
+
* @param {AppiumJSONSchema} schema
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
function makeDescription (schema) {
|
|
88
|
+
const {appiumCliDescription, description = '', appiumDeprecated} = schema;
|
|
89
|
+
let desc = appiumCliDescription ?? description;
|
|
90
|
+
if (appiumDeprecated) {
|
|
91
|
+
desc = `[DEPRECATED] ${desc}`;
|
|
92
|
+
}
|
|
93
|
+
return desc;
|
|
94
|
+
}
|
|
95
|
+
|
|
82
96
|
/**
|
|
83
97
|
* Given arg `name`, a JSON schema `subSchema`, and options, return an argument definition
|
|
84
98
|
* as understood by `argparse`.
|
|
85
99
|
* @param {AppiumJSONSchema} subSchema - JSON schema for the option
|
|
86
100
|
* @param {ArgSpec} argSpec - Argument spec tuple
|
|
87
|
-
* @param {SubSchemaToArgDefOptions} [opts] - Options
|
|
88
101
|
* @returns {[string[], import('argparse').ArgumentOptions]} Tuple of flag and options
|
|
89
102
|
*/
|
|
90
|
-
function subSchemaToArgDef (subSchema, argSpec
|
|
91
|
-
const {overrides = {}} = opts;
|
|
103
|
+
function subSchemaToArgDef (subSchema, argSpec) {
|
|
92
104
|
let {
|
|
93
105
|
type,
|
|
94
106
|
appiumCliAliases,
|
|
95
107
|
appiumCliTransformer,
|
|
96
|
-
appiumCliDescription,
|
|
97
|
-
description,
|
|
98
108
|
enum: enumValues,
|
|
99
109
|
} = subSchema;
|
|
100
110
|
|
|
101
|
-
const {name, arg
|
|
111
|
+
const {name, arg} = argSpec;
|
|
102
112
|
|
|
103
113
|
const aliases = [
|
|
104
114
|
aliasToFlag(argSpec),
|
|
@@ -110,7 +120,7 @@ function subSchemaToArgDef (subSchema, argSpec, opts = {}) {
|
|
|
110
120
|
/** @type {import('argparse').ArgumentOptions} */
|
|
111
121
|
let argOpts = {
|
|
112
122
|
required: false,
|
|
113
|
-
help:
|
|
123
|
+
help: makeDescription(subSchema)
|
|
114
124
|
};
|
|
115
125
|
|
|
116
126
|
/**
|
|
@@ -130,7 +140,8 @@ function subSchemaToArgDef (subSchema, argSpec, opts = {}) {
|
|
|
130
140
|
switch (type) {
|
|
131
141
|
// booleans do not have a type per `ArgumentOptions`, just an "action"
|
|
132
142
|
case TYPENAMES.BOOLEAN: {
|
|
133
|
-
argOpts.action = '
|
|
143
|
+
argOpts.action = 'store_const';
|
|
144
|
+
argOpts.const = true;
|
|
134
145
|
break;
|
|
135
146
|
}
|
|
136
147
|
|
|
@@ -215,16 +226,6 @@ function subSchemaToArgDef (subSchema, argSpec, opts = {}) {
|
|
|
215
226
|
}
|
|
216
227
|
}
|
|
217
228
|
|
|
218
|
-
// overrides override anything we computed here. usually this involves "custom types",
|
|
219
|
-
// which are really just transform functions.
|
|
220
|
-
argOpts = _.merge(
|
|
221
|
-
argOpts,
|
|
222
|
-
/** should the override keys correspond to the prop name or the prop dest?
|
|
223
|
-
* the prop dest is computed by {@link aliasToDest}.
|
|
224
|
-
*/
|
|
225
|
-
overrides[dest] ?? {},
|
|
226
|
-
);
|
|
227
|
-
|
|
228
229
|
return [aliases, argOpts];
|
|
229
230
|
}
|
|
230
231
|
|
|
@@ -232,32 +233,19 @@ function subSchemaToArgDef (subSchema, argSpec, opts = {}) {
|
|
|
232
233
|
* Converts the finalized, flattened schema representation into
|
|
233
234
|
* ArgumentDefinitions for handoff to `argparse`.
|
|
234
235
|
*
|
|
235
|
-
* @param {ToParserArgsOptions} opts - Options
|
|
236
236
|
* @throws If schema has not been added to ajv (via `finalizeSchema()`)
|
|
237
237
|
* @returns {import('../cli/args').ArgumentDefinitions} A map of arryas of
|
|
238
238
|
* aliases to `argparse` arguments; empty if no schema found
|
|
239
239
|
*/
|
|
240
|
-
export function toParserArgs (
|
|
241
|
-
const flattened = flattenSchema();
|
|
240
|
+
export function toParserArgs () {
|
|
241
|
+
const flattened = flattenSchema().filter(({schema}) => !schema.appiumCliIgnored);
|
|
242
242
|
return new Map(
|
|
243
243
|
_.map(flattened, ({schema, argSpec}) =>
|
|
244
|
-
subSchemaToArgDef(schema, argSpec
|
|
244
|
+
subSchemaToArgDef(schema, argSpec),
|
|
245
245
|
),
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
/**
|
|
250
|
-
* Options for {@link toParserArgs}
|
|
251
|
-
* @typedef {SubSchemaToArgDefOptions} ToParserArgsOptions
|
|
252
|
-
*/
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Options for {@link subSchemaToArgDef}.
|
|
256
|
-
* @typedef {Object} SubSchemaToArgDefOptions
|
|
257
|
-
* @property {string} [prefix] - The prefix to use for the flag, if any
|
|
258
|
-
* @property {{[key: string]: import('argparse').ArgumentOptions}} [overrides] - An object of key/value pairs to override the default values
|
|
259
|
-
*/
|
|
260
|
-
|
|
261
249
|
/**
|
|
262
250
|
* @template T
|
|
263
251
|
* @typedef {import('ajv/dist/types').FormatValidator<T>} FormatValidator<T>
|
package/lib/schema/keywords.js
CHANGED
|
@@ -86,11 +86,26 @@ export const keywords = {
|
|
|
86
86
|
* Flag to tell Appium to _not_ provide this property as a CLI argument.
|
|
87
87
|
* @type {KeywordDefinition}
|
|
88
88
|
*/
|
|
89
|
-
|
|
90
|
-
keyword: '
|
|
89
|
+
appiumCliIgnored: {
|
|
90
|
+
keyword: 'appiumCliIgnored',
|
|
91
91
|
metaSchema: {
|
|
92
92
|
type: 'boolean',
|
|
93
|
-
description: 'If `true`, Appium will not provide this property as a CLI argument.'
|
|
93
|
+
description: 'If `true`, Appium will not provide this property as a CLI argument. This is NOT the same as a "hidden" argument.',
|
|
94
|
+
enum: [true]
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Mark this property as deprecated.
|
|
100
|
+
* @type {KeywordDefinition}
|
|
101
|
+
*/
|
|
102
|
+
appiumDeprecated: {
|
|
103
|
+
keyword: 'appiumDeprecated',
|
|
104
|
+
metaSchema: {
|
|
105
|
+
type: 'boolean',
|
|
106
|
+
description: 'If `true`, this property will be displayed as "deprecated" to the user',
|
|
107
|
+
enum: [true],
|
|
108
|
+
$comment: 'JSON schema draft-2019-09 keyword `deprecated` serves the same purpose. This keyword should itself be deprecated if we move to draft-2019-09!'
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
111
|
};
|
|
@@ -109,8 +124,9 @@ export const keywords = {
|
|
|
109
124
|
* @property {string} [appiumCliDest]
|
|
110
125
|
* @property {string} [appiumCliDescription]
|
|
111
126
|
* @property {string[]} [appiumCliAliases]
|
|
112
|
-
* @property {boolean} [
|
|
127
|
+
* @property {boolean} [appiumCliIgnored]
|
|
113
128
|
* @property {AppiumCliTransformerName} [appiumCliTransformer]
|
|
129
|
+
* @property {boolean} [appiumDeprecated]
|
|
114
130
|
*/
|
|
115
131
|
|
|
116
132
|
|
package/lib/schema/schema.js
CHANGED
|
@@ -4,11 +4,11 @@ import Ajv from 'ajv';
|
|
|
4
4
|
import addFormats from 'ajv-formats';
|
|
5
5
|
import _ from 'lodash';
|
|
6
6
|
import path from 'path';
|
|
7
|
-
import {DRIVER_TYPE, PLUGIN_TYPE} from '../extension-config';
|
|
8
|
-
import {ReadonlyMap} from '../utils';
|
|
7
|
+
import { DRIVER_TYPE, PLUGIN_TYPE } from '../extension-config';
|
|
8
|
+
import { ReadonlyMap } from '../utils';
|
|
9
9
|
import appiumConfigSchema from './appium-config-schema';
|
|
10
|
-
import {ArgSpec, SERVER_PROP_NAME
|
|
11
|
-
import {keywords} from './keywords';
|
|
10
|
+
import { APPIUM_CONFIG_SCHEMA_ID, ArgSpec, SERVER_PROP_NAME } from './arg-spec';
|
|
11
|
+
import { keywords } from './keywords';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Extensions that an extension schema file can have.
|
|
@@ -89,8 +89,10 @@ class AppiumSchema {
|
|
|
89
89
|
_.bindAll(instance, [
|
|
90
90
|
'finalize',
|
|
91
91
|
'flatten',
|
|
92
|
+
'getAllArgSpecs',
|
|
92
93
|
'getArgSpec',
|
|
93
94
|
'getDefaults',
|
|
95
|
+
'getDefaultsForExtension',
|
|
94
96
|
'getSchema',
|
|
95
97
|
'hasArgSpec',
|
|
96
98
|
'isFinalized',
|
|
@@ -123,6 +125,10 @@ class AppiumSchema {
|
|
|
123
125
|
return Boolean(this._finalizedSchemas);
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
getAllArgSpecs () {
|
|
129
|
+
return this._argSpecs;
|
|
130
|
+
}
|
|
131
|
+
|
|
126
132
|
/**
|
|
127
133
|
* Call this when no more schemas will be registered.
|
|
128
134
|
*
|
|
@@ -152,7 +158,7 @@ class AppiumSchema {
|
|
|
152
158
|
const ajv = this._ajv;
|
|
153
159
|
|
|
154
160
|
// Ajv will _mutate_ the schema, so we need to clone it.
|
|
155
|
-
const baseSchema = _.cloneDeep(
|
|
161
|
+
const baseSchema = _.cloneDeep(appiumConfigSchema);
|
|
156
162
|
|
|
157
163
|
/**
|
|
158
164
|
*
|
|
@@ -202,7 +208,7 @@ class AppiumSchema {
|
|
|
202
208
|
ajv.validateSchema(schema, true);
|
|
203
209
|
addArgSpecs(schema.properties, extType, extName);
|
|
204
210
|
ajv.addSchema(schema, $ref);
|
|
205
|
-
finalizedSchemas[$ref] = /** @type {StrictSchemaObject} */(schema);
|
|
211
|
+
finalizedSchemas[$ref] = /** @type {StrictSchemaObject} */ (schema);
|
|
206
212
|
});
|
|
207
213
|
return baseSchema;
|
|
208
214
|
},
|
|
@@ -277,12 +283,14 @@ class AppiumSchema {
|
|
|
277
283
|
* @returns {void}
|
|
278
284
|
*/
|
|
279
285
|
registerSchema (extType, extName, schema) {
|
|
280
|
-
if (!(extType && extName
|
|
286
|
+
if (!(extType && extName) || _.isUndefined(schema)) {
|
|
281
287
|
throw new TypeError(
|
|
282
|
-
'Expected
|
|
288
|
+
'Expected extension type, extension name, and a defined schema',
|
|
283
289
|
);
|
|
284
290
|
}
|
|
285
|
-
|
|
291
|
+
if (!AppiumSchema.isSupportedSchemaType(schema)) {
|
|
292
|
+
throw new SchemaUnsupportedSchemaError(schema, extType, extName);
|
|
293
|
+
}
|
|
286
294
|
const normalizedExtName = _.kebabCase(extName);
|
|
287
295
|
if (this.hasRegisteredSchema(extType, normalizedExtName)) {
|
|
288
296
|
if (this._registeredSchemas[extType].get(normalizedExtName) === schema) {
|
|
@@ -320,22 +328,67 @@ class AppiumSchema {
|
|
|
320
328
|
/**
|
|
321
329
|
* Returns a `Record` of argument "dest" strings to default values.
|
|
322
330
|
*
|
|
323
|
-
* The "dest" string is the property name in object returned by
|
|
324
|
-
*
|
|
331
|
+
* The "dest" string is the property name in object returned by
|
|
332
|
+
* `argparse.ArgumentParser['parse_args']`.
|
|
333
|
+
* @template {boolean|undefined} Flattened
|
|
334
|
+
* @param {Flattened} [flatten=true] - If `true`, flattens the returned object
|
|
335
|
+
* using "keypath"-style keys of the format `<extType>.<extName>.<argName>`.
|
|
336
|
+
* Otherwise, returns a nested object using `extType` and `extName` as
|
|
337
|
+
* properties. Base arguments (server arguments) are always at the top level.
|
|
338
|
+
* @returns {DefaultValues<Flattened>}
|
|
325
339
|
*/
|
|
326
|
-
getDefaults () {
|
|
340
|
+
getDefaults (flatten = /** @type {Flattened} */ (true)) {
|
|
327
341
|
if (!this.isFinalized()) {
|
|
328
342
|
throw new SchemaFinalizationError();
|
|
329
343
|
}
|
|
330
|
-
|
|
331
|
-
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @private
|
|
347
|
+
* @callback DefaultReducer
|
|
348
|
+
* @param {DefaultValues<Flattened>} defaults
|
|
349
|
+
* @param {ArgSpec} argSpec
|
|
350
|
+
* @returns {DefaultValues<Flattened>}
|
|
351
|
+
*/
|
|
352
|
+
/** @type {DefaultReducer} */
|
|
353
|
+
const reducer = flatten
|
|
354
|
+
? (defaults, {defaultValue, dest}) => {
|
|
332
355
|
if (!_.isUndefined(defaultValue)) {
|
|
333
356
|
defaults[dest] = defaultValue;
|
|
334
357
|
}
|
|
335
358
|
return defaults;
|
|
336
|
-
}
|
|
337
|
-
{}
|
|
359
|
+
}
|
|
360
|
+
: (defaults, {defaultValue, dest}) => {
|
|
361
|
+
if (!_.isUndefined(defaultValue)) {
|
|
362
|
+
_.set(defaults, dest, defaultValue);
|
|
363
|
+
}
|
|
364
|
+
return defaults;
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
/** @type {DefaultValues<Flattened>} */
|
|
368
|
+
const retval = {};
|
|
369
|
+
return [...this._argSpecs.values()].reduce(reducer, retval);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Returns a flattened Record of defaults for a specific extension. Keys will
|
|
374
|
+
* be of format `<argName>`.
|
|
375
|
+
* @param {ExtensionType} extType - Extension type
|
|
376
|
+
* @param {string} extName - Extension name
|
|
377
|
+
* @returns {Record<string,ArgSpecDefaultValue>}
|
|
378
|
+
*/
|
|
379
|
+
getDefaultsForExtension (extType, extName) {
|
|
380
|
+
if (!this.isFinalized()) {
|
|
381
|
+
throw new SchemaFinalizationError();
|
|
382
|
+
}
|
|
383
|
+
const specs = [...this._argSpecs.values()].filter(
|
|
384
|
+
(spec) => spec.extType === extType && spec.extName === extName,
|
|
338
385
|
);
|
|
386
|
+
return specs.reduce((defaults, {defaultValue, rawDest}) => {
|
|
387
|
+
if (!_.isUndefined(defaultValue)) {
|
|
388
|
+
defaults[rawDest] = defaultValue;
|
|
389
|
+
}
|
|
390
|
+
return defaults;
|
|
391
|
+
}, {});
|
|
339
392
|
}
|
|
340
393
|
|
|
341
394
|
/**
|
|
@@ -355,7 +408,7 @@ class AppiumSchema {
|
|
|
355
408
|
flatten () {
|
|
356
409
|
const schema = this.getSchema();
|
|
357
410
|
|
|
358
|
-
/** @type {{properties: SchemaObject, prefix: string[]}[]} */
|
|
411
|
+
/** @type { {properties: SchemaObject, prefix: string[]}[] } */
|
|
359
412
|
const stack = [{properties: schema.properties, prefix: []}];
|
|
360
413
|
/** @type {FlattenedSchema} */
|
|
361
414
|
const flattened = [];
|
|
@@ -416,7 +469,7 @@ class AppiumSchema {
|
|
|
416
469
|
* Retrieves the schema itself
|
|
417
470
|
* @public
|
|
418
471
|
* @param {string} [ref] - Schema ID
|
|
419
|
-
* @throws If the schema has not yet been
|
|
472
|
+
* @throws If the schema has not yet been finalized
|
|
420
473
|
* @returns {SchemaObject}
|
|
421
474
|
*/
|
|
422
475
|
getSchema (ref = APPIUM_CONFIG_SCHEMA_ID) {
|
|
@@ -450,9 +503,7 @@ class AppiumSchema {
|
|
|
450
503
|
* @returns {import('ajv').ErrorObject[]} Array of errors, if any.
|
|
451
504
|
*/
|
|
452
505
|
validate (value, ref = APPIUM_CONFIG_SCHEMA_ID) {
|
|
453
|
-
const validator =
|
|
454
|
-
this._getValidator(ref)
|
|
455
|
-
);
|
|
506
|
+
const validator = this._getValidator(ref);
|
|
456
507
|
return !validator(value) && _.isArray(validator.errors)
|
|
457
508
|
? [...validator.errors]
|
|
458
509
|
: [];
|
|
@@ -466,6 +517,15 @@ class AppiumSchema {
|
|
|
466
517
|
static isAllowedSchemaFileExtension (filename) {
|
|
467
518
|
return ALLOWED_SCHEMA_EXTENSIONS.has(path.extname(filename));
|
|
468
519
|
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Returns `true` if `schema` is a plain object with a non-true `$async` property.
|
|
523
|
+
* @param {any} schema - Schema to check
|
|
524
|
+
* @returns {schema is SchemaObject}
|
|
525
|
+
*/
|
|
526
|
+
static isSupportedSchemaType (schema) {
|
|
527
|
+
return _.isPlainObject(schema) && schema.$async !== true;
|
|
528
|
+
}
|
|
469
529
|
}
|
|
470
530
|
|
|
471
531
|
/**
|
|
@@ -534,10 +594,59 @@ export class SchemaUnknownSchemaError extends ReferenceError {
|
|
|
534
594
|
}
|
|
535
595
|
}
|
|
536
596
|
|
|
597
|
+
/**
|
|
598
|
+
* Thrown when a schema is provided, but it's of an unsupported type.
|
|
599
|
+
*
|
|
600
|
+
* "Valid" schemas which are unsupported include boolean schemas and async schemas
|
|
601
|
+
* (having a `true` `$async` property).
|
|
602
|
+
*/
|
|
603
|
+
export class SchemaUnsupportedSchemaError extends TypeError {
|
|
604
|
+
/**
|
|
605
|
+
* @type {Readonly<string>}
|
|
606
|
+
*/
|
|
607
|
+
code = 'APPIUMERR_SCHEMA_UNSUPPORTED_SCHEMA';
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* @type {Readonly<{schema: any, extType: ExtensionType, extName: string}>}
|
|
611
|
+
*/
|
|
612
|
+
data;
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* @param {any} schema
|
|
616
|
+
* @param {ExtensionType} extType
|
|
617
|
+
* @param {string} extName
|
|
618
|
+
*/
|
|
619
|
+
constructor (schema, extType, extName) {
|
|
620
|
+
// https://github.com/Microsoft/TypeScript/issues/8277
|
|
621
|
+
super(
|
|
622
|
+
(() => {
|
|
623
|
+
let msg = `Unsupported schema from ${extType} "${extName}":`;
|
|
624
|
+
if (_.isBoolean(schema)) {
|
|
625
|
+
return `${msg} schema cannot be a boolean`;
|
|
626
|
+
}
|
|
627
|
+
if (_.isPlainObject(schema)) {
|
|
628
|
+
if (schema.$async) {
|
|
629
|
+
return `${msg} schema cannot be an async schema`;
|
|
630
|
+
}
|
|
631
|
+
/* istanbul ignore next */
|
|
632
|
+
throw new TypeError(
|
|
633
|
+
`schema IS supported; this error should not be thrown (this is a bug). value of schema: ${JSON.stringify(
|
|
634
|
+
schema,
|
|
635
|
+
)}`,
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
return `${msg} schema must be a plain object without a true "$async" property`;
|
|
639
|
+
})(),
|
|
640
|
+
);
|
|
641
|
+
this.data = {schema, extType, extName};
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
537
645
|
const appiumSchema = AppiumSchema.create();
|
|
538
646
|
|
|
539
647
|
export const {
|
|
540
648
|
registerSchema,
|
|
649
|
+
getAllArgSpecs,
|
|
541
650
|
getArgSpec,
|
|
542
651
|
hasArgSpec,
|
|
543
652
|
isFinalized,
|
|
@@ -546,12 +655,14 @@ export const {
|
|
|
546
655
|
validate,
|
|
547
656
|
getSchema,
|
|
548
657
|
flatten: flattenSchema,
|
|
549
|
-
getDefaults:
|
|
658
|
+
getDefaults: getDefaultsForSchema,
|
|
659
|
+
getDefaultsForExtension,
|
|
550
660
|
} = appiumSchema;
|
|
551
661
|
export const {isAllowedSchemaFileExtension} = AppiumSchema;
|
|
552
662
|
|
|
553
663
|
/**
|
|
554
|
-
*
|
|
664
|
+
* Appium only supports schemas that are plain objects; not arrays.
|
|
665
|
+
* @typedef {import('ajv').SchemaObject & {[key: number]: never}} SchemaObject
|
|
555
666
|
*/
|
|
556
667
|
|
|
557
668
|
/**
|
|
@@ -573,5 +684,20 @@ export const {isAllowedSchemaFileExtension} = AppiumSchema;
|
|
|
573
684
|
* A list of schemas associated with properties and their corresponding {@link ArgSpec} objects.
|
|
574
685
|
*
|
|
575
686
|
* Intermediate data structure used when converting the entire schema down to CLI arguments.
|
|
576
|
-
* @typedef {{schema: SchemaObject, argSpec: ArgSpec}[]} FlattenedSchema
|
|
687
|
+
* @typedef { {schema: SchemaObject, argSpec: ArgSpec}[] } FlattenedSchema
|
|
688
|
+
*/
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* @typedef {ArgSpec['defaultValue']} ArgSpecDefaultValue
|
|
692
|
+
*/
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* e.g. `{driver: {foo: 'bar'}}` where `foo` is the arg name and `bar` is the default value.
|
|
696
|
+
* @typedef {Record<string,Record<string,ArgSpecDefaultValue>>} NestedArgSpecDefaultValue
|
|
697
|
+
*/
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Helper type for the return value of {@link AppiumSchema.getDefaults}
|
|
701
|
+
* @template {boolean|undefined} Flattened
|
|
702
|
+
* @typedef {Record<string,Flattened extends true ? ArgSpecDefaultValue : ArgSpecDefaultValue | NestedArgSpecDefaultValue>} DefaultValues
|
|
577
703
|
*/
|
package/lib/utils.js
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import _ from 'lodash';
|
|
2
4
|
import logger from './logger';
|
|
5
|
+
// @ts-ignore
|
|
3
6
|
import { processCapabilities, PROTOCOLS } from '@appium/base-driver';
|
|
4
7
|
import { fs } from '@appium/support';
|
|
8
|
+
import { inspect as dump } from 'util';
|
|
5
9
|
|
|
6
10
|
const W3C_APPIUM_PREFIX = 'appium';
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* If `stdout` is a TTY, this is `true`.
|
|
15
|
+
*
|
|
16
|
+
* Used for tighter control over log output.
|
|
17
|
+
* @type {boolean}
|
|
18
|
+
*/
|
|
19
|
+
const isStdoutTTY = process.stdout.isTTY;
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
for (let [arg, value] of _.toPairs(args)) {
|
|
28
|
-
value = getValueArray(value);
|
|
29
|
-
logger.info(` ${arg}: ${value.shift()}`);
|
|
30
|
-
for (let val of value) {
|
|
31
|
-
logger.info(val);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
21
|
+
/**
|
|
22
|
+
* Dumps to value to the console using `info` logger.
|
|
23
|
+
*
|
|
24
|
+
* @todo May want to force color to be `false` if {@link isStdoutTTY} is `false`.
|
|
25
|
+
*/
|
|
26
|
+
const inspect = _.flow(
|
|
27
|
+
_.partialRight(
|
|
28
|
+
/** @type {(object: any, options: import('util').InspectOptions) => string} */(dump),
|
|
29
|
+
{colors: true, depth: null, compact: !isStdoutTTY}
|
|
30
|
+
),
|
|
31
|
+
(...args) => {
|
|
32
|
+
logger.info(...args);
|
|
33
|
+
});
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Takes the caps that were provided in the request and translates them
|
|
@@ -236,8 +235,8 @@ class ReadonlyMap extends Map {
|
|
|
236
235
|
return super.set(key, value);
|
|
237
236
|
}
|
|
238
237
|
|
|
239
|
-
delete (
|
|
240
|
-
|
|
238
|
+
delete () {
|
|
239
|
+
return false;
|
|
241
240
|
}
|
|
242
241
|
|
|
243
242
|
clear () {
|
|
@@ -246,6 +245,6 @@ class ReadonlyMap extends Map {
|
|
|
246
245
|
}
|
|
247
246
|
|
|
248
247
|
export {
|
|
249
|
-
|
|
248
|
+
inspect, parseCapsForInnerDriver, insertAppiumPrefixes, rootDir,
|
|
250
249
|
getPackageVersion, pullSettings, removeAppiumPrefixes, ReadonlyMap
|
|
251
250
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.25",
|
|
4
4
|
"description": "Automation for Apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "Apache-2.0",
|
|
23
23
|
"author": "https://github.com/appium",
|
|
24
|
-
"main": "./build/lib/main.js",
|
|
25
24
|
"bin": {
|
|
26
|
-
"appium": "
|
|
25
|
+
"appium": "index.js"
|
|
27
26
|
},
|
|
28
27
|
"directories": {
|
|
29
28
|
"lib": "./lib"
|
|
@@ -31,25 +30,25 @@
|
|
|
31
30
|
"files": [
|
|
32
31
|
"bin",
|
|
33
32
|
"lib",
|
|
34
|
-
"build
|
|
33
|
+
"build",
|
|
34
|
+
"index.js",
|
|
35
35
|
"postinstall.js",
|
|
36
36
|
"types"
|
|
37
37
|
],
|
|
38
38
|
"scripts": {
|
|
39
39
|
"generate-docs": "gulp transpile && node ./build/commands-yml/parse.js",
|
|
40
40
|
"postinstall": "node ./postinstall.js",
|
|
41
|
-
"install-fake-driver": "node . driver install --source=local ../fake-driver",
|
|
42
41
|
"upload": "gulp github-upload",
|
|
43
42
|
"zip": "zip -qr appium.zip .",
|
|
44
43
|
"zip-and-upload": "npm run zip && npm run upload"
|
|
45
44
|
},
|
|
46
45
|
"dependencies": {
|
|
47
|
-
"@appium/base-driver": "^8.2.
|
|
46
|
+
"@appium/base-driver": "^8.2.4",
|
|
48
47
|
"@appium/base-plugin": "1.8.0",
|
|
49
|
-
"@appium/support": "^2.55.
|
|
48
|
+
"@appium/support": "^2.55.4",
|
|
50
49
|
"@babel/runtime": "7.16.3",
|
|
51
50
|
"@sidvind/better-ajv-errors": "0.9.2",
|
|
52
|
-
"ajv": "8.8.
|
|
51
|
+
"ajv": "8.8.2",
|
|
53
52
|
"ajv-formats": "2.1.1",
|
|
54
53
|
"argparse": "2.0.1",
|
|
55
54
|
"async-lock": "1.3.0",
|
|
@@ -65,16 +64,12 @@
|
|
|
65
64
|
"ora": "5.4.1",
|
|
66
65
|
"resolve-from": "5.0.0",
|
|
67
66
|
"semver": "7.3.5",
|
|
68
|
-
"source-map-support": "0.5.
|
|
67
|
+
"source-map-support": "0.5.21",
|
|
69
68
|
"teen_process": "1.16.0",
|
|
70
69
|
"winston": "3.3.3",
|
|
71
70
|
"word-wrap": "1.2.3",
|
|
72
71
|
"yaml": "1.10.2"
|
|
73
72
|
},
|
|
74
|
-
"devDependencies": {
|
|
75
|
-
"@appium/fake-driver": "^3.2.0",
|
|
76
|
-
"@appium/gulp-plugins": "^5.5.5"
|
|
77
|
-
},
|
|
78
73
|
"engines": {
|
|
79
74
|
"node": ">=12",
|
|
80
75
|
"npm": ">=6"
|
|
@@ -84,5 +79,5 @@
|
|
|
84
79
|
"tag": "next"
|
|
85
80
|
},
|
|
86
81
|
"homepage": "https://appium.io",
|
|
87
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "42f4a2de2d763d57cf0bdb6fb6c9a3bc9c3d232f"
|
|
88
83
|
}
|