appium 3.2.2 → 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 +16 -16
- 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/utils.ts
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseDriverCapConstraints,
|
|
3
|
+
Capabilities,
|
|
4
|
+
Constraints,
|
|
5
|
+
NSCapabilities,
|
|
6
|
+
W3CCapabilities,
|
|
7
|
+
} from '@appium/types';
|
|
8
|
+
import type {
|
|
9
|
+
Args,
|
|
10
|
+
CliCommand,
|
|
11
|
+
CliCommandDriver,
|
|
12
|
+
CliCommandPlugin,
|
|
13
|
+
CliCommandServer,
|
|
14
|
+
CliCommandSetup,
|
|
15
|
+
CliExtensionCommand,
|
|
16
|
+
CliExtensionSubcommand,
|
|
17
|
+
CliCommandSetupSubcommand,
|
|
18
|
+
} from 'appium/types';
|
|
19
|
+
import _ from 'lodash';
|
|
20
|
+
import logger from './logger';
|
|
21
|
+
import {
|
|
22
|
+
processCapabilities,
|
|
23
|
+
STANDARD_CAPS,
|
|
24
|
+
errors,
|
|
25
|
+
isW3cCaps,
|
|
26
|
+
} from '@appium/base-driver';
|
|
27
|
+
import {inspect as dump, type InspectOptions} from 'node:util';
|
|
28
|
+
import {node, fs} from '@appium/support';
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
import {SERVER_SUBCOMMAND, DRIVER_TYPE, PLUGIN_TYPE, SETUP_SUBCOMMAND} from './constants';
|
|
31
|
+
import os from 'node:os';
|
|
32
|
+
|
|
33
|
+
const W3C_APPIUM_PREFIX = 'appium';
|
|
34
|
+
const STANDARD_CAPS_LOWERCASE = new Set([...STANDARD_CAPS].map((cap) => cap.toLowerCase()));
|
|
35
|
+
export const V4_BROADCAST_IP = '0.0.0.0';
|
|
36
|
+
export const V6_BROADCAST_IP = '::';
|
|
37
|
+
export const npmPackage = fs.readPackageJsonFrom(__dirname);
|
|
38
|
+
|
|
39
|
+
/** If stdout is a TTY; used for tighter control over log output. */
|
|
40
|
+
const isStdoutTTY = process.stdout.isTTY;
|
|
41
|
+
|
|
42
|
+
/** Result of successfully parsing W3C capabilities for the inner driver. */
|
|
43
|
+
export interface ParsedDriverCaps<C extends Constraints = BaseDriverCapConstraints> {
|
|
44
|
+
desiredCaps: Capabilities<C>;
|
|
45
|
+
processedW3CCapabilities: W3CCapabilities<C>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Result when capability parsing fails or caps are invalid. */
|
|
49
|
+
export interface InvalidCaps<C extends Constraints = BaseDriverCapConstraints> {
|
|
50
|
+
error: Error;
|
|
51
|
+
desiredCaps?: Capabilities<C>;
|
|
52
|
+
processedW3CCapabilities?: W3CCapabilities<C>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates an error when a session receives non-W3C capabilities.
|
|
57
|
+
*/
|
|
58
|
+
export function makeNonW3cCapsError(): Error {
|
|
59
|
+
return new errors.SessionNotCreatedError(
|
|
60
|
+
'Session capabilities format must comply to the W3C standard. Make sure your client is up to date. ' +
|
|
61
|
+
'See https://www.w3.org/TR/webdriver/#new-session for more details.'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Logs a value to the console using the info logger (with util.inspect formatting).
|
|
67
|
+
*/
|
|
68
|
+
export const inspect = _.flow(
|
|
69
|
+
_.partialRight(dump as (object: unknown, options: InspectOptions) => string, {
|
|
70
|
+
colors: true,
|
|
71
|
+
depth: null,
|
|
72
|
+
compact: !isStdoutTTY,
|
|
73
|
+
}),
|
|
74
|
+
(...args: unknown[]) => {
|
|
75
|
+
logger.info(...args);
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parses W3C capabilities for the inner driver and applies defaults.
|
|
81
|
+
*
|
|
82
|
+
* @returns Parsed caps or an invalid result with an error.
|
|
83
|
+
*/
|
|
84
|
+
export function parseCapsForInnerDriver<C extends Constraints = BaseDriverCapConstraints>(
|
|
85
|
+
w3cCapabilities: W3CCapabilities<C>,
|
|
86
|
+
constraints: C = {} as C,
|
|
87
|
+
defaultCapabilities: NSCapabilities<C> = {}
|
|
88
|
+
): ParsedDriverCaps<C> | InvalidCaps<C> {
|
|
89
|
+
if (!isW3cCaps(w3cCapabilities)) {
|
|
90
|
+
return {error: makeNonW3cCapsError()};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let desiredCaps: Capabilities<C> = {} as Capabilities<C>;
|
|
94
|
+
// eslint-disable-next-line prefer-const -- assigned in success path after try
|
|
95
|
+
let processedW3CCapabilities: W3CCapabilities<C> | undefined;
|
|
96
|
+
|
|
97
|
+
w3cCapabilities = _.cloneDeep(w3cCapabilities);
|
|
98
|
+
defaultCapabilities = _.cloneDeep(defaultCapabilities);
|
|
99
|
+
|
|
100
|
+
if (!_.isEmpty(defaultCapabilities)) {
|
|
101
|
+
for (const [defaultCapKey, defaultCapValue] of _.toPairs(defaultCapabilities)) {
|
|
102
|
+
let isCapAlreadySet = false;
|
|
103
|
+
for (const firstMatchEntry of w3cCapabilities.firstMatch ?? []) {
|
|
104
|
+
if (
|
|
105
|
+
_.isPlainObject(firstMatchEntry) &&
|
|
106
|
+
_.has(removeAppiumPrefixes(firstMatchEntry as NSCapabilities<C>), removeAppiumPrefix(defaultCapKey))
|
|
107
|
+
) {
|
|
108
|
+
isCapAlreadySet = true;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
isCapAlreadySet =
|
|
113
|
+
isCapAlreadySet ||
|
|
114
|
+
(_.isPlainObject(w3cCapabilities.alwaysMatch) &&
|
|
115
|
+
_.has(
|
|
116
|
+
removeAppiumPrefixes(w3cCapabilities.alwaysMatch),
|
|
117
|
+
removeAppiumPrefix(defaultCapKey)
|
|
118
|
+
));
|
|
119
|
+
if (isCapAlreadySet) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (_.isEmpty(w3cCapabilities.firstMatch)) {
|
|
124
|
+
w3cCapabilities.firstMatch = [{[defaultCapKey]: defaultCapValue}] as W3CCapabilities<C>['firstMatch'];
|
|
125
|
+
} else {
|
|
126
|
+
(w3cCapabilities.firstMatch[0] as Record<string, unknown>)[defaultCapKey] = defaultCapValue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
desiredCaps = processCapabilities(w3cCapabilities, constraints, true) as Capabilities<C>;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
logger.info(`Could not parse W3C capabilities: ${(error as Error).message}`);
|
|
135
|
+
return {
|
|
136
|
+
desiredCaps,
|
|
137
|
+
processedW3CCapabilities,
|
|
138
|
+
error: error as Error,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
processedW3CCapabilities = {
|
|
143
|
+
alwaysMatch: {...insertAppiumPrefixes(desiredCaps)},
|
|
144
|
+
firstMatch: [{}],
|
|
145
|
+
} as W3CCapabilities<C>;
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
desiredCaps,
|
|
149
|
+
processedW3CCapabilities,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Prefixes capability keys with `appium:` where appropriate.
|
|
155
|
+
*/
|
|
156
|
+
export function insertAppiumPrefixes<C extends Constraints = BaseDriverCapConstraints>(
|
|
157
|
+
caps: Capabilities<C>
|
|
158
|
+
): NSCapabilities<C> {
|
|
159
|
+
return _.mapKeys(caps, (_, key) =>
|
|
160
|
+
STANDARD_CAPS_LOWERCASE.has(key.toLowerCase()) || key.includes(':')
|
|
161
|
+
? key
|
|
162
|
+
: `${W3C_APPIUM_PREFIX}:${key}`
|
|
163
|
+
) as NSCapabilities<C>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Removes `appium:` prefix from capability keys.
|
|
168
|
+
*/
|
|
169
|
+
export function removeAppiumPrefixes<C extends Constraints = BaseDriverCapConstraints>(
|
|
170
|
+
caps: NSCapabilities<C>
|
|
171
|
+
): Capabilities<C> {
|
|
172
|
+
return _.mapKeys(caps, (_, key) => removeAppiumPrefix(key)) as Capabilities<C>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Returns the root directory of the Appium module (memoized).
|
|
177
|
+
*
|
|
178
|
+
* @throws {Error} If the appium module root cannot be determined.
|
|
179
|
+
*/
|
|
180
|
+
export const getAppiumModuleRoot = _.memoize(function getAppiumModuleRoot(): string {
|
|
181
|
+
const selfRoot = node.getModuleRootSync('appium', __filename);
|
|
182
|
+
if (!selfRoot) {
|
|
183
|
+
throw new Error('Cannot find the appium module root. This is likely a bug in Appium.');
|
|
184
|
+
}
|
|
185
|
+
return selfRoot;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Adjusts NODE_PATH so CJS drivers/plugins can load peer deps. Does not work with ESM.
|
|
190
|
+
*/
|
|
191
|
+
export function adjustNodePath(): void {
|
|
192
|
+
let appiumModuleSearchRoot: string;
|
|
193
|
+
try {
|
|
194
|
+
appiumModuleSearchRoot = path.dirname(getAppiumModuleRoot());
|
|
195
|
+
} catch (error) {
|
|
196
|
+
logger.warn((error as Error).message);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const refreshRequirePaths = (): boolean => {
|
|
201
|
+
try {
|
|
202
|
+
// Private API; see https://gist.github.com/branneman/8048520#7-the-hack
|
|
203
|
+
(require('node:module') as NodeModuleWithInitPaths).Module._initPaths();
|
|
204
|
+
return true;
|
|
205
|
+
} catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
if (!process.env.NODE_PATH) {
|
|
211
|
+
process.env.NODE_PATH = appiumModuleSearchRoot;
|
|
212
|
+
if (refreshRequirePaths()) {
|
|
213
|
+
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
214
|
+
} else {
|
|
215
|
+
delete process.env.NODE_PATH;
|
|
216
|
+
}
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const nodePathParts = process.env.NODE_PATH.split(path.delimiter);
|
|
221
|
+
if (nodePathParts.includes(appiumModuleSearchRoot)) {
|
|
222
|
+
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
nodePathParts.push(appiumModuleSearchRoot);
|
|
227
|
+
process.env.NODE_PATH = nodePathParts.join(path.delimiter);
|
|
228
|
+
if (refreshRequirePaths()) {
|
|
229
|
+
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
230
|
+
} else {
|
|
231
|
+
process.env.NODE_PATH = _.without(nodePathParts, appiumModuleSearchRoot).join(path.delimiter);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
interface NodeModuleWithInitPaths {
|
|
236
|
+
Module: {_initPaths(): void};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Pulls Appium settings from capabilities (mutates caps). Supports
|
|
241
|
+
* `settings[key]: value` and `settings: { key: value }`.
|
|
242
|
+
*
|
|
243
|
+
* @returns Parsed settings object; empty if none found.
|
|
244
|
+
*/
|
|
245
|
+
export function pullSettings(caps: Record<string, unknown> | null | undefined): Record<string, unknown> {
|
|
246
|
+
if (!_.isPlainObject(caps) || _.isEmpty(caps)) {
|
|
247
|
+
return {};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const result: Record<string, unknown> = {};
|
|
251
|
+
const singleSettings: Record<string, unknown> = {};
|
|
252
|
+
for (const [key, value] of _.toPairs(caps)) {
|
|
253
|
+
let match: RegExpExecArray | null;
|
|
254
|
+
if (/^(s|appium:s)ettings$/.test(key) && _.isPlainObject(value)) {
|
|
255
|
+
Object.assign(result, value);
|
|
256
|
+
delete caps[key];
|
|
257
|
+
} else if ((match = /^(s|appium:s)ettings\[(\S+)\]$/.exec(key))) {
|
|
258
|
+
singleSettings[match[2]] = value;
|
|
259
|
+
delete caps[key];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!_.isEmpty(singleSettings)) {
|
|
263
|
+
Object.assign(result, singleSettings);
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
type AnyArgs = Args<CliCommand, CliExtensionSubcommand | CliCommandSetupSubcommand | void>;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Type guard: args are for the server command.
|
|
272
|
+
*/
|
|
273
|
+
export function isServerCommandArgs(args: AnyArgs): args is Args<CliCommandServer, void> {
|
|
274
|
+
return args.subcommand === SERVER_SUBCOMMAND;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Type guard: args are for the setup command.
|
|
279
|
+
*/
|
|
280
|
+
export function isSetupCommandArgs(
|
|
281
|
+
args: AnyArgs
|
|
282
|
+
): args is Args<CliCommandSetup, CliCommandSetupSubcommand> {
|
|
283
|
+
return args.subcommand === SETUP_SUBCOMMAND;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Type guard: args are for an extension command (driver or plugin).
|
|
288
|
+
*/
|
|
289
|
+
export function isExtensionCommandArgs(
|
|
290
|
+
args: AnyArgs
|
|
291
|
+
): args is Args<CliExtensionCommand, CliExtensionSubcommand> {
|
|
292
|
+
return args.subcommand === DRIVER_TYPE || args.subcommand === PLUGIN_TYPE;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Type guard: args are for a driver extension command.
|
|
297
|
+
*/
|
|
298
|
+
export function isDriverCommandArgs(
|
|
299
|
+
args: AnyArgs
|
|
300
|
+
): args is Args<CliCommandDriver, CliExtensionSubcommand> {
|
|
301
|
+
return args.subcommand === DRIVER_TYPE;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Type guard: args are for a plugin extension command.
|
|
306
|
+
*/
|
|
307
|
+
export function isPluginCommandArgs(
|
|
308
|
+
args: AnyArgs
|
|
309
|
+
): args is Args<CliCommandPlugin, CliExtensionSubcommand> {
|
|
310
|
+
return args.subcommand === PLUGIN_TYPE;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Returns network interfaces for the given IP family.
|
|
315
|
+
*
|
|
316
|
+
* @param family - 4 for IPv4, 6 for IPv6, or null for all.
|
|
317
|
+
*/
|
|
318
|
+
export function fetchInterfaces(
|
|
319
|
+
family: 4 | 6 | null = null
|
|
320
|
+
): os.NetworkInterfaceInfo[] {
|
|
321
|
+
let familyValue: (4 | 6 | string)[] | null = null;
|
|
322
|
+
if (family === 4) {
|
|
323
|
+
familyValue = [4, 'IPv4'];
|
|
324
|
+
} else if (family === 6) {
|
|
325
|
+
familyValue = [6, 'IPv6'];
|
|
326
|
+
}
|
|
327
|
+
const ifaces = _.values(os.networkInterfaces()).filter(Boolean) as os.NetworkInterfaceInfo[][];
|
|
328
|
+
return _.flatMap(ifaces).filter(
|
|
329
|
+
(info) => !familyValue || familyValue.includes(info.family as 4 | 6 | string)
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Adler-32 checksum (see https://github.com/SheetJS/js-adler32).
|
|
336
|
+
*/
|
|
337
|
+
export function adler32(str: string, seed: number | null = null): number {
|
|
338
|
+
let a = 1,
|
|
339
|
+
b = 0,
|
|
340
|
+
M = 0,
|
|
341
|
+
c = 0,
|
|
342
|
+
d = 0;
|
|
343
|
+
const L = str.length;
|
|
344
|
+
if (typeof seed === 'number') {
|
|
345
|
+
a = seed & 0xffff;
|
|
346
|
+
b = seed >>> 16;
|
|
347
|
+
}
|
|
348
|
+
for (let i = 0; i < L;) {
|
|
349
|
+
M = Math.min(L - i, 2918);
|
|
350
|
+
while (M > 0) {
|
|
351
|
+
c = str.charCodeAt(i++);
|
|
352
|
+
if (c < 0x80) {
|
|
353
|
+
a += c;
|
|
354
|
+
} else if (c < 0x800) {
|
|
355
|
+
a += 192 | ((c >> 6) & 31);
|
|
356
|
+
b += a;
|
|
357
|
+
--M;
|
|
358
|
+
a += 128 | (c & 63);
|
|
359
|
+
} else if (c >= 0xd800 && c < 0xe000) {
|
|
360
|
+
c = (c & 1023) + 64;
|
|
361
|
+
d = str.charCodeAt(i++) & 1023;
|
|
362
|
+
a += 240 | ((c >> 8) & 7);
|
|
363
|
+
b += a;
|
|
364
|
+
--M;
|
|
365
|
+
a += 128 | ((c >> 2) & 63);
|
|
366
|
+
b += a;
|
|
367
|
+
--M;
|
|
368
|
+
a += 128 | ((d >> 6) & 15) | ((c & 3) << 4);
|
|
369
|
+
b += a;
|
|
370
|
+
--M;
|
|
371
|
+
a += 128 | (d & 63);
|
|
372
|
+
} else {
|
|
373
|
+
a += 224 | ((c >> 12) & 15);
|
|
374
|
+
b += a;
|
|
375
|
+
--M;
|
|
376
|
+
a += 128 | ((c >> 6) & 63);
|
|
377
|
+
b += a;
|
|
378
|
+
--M;
|
|
379
|
+
a += 128 | (c & 63);
|
|
380
|
+
}
|
|
381
|
+
b += a;
|
|
382
|
+
--M;
|
|
383
|
+
}
|
|
384
|
+
a = 15 * (a >>> 16) + (a & 65535);
|
|
385
|
+
b = 15 * (b >>> 16) + (b & 65535);
|
|
386
|
+
}
|
|
387
|
+
return ((b % 65521) << 16) | (a % 65521);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Returns true if the address is a broadcast IP (0.0.0.0 or ::).
|
|
392
|
+
*/
|
|
393
|
+
export function isBroadcastIp(address: string): boolean {
|
|
394
|
+
return [V4_BROADCAST_IP, V6_BROADCAST_IP, `[${V6_BROADCAST_IP}]`].includes(address);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// #region private helpers
|
|
398
|
+
|
|
399
|
+
function removeAppiumPrefix(key: string): string {
|
|
400
|
+
const prefix = `${W3C_APPIUM_PREFIX}:`;
|
|
401
|
+
return _.startsWith(key, prefix) ? key.substring(prefix.length) : key;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// #endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Automation for Apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -60,32 +60,32 @@
|
|
|
60
60
|
"test:unit": "mocha \"./test/unit/**/*.spec.ts\""
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@appium/base-driver": "
|
|
64
|
-
"@appium/base-plugin": "
|
|
65
|
-
"@appium/docutils": "
|
|
66
|
-
"@appium/logger": "
|
|
67
|
-
"@appium/schema": "
|
|
68
|
-
"@appium/support": "
|
|
69
|
-
"@appium/types": "
|
|
63
|
+
"@appium/base-driver": "10.3.0",
|
|
64
|
+
"@appium/base-plugin": "3.2.0",
|
|
65
|
+
"@appium/docutils": "2.3.0",
|
|
66
|
+
"@appium/logger": "2.0.6",
|
|
67
|
+
"@appium/schema": "1.1.0",
|
|
68
|
+
"@appium/support": "7.1.0",
|
|
69
|
+
"@appium/types": "1.3.0",
|
|
70
70
|
"@sidvind/better-ajv-errors": "4.0.1",
|
|
71
71
|
"ajv": "8.18.0",
|
|
72
72
|
"ajv-formats": "3.0.1",
|
|
73
73
|
"argparse": "2.0.1",
|
|
74
74
|
"async-lock": "1.4.1",
|
|
75
|
-
"axios": "1.
|
|
75
|
+
"axios": "1.15.0",
|
|
76
76
|
"bluebird": "3.7.2",
|
|
77
77
|
"lilconfig": "3.1.3",
|
|
78
|
-
"lodash": "4.
|
|
79
|
-
"lru-cache": "11.
|
|
78
|
+
"lodash": "4.18.1",
|
|
79
|
+
"lru-cache": "11.3.3",
|
|
80
80
|
"ora": "5.4.1",
|
|
81
81
|
"package-changed": "3.0.0",
|
|
82
82
|
"resolve-from": "5.0.0",
|
|
83
83
|
"semver": "7.7.4",
|
|
84
|
-
"teen_process": "4.0
|
|
85
|
-
"type-fest": "5.
|
|
84
|
+
"teen_process": "4.1.0",
|
|
85
|
+
"type-fest": "5.5.0",
|
|
86
86
|
"winston": "3.19.0",
|
|
87
|
-
"ws": "8.
|
|
88
|
-
"yaml": "2.8.
|
|
87
|
+
"ws": "8.20.0",
|
|
88
|
+
"yaml": "2.8.3"
|
|
89
89
|
},
|
|
90
90
|
"engines": {
|
|
91
91
|
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
|
|
@@ -94,5 +94,5 @@
|
|
|
94
94
|
"publishConfig": {
|
|
95
95
|
"access": "public"
|
|
96
96
|
},
|
|
97
|
-
"gitHead": "
|
|
97
|
+
"gitHead": "7a8965f5c30ffec2ad04ce75903b3960537cef06"
|
|
98
98
|
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import _ from 'lodash';
|
|
2
|
-
import ExtensionCliCommand from './extension-command';
|
|
3
|
-
import {KNOWN_DRIVERS} from '../constants';
|
|
4
|
-
import '@colors/colors';
|
|
5
|
-
|
|
6
|
-
const REQ_DRIVER_FIELDS = ['driverName', 'automationName', 'platformNames', 'mainClass'];
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @extends {ExtensionCliCommand<DriverType>}
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
export default class DriverCliCommand extends ExtensionCliCommand {
|
|
13
|
-
/**
|
|
14
|
-
* @param {import('./extension-command').ExtensionCommandOptions<DriverType>} opts
|
|
15
|
-
*/
|
|
16
|
-
constructor({config, json}) {
|
|
17
|
-
super({config, json});
|
|
18
|
-
this.knownExtensions = KNOWN_DRIVERS;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Install a driver
|
|
23
|
-
*
|
|
24
|
-
* @param {DriverInstallOpts} opts
|
|
25
|
-
* @return {Promise<ExtRecord<DriverType>>}
|
|
26
|
-
*/
|
|
27
|
-
async install({driver, installType, packageName}) {
|
|
28
|
-
return await super._install({
|
|
29
|
-
installSpec: driver,
|
|
30
|
-
installType,
|
|
31
|
-
packageName,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Uninstall a driver
|
|
37
|
-
*
|
|
38
|
-
* @param {DriverUninstallOpts} opts
|
|
39
|
-
* @return {Promise<ExtRecord<DriverType>>}
|
|
40
|
-
*/
|
|
41
|
-
async uninstall({driver}) {
|
|
42
|
-
return await super._uninstall({installSpec: driver});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Update a driver
|
|
47
|
-
*
|
|
48
|
-
* @param {DriverUpdateOpts} opts
|
|
49
|
-
* @return {Promise<import('./extension-command').ExtensionUpdateResult>}
|
|
50
|
-
*/
|
|
51
|
-
async update({driver, unsafe}) {
|
|
52
|
-
return await super._update({installSpec: driver, unsafe});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Run a script from a driver
|
|
57
|
-
*
|
|
58
|
-
* @param {DriverRunOptions} opts
|
|
59
|
-
* @return {Promise<import('./extension-command').RunOutput>}
|
|
60
|
-
* @throws {Error} if the script fails to run
|
|
61
|
-
*/
|
|
62
|
-
async run({driver, scriptName, extraArgs}) {
|
|
63
|
-
return await super._run({
|
|
64
|
-
installSpec: driver,
|
|
65
|
-
scriptName,
|
|
66
|
-
extraArgs,
|
|
67
|
-
bufferOutput: this.isJsonOutput,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Runs doctor checks for the given driver.
|
|
73
|
-
*
|
|
74
|
-
* @param {DriverDoctorOptions} opts
|
|
75
|
-
* @returns {Promise<number>} The amount of executed doctor checks.
|
|
76
|
-
* @throws {Error} If any of the mandatory Doctor checks fails.
|
|
77
|
-
*/
|
|
78
|
-
async doctor({driver}) {
|
|
79
|
-
return await super._doctor({
|
|
80
|
-
installSpec: driver,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
86
|
-
* @param {import('./extension-command').ExtensionArgs} opts
|
|
87
|
-
* @returns {string}
|
|
88
|
-
*/
|
|
89
|
-
getPostInstallText({extName, extData}) {
|
|
90
|
-
return (
|
|
91
|
-
`Driver ${extName}@${extData.version} successfully installed\n`.green +
|
|
92
|
-
`- automationName: ${extData.automationName.green}\n` +
|
|
93
|
-
`- platformNames: ${JSON.stringify(extData.platformNames).green}`
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Validates fields in `appium` field of `driverMetadata`
|
|
99
|
-
*
|
|
100
|
-
* For any `package.json` fields which a driver requires, validate the type of
|
|
101
|
-
* those fields on the `package.json` data, throwing an error if anything is
|
|
102
|
-
* amiss.
|
|
103
|
-
* @param {import('appium/types').ExtMetadata<DriverType>} driverMetadata
|
|
104
|
-
* @param {string} installSpec
|
|
105
|
-
*/
|
|
106
|
-
validateExtensionFields(driverMetadata, installSpec) {
|
|
107
|
-
const missingFields = REQ_DRIVER_FIELDS.reduce(
|
|
108
|
-
(acc, field) => (driverMetadata[field] ? acc : [...acc, field]),
|
|
109
|
-
[]
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
if (!_.isEmpty(missingFields)) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Driver "${installSpec}" did not expose correct fields for compatibility ` +
|
|
115
|
-
`with Appium. Missing fields: ${JSON.stringify(missingFields)}`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* @typedef {import('@appium/types').ExtensionType} ExtensionType
|
|
123
|
-
* @typedef {import('@appium/types').DriverType} DriverType
|
|
124
|
-
*/
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @template {ExtensionType} ExtType
|
|
128
|
-
* @typedef {import('appium/types').ExtRecord<ExtType>} ExtRecord
|
|
129
|
-
*/
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* @typedef DriverCommandOptions
|
|
133
|
-
* @property {import('../extension/extension-config').ExtensionConfig<DriverType>} config
|
|
134
|
-
* @property {boolean} json
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Options for {@linkcode DriverCliCommand.install}
|
|
139
|
-
* @typedef DriverInstallOpts
|
|
140
|
-
* @property {string} driver - the name or spec of a driver to install
|
|
141
|
-
* @property {InstallType} installType - how to install this driver. One of the INSTALL_TYPES
|
|
142
|
-
* @property {string} [packageName] - for git/github installs, the driver node package name
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @typedef {import('appium/types').InstallType} InstallType
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Options for {@linkcode DriverCliCommand.uninstall}
|
|
151
|
-
* @typedef DriverUninstallOpts
|
|
152
|
-
* @property {string} driver - the name or spec of a driver to uninstall
|
|
153
|
-
*/
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Options for {@linkcode DriverCliCommand.update}
|
|
157
|
-
* @typedef DriverUpdateOpts
|
|
158
|
-
* @property {string} driver - the name of the driver to update
|
|
159
|
-
* @property {boolean} unsafe - if true, will perform unsafe updates past major revision boundaries
|
|
160
|
-
*/
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Options for {@linkcode DriverCliCommand.run}.
|
|
164
|
-
* @typedef DriverRunOptions
|
|
165
|
-
* @property {string} driver - name of the driver to run a script from
|
|
166
|
-
* @property {string} scriptName - name of the script to run
|
|
167
|
-
* @property {string[]} [extraArgs] - arguments to pass to the script
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Options for {@linkcode DriverCliCommand.doctor}.
|
|
172
|
-
* @typedef DriverDoctorOptions
|
|
173
|
-
* @property {string} driver - name of the driver to run doctor checks for
|
|
174
|
-
*/
|