appium 3.5.0 → 3.5.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/build/lib/appium.d.ts.map +1 -1
- package/build/lib/appium.js +43 -45
- package/build/lib/appium.js.map +1 -1
- package/build/lib/bidi-commands.d.ts.map +1 -1
- package/build/lib/bidi-commands.js +34 -29
- package/build/lib/bidi-commands.js.map +1 -1
- package/build/lib/bootstrap/appium-initializer.d.ts.map +1 -1
- package/build/lib/bootstrap/appium-initializer.js +13 -13
- package/build/lib/bootstrap/appium-initializer.js.map +1 -1
- package/build/lib/bootstrap/appium-main-runner.d.ts.map +1 -1
- package/build/lib/bootstrap/appium-main-runner.js +2 -2
- package/build/lib/bootstrap/appium-main-runner.js.map +1 -1
- package/build/lib/bootstrap/config-file.d.ts.map +1 -1
- package/build/lib/bootstrap/config-file.js +11 -11
- package/build/lib/bootstrap/config-file.js.map +1 -1
- package/build/lib/bootstrap/grid-v3-register.d.ts.map +1 -1
- package/build/lib/bootstrap/grid-v3-register.js +9 -6
- package/build/lib/bootstrap/grid-v3-register.js.map +1 -1
- package/build/lib/bootstrap/main-helpers.d.ts +1 -1
- package/build/lib/bootstrap/main-helpers.d.ts.map +1 -1
- package/build/lib/bootstrap/main-helpers.js +19 -20
- package/build/lib/bootstrap/main-helpers.js.map +1 -1
- package/build/lib/bootstrap/node-helpers.d.ts +1 -1
- package/build/lib/bootstrap/node-helpers.d.ts.map +1 -1
- package/build/lib/bootstrap/node-helpers.js +7 -14
- package/build/lib/bootstrap/node-helpers.js.map +1 -1
- package/build/lib/bootstrap/startup-config.d.ts.map +1 -1
- package/build/lib/bootstrap/startup-config.js +32 -30
- package/build/lib/bootstrap/startup-config.js.map +1 -1
- package/build/lib/cli/args.d.ts +3 -2
- package/build/lib/cli/args.d.ts.map +1 -1
- package/build/lib/cli/args.js +2 -5
- package/build/lib/cli/args.js.map +1 -1
- package/build/lib/cli/driver-command.d.ts +1 -2
- package/build/lib/cli/driver-command.d.ts.map +1 -1
- package/build/lib/cli/driver-command.js +7 -8
- package/build/lib/cli/driver-command.js.map +1 -1
- package/build/lib/cli/extension-command.d.ts +2 -2
- package/build/lib/cli/extension-command.d.ts.map +1 -1
- package/build/lib/cli/extension-command.js +100 -66
- package/build/lib/cli/extension-command.js.map +1 -1
- package/build/lib/cli/extension.d.ts.map +1 -1
- package/build/lib/cli/extension.js.map +1 -1
- package/build/lib/cli/parser.d.ts.map +1 -1
- package/build/lib/cli/parser.js +21 -14
- package/build/lib/cli/parser.js.map +1 -1
- package/build/lib/cli/plugin-command.d.ts +1 -1
- package/build/lib/cli/plugin-command.d.ts.map +1 -1
- package/build/lib/cli/plugin-command.js +5 -5
- package/build/lib/cli/plugin-command.js.map +1 -1
- package/build/lib/cli/setup-command.d.ts +1 -1
- package/build/lib/cli/setup-command.d.ts.map +1 -1
- package/build/lib/cli/setup-command.js +14 -19
- package/build/lib/cli/setup-command.js.map +1 -1
- package/build/lib/cli/utils.d.ts.map +1 -1
- package/build/lib/cli/utils.js +3 -2
- package/build/lib/cli/utils.js.map +1 -1
- package/build/lib/doctor/doctor.d.ts +0 -1
- package/build/lib/doctor/doctor.d.ts.map +1 -1
- package/build/lib/doctor/doctor.js +12 -17
- package/build/lib/doctor/doctor.js.map +1 -1
- package/build/lib/extension/driver-config.d.ts.map +1 -1
- package/build/lib/extension/driver-config.js +11 -12
- 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 +28 -27
- package/build/lib/extension/extension-config.js.map +1 -1
- package/build/lib/extension/index.d.ts.map +1 -1
- package/build/lib/extension/index.js +13 -16
- package/build/lib/extension/index.js.map +1 -1
- package/build/lib/extension/manifest.d.ts +3 -2
- package/build/lib/extension/manifest.d.ts.map +1 -1
- package/build/lib/extension/manifest.js +19 -22
- package/build/lib/extension/manifest.js.map +1 -1
- package/build/lib/extension/plugin-config.d.ts.map +1 -1
- package/build/lib/extension/plugin-config.js +7 -9
- package/build/lib/extension/plugin-config.js.map +1 -1
- package/build/lib/helpers/build.d.ts +0 -1
- package/build/lib/helpers/build.d.ts.map +1 -1
- package/build/lib/helpers/build.js +2 -4
- package/build/lib/helpers/build.js.map +1 -1
- package/build/lib/helpers/capability.d.ts.map +1 -1
- package/build/lib/helpers/capability.js +27 -22
- package/build/lib/helpers/capability.js.map +1 -1
- package/build/lib/helpers/network.d.ts.map +1 -1
- package/build/lib/helpers/network.js +4 -3
- package/build/lib/helpers/network.js.map +1 -1
- package/build/lib/insecure-features.d.ts.map +1 -1
- package/build/lib/insecure-features.js +9 -13
- package/build/lib/insecure-features.js.map +1 -1
- package/build/lib/inspector-commands.d.ts.map +1 -1
- package/build/lib/inspector-commands.js +29 -28
- package/build/lib/inspector-commands.js.map +1 -1
- package/build/lib/logsink.d.ts.map +1 -1
- package/build/lib/logsink.js +8 -7
- package/build/lib/logsink.js.map +1 -1
- package/build/lib/schema/arg-spec.d.ts.map +1 -1
- package/build/lib/schema/arg-spec.js +5 -8
- package/build/lib/schema/arg-spec.js.map +1 -1
- package/build/lib/schema/cli-args.d.ts.map +1 -1
- package/build/lib/schema/cli-args.js +20 -19
- package/build/lib/schema/cli-args.js.map +1 -1
- package/build/lib/schema/cli-transformers.d.ts.map +1 -1
- package/build/lib/schema/cli-transformers.js.map +1 -1
- package/build/lib/schema/schema.d.ts.map +1 -1
- package/build/lib/schema/schema.js +28 -21
- package/build/lib/schema/schema.js.map +1 -1
- package/build/lib/utils/hash.d.ts +5 -0
- package/build/lib/utils/hash.d.ts.map +1 -0
- package/build/lib/{utils.js → utils/hash.js} +3 -21
- package/build/lib/utils/hash.js.map +1 -0
- package/build/lib/utils/index.d.ts +8 -0
- package/build/lib/utils/index.d.ts.map +1 -0
- package/build/lib/utils/index.js +31 -0
- package/build/lib/utils/index.js.map +1 -0
- package/build/lib/utils/is-package-changed.d.ts +16 -0
- package/build/lib/utils/is-package-changed.d.ts.map +1 -0
- package/build/lib/utils/is-package-changed.js +62 -0
- package/build/lib/utils/is-package-changed.js.map +1 -0
- package/build/lib/utils/object.d.ts +120 -0
- package/build/lib/utils/object.d.ts.map +1 -0
- package/build/lib/utils/object.js +288 -0
- package/build/lib/utils/object.js.map +1 -0
- package/build/lib/{extension → utils}/package-changed.d.ts +0 -1
- package/build/lib/utils/package-changed.d.ts.map +1 -0
- package/build/lib/{extension → utils}/package-changed.js +3 -4
- package/build/lib/utils/package-changed.js.map +1 -0
- package/build/lib/utils/package-json.d.ts +9 -0
- package/build/lib/utils/package-json.d.ts.map +1 -0
- package/build/lib/utils/package-json.js +32 -0
- package/build/lib/utils/package-json.js.map +1 -0
- package/build/lib/utils/resolve-from.d.ts +11 -0
- package/build/lib/utils/resolve-from.d.ts.map +1 -0
- package/build/lib/utils/resolve-from.js +41 -0
- package/build/lib/utils/resolve-from.js.map +1 -0
- package/build/types/cli.d.ts.map +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/manifest/base.d.ts.map +1 -1
- package/build/types/manifest/v3.d.ts.map +1 -1
- package/build/types/manifest/v4.d.ts.map +1 -1
- package/lib/appium.ts +59 -55
- package/lib/bidi-commands.ts +106 -60
- package/lib/bootstrap/appium-initializer.ts +27 -19
- package/lib/bootstrap/appium-main-runner.ts +8 -4
- package/lib/bootstrap/config-file.ts +33 -16
- package/lib/bootstrap/grid-v3-register.ts +26 -19
- package/lib/bootstrap/main-helpers.ts +25 -19
- package/lib/bootstrap/node-helpers.ts +19 -22
- package/lib/bootstrap/startup-config.ts +42 -39
- package/lib/cli/args.ts +3 -4
- package/lib/cli/driver-command.ts +19 -13
- package/lib/cli/extension-command.ts +208 -143
- package/lib/cli/extension.ts +4 -6
- package/lib/cli/parser.ts +32 -30
- package/lib/cli/plugin-command.ts +20 -9
- package/lib/cli/setup-command.ts +54 -39
- package/lib/cli/utils.ts +4 -3
- package/lib/doctor/doctor.ts +15 -17
- package/lib/extension/driver-config.ts +22 -17
- package/lib/extension/extension-config.ts +74 -66
- package/lib/extension/index.ts +42 -25
- package/lib/extension/manifest.ts +34 -31
- package/lib/extension/plugin-config.ts +15 -10
- package/lib/helpers/build.ts +6 -5
- package/lib/helpers/capability.ts +40 -35
- package/lib/helpers/network.ts +6 -5
- package/lib/insecure-features.ts +16 -14
- package/lib/inspector-commands.ts +72 -40
- package/lib/logsink.ts +22 -26
- package/lib/schema/arg-spec.ts +9 -8
- package/lib/schema/cli-args-guards.ts +4 -4
- package/lib/schema/cli-args.ts +25 -21
- package/lib/schema/cli-transformers.ts +6 -2
- package/lib/schema/format-errors.ts +1 -1
- package/lib/schema/schema.ts +52 -38
- package/lib/{utils.ts → utils/hash.ts} +2 -19
- package/lib/utils/index.ts +23 -0
- package/lib/utils/is-package-changed.ts +78 -0
- package/lib/utils/object.ts +312 -0
- package/lib/{extension → utils}/package-changed.ts +6 -7
- package/lib/utils/package-json.ts +36 -0
- package/lib/utils/resolve-from.ts +40 -0
- package/package.json +13 -16
- package/scripts/autoinstall-extensions.js +8 -8
- package/tsconfig.json +8 -2
- package/types/cli.ts +18 -18
- package/types/index.ts +2 -2
- package/types/manifest/base.ts +2 -2
- package/types/manifest/v3.ts +2 -2
- package/types/manifest/v4.ts +2 -2
- package/build/lib/extension/package-changed.d.ts.map +0 -1
- package/build/lib/extension/package-changed.js.map +0 -1
- package/build/lib/utils.d.ts +0 -13
- package/build/lib/utils.d.ts.map +0 -1
- package/build/lib/utils.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import {fs} from '@appium/support';
|
|
3
3
|
import type {StringRecord} from '@appium/types';
|
|
4
|
-
import _ from 'lodash';
|
|
5
4
|
import {log as logger} from '../logger';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -44,13 +43,13 @@ export default async function registerNode(
|
|
|
44
43
|
data: string,
|
|
45
44
|
addr: string,
|
|
46
45
|
port: number,
|
|
47
|
-
basePath: string
|
|
46
|
+
basePath: string,
|
|
48
47
|
): Promise<void>;
|
|
49
48
|
export default async function registerNode(
|
|
50
49
|
data: Grid3NodeConfig,
|
|
51
50
|
addr?: string,
|
|
52
51
|
port?: number,
|
|
53
|
-
basePath?: string
|
|
52
|
+
basePath?: string,
|
|
54
53
|
): Promise<void>;
|
|
55
54
|
/**
|
|
56
55
|
* Registers this server as a node with a **Selenium Grid 3** hub.
|
|
@@ -71,24 +70,24 @@ export default async function registerNode(
|
|
|
71
70
|
data: string | Grid3NodeConfig,
|
|
72
71
|
addr?: string,
|
|
73
72
|
port?: number,
|
|
74
|
-
basePath?: string
|
|
73
|
+
basePath?: string,
|
|
75
74
|
): Promise<void> {
|
|
76
75
|
if (typeof data === 'string') {
|
|
77
76
|
if (addr === undefined || port === undefined || basePath === undefined) {
|
|
78
77
|
throw logger.errorWithException(
|
|
79
78
|
'When the first argument is a Selenium Grid 3 node config file path, address, port, and basePath ' +
|
|
80
|
-
'are required (e.g. match your Appium `--address`, `--port`, and base path).'
|
|
79
|
+
'are required (e.g. match your Appium `--address`, `--port`, and base path).',
|
|
81
80
|
);
|
|
82
81
|
}
|
|
83
82
|
if (typeof port !== 'number' || !Number.isFinite(port)) {
|
|
84
83
|
throw logger.errorWithException(
|
|
85
|
-
'When registering from a node config file path, port must be a finite number.'
|
|
84
|
+
'When registering from a node config file path, port must be a finite number.',
|
|
86
85
|
);
|
|
87
86
|
}
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
let configHolder: Grid3NodeConfig;
|
|
91
|
-
if (
|
|
90
|
+
if (typeof data === 'string') {
|
|
92
91
|
const configFilePath = data;
|
|
93
92
|
let fileContent: string;
|
|
94
93
|
try {
|
|
@@ -96,7 +95,7 @@ export default async function registerNode(
|
|
|
96
95
|
} catch (err) {
|
|
97
96
|
logger.error(
|
|
98
97
|
`Unable to load Selenium Grid 3 node configuration file ${configFilePath} to ` +
|
|
99
|
-
|
|
98
|
+
`register with the hub: ${(err as Error).message}`,
|
|
100
99
|
);
|
|
101
100
|
return;
|
|
102
101
|
}
|
|
@@ -105,7 +104,7 @@ export default async function registerNode(
|
|
|
105
104
|
} catch (err) {
|
|
106
105
|
throw logger.errorWithException(
|
|
107
106
|
`Syntax error in Selenium Grid 3 node configuration file ${configFilePath}: ` +
|
|
108
|
-
|
|
107
|
+
(err as Error).message,
|
|
109
108
|
);
|
|
110
109
|
}
|
|
111
110
|
} else {
|
|
@@ -124,7 +123,7 @@ function hubUri(config: Grid3HubConfiguration): string {
|
|
|
124
123
|
/** POST registration payload to the Selenium Grid 3 hub. */
|
|
125
124
|
async function registerToGrid(
|
|
126
125
|
postOptions: {url: string; method: string; data: Grid3NodeConfig},
|
|
127
|
-
configHolder: Grid3NodeConfig
|
|
126
|
+
configHolder: Grid3NodeConfig,
|
|
128
127
|
): Promise<void> {
|
|
129
128
|
const hubCfg = configHolder.configuration;
|
|
130
129
|
if (!hubCfg) {
|
|
@@ -136,12 +135,12 @@ async function registerToGrid(
|
|
|
136
135
|
throw new Error(`Request failed with code ${status}`);
|
|
137
136
|
}
|
|
138
137
|
logger.debug(
|
|
139
|
-
`Appium successfully registered with the Selenium Grid 3 hub at ` + hubUri(hubCfg)
|
|
138
|
+
`Appium successfully registered with the Selenium Grid 3 hub at ` + hubUri(hubCfg),
|
|
140
139
|
);
|
|
141
140
|
} catch (err) {
|
|
142
141
|
logger.error(
|
|
143
142
|
`An attempt to register with the Selenium Grid 3 hub was unsuccessful: ` +
|
|
144
|
-
|
|
143
|
+
(err as Error).message,
|
|
145
144
|
);
|
|
146
145
|
}
|
|
147
146
|
}
|
|
@@ -150,14 +149,18 @@ function postRequest(
|
|
|
150
149
|
configHolder: Grid3NodeConfig,
|
|
151
150
|
addr?: string,
|
|
152
151
|
port?: number,
|
|
153
|
-
basePath?: string
|
|
152
|
+
basePath?: string,
|
|
154
153
|
): void {
|
|
155
154
|
// Move Selenium Grid 3 (flat) configuration properties into `configuration`
|
|
156
|
-
if (
|
|
155
|
+
if (
|
|
156
|
+
configHolder != null &&
|
|
157
|
+
typeof configHolder === 'object' &&
|
|
158
|
+
!Object.hasOwn(configHolder, 'configuration')
|
|
159
|
+
) {
|
|
157
160
|
const configuration: StringRecord = {};
|
|
158
161
|
const holder = configHolder as StringRecord;
|
|
159
|
-
for (const property
|
|
160
|
-
if (
|
|
162
|
+
for (const property of Object.keys(holder)) {
|
|
163
|
+
if (property !== 'capabilities') {
|
|
161
164
|
configuration[property] = holder[property];
|
|
162
165
|
delete holder[property];
|
|
163
166
|
}
|
|
@@ -198,10 +201,14 @@ function postRequest(
|
|
|
198
201
|
}
|
|
199
202
|
|
|
200
203
|
const registerCycleInterval = cfg.registerCycle;
|
|
201
|
-
if (
|
|
204
|
+
if (
|
|
205
|
+
registerCycleInterval === undefined ||
|
|
206
|
+
isNaN(registerCycleInterval) ||
|
|
207
|
+
registerCycleInterval <= 0
|
|
208
|
+
) {
|
|
202
209
|
logger.warn(
|
|
203
210
|
`'registerCycle' is not a valid positive number. ` +
|
|
204
|
-
`No registration request will be sent to the Selenium Grid 3 hub
|
|
211
|
+
`No registration request will be sent to the Selenium Grid 3 hub.`,
|
|
205
212
|
);
|
|
206
213
|
return;
|
|
207
214
|
}
|
|
@@ -209,7 +216,7 @@ function postRequest(
|
|
|
209
216
|
let first = true;
|
|
210
217
|
logger.debug(
|
|
211
218
|
`Starting auto-register thread for Selenium Grid 3. ` +
|
|
212
|
-
`Will try to register every ${registerCycleInterval} ms
|
|
219
|
+
`Will try to register every ${registerCycleInterval} ms.`,
|
|
213
220
|
);
|
|
214
221
|
setInterval(async function registerRetry() {
|
|
215
222
|
if (first) {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
server as baseServer,
|
|
7
7
|
type ServerOpts,
|
|
8
8
|
} from '@appium/base-driver';
|
|
9
|
-
import
|
|
9
|
+
import {console as supportConsole, util} from '@appium/support';
|
|
10
10
|
import type {AppiumServer, Driver, MethodMap, UpdateServerCallback} from '@appium/types';
|
|
11
11
|
import {WebSocketServer} from 'ws';
|
|
12
12
|
import type {NetworkInterfaceInfo} from 'node:os';
|
|
@@ -25,16 +25,15 @@ const isStdoutTTY = process.stdout.isTTY;
|
|
|
25
25
|
/**
|
|
26
26
|
* Logs a value to the console using the info logger (with util.inspect formatting).
|
|
27
27
|
*/
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
28
|
+
export function inspect(value: unknown): void {
|
|
29
|
+
logger.info(
|
|
30
|
+
dump(value, {
|
|
31
|
+
colors: true,
|
|
32
|
+
depth: null,
|
|
33
|
+
compact: !isStdoutTTY,
|
|
34
|
+
} satisfies InspectOptions),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* Prints the current build info JSON to stdout.
|
|
@@ -52,7 +51,7 @@ export async function showBuildInfo(): Promise<void> {
|
|
|
52
51
|
* Human-readable label for where Appium resolved `APPIUM_HOME` from (CLI, env, or autodetect).
|
|
53
52
|
*/
|
|
54
53
|
export function determineAppiumHomeSource(appiumHomeFromArgs?: string | null): string {
|
|
55
|
-
if (
|
|
54
|
+
if (util.hasValue(appiumHomeFromArgs)) {
|
|
56
55
|
return 'appiumHome config value';
|
|
57
56
|
}
|
|
58
57
|
if (process.env.APPIUM_HOME) {
|
|
@@ -110,7 +109,7 @@ export async function preflightChecks(
|
|
|
110
109
|
}
|
|
111
110
|
} catch (err: unknown) {
|
|
112
111
|
const message = err instanceof Error ? err.message : String(err);
|
|
113
|
-
logger.error((
|
|
112
|
+
logger.error(supportConsole.styleText('red', message));
|
|
114
113
|
if (throwInsteadOfExit) {
|
|
115
114
|
throw err;
|
|
116
115
|
}
|
|
@@ -131,10 +130,10 @@ export async function logStartupInfo(args: ParsedArgs<CliCommandServer>): Promis
|
|
|
131
130
|
logger.info(welcome);
|
|
132
131
|
|
|
133
132
|
const showArgs = getNonDefaultServerArgs(args);
|
|
134
|
-
if (
|
|
133
|
+
if (Object.keys(showArgs).length) {
|
|
135
134
|
logNonDefaultArgsWarning(showArgs);
|
|
136
135
|
}
|
|
137
|
-
if (!
|
|
136
|
+
if (!util.isEmpty(args.defaultCapabilities)) {
|
|
138
137
|
logDefaultCapabilitiesWarning(args.defaultCapabilities);
|
|
139
138
|
}
|
|
140
139
|
}
|
|
@@ -146,13 +145,18 @@ export function getServerUpdaters(
|
|
|
146
145
|
driverClasses: DriverNameMap,
|
|
147
146
|
pluginClasses: PluginNameMap,
|
|
148
147
|
): UpdateServerCallback[] {
|
|
149
|
-
return
|
|
148
|
+
return [...driverClasses.keys(), ...pluginClasses.keys()]
|
|
149
|
+
.map((klass) => klass.updateServer)
|
|
150
|
+
.filter(Boolean) as UpdateServerCallback[];
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
/**
|
|
153
154
|
* Merges `newMethodMap` contributions from all active drivers and plugins into one method map.
|
|
154
155
|
*/
|
|
155
|
-
export function getExtraMethodMap(
|
|
156
|
+
export function getExtraMethodMap(
|
|
157
|
+
driverClasses: DriverNameMap,
|
|
158
|
+
pluginClasses: PluginNameMap,
|
|
159
|
+
): MethodMap<Driver> {
|
|
156
160
|
return [...driverClasses.keys(), ...pluginClasses.keys()].reduce<MethodMap<Driver>>(
|
|
157
161
|
(map, klass) => ({
|
|
158
162
|
...map,
|
|
@@ -184,7 +188,7 @@ export function buildServerOpts(
|
|
|
184
188
|
};
|
|
185
189
|
const normalizedBasePath = normalizeBasePath(parsedArgs.basePath);
|
|
186
190
|
for (const timeoutArgName of ['keepAliveTimeout', 'requestTimeout'] as const) {
|
|
187
|
-
if (
|
|
191
|
+
if (Number.isInteger(parsedArgs[timeoutArgName])) {
|
|
188
192
|
serverOpts[timeoutArgName] = parsedArgs[timeoutArgName] * 1000;
|
|
189
193
|
}
|
|
190
194
|
}
|
|
@@ -214,7 +218,9 @@ function logNonDefaultArgsWarning(args: Args): void {
|
|
|
214
218
|
inspect(args);
|
|
215
219
|
}
|
|
216
220
|
|
|
217
|
-
function logDefaultCapabilitiesWarning(
|
|
221
|
+
function logDefaultCapabilitiesWarning(
|
|
222
|
+
caps: ParsedArgs<CliCommandServer>['defaultCapabilities'],
|
|
223
|
+
): void {
|
|
218
224
|
logger.info(
|
|
219
225
|
'Default capabilities, which will be added to each request ' +
|
|
220
226
|
'unless overridden by desired capabilities:',
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import _ from 'lodash';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import os from 'node:os';
|
|
5
4
|
import * as semver from 'semver';
|
|
6
5
|
import {system, fs, npm} from '@appium/support';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {rootDir, updateBuildInfo, getBuildInfo} from '../helpers/build';
|
|
6
|
+
import {appiumPackageRoot, npmPackage} from '../utils';
|
|
7
|
+
import {updateBuildInfo, getBuildInfo} from '../helpers/build';
|
|
10
8
|
|
|
11
9
|
const MIN_NODE_VERSION = (npmPackage.engines as Record<string, string>).node;
|
|
12
10
|
|
|
@@ -26,7 +24,9 @@ interface DebugInfoInput {
|
|
|
26
24
|
export function checkNodeOk(): void {
|
|
27
25
|
const version = getNodeVersion();
|
|
28
26
|
if (!semver.satisfies(version, MIN_NODE_VERSION)) {
|
|
29
|
-
throw new Error(
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Node version must be at least ${MIN_NODE_VERSION}; current is ${version.version}`,
|
|
29
|
+
);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -34,13 +34,7 @@ export function checkNodeOk(): void {
|
|
|
34
34
|
* Adjusts NODE_PATH so CJS drivers/plugins can load peer deps. Does not work with ESM.
|
|
35
35
|
*/
|
|
36
36
|
export function adjustNodePath(): void {
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
appiumModuleSearchRoot = path.dirname(getAppiumModuleRoot());
|
|
40
|
-
} catch (error) {
|
|
41
|
-
logger.warn((error as Error).message);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
37
|
+
const appiumModuleSearchRoot = path.dirname(appiumPackageRoot);
|
|
44
38
|
|
|
45
39
|
const refreshRequirePaths = (): boolean => {
|
|
46
40
|
try {
|
|
@@ -73,7 +67,9 @@ export function adjustNodePath(): void {
|
|
|
73
67
|
if (refreshRequirePaths()) {
|
|
74
68
|
process.env.APPIUM_OMIT_PEER_DEPS = '1';
|
|
75
69
|
} else {
|
|
76
|
-
process.env.NODE_PATH =
|
|
70
|
+
process.env.NODE_PATH = nodePathParts
|
|
71
|
+
.filter((p) => p !== appiumModuleSearchRoot)
|
|
72
|
+
.join(path.delimiter);
|
|
77
73
|
}
|
|
78
74
|
}
|
|
79
75
|
|
|
@@ -81,10 +77,14 @@ export function adjustNodePath(): void {
|
|
|
81
77
|
* Prints JSON debug info (OS, Node/npm, Appium build, installed drivers/plugins) to stdout.
|
|
82
78
|
* Input combines extension config snapshots with the resolved Appium home path.
|
|
83
79
|
*/
|
|
84
|
-
export async function showDebugInfo({
|
|
80
|
+
export async function showDebugInfo({
|
|
81
|
+
driverConfig,
|
|
82
|
+
pluginConfig,
|
|
83
|
+
appiumHome,
|
|
84
|
+
}: DebugInfoInput): Promise<void> {
|
|
85
85
|
const getNpmVersion = async (): Promise<string> => {
|
|
86
86
|
const {stdout} = await npm.exec('--version', [], {cwd: process.cwd()});
|
|
87
|
-
return
|
|
87
|
+
return stdout.trim();
|
|
88
88
|
};
|
|
89
89
|
const findNpmLocation = async (): Promise<string> =>
|
|
90
90
|
await fs.which(system.isWindows() ? 'npm.cmd' : 'npm');
|
|
@@ -114,7 +114,7 @@ export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}: De
|
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
116
|
appium: {
|
|
117
|
-
location:
|
|
117
|
+
location: appiumPackageRoot,
|
|
118
118
|
homedir: appiumHome,
|
|
119
119
|
build: getBuildInfo(),
|
|
120
120
|
drivers: driverConfig.installedExtensions,
|
|
@@ -134,7 +134,7 @@ export async function showDebugInfo({driverConfig, pluginConfig, appiumHome}: De
|
|
|
134
134
|
export async function requireDir(
|
|
135
135
|
root: string,
|
|
136
136
|
requireWriteable = true,
|
|
137
|
-
displayName = 'folder path'
|
|
137
|
+
displayName = 'folder path',
|
|
138
138
|
): Promise<void> {
|
|
139
139
|
let stat;
|
|
140
140
|
try {
|
|
@@ -146,10 +146,7 @@ export async function requireDir(
|
|
|
146
146
|
return;
|
|
147
147
|
} catch {}
|
|
148
148
|
}
|
|
149
|
-
throw new Error(
|
|
150
|
-
`The ${displayName} '${root}' must exist and be a valid directory`,
|
|
151
|
-
{cause: e}
|
|
152
|
-
);
|
|
149
|
+
throw new Error(`The ${displayName} '${root}' must exist and be a valid directory`, {cause: e});
|
|
153
150
|
}
|
|
154
151
|
if (stat && !stat.isDirectory()) {
|
|
155
152
|
throw new Error(`The ${displayName} '${root}' must be a valid directory`);
|
|
@@ -160,7 +157,7 @@ export async function requireDir(
|
|
|
160
157
|
} catch (e) {
|
|
161
158
|
throw new Error(
|
|
162
159
|
`The ${displayName} '${root}' must be writeable for the current user account '${os.userInfo().username}'`,
|
|
163
|
-
{cause: e}
|
|
160
|
+
{cause: e},
|
|
164
161
|
);
|
|
165
162
|
}
|
|
166
163
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import
|
|
2
|
+
import {util} from '@appium/support';
|
|
3
3
|
import {getDefaultsForSchema, getAllArgSpecs} from '../schema/schema';
|
|
4
4
|
import type {Args} from 'appium/types';
|
|
5
5
|
import type {ReadConfigFileResult} from './config-file';
|
|
6
|
+
import {difference, getPath, pickBy, setPath} from '../utils';
|
|
6
7
|
|
|
7
8
|
interface FlattenedArg {
|
|
8
9
|
value: unknown;
|
|
@@ -21,15 +22,15 @@ export function getNonDefaultServerArgs(parsedArgs: Args): Args {
|
|
|
21
22
|
*/
|
|
22
23
|
const flatten = (args: Args): Record<string, FlattenedArg> => {
|
|
23
24
|
const argSpecs = getAllArgSpecs();
|
|
24
|
-
const flattened =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
acc[argSpec.dest] = {value
|
|
25
|
+
const flattened = [...argSpecs.values()].reduce<Record<string, FlattenedArg>>(
|
|
26
|
+
(acc, argSpec: {dest: string}) => {
|
|
27
|
+
const value = getPath(args, argSpec.dest);
|
|
28
|
+
if (value !== undefined) {
|
|
29
|
+
acc[argSpec.dest] = {value, argSpec};
|
|
29
30
|
}
|
|
30
31
|
return acc;
|
|
31
32
|
},
|
|
32
|
-
{}
|
|
33
|
+
{},
|
|
33
34
|
);
|
|
34
35
|
|
|
35
36
|
return flattened;
|
|
@@ -41,24 +42,22 @@ export function getNonDefaultServerArgs(parsedArgs: Args): Args {
|
|
|
41
42
|
const typesDiffer = (dest: string): boolean =>
|
|
42
43
|
typeof args[dest].value !== typeof defaultsFromSchema[dest];
|
|
43
44
|
|
|
44
|
-
const defaultValueIsArray = (dest: string): boolean =>
|
|
45
|
+
const defaultValueIsArray = (dest: string): boolean => Array.isArray(defaultsFromSchema[dest]);
|
|
45
46
|
|
|
46
|
-
const argsValueIsArray = (dest: string): boolean =>
|
|
47
|
+
const argsValueIsArray = (dest: string): boolean => Array.isArray(args[dest].value);
|
|
47
48
|
|
|
48
49
|
const arraysDiffer = (dest: string): boolean =>
|
|
49
|
-
|
|
50
|
+
difference(args[dest].value as unknown[], defaultsFromSchema[dest] as unknown[]).length > 0;
|
|
50
51
|
|
|
51
52
|
const valuesDiffer = (dest: string): boolean => args[dest].value !== defaultsFromSchema[dest];
|
|
52
53
|
|
|
53
|
-
const defaultIsDefined = (dest: string): boolean =>
|
|
54
|
+
const defaultIsDefined = (dest: string): boolean => defaultsFromSchema[dest] !== undefined;
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
const argValueNotArrayOrArraysDiffer = (dest: string) =>
|
|
57
|
+
!argsValueIsArray(dest) || arraysDiffer(dest);
|
|
57
58
|
|
|
58
|
-
const defaultValueNotArrayAndValuesDiffer =
|
|
59
|
-
|
|
60
|
-
valuesDiffer,
|
|
61
|
-
]);
|
|
59
|
+
const defaultValueNotArrayAndValuesDiffer = (dest: string) =>
|
|
60
|
+
!defaultValueIsArray(dest) && valuesDiffer(dest);
|
|
62
61
|
|
|
63
62
|
/**
|
|
64
63
|
* This used to be a hideous conditional, but it's broken up into a hideous function instead.
|
|
@@ -71,23 +70,24 @@ export function getNonDefaultServerArgs(parsedArgs: Args): Args {
|
|
|
71
70
|
* - ensures the args value is an array
|
|
72
71
|
* - ensures the args values do not differ from the default values
|
|
73
72
|
*/
|
|
74
|
-
const isNotDefault =
|
|
75
|
-
defaultIsDefined
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
defaultValueNotArrayAndValuesDiffer,
|
|
80
|
-
]),
|
|
81
|
-
]);
|
|
73
|
+
const isNotDefault = (dest: string) =>
|
|
74
|
+
defaultIsDefined(dest) &&
|
|
75
|
+
(typesDiffer(dest) ||
|
|
76
|
+
(defaultValueIsArray(dest) && argValueNotArrayOrArraysDiffer(dest)) ||
|
|
77
|
+
defaultValueNotArrayAndValuesDiffer(dest));
|
|
82
78
|
|
|
83
79
|
const defaultsFromSchema = getDefaultsForSchema(true) as Record<string, unknown>;
|
|
84
80
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
(
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
const nonDefault = pickBy(args, (_v, key) => isNotDefault(String(key)));
|
|
82
|
+
const result = {} as Args;
|
|
83
|
+
for (const entry of Object.values(nonDefault)) {
|
|
84
|
+
if (!entry) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const {value, argSpec} = entry;
|
|
88
|
+
setPath(result as Record<string, unknown>, argSpec.dest, value);
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -106,7 +106,7 @@ export function showConfig(
|
|
|
106
106
|
nonDefaultPreConfigParsedArgs: Partial<Args>,
|
|
107
107
|
configResult: ReadConfigFileResult,
|
|
108
108
|
defaults: Partial<Args>,
|
|
109
|
-
parsedArgs: Args
|
|
109
|
+
parsedArgs: Args,
|
|
110
110
|
): void {
|
|
111
111
|
console.log('Appium Configuration\n');
|
|
112
112
|
console.log('from defaults:\n');
|
|
@@ -118,7 +118,7 @@ export function showConfig(
|
|
|
118
118
|
console.log(`\n(no configuration file loaded)`);
|
|
119
119
|
}
|
|
120
120
|
const compactedNonDefaultPreConfigArgs = compactConfig(nonDefaultPreConfigParsedArgs);
|
|
121
|
-
if (
|
|
121
|
+
if (util.isEmpty(compactedNonDefaultPreConfigArgs)) {
|
|
122
122
|
console.log(`\n(no CLI parameters provided)`);
|
|
123
123
|
} else {
|
|
124
124
|
console.log('\nvia CLI or function call:\n');
|
|
@@ -135,9 +135,12 @@ export function showConfig(
|
|
|
135
135
|
* 3. Removes empty objects (but not `false` values)
|
|
136
136
|
* Does not operate recursively.
|
|
137
137
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
function compactConfig<T extends Record<string, unknown>>(obj: T): Partial<T> {
|
|
139
|
+
return pickBy(
|
|
140
|
+
obj,
|
|
141
|
+
(value, key) =>
|
|
142
|
+
key !== 'subcommand' &&
|
|
143
|
+
value !== undefined &&
|
|
144
|
+
!(value !== null && typeof value === 'object' && util.isEmpty(value)),
|
|
145
|
+
);
|
|
146
|
+
}
|
package/lib/cli/args.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {util} from '@appium/support';
|
|
2
2
|
import type {ArgumentOptions} from 'argparse';
|
|
3
3
|
import type {ExtensionType} from '@appium/types';
|
|
4
4
|
import type {CliExtensionSubcommand} from 'appium/types';
|
|
@@ -49,7 +49,7 @@ const globalExtensionArgs: ArgumentDefinitions = new Map([
|
|
|
49
49
|
*
|
|
50
50
|
* The result is memoized because parser setup is static across process lifetime.
|
|
51
51
|
*/
|
|
52
|
-
export const getExtensionArgs =
|
|
52
|
+
export const getExtensionArgs = util.memoize(function getExtensionArgs(): Record<
|
|
53
53
|
ExtensionType,
|
|
54
54
|
Record<CliExtensionSubcommand, ArgumentDefinitions>
|
|
55
55
|
> {
|
|
@@ -220,8 +220,7 @@ function makeUpdateArgs(type: ExtensionType): ArgumentDefinitions {
|
|
|
220
220
|
required: false,
|
|
221
221
|
default: false,
|
|
222
222
|
action: 'store_true',
|
|
223
|
-
help:
|
|
224
|
-
'Include any available major revision updates, which may have breaking changes',
|
|
223
|
+
help: 'Include any available major revision updates, which may have breaking changes',
|
|
225
224
|
},
|
|
226
225
|
],
|
|
227
226
|
]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {console, util} from '@appium/support';
|
|
2
2
|
import type {ExtMetadata, ExtRecord, InstallType} from 'appium/types';
|
|
3
3
|
import ExtensionCliCommand from './extension-command';
|
|
4
4
|
import type {
|
|
@@ -9,8 +9,6 @@ import type {
|
|
|
9
9
|
RunOutput,
|
|
10
10
|
} from './extension-command';
|
|
11
11
|
import {KNOWN_DRIVERS} from '../constants';
|
|
12
|
-
import '@colors/colors';
|
|
13
|
-
|
|
14
12
|
const REQ_DRIVER_FIELDS = ['driverName', 'automationName', 'platformNames', 'mainClass'];
|
|
15
13
|
type DriverInstallOpts = {driver: string; installType: InstallType; packageName?: string};
|
|
16
14
|
type DriverUninstallOpts = {driver: string};
|
|
@@ -29,7 +27,11 @@ export default class DriverCliCommand extends ExtensionCliCommand<'driver'> {
|
|
|
29
27
|
*
|
|
30
28
|
* @param opts - install options
|
|
31
29
|
*/
|
|
32
|
-
async install({
|
|
30
|
+
async install({
|
|
31
|
+
driver,
|
|
32
|
+
installType,
|
|
33
|
+
packageName,
|
|
34
|
+
}: DriverInstallOpts): Promise<ExtRecord<'driver'>> {
|
|
33
35
|
return await super._install({
|
|
34
36
|
installSpec: driver,
|
|
35
37
|
installType,
|
|
@@ -91,9 +93,9 @@ export default class DriverCliCommand extends ExtensionCliCommand<'driver'> {
|
|
|
91
93
|
*/
|
|
92
94
|
override getPostInstallText({extName, extData}: ExtensionArgs<'driver'>): PostInstallText {
|
|
93
95
|
return (
|
|
94
|
-
`Driver ${extName}@${extData.version} successfully installed\n
|
|
95
|
-
`- automationName: ${extData.automationName
|
|
96
|
-
`- platformNames: ${JSON.stringify(extData.platformNames)
|
|
96
|
+
`${console.styleText('green', `Driver ${extName}@${extData.version} successfully installed`)}\n` +
|
|
97
|
+
`- automationName: ${console.styleText('green', extData.automationName)}\n` +
|
|
98
|
+
`- platformNames: ${console.styleText('green', JSON.stringify(extData.platformNames))}`
|
|
97
99
|
);
|
|
98
100
|
}
|
|
99
101
|
|
|
@@ -106,16 +108,20 @@ export default class DriverCliCommand extends ExtensionCliCommand<'driver'> {
|
|
|
106
108
|
* @param driverMetadata - `appium` metadata from extension package
|
|
107
109
|
* @param installSpec - install spec from CLI
|
|
108
110
|
*/
|
|
109
|
-
override validateExtensionFields(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
override validateExtensionFields(
|
|
112
|
+
driverMetadata: ExtMetadata<'driver'>,
|
|
113
|
+
installSpec: string,
|
|
114
|
+
): void {
|
|
115
|
+
const missingFields = REQ_DRIVER_FIELDS.reduce<string[]>(
|
|
116
|
+
(acc, field) =>
|
|
117
|
+
driverMetadata[field as keyof typeof driverMetadata] ? acc : [...acc, field],
|
|
118
|
+
[],
|
|
113
119
|
);
|
|
114
120
|
|
|
115
|
-
if (!
|
|
121
|
+
if (!util.isEmpty(missingFields)) {
|
|
116
122
|
throw new Error(
|
|
117
123
|
`Driver "${installSpec}" did not expose correct fields for compatibility ` +
|
|
118
|
-
`with Appium. Missing fields: ${JSON.stringify(missingFields)}
|
|
124
|
+
`with Appium. Missing fields: ${JSON.stringify(missingFields)}`,
|
|
119
125
|
);
|
|
120
126
|
}
|
|
121
127
|
}
|