appium 3.0.0-beta.1 → 3.0.0-rc.2
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/README.md +10 -0
- package/build/lib/appium.d.ts +9 -5
- package/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +12 -25
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.js +2 -2
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/cli/driver-command.js +1 -1
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +32 -5
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/parser.js +1 -1
- package/build/lib/cli/plugin-command.js +1 -1
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/constants.d.ts +4 -0
- package/build/lib/constants.d.ts.map +1 -1
- package/build/lib/constants.js +5 -1
- package/build/lib/constants.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +12 -14
- package/build/lib/extension/driver-config.js.map +1 -1
- package/build/lib/extension/extension-config.d.ts.map +1 -1
- package/build/lib/extension/extension-config.js +5 -7
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +5 -7
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/insecure-features.d.ts +18 -0
- package/build/lib/insecure-features.d.ts.map +1 -0
- package/build/lib/insecure-features.js +116 -0
- package/build/lib/insecure-features.js.map +1 -0
- package/build/lib/logsink.d.ts +10 -0
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +17 -18
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/main.d.ts +1 -1
- package/build/lib/main.d.ts.map +1 -1
- package/build/lib/main.js +3 -1
- package/build/lib/main.js.map +1 -1
- package/build/lib/schema/cli-args.d.ts +1 -1
- package/build/lib/schema/cli-args.js +1 -1
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/schema.d.ts +1 -1
- package/build/lib/schema/schema.js +1 -1
- package/build/lib/utils.d.ts +12 -9
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +28 -39
- package/build/lib/utils.js.map +1 -1
- package/lib/appium.js +15 -37
- package/lib/bidi-commands.ts +2 -2
- package/lib/cli/driver-command.js +1 -1
- package/lib/cli/extension-command.js +36 -6
- package/lib/cli/parser.js +1 -1
- package/lib/cli/plugin-command.js +1 -1
- package/lib/constants.js +5 -0
- package/lib/extension/driver-config.js +11 -13
- package/lib/extension/extension-config.js +11 -14
- package/lib/extension/manifest.js +10 -12
- package/lib/insecure-features.ts +129 -0
- package/lib/logsink.js +17 -18
- package/lib/main.js +4 -1
- package/lib/schema/cli-args.js +2 -2
- package/lib/schema/schema.js +1 -1
- package/lib/utils.js +27 -39
- package/package.json +19 -19
|
@@ -84,20 +84,18 @@ export class DriverConfig extends ExtensionConfig {
|
|
|
84
84
|
err: 'Missing or incorrect supported platformNames list.',
|
|
85
85
|
val: platformNames,
|
|
86
86
|
});
|
|
87
|
+
} else if (_.isEmpty(platformNames)) {
|
|
88
|
+
problems.push({
|
|
89
|
+
err: 'Empty platformNames list.',
|
|
90
|
+
val: platformNames,
|
|
91
|
+
});
|
|
87
92
|
} else {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
for (const pName of platformNames) {
|
|
95
|
-
if (!_.isString(pName)) {
|
|
96
|
-
problems.push({
|
|
97
|
-
err: 'Incorrectly formatted platformName.',
|
|
98
|
-
val: pName,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
93
|
+
for (const pName of platformNames) {
|
|
94
|
+
if (!_.isString(pName)) {
|
|
95
|
+
problems.push({
|
|
96
|
+
err: 'Incorrectly formatted platformName.',
|
|
97
|
+
val: pName,
|
|
98
|
+
});
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
}
|
|
@@ -240,20 +240,17 @@ export class ExtensionConfig {
|
|
|
240
240
|
for (const summary of errorSummaries) {
|
|
241
241
|
log.error(summary);
|
|
242
242
|
}
|
|
243
|
-
} else {
|
|
243
|
+
} else if (!_.isEmpty(warningSummaries)) {
|
|
244
244
|
// only display warnings if there are no errors!
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
);
|
|
254
|
-
for (const summary of warningSummaries) {
|
|
255
|
-
log.warn(summary);
|
|
256
|
-
}
|
|
245
|
+
log.warn(
|
|
246
|
+
`Appium encountered ${util.pluralize(
|
|
247
|
+
'warning',
|
|
248
|
+
warningMap.size,
|
|
249
|
+
true
|
|
250
|
+
)} while validating ${this.extensionType}s found in manifest ${this.manifestPath}`
|
|
251
|
+
);
|
|
252
|
+
for (const summary of warningSummaries) {
|
|
253
|
+
log.warn(summary);
|
|
257
254
|
}
|
|
258
255
|
}
|
|
259
256
|
return exts;
|
|
@@ -464,7 +461,7 @@ export class ExtensionConfig {
|
|
|
464
461
|
*/
|
|
465
462
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
466
463
|
getConfigProblems(extManifest, extName) {
|
|
467
|
-
//
|
|
464
|
+
// should override this method if special validation is necessary for this extension type
|
|
468
465
|
return [];
|
|
469
466
|
}
|
|
470
467
|
|
|
@@ -390,19 +390,17 @@ export class Manifest {
|
|
|
390
390
|
if (err.code === 'ENOENT') {
|
|
391
391
|
data = _.cloneDeep(INITIAL_MANIFEST_DATA);
|
|
392
392
|
shouldWrite = true;
|
|
393
|
+
} else if (this.#manifestPath) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`Appium had trouble loading the extension installation ` +
|
|
396
|
+
`cache file (${this.#manifestPath}). It may be invalid YAML. Specific error: ${
|
|
397
|
+
err.message
|
|
398
|
+
}`
|
|
399
|
+
);
|
|
393
400
|
} else {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
`cache file (${this.#manifestPath}). It may be invalid YAML. Specific error: ${
|
|
398
|
-
err.message
|
|
399
|
-
}`
|
|
400
|
-
);
|
|
401
|
-
} else {
|
|
402
|
-
throw new Error(
|
|
403
|
-
`Appium encountered an unknown problem. Specific error: ${err.message}`
|
|
404
|
-
);
|
|
405
|
-
}
|
|
401
|
+
throw new Error(
|
|
402
|
+
`Appium encountered an unknown problem. Specific error: ${err.message}`
|
|
403
|
+
);
|
|
406
404
|
}
|
|
407
405
|
}
|
|
408
406
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import logger from './logger';
|
|
3
|
+
|
|
4
|
+
import type {AppiumDriver} from './appium';
|
|
5
|
+
import type {ExternalDriver} from '@appium/types';
|
|
6
|
+
|
|
7
|
+
const ALL_DRIVERS_MATCH = '*';
|
|
8
|
+
const FEATURE_NAME_SEPARATOR = ':';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configures insecure features according to the values in `args.relaxedSecurityEnabled`,
|
|
12
|
+
* `args.allowInsecure`, and `args.denyInsecure`, and informs the user about any
|
|
13
|
+
* globally-applied features.
|
|
14
|
+
* Uses `logger` instead of `this.log` to reduce user confusion.
|
|
15
|
+
*/
|
|
16
|
+
export function configureGlobalFeatures(this: AppiumDriver) {
|
|
17
|
+
if (this.args.relaxedSecurityEnabled) {
|
|
18
|
+
logger.info(
|
|
19
|
+
`Enabling relaxed security. All insecure features will be ` +
|
|
20
|
+
`enabled unless explicitly disabled by --deny-insecure`,
|
|
21
|
+
);
|
|
22
|
+
this.relaxedSecurityEnabled = true;
|
|
23
|
+
} else if (!_.isEmpty(this.args.allowInsecure)) {
|
|
24
|
+
this.allowInsecure = validateFeatures(this.args.allowInsecure);
|
|
25
|
+
const globalAllowedFeatures = filterInsecureFeatures(this.allowInsecure);
|
|
26
|
+
if (!_.isEmpty(globalAllowedFeatures)) {
|
|
27
|
+
logger.info('Explicitly enabling insecure features:');
|
|
28
|
+
globalAllowedFeatures.forEach((a) => logger.info(` ${a}`));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (_.isEmpty(this.args.denyInsecure)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.denyInsecure = validateFeatures(this.args.denyInsecure);
|
|
35
|
+
const globalDeniedFeatures = filterInsecureFeatures(this.denyInsecure);
|
|
36
|
+
if (_.isEmpty(globalDeniedFeatures)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
logger.info('Explicitly disabling insecure features:');
|
|
40
|
+
globalDeniedFeatures.forEach((a) => logger.info(` ${a}`));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* If anything in the umbrella driver's insecure feature configuration applies to this driver,
|
|
45
|
+
* assign it to the driver instance
|
|
46
|
+
*
|
|
47
|
+
* @param driver
|
|
48
|
+
* @param driverName
|
|
49
|
+
*/
|
|
50
|
+
export function configureDriverFeatures(
|
|
51
|
+
this: AppiumDriver,
|
|
52
|
+
driver: ExternalDriver,
|
|
53
|
+
driverName: string,
|
|
54
|
+
) {
|
|
55
|
+
if (this.relaxedSecurityEnabled) {
|
|
56
|
+
this.log.info(
|
|
57
|
+
`Enabling relaxed security for this session as per the server configuration. ` +
|
|
58
|
+
`All insecure features will be enabled unless explicitly disabled by --deny-insecure`,
|
|
59
|
+
);
|
|
60
|
+
driver.relaxedSecurityEnabled = true;
|
|
61
|
+
}
|
|
62
|
+
const allowedDriverFeatures = filterInsecureFeatures(this.allowInsecure, driverName);
|
|
63
|
+
if (!_.isEmpty(allowedDriverFeatures)) {
|
|
64
|
+
this.log.info('Explicitly enabling insecure features for this session ' +
|
|
65
|
+
'as per the server configuration:',
|
|
66
|
+
);
|
|
67
|
+
allowedDriverFeatures.forEach((a) => this.log.info(` ${a}`));
|
|
68
|
+
driver.allowInsecure = allowedDriverFeatures;
|
|
69
|
+
}
|
|
70
|
+
const deniedDriverFeatures = filterInsecureFeatures(this.denyInsecure, driverName);
|
|
71
|
+
if (_.isEmpty(deniedDriverFeatures)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this.log.info('Explicitly disabling insecure features for this session ' +
|
|
75
|
+
'as per the server configuration:',
|
|
76
|
+
);
|
|
77
|
+
deniedDriverFeatures.forEach((a) => this.log.info(` ${a}`));
|
|
78
|
+
driver.denyInsecure = deniedDriverFeatures;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Validates the list of allowed/denied server features
|
|
83
|
+
*
|
|
84
|
+
* @param features
|
|
85
|
+
*/
|
|
86
|
+
function validateFeatures(features: string[]): string[] {
|
|
87
|
+
const validator = (fullName: string) => {
|
|
88
|
+
const errMsg = `The full feature name must include both the destination automation name or the ` +
|
|
89
|
+
`'${ALL_DRIVERS_MATCH}' wildcard to apply the feature to all installed drivers, and ` +
|
|
90
|
+
`the feature name split by a colon. Got '${fullName}' instead`;
|
|
91
|
+
|
|
92
|
+
const separatorPos = fullName.indexOf(FEATURE_NAME_SEPARATOR);
|
|
93
|
+
if (separatorPos < 0) {
|
|
94
|
+
throw new Error(errMsg);
|
|
95
|
+
}
|
|
96
|
+
const [automationName, featureName] = [
|
|
97
|
+
fullName.substring(0, separatorPos),
|
|
98
|
+
fullName.substring(separatorPos + 1)
|
|
99
|
+
];
|
|
100
|
+
if (!automationName || !featureName) {
|
|
101
|
+
throw new Error(errMsg);
|
|
102
|
+
}
|
|
103
|
+
return fullName;
|
|
104
|
+
};
|
|
105
|
+
return features.map(validator);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Filters the list of insecure features to only those that are
|
|
110
|
+
* applicable to the given driver name.
|
|
111
|
+
* Assumes that all feature names have already been validated
|
|
112
|
+
*
|
|
113
|
+
* @param features
|
|
114
|
+
* @param driverName
|
|
115
|
+
*/
|
|
116
|
+
function filterInsecureFeatures(
|
|
117
|
+
features: string[],
|
|
118
|
+
driverName: string = ALL_DRIVERS_MATCH
|
|
119
|
+
): string[] {
|
|
120
|
+
const filterFn = (fullName: string) => {
|
|
121
|
+
const separatorPos = fullName.indexOf(FEATURE_NAME_SEPARATOR);
|
|
122
|
+
if (separatorPos <= 0) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const automationName = fullName.substring(0, separatorPos);
|
|
126
|
+
return [driverName, ALL_DRIVERS_MATCH].includes(automationName);
|
|
127
|
+
};
|
|
128
|
+
return features.filter(filterFn);
|
|
129
|
+
}
|
package/lib/logsink.js
CHANGED
|
@@ -61,6 +61,8 @@ export async function init(args) {
|
|
|
61
61
|
log = createLogger({
|
|
62
62
|
transports,
|
|
63
63
|
levels: LEVELS_MAP,
|
|
64
|
+
handleExceptions: true,
|
|
65
|
+
exitOnError: false
|
|
64
66
|
});
|
|
65
67
|
|
|
66
68
|
const reportedLoggerErrors = new Set();
|
|
@@ -131,12 +133,9 @@ const stripColorFormat = format(function stripColor(info) {
|
|
|
131
133
|
* @returns {transports.ConsoleTransportInstance}
|
|
132
134
|
*/
|
|
133
135
|
function createConsoleTransport(args, logLvl) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
/** @type {AppiumConsoleTransportOptions} */
|
|
137
|
+
const opt = {
|
|
136
138
|
name: 'console',
|
|
137
|
-
handleExceptions: true,
|
|
138
|
-
exitOnError: false,
|
|
139
|
-
json: false,
|
|
140
139
|
level: logLvl,
|
|
141
140
|
stderrLevels: ['error'],
|
|
142
141
|
format: format.combine(
|
|
@@ -144,7 +143,8 @@ function createConsoleTransport(args, logLvl) {
|
|
|
144
143
|
isLogColorEnabled(args) ? colorizeFormat : stripColorFormat,
|
|
145
144
|
formatLog(args, true),
|
|
146
145
|
),
|
|
147
|
-
}
|
|
146
|
+
};
|
|
147
|
+
return new transports.Console(opt);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
/**
|
|
@@ -154,21 +154,19 @@ function createConsoleTransport(args, logLvl) {
|
|
|
154
154
|
* @returns {transports.FileTransportInstance}
|
|
155
155
|
*/
|
|
156
156
|
function createFileTransport(args, logLvl) {
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
/** @type {AppiumFileTransportOptions} */
|
|
158
|
+
const opt = {
|
|
159
159
|
name: 'file',
|
|
160
160
|
filename: args.logFile,
|
|
161
161
|
maxFiles: 1,
|
|
162
|
-
handleExceptions: true,
|
|
163
|
-
exitOnError: false,
|
|
164
|
-
json: false,
|
|
165
162
|
level: logLvl,
|
|
166
163
|
format: format.combine(
|
|
167
164
|
stripColorFormat,
|
|
168
165
|
formatTimestamp(args),
|
|
169
166
|
formatLog(args, false),
|
|
170
167
|
),
|
|
171
|
-
}
|
|
168
|
+
};
|
|
169
|
+
return new transports.File(opt);
|
|
172
170
|
}
|
|
173
171
|
|
|
174
172
|
/**
|
|
@@ -187,21 +185,19 @@ function createHttpTransport(args, logLvl) {
|
|
|
187
185
|
port = parseInt(hostAndPort[1], 10);
|
|
188
186
|
}
|
|
189
187
|
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
/** @type {AppiumHttpTransportOptions} */
|
|
189
|
+
const opt = {
|
|
192
190
|
name: 'http',
|
|
193
191
|
host,
|
|
194
192
|
port,
|
|
195
193
|
path: '/',
|
|
196
|
-
handleExceptions: true,
|
|
197
|
-
exitOnError: false,
|
|
198
|
-
json: false,
|
|
199
194
|
level: logLvl,
|
|
200
195
|
format: format.combine(
|
|
201
196
|
stripColorFormat,
|
|
202
197
|
formatLog(args, false),
|
|
203
198
|
),
|
|
204
|
-
}
|
|
199
|
+
};
|
|
200
|
+
return new transports.Http(opt);
|
|
205
201
|
}
|
|
206
202
|
|
|
207
203
|
/**
|
|
@@ -362,4 +358,7 @@ export default init;
|
|
|
362
358
|
/**
|
|
363
359
|
* @typedef {import('appium/types').ParsedArgs} ParsedArgs
|
|
364
360
|
* @typedef {import('@appium/logger').MessageObject} MessageObject
|
|
361
|
+
* @typedef {transports.ConsoleTransportOptions & {name: string}} AppiumConsoleTransportOptions
|
|
362
|
+
* @typedef {transports.FileTransportOptions & {name: string}} AppiumFileTransportOptions
|
|
363
|
+
* @typedef {transports.HttpTransportOptions & {name: string}} AppiumHttpTransportOptions
|
|
365
364
|
*/
|
package/lib/main.js
CHANGED
|
@@ -177,7 +177,7 @@ function determineAppiumHomeSource(appiumHomeFromArgs) {
|
|
|
177
177
|
*
|
|
178
178
|
* @template {CliCommand} [Cmd=ServerCommand]
|
|
179
179
|
* @template {CliExtensionSubcommand|void} [SubCmd=void]
|
|
180
|
-
* @param {Args<Cmd, SubCmd>} [args] - Partial args (
|
|
180
|
+
* @param {Args<Cmd, SubCmd>} [args] - Partial args (programmatic usage only)
|
|
181
181
|
* @returns {Promise<InitResult<Cmd>>}
|
|
182
182
|
* @example
|
|
183
183
|
* import {init, getSchema} from 'appium';
|
|
@@ -375,6 +375,9 @@ async function main(args) {
|
|
|
375
375
|
|
|
376
376
|
await logStartupInfo(parsedArgs);
|
|
377
377
|
|
|
378
|
+
// handle the insecure feature configuration since some features may apply globally
|
|
379
|
+
appiumDriver.configureGlobalFeatures();
|
|
380
|
+
|
|
378
381
|
const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
|
|
379
382
|
logger.debug(`The ${appiumHomeSourceName}: ${appiumHome}`);
|
|
380
383
|
|
package/lib/schema/cli-args.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ArgumentTypeError} from 'argparse';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
-
import {formatErrors
|
|
3
|
+
import {formatErrors} from '../config-file';
|
|
4
4
|
import {flattenSchema, validate} from './schema';
|
|
5
5
|
import {transformers, parseCsvLine} from './cli-transformers';
|
|
6
6
|
|
|
@@ -225,7 +225,7 @@ function subSchemaToArgDef(subSchema, argSpec) {
|
|
|
225
225
|
* ArgumentDefinitions for handoff to `argparse`.
|
|
226
226
|
*
|
|
227
227
|
* @throws If schema has not been added to ajv (via `finalizeSchema()`)
|
|
228
|
-
* @returns {import('../cli/args').ArgumentDefinitions} A map of
|
|
228
|
+
* @returns {import('../cli/args').ArgumentDefinitions} A map of arrays of
|
|
229
229
|
* aliases to `argparse` arguments; empty if no schema found
|
|
230
230
|
*/
|
|
231
231
|
export function toParserArgs() {
|
package/lib/schema/schema.js
CHANGED
|
@@ -421,7 +421,7 @@ class AppiumSchema {
|
|
|
421
421
|
* name. Used when translating to `argparse` options or getting the list of
|
|
422
422
|
* default values (see {@link AppiumSchema.getDefaults}) for CLI or otherwise.
|
|
423
423
|
*
|
|
424
|
-
* The return value is an intermediate
|
|
424
|
+
* The return value is an intermediate representation used by `cli-args`
|
|
425
425
|
* module's `toParserArgs`, which converts the finalized schema to parameters
|
|
426
426
|
* used by `argparse`.
|
|
427
427
|
* @throws If {@link AppiumSchema.finalize} has not been called yet.
|
package/lib/utils.js
CHANGED
|
@@ -17,8 +17,6 @@ const STANDARD_CAPS_LOWERCASE = new Set([...STANDARD_CAPS].map((cap) => cap.toLo
|
|
|
17
17
|
export const V4_BROADCAST_IP = '0.0.0.0';
|
|
18
18
|
export const V6_BROADCAST_IP = '::';
|
|
19
19
|
export const npmPackage = fs.readPackageJsonFrom(__dirname);
|
|
20
|
-
const ALL_DRIVERS_MATCH = '*';
|
|
21
|
-
const FEATURE_NAME_SEPARATOR = ':';
|
|
22
20
|
|
|
23
21
|
/**
|
|
24
22
|
*
|
|
@@ -191,19 +189,37 @@ export function getPackageVersion(pkgName) {
|
|
|
191
189
|
return pkgInfo.version;
|
|
192
190
|
}
|
|
193
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Returns the root directory of the Appium module.
|
|
194
|
+
*
|
|
195
|
+
* @returns {string} - The absolute path to the Appium module root directory.
|
|
196
|
+
* @throws {Error} - If the Appium module root cannot be determined.
|
|
197
|
+
*/
|
|
198
|
+
export const getAppiumModuleRoot = _.memoize(function getAppiumModuleRoot() {
|
|
199
|
+
const selfRoot = node.getModuleRootSync('appium', __filename);
|
|
200
|
+
if (!selfRoot) {
|
|
201
|
+
throw new Error('Cannot find the appium module root. This is likely a bug in Appium.');
|
|
202
|
+
}
|
|
203
|
+
return selfRoot;
|
|
204
|
+
});
|
|
205
|
+
|
|
194
206
|
/**
|
|
195
207
|
* Adjusts NODE_PATH environment variable,
|
|
196
|
-
* so drivers and plugins could load their peer dependencies.
|
|
208
|
+
* so CJS drivers and plugins could load their peer dependencies.
|
|
197
209
|
* Read https://nodejs.org/api/modules.html#loading-from-the-global-folders
|
|
198
210
|
* for more details.
|
|
211
|
+
*
|
|
212
|
+
* Unfortunately this hack does not work with ESM modules,
|
|
199
213
|
* @returns {void}
|
|
200
214
|
*/
|
|
201
215
|
export function adjustNodePath() {
|
|
202
|
-
|
|
203
|
-
|
|
216
|
+
let appiumModuleSearchRoot;
|
|
217
|
+
try {
|
|
218
|
+
appiumModuleSearchRoot = path.dirname(getAppiumModuleRoot());
|
|
219
|
+
} catch (error) {
|
|
220
|
+
logger.warn(error.message);
|
|
204
221
|
return;
|
|
205
222
|
}
|
|
206
|
-
const nodeModulesRoot = path.dirname(selfRoot);
|
|
207
223
|
|
|
208
224
|
const refreshRequirePaths = () => {
|
|
209
225
|
try {
|
|
@@ -221,7 +237,7 @@ export function adjustNodePath() {
|
|
|
221
237
|
};
|
|
222
238
|
|
|
223
239
|
if (!process.env.NODE_PATH) {
|
|
224
|
-
process.env.NODE_PATH =
|
|
240
|
+
process.env.NODE_PATH = appiumModuleSearchRoot;
|
|
225
241
|
if (refreshRequirePaths()) {
|
|
226
242
|
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
227
243
|
} else {
|
|
@@ -231,17 +247,17 @@ export function adjustNodePath() {
|
|
|
231
247
|
}
|
|
232
248
|
|
|
233
249
|
const nodePathParts = process.env.NODE_PATH.split(path.delimiter);
|
|
234
|
-
if (nodePathParts.includes(
|
|
250
|
+
if (nodePathParts.includes(appiumModuleSearchRoot)) {
|
|
235
251
|
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
236
252
|
return;
|
|
237
253
|
}
|
|
238
254
|
|
|
239
|
-
nodePathParts.push(
|
|
255
|
+
nodePathParts.push(appiumModuleSearchRoot);
|
|
240
256
|
process.env.NODE_PATH = nodePathParts.join(path.delimiter);
|
|
241
257
|
if (refreshRequirePaths()) {
|
|
242
258
|
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
243
259
|
} else {
|
|
244
|
-
process.env.NODE_PATH = _.without(nodePathParts,
|
|
260
|
+
process.env.NODE_PATH = _.without(nodePathParts, appiumModuleSearchRoot).join(path.delimiter);
|
|
245
261
|
}
|
|
246
262
|
}
|
|
247
263
|
|
|
@@ -346,7 +362,7 @@ export function isPluginCommandArgs(args) {
|
|
|
346
362
|
*
|
|
347
363
|
* @param {4|6|null} family Either 4 to include ipv4 addresses only,
|
|
348
364
|
* 6 to include ipv6 addresses only, or null to include all of them
|
|
349
|
-
* @returns {os.NetworkInterfaceInfo[]} The list of matched
|
|
365
|
+
* @returns {os.NetworkInterfaceInfo[]} The list of matched interfaces
|
|
350
366
|
*/
|
|
351
367
|
export function fetchInterfaces (family = null) {
|
|
352
368
|
let familyValue = null;
|
|
@@ -427,34 +443,6 @@ export function isBroadcastIp(address) {
|
|
|
427
443
|
return [V4_BROADCAST_IP, V6_BROADCAST_IP, `[${V6_BROADCAST_IP}]`].includes(address);
|
|
428
444
|
}
|
|
429
445
|
|
|
430
|
-
/**
|
|
431
|
-
* Validates the list of allowed/denied server features
|
|
432
|
-
*
|
|
433
|
-
* @param {string[]} features
|
|
434
|
-
* @returns {string[]}
|
|
435
|
-
*/
|
|
436
|
-
export function validateFeatures(features) {
|
|
437
|
-
const validator = (/** @type {string} */ fullName) => {
|
|
438
|
-
const errMsg = `The full feature name must include both the destination automation name or the ` +
|
|
439
|
-
`'${ALL_DRIVERS_MATCH}' wildcard to apply the feature to all installed drivers, and ` +
|
|
440
|
-
`the feature name split by a colon. Got '${fullName}' instead`;
|
|
441
|
-
|
|
442
|
-
const separatorPos = fullName.indexOf(FEATURE_NAME_SEPARATOR);
|
|
443
|
-
if (separatorPos < 0) {
|
|
444
|
-
throw new Error(errMsg);
|
|
445
|
-
}
|
|
446
|
-
const [automationName, featureName] = [
|
|
447
|
-
fullName.substring(0, separatorPos),
|
|
448
|
-
fullName.substring(separatorPos + 1)
|
|
449
|
-
];
|
|
450
|
-
if (!automationName || !featureName) {
|
|
451
|
-
throw new Error(errMsg);
|
|
452
|
-
}
|
|
453
|
-
return fullName;
|
|
454
|
-
};
|
|
455
|
-
return features.map(validator);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
446
|
/**
|
|
459
447
|
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
460
448
|
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-rc.2",
|
|
4
4
|
"description": "Automation for Apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -60,43 +60,43 @@
|
|
|
60
60
|
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@appium/base-driver": "^10.0.0-
|
|
64
|
-
"@appium/base-plugin": "^3.0.0-
|
|
65
|
-
"@appium/docutils": "^
|
|
66
|
-
"@appium/logger": "^
|
|
67
|
-
"@appium/schema": "^0.
|
|
68
|
-
"@appium/support": "^
|
|
69
|
-
"@appium/types": "^0.
|
|
70
|
-
"@sidvind/better-ajv-errors": "
|
|
63
|
+
"@appium/base-driver": "^10.0.0-rc.2",
|
|
64
|
+
"@appium/base-plugin": "^3.0.0-rc.2",
|
|
65
|
+
"@appium/docutils": "^2.0.0-rc.1",
|
|
66
|
+
"@appium/logger": "^2.0.0-rc.1",
|
|
67
|
+
"@appium/schema": "^1.0.0-rc.1",
|
|
68
|
+
"@appium/support": "^7.0.0-rc.1",
|
|
69
|
+
"@appium/types": "^1.0.0-rc.1",
|
|
70
|
+
"@sidvind/better-ajv-errors": "4.0.0",
|
|
71
71
|
"ajv": "8.17.1",
|
|
72
72
|
"ajv-formats": "3.0.1",
|
|
73
73
|
"argparse": "2.0.1",
|
|
74
74
|
"async-lock": "1.4.1",
|
|
75
75
|
"asyncbox": "3.0.0",
|
|
76
|
-
"axios": "1.
|
|
76
|
+
"axios": "1.11.0",
|
|
77
77
|
"bluebird": "3.7.2",
|
|
78
78
|
"lilconfig": "3.1.3",
|
|
79
79
|
"lodash": "4.17.21",
|
|
80
|
-
"lru-cache": "
|
|
80
|
+
"lru-cache": "11.1.0",
|
|
81
81
|
"ora": "5.4.1",
|
|
82
82
|
"package-changed": "3.0.0",
|
|
83
83
|
"resolve-from": "5.0.0",
|
|
84
|
-
"semver": "7.7.
|
|
84
|
+
"semver": "7.7.2",
|
|
85
85
|
"source-map-support": "0.5.21",
|
|
86
|
-
"teen_process": "2.3.
|
|
87
|
-
"type-fest": "4.
|
|
86
|
+
"teen_process": "2.3.3",
|
|
87
|
+
"type-fest": "4.41.0",
|
|
88
88
|
"winston": "3.17.0",
|
|
89
89
|
"wrap-ansi": "7.0.0",
|
|
90
|
-
"ws": "8.18.
|
|
91
|
-
"yaml": "2.
|
|
90
|
+
"ws": "8.18.3",
|
|
91
|
+
"yaml": "2.8.1"
|
|
92
92
|
},
|
|
93
93
|
"engines": {
|
|
94
|
-
"node": "^20.
|
|
94
|
+
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
|
|
95
95
|
"npm": ">=10"
|
|
96
96
|
},
|
|
97
97
|
"publishConfig": {
|
|
98
98
|
"access": "public",
|
|
99
|
-
"tag": "
|
|
99
|
+
"tag": "rc"
|
|
100
100
|
},
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "157425ce6aa01c009533f5bf6a56b14570222b00"
|
|
102
102
|
}
|