appium 3.2.1 → 3.3.0
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/cli/args.d.ts +16 -12
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +15 -35
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +51 -93
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +11 -66
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +211 -415
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +384 -653
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts +11 -16
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js +10 -28
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts +40 -69
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +24 -59
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +50 -90
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +11 -63
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts +21 -26
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +13 -55
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts +27 -29
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +29 -31
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/config-file.d.ts +24 -67
- package/build/lib/config-file.d.ts.map +1 -1
- package/build/lib/config-file.js +56 -115
- package/build/lib/config-file.js.map +1 -1
- package/build/lib/config.d.ts +42 -44
- package/build/lib/config.d.ts.map +1 -1
- package/build/lib/config.js +75 -107
- package/build/lib/config.js.map +1 -1
- package/build/lib/constants.d.ts +23 -23
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +10 -15
- package/build/lib/constants.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +40 -57
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +29 -60
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/grid-register.d.ts +32 -7
- package/build/lib/grid-register.d.ts.map +1 -1
- package/build/lib/grid-register.js +84 -48
- package/build/lib/grid-register.js.map +1 -1
- package/build/lib/logsink.d.ts +13 -22
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +48 -103
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/main.js +1 -1
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/arg-spec.d.ts +32 -107
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js +11 -107
- package/build/lib/schema/arg-spec.js.map +1 -1
- package/build/lib/schema/cli-args.d.ts +3 -15
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +15 -105
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts +15 -12
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js +15 -45
- package/build/lib/schema/cli-transformers.js.map +1 -1
- package/build/lib/schema/index.d.ts +2 -2
- package/build/lib/schema/index.d.ts.map +1 -1
- package/build/lib/schema/index.js.map +1 -1
- package/build/lib/schema/keywords.d.ts +12 -20
- package/build/lib/schema/keywords.d.ts.map +1 -1
- package/build/lib/schema/keywords.js +6 -51
- package/build/lib/schema/keywords.js.map +1 -1
- package/build/lib/schema/schema.d.ts +106 -231
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +75 -345
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils.d.ts +59 -238
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +55 -207
- package/build/lib/utils.js.map +1 -1
- package/lib/cli/{args.js → args.ts} +40 -51
- package/lib/cli/driver-command.ts +122 -0
- package/lib/cli/{extension-command.js → extension-command.ts} +610 -689
- package/lib/cli/extension.ts +65 -0
- package/lib/cli/{parser.js → parser.ts} +48 -71
- package/lib/cli/plugin-command.ts +117 -0
- package/lib/cli/{setup-command.js → setup-command.ts} +57 -72
- package/lib/cli/utils.ts +97 -0
- package/lib/config-file.ts +212 -0
- package/lib/{config.js → config.ts} +129 -141
- package/lib/{constants.js → constants.ts} +30 -41
- package/lib/doctor/{doctor.js → doctor.ts} +81 -91
- package/lib/grid-register.ts +250 -0
- package/lib/{logsink.js → logsink.ts} +91 -137
- package/lib/main.js +1 -1
- package/lib/schema/arg-spec.ts +131 -0
- package/lib/schema/cli-args.ts +171 -0
- package/lib/schema/cli-transformers.ts +83 -0
- package/lib/schema/keywords.ts +96 -0
- package/lib/schema/schema.ts +449 -0
- package/lib/utils.ts +404 -0
- package/package.json +19 -20
- package/tsconfig.json +1 -1
- package/build/package.json +0 -99
- package/lib/cli/driver-command.js +0 -174
- package/lib/cli/extension.js +0 -74
- package/lib/cli/plugin-command.js +0 -164
- package/lib/cli/utils.js +0 -91
- package/lib/config-file.js +0 -228
- package/lib/grid-register.js +0 -146
- package/lib/schema/arg-spec.js +0 -229
- package/lib/schema/cli-args.js +0 -254
- package/lib/schema/cli-transformers.js +0 -113
- package/lib/schema/keywords.js +0 -136
- package/lib/schema/schema.js +0 -725
- package/lib/utils.js +0 -512
- /package/lib/schema/{index.js → index.ts} +0 -0
package/lib/config-file.js
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import betterAjvErrors from '@sidvind/better-ajv-errors';
|
|
2
|
-
import {lilconfig} from 'lilconfig';
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
import * as yaml from 'yaml';
|
|
5
|
-
import {getSchema, validate} from './schema/schema';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* lilconfig loader to handle `.yaml` files
|
|
9
|
-
* @type {import('lilconfig').LoaderSync}
|
|
10
|
-
*/
|
|
11
|
-
function yamlLoader(filepath, content) {
|
|
12
|
-
try {
|
|
13
|
-
return yaml.parse(content);
|
|
14
|
-
} catch (e) {
|
|
15
|
-
throw new Error(`The YAML config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A cache of the raw config file (a JSON string) at a filepath.
|
|
21
|
-
* This is used for better error reporting.
|
|
22
|
-
* Note that config files needn't be JSON, but it helps if they are.
|
|
23
|
-
* @type {Map<string,RawJson>}
|
|
24
|
-
*/
|
|
25
|
-
const rawConfig = new Map();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Custom JSON loader that caches the raw config file (for use with `better-ajv-errors`).
|
|
29
|
-
* If it weren't for this cache, this would be unnecessary.
|
|
30
|
-
* @type {import('lilconfig').LoaderSync}
|
|
31
|
-
*/
|
|
32
|
-
function jsonLoader(filepath, content) {
|
|
33
|
-
rawConfig.set(filepath, content);
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(content);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
throw new Error(`The JSON config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Loads a config file from an explicit path
|
|
43
|
-
* @param {LilconfigAsyncSearcher} lc - lilconfig instance
|
|
44
|
-
* @param {string} filepath - Path to config file
|
|
45
|
-
* @returns {Promise<import('lilconfig').LilconfigResult>}
|
|
46
|
-
*/
|
|
47
|
-
async function loadConfigFile(lc, filepath) {
|
|
48
|
-
try {
|
|
49
|
-
// removing "await" will cause any rejection to _not_ be caught in this block!
|
|
50
|
-
return await lc.load(filepath);
|
|
51
|
-
} catch (/** @type {unknown} */ err) {
|
|
52
|
-
if (/** @type {NodeJS.ErrnoException} */ (err).code === 'ENOENT') {
|
|
53
|
-
/** @type {NodeJS.ErrnoException} */ (
|
|
54
|
-
err
|
|
55
|
-
).message = `Config file not found at user-provided path: ${filepath}`;
|
|
56
|
-
throw err;
|
|
57
|
-
} else if (err instanceof SyntaxError) {
|
|
58
|
-
// generally invalid JSON
|
|
59
|
-
err.message = `Config file at user-provided path ${filepath} is invalid:\n${err.message}`;
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Searches for a config file
|
|
68
|
-
* @param {LilconfigAsyncSearcher} lc - lilconfig instance
|
|
69
|
-
* @returns {Promise<import('lilconfig').LilconfigResult>}
|
|
70
|
-
*/
|
|
71
|
-
async function searchConfigFile(lc) {
|
|
72
|
-
return await lc.search();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Given an array of errors and the result of loading a config file, generate a
|
|
77
|
-
* helpful string for the user.
|
|
78
|
-
*
|
|
79
|
-
* - If `opts` contains a `json` property, this should be the original JSON
|
|
80
|
-
* _string_ of the config file. This is only applicable if the config file
|
|
81
|
-
* was in JSON format. If present, it will associate line numbers with errors.
|
|
82
|
-
* - If `errors` happens to be empty, this will throw.
|
|
83
|
-
* @param {import('ajv').ErrorObject[]} errors - Non-empty array of errors. Required.
|
|
84
|
-
* @param {ReadConfigFileResult['config']|any} [config] -
|
|
85
|
-
* Configuration & metadata
|
|
86
|
-
* @param {FormatConfigErrorsOptions} [opts]
|
|
87
|
-
* @throws {TypeError} If `errors` is empty
|
|
88
|
-
* @returns {string}
|
|
89
|
-
*/
|
|
90
|
-
export function formatErrors(errors = [], config = {}, opts = {}) {
|
|
91
|
-
if (errors && !errors.length) {
|
|
92
|
-
throw new TypeError('Array of errors must be non-empty');
|
|
93
|
-
}
|
|
94
|
-
return betterAjvErrors(getSchema(opts.schemaId), config, errors, {
|
|
95
|
-
json: opts.json,
|
|
96
|
-
format: 'cli',
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Given an optional path, read a config file. Validates the config file.
|
|
102
|
-
*
|
|
103
|
-
* Call {@link validate} if you already have a config object.
|
|
104
|
-
* @param {string} [filepath] - Path to config file, if we have one
|
|
105
|
-
* @param {ReadConfigFileOptions} [opts] - Options
|
|
106
|
-
* @public
|
|
107
|
-
* @returns {Promise<ReadConfigFileResult>} Contains config and filepath, if found, and any errors
|
|
108
|
-
*/
|
|
109
|
-
export async function readConfigFile(filepath, opts = {}) {
|
|
110
|
-
const lc = lilconfig('appium', {
|
|
111
|
-
loaders: {
|
|
112
|
-
'.yaml': yamlLoader,
|
|
113
|
-
'.yml': yamlLoader,
|
|
114
|
-
'.json': jsonLoader,
|
|
115
|
-
noExt: jsonLoader,
|
|
116
|
-
},
|
|
117
|
-
packageProp: 'appiumConfig',
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const result = filepath ? await loadConfigFile(lc, filepath) : await searchConfigFile(lc);
|
|
121
|
-
|
|
122
|
-
if (result?.filepath && !result?.isEmpty) {
|
|
123
|
-
const {pretty = true} = opts;
|
|
124
|
-
try {
|
|
125
|
-
let configResult;
|
|
126
|
-
const errors = validate(result.config);
|
|
127
|
-
if (_.isEmpty(errors)) {
|
|
128
|
-
configResult = {...result, errors};
|
|
129
|
-
} else {
|
|
130
|
-
const reason = formatErrors(errors, result.config, {
|
|
131
|
-
json: rawConfig.get(result.filepath),
|
|
132
|
-
pretty,
|
|
133
|
-
});
|
|
134
|
-
configResult = reason ? {...result, errors, reason} : {...result, errors};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// normalize (to camel case) all top-level property names of the config file
|
|
138
|
-
configResult.config = normalizeConfig(/** @type {AppiumConfig} */ (configResult.config));
|
|
139
|
-
|
|
140
|
-
return configResult;
|
|
141
|
-
} finally {
|
|
142
|
-
// clean up the raw config file cache, which is only kept to better report errors.
|
|
143
|
-
rawConfig.delete(result.filepath);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return result ?? {};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Convert schema property names to either a) the value of the `appiumCliDest` property, if any; or b) camel-case
|
|
151
|
-
* @param {AppiumConfig} config - Configuration object
|
|
152
|
-
* @returns {NormalizedAppiumConfig} New object with camel-cased keys (or `dest` keys).
|
|
153
|
-
*/
|
|
154
|
-
export function normalizeConfig(config) {
|
|
155
|
-
const schema = getSchema();
|
|
156
|
-
/**
|
|
157
|
-
* @param {AppiumConfig} config
|
|
158
|
-
* @param {string} [section] - Keypath (lodash `_.get()` style) to section of config. If omitted, assume root Appium config schema
|
|
159
|
-
* @todo Rewrite as a loop
|
|
160
|
-
* @returns Normalized section of config
|
|
161
|
-
*/
|
|
162
|
-
const normalize = (config, section) => {
|
|
163
|
-
const obj = _.isUndefined(section) ? config : _.get(config, section, config);
|
|
164
|
-
|
|
165
|
-
const mappedObj = _.mapKeys(obj, (__, prop) =>
|
|
166
|
-
_.get(schema, `properties.server.properties[${prop}].appiumCliDest`, _.camelCase(prop))
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
return _.mapValues(mappedObj, (value, property) => {
|
|
170
|
-
const nextSection = section ? `${section}.${property}` : property;
|
|
171
|
-
return isSchemaTypeObject(schema.properties?.[property])
|
|
172
|
-
? normalize(config, nextSection)
|
|
173
|
-
: value;
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Returns `true` if the schema prop references an object, or if it's an object itself
|
|
179
|
-
* @param {import('ajv').SchemaObject|object} schema - Referencing schema object
|
|
180
|
-
*/
|
|
181
|
-
const isSchemaTypeObject = (schema) => Boolean(schema?.properties || schema?.type === 'object');
|
|
182
|
-
|
|
183
|
-
return normalize(config);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Result of calling {@link readConfigFile}.
|
|
188
|
-
* @typedef ReadConfigFileResult
|
|
189
|
-
* @property {import('ajv').ErrorObject[]} [errors] - Validation errors
|
|
190
|
-
* @property {string} [filepath] - The path to the config file, if found
|
|
191
|
-
* @property {boolean} [isEmpty] - If `true`, the config file exists but is empty
|
|
192
|
-
* @property {NormalizedAppiumConfig} [config] - The parsed configuration
|
|
193
|
-
* @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.
|
|
194
|
-
*/
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Options for {@link readConfigFile}.
|
|
198
|
-
* @typedef ReadConfigFileOptions
|
|
199
|
-
* @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.
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* This is an `AsyncSearcher` which is inexplicably _not_ exported by the `lilconfig` type definition.
|
|
204
|
-
* @typedef {ReturnType<import('lilconfig')["lilconfig"]>} LilconfigAsyncSearcher
|
|
205
|
-
*/
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* The contents of an Appium config file. Generated from schema
|
|
209
|
-
* @typedef {import('@appium/types').AppiumConfig} AppiumConfig
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* The contents of an Appium config file with camelcased property names (and using `appiumCliDest` value if present). Generated from {@link AppiumConfig}
|
|
214
|
-
* @typedef {import('@appium/types').NormalizedAppiumConfig} NormalizedAppiumConfig
|
|
215
|
-
*/
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* The string should be a raw JSON string.
|
|
219
|
-
* @typedef {string} RawJson
|
|
220
|
-
*/
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Options for {@link formatErrors}.
|
|
224
|
-
* @typedef FormatConfigErrorsOptions
|
|
225
|
-
* @property {import('./config-file').RawJson} [json] - Raw JSON config (as string)
|
|
226
|
-
* @property {boolean} [pretty=true] - Whether to format errors as a CLI-friendly string
|
|
227
|
-
* @property {string} [schemaId] - Specific ID of a prop; otherwise entire schema
|
|
228
|
-
*/
|
package/lib/grid-register.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import {fs} from '@appium/support';
|
|
3
|
-
import logger from './logger';
|
|
4
|
-
import _ from 'lodash';
|
|
5
|
-
|
|
6
|
-
const hubUri = (config) => {
|
|
7
|
-
const protocol = config.hubProtocol || 'http';
|
|
8
|
-
return `${protocol}://${config.hubHost}:${config.hubPort}`;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Registers a new node with a selenium grid
|
|
13
|
-
* @param {string|object} data - Path or object representing selenium grid node config file. If a `string`, all subsequent arguments are required!
|
|
14
|
-
* @param {string} [addr] - Bind to this address
|
|
15
|
-
* @param {number} [port] - Bind to this port
|
|
16
|
-
* @param {string} [basePath] - Base path for the grid
|
|
17
|
-
*/
|
|
18
|
-
async function registerNode(data, addr, port, basePath) {
|
|
19
|
-
let configFilePath;
|
|
20
|
-
if (_.isString(data)) {
|
|
21
|
-
configFilePath = data;
|
|
22
|
-
try {
|
|
23
|
-
data = await fs.readFile(data, 'utf-8');
|
|
24
|
-
} catch (err) {
|
|
25
|
-
logger.error(
|
|
26
|
-
`Unable to load node configuration file ${configFilePath} to register with grid: ${err.message}`
|
|
27
|
-
);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
data = JSON.parse(data);
|
|
32
|
-
} catch (err) {
|
|
33
|
-
throw logger.errorWithException(
|
|
34
|
-
`Syntax error in node configuration file ${configFilePath}: ${err.message}`
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
postRequest(data, addr, port, basePath);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function registerToGrid(postOptions, configHolder) {
|
|
43
|
-
try {
|
|
44
|
-
const {status} = await axios(postOptions);
|
|
45
|
-
if (status !== 200) {
|
|
46
|
-
throw new Error(`Request failed with code ${status}`);
|
|
47
|
-
}
|
|
48
|
-
logger.debug(
|
|
49
|
-
`Appium successfully registered with the the grid on ` + hubUri(configHolder.configuration)
|
|
50
|
-
);
|
|
51
|
-
} catch (err) {
|
|
52
|
-
logger.error(`An attempt to register with the grid was unsuccessful: ${err.message}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function postRequest(configHolder, addr, port, basePath) {
|
|
57
|
-
// Move Selenium 3 configuration properties to configuration object
|
|
58
|
-
if (!_.has(configHolder, 'configuration')) {
|
|
59
|
-
let configuration = {};
|
|
60
|
-
for (const property in /** @type {import('@appium/types').StringRecord} */ (configHolder)) {
|
|
61
|
-
if (_.has(configHolder, property) && property !== 'capabilities') {
|
|
62
|
-
configuration[property] = configHolder[property];
|
|
63
|
-
delete configHolder[property];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/** @type {import('@appium/types').StringRecord} */ (configHolder).configuration = configuration;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// if the node config does not have the appium/webdriver url, host, and port,
|
|
70
|
-
// automatically add it based on how appium was initialized
|
|
71
|
-
// otherwise, we will take whatever the user setup
|
|
72
|
-
// because we will always set localhost/127.0.0.1. this won't work if your
|
|
73
|
-
// node and grid aren't in the same place
|
|
74
|
-
if (
|
|
75
|
-
!configHolder.configuration.url ||
|
|
76
|
-
!configHolder.configuration.host ||
|
|
77
|
-
!configHolder.configuration.port
|
|
78
|
-
) {
|
|
79
|
-
configHolder.configuration.url = `http://${addr}:${port}${basePath}`;
|
|
80
|
-
configHolder.configuration.host = addr;
|
|
81
|
-
configHolder.configuration.port = port;
|
|
82
|
-
}
|
|
83
|
-
// if the node config does not have id automatically add it
|
|
84
|
-
if (!configHolder.configuration.id) {
|
|
85
|
-
configHolder.configuration.id = `http://${configHolder.configuration.host}:${configHolder.configuration.port}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// the post options
|
|
89
|
-
const regRequest = {
|
|
90
|
-
url: `${hubUri(configHolder.configuration)}/grid/register`,
|
|
91
|
-
method: 'POST',
|
|
92
|
-
data: configHolder,
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
if (configHolder.configuration.register !== true) {
|
|
96
|
-
logger.debug(`No registration sent (${configHolder.configuration.register} = false)`);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const registerCycleInterval = configHolder.configuration.registerCycle;
|
|
101
|
-
if (isNaN(registerCycleInterval) || registerCycleInterval <= 0) {
|
|
102
|
-
logger.warn(
|
|
103
|
-
`'registerCycle' is not a valid positive number. ` +
|
|
104
|
-
`No registration request will be sent to the grid.`
|
|
105
|
-
);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
// initiate a new Thread
|
|
109
|
-
let first = true;
|
|
110
|
-
logger.debug(
|
|
111
|
-
`Starting auto register thread for the grid. ` +
|
|
112
|
-
`Will try to register every ${registerCycleInterval} ms.`
|
|
113
|
-
);
|
|
114
|
-
setInterval(async function registerRetry() {
|
|
115
|
-
if (first) {
|
|
116
|
-
first = false;
|
|
117
|
-
await registerToGrid(regRequest, configHolder);
|
|
118
|
-
} else if (!(await isAlreadyRegistered(configHolder))) {
|
|
119
|
-
// make the http POST to the grid for registration
|
|
120
|
-
await registerToGrid(regRequest, configHolder);
|
|
121
|
-
}
|
|
122
|
-
}, registerCycleInterval);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async function isAlreadyRegistered(configHolder) {
|
|
126
|
-
//check if node is already registered
|
|
127
|
-
const id = configHolder.configuration.id;
|
|
128
|
-
try {
|
|
129
|
-
const {data, status} = await axios({
|
|
130
|
-
url: `${hubUri(configHolder.configuration)}/grid/api/proxy?id=${id}`,
|
|
131
|
-
timeout: 10000,
|
|
132
|
-
});
|
|
133
|
-
if (status !== 200) {
|
|
134
|
-
throw new Error(`Request failed with code ${status}`);
|
|
135
|
-
}
|
|
136
|
-
if (!data.success) {
|
|
137
|
-
// if register fail, print the debug msg
|
|
138
|
-
logger.debug(`Grid registration error: ${data.msg}`);
|
|
139
|
-
}
|
|
140
|
-
return data.success;
|
|
141
|
-
} catch (err) {
|
|
142
|
-
logger.debug(`Hub down or not responding: ${err.message}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export default registerNode;
|
package/lib/schema/arg-spec.js
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The original ID of the Appium config schema.
|
|
5
|
-
* We use this in the CLI to convert it to `argparse` options.
|
|
6
|
-
*/
|
|
7
|
-
export const APPIUM_CONFIG_SCHEMA_ID = 'appium.json';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The schema prop containing server-related options. Everything in here
|
|
11
|
-
* is "native" to Appium.
|
|
12
|
-
* Used by {@link flattenSchema} for transforming the schema into CLI args.
|
|
13
|
-
*/
|
|
14
|
-
export const SERVER_PROP_NAME = 'server';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Used to parse extension info from a schema ID.
|
|
18
|
-
*/
|
|
19
|
-
const SCHEMA_ID_REGEXP = /^(?<extType>.+?)-(?<normalizedExtName>.+)\.json$/;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Avoid typos by using constants!
|
|
23
|
-
*/
|
|
24
|
-
const PROPERTIES = 'properties';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* An `ArgSpec` is a class representing metadata about an argument (or config
|
|
28
|
-
* option) used for cross-referencing.
|
|
29
|
-
*
|
|
30
|
-
* This class has no instance methods, and is basically just a read-only "struct".
|
|
31
|
-
* @template D
|
|
32
|
-
*/
|
|
33
|
-
export class ArgSpec {
|
|
34
|
-
/**
|
|
35
|
-
* The canonical name of the argument. Corresponds to key in schema's `properties` prop.
|
|
36
|
-
* @type {string}
|
|
37
|
-
*/
|
|
38
|
-
name;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The `ExtensionType` of the argument. This will be set if the arg came from an extension;
|
|
42
|
-
* otherwise it will be `undefined`.
|
|
43
|
-
* @type {ExtensionType|undefined}
|
|
44
|
-
*/
|
|
45
|
-
extType;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The name of the extension, if this argument came from an extension.
|
|
49
|
-
*
|
|
50
|
-
* Otherwise `undefined`.
|
|
51
|
-
* @type {string|undefined}
|
|
52
|
-
*/
|
|
53
|
-
extName;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* The schema ID (`$id`) for the argument. This is automatically determined, and any user-provided `$id`s will be overwritten.
|
|
57
|
-
*
|
|
58
|
-
* @type {string}
|
|
59
|
-
*/
|
|
60
|
-
ref;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* The CLI argument, sans leading dashes.
|
|
64
|
-
* @type {string}
|
|
65
|
-
*/
|
|
66
|
-
arg;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* The desired keypath for the argument after arguments have been parsed.
|
|
70
|
-
*
|
|
71
|
-
* Typically this is camelCased. If the arg came from an extension, it will be prefixed with
|
|
72
|
-
* `<extType>.<extName>.`
|
|
73
|
-
* @type {string}
|
|
74
|
-
*/
|
|
75
|
-
dest;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* The same as {@link ArgSpec.dest} but without the leading `<extType>.<extName>.` prefix.
|
|
79
|
-
*/
|
|
80
|
-
rawDest;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Whatever the default value of this argument is, as specified by the
|
|
84
|
-
* `default` property of the schema.
|
|
85
|
-
* @type {D|undefined}
|
|
86
|
-
*/
|
|
87
|
-
defaultValue;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Builds some computed fields and assigns them to the instance.
|
|
91
|
-
*
|
|
92
|
-
* Undefined properties are not assigned.
|
|
93
|
-
*
|
|
94
|
-
* The _constructor_ is private. Use {@link ArgSpec.create} instead.
|
|
95
|
-
* @private
|
|
96
|
-
* @param {string} name
|
|
97
|
-
* @param {ArgSpecOptions<D>} opts
|
|
98
|
-
*/
|
|
99
|
-
constructor(name, {extType, extName, dest, defaultValue} = {}) {
|
|
100
|
-
// we must normalize the extension name to fit into our convention for CLI
|
|
101
|
-
// args.
|
|
102
|
-
const arg = ArgSpec.toArg(name, extType, extName);
|
|
103
|
-
|
|
104
|
-
const ref = ArgSpec.toSchemaRef(name, extType, extName);
|
|
105
|
-
|
|
106
|
-
// if no explicit `dest` provided, just camelCase the name to avoid needing
|
|
107
|
-
// to use bracket syntax when accessing props on the parsed args object.
|
|
108
|
-
const rawDest = _.camelCase(dest ?? name);
|
|
109
|
-
|
|
110
|
-
const destKeypath = extType && extName ? [extType, extName, rawDest].join('.') : rawDest;
|
|
111
|
-
|
|
112
|
-
this.defaultValue = defaultValue;
|
|
113
|
-
this.name = name;
|
|
114
|
-
this.extType = extType;
|
|
115
|
-
this.extName = extName;
|
|
116
|
-
this.arg = arg;
|
|
117
|
-
this.dest = destKeypath;
|
|
118
|
-
this.ref = ref;
|
|
119
|
-
this.rawDest = rawDest;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Return the schema ID (`$id`) for the **argument** given the parameters.
|
|
124
|
-
*
|
|
125
|
-
* If you need the "root" or "base" schema ID, use {@link ArgSpec.toSchemaBaseRef} instead.
|
|
126
|
-
* @param {string} name - Argument name
|
|
127
|
-
* @param {ExtensionType} [extType] - Extension type
|
|
128
|
-
* @param {string} [extName] - Extension name
|
|
129
|
-
* @returns {string} Schema ID
|
|
130
|
-
*/
|
|
131
|
-
static toSchemaRef(name, extType, extName) {
|
|
132
|
-
const baseRef = ArgSpec.toSchemaBaseRef(extType, extName);
|
|
133
|
-
if (extType && extName) {
|
|
134
|
-
return [`${baseRef}#`, PROPERTIES, name].join('/');
|
|
135
|
-
}
|
|
136
|
-
return [`${baseRef}#`, PROPERTIES, SERVER_PROP_NAME, PROPERTIES, name].join('/');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Return the schema ID for an extension or the base schema ID.
|
|
141
|
-
* @param {ExtensionType} [extType] - Extension type
|
|
142
|
-
* @param {string} [extName] - Extension name
|
|
143
|
-
*/
|
|
144
|
-
static toSchemaBaseRef(extType, extName) {
|
|
145
|
-
if (extType && extName) {
|
|
146
|
-
return `${extType}-${ArgSpec.toNormalizedExtName(extName)}.json`;
|
|
147
|
-
}
|
|
148
|
-
return APPIUM_CONFIG_SCHEMA_ID;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Return the unique ID for the argument given the parameters.
|
|
153
|
-
* @param {string} name - Argument name
|
|
154
|
-
* @param {ExtensionType} [extType] - Extension type
|
|
155
|
-
* @param {string} [extName] - Extension name
|
|
156
|
-
* @returns {string} Unique ID
|
|
157
|
-
*/
|
|
158
|
-
static toArg(name, extType, extName) {
|
|
159
|
-
const properName = _.kebabCase(name.replace(/^--?/, ''));
|
|
160
|
-
if (extType && extName) {
|
|
161
|
-
return [extType, _.kebabCase(extName), properName].join('-');
|
|
162
|
-
}
|
|
163
|
-
return properName;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Normalizes a raw extension name (not including the type).
|
|
168
|
-
* @param {string} extName - Extension name
|
|
169
|
-
* @returns {string} Normalized extension name
|
|
170
|
-
*/
|
|
171
|
-
static toNormalizedExtName(extName) {
|
|
172
|
-
return _.kebabCase(extName);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* 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.
|
|
177
|
-
* @param {string} schemaId - Root schema ID
|
|
178
|
-
* @returns { {extType?: ExtensionType, normalizedExtName?: string} }
|
|
179
|
-
*/
|
|
180
|
-
static extensionInfoFromRootSchemaId(schemaId) {
|
|
181
|
-
const matches = schemaId.match(SCHEMA_ID_REGEXP);
|
|
182
|
-
if (matches?.groups) {
|
|
183
|
-
const {extType, normalizedExtName} =
|
|
184
|
-
/** @type { {extType: ExtensionType, normalizedExtName: string} } */ (matches.groups);
|
|
185
|
-
return {extType, normalizedExtName};
|
|
186
|
-
}
|
|
187
|
-
return {};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Creates an `ArgSpec`
|
|
192
|
-
*
|
|
193
|
-
* @param {string} name - The canonical name of the argument. Corresponds to a key in a schema's
|
|
194
|
-
* `properties` property.
|
|
195
|
-
* @template D
|
|
196
|
-
* @param {ArgSpecOptions<D>} [opts] - Options
|
|
197
|
-
* @returns {Readonly<ArgSpec>}
|
|
198
|
-
*/
|
|
199
|
-
static create(name, opts) {
|
|
200
|
-
return Object.freeze(new ArgSpec(name, opts));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* String representation, useful for debugging
|
|
205
|
-
* @returns {string}
|
|
206
|
-
*/
|
|
207
|
-
/* istanbul ignore next */
|
|
208
|
-
toString() {
|
|
209
|
-
let str = `[ArgSpec] ${this.name} (${this.ref})`;
|
|
210
|
-
if (this.extType && this.extName) {
|
|
211
|
-
str += ` (ext: ${this.extType}/${this.extName})`;
|
|
212
|
-
}
|
|
213
|
-
return str;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Options for {@link ArgSpec.create}
|
|
219
|
-
* @template D
|
|
220
|
-
* @typedef ArgSpecOptions
|
|
221
|
-
* @property {string} [extName]
|
|
222
|
-
* @property {ExtensionType} [extType]
|
|
223
|
-
* @property {string} [dest]
|
|
224
|
-
* @property {D} [defaultValue]
|
|
225
|
-
*/
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* @typedef {import('@appium/types').ExtensionType} ExtensionType
|
|
229
|
-
*/
|