appium 2.2.3 → 2.4.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.
Files changed (90) hide show
  1. package/README.md +131 -158
  2. package/build/lib/appium.d.ts +76 -4
  3. package/build/lib/appium.d.ts.map +1 -1
  4. package/build/lib/appium.js +327 -1
  5. package/build/lib/appium.js.map +1 -1
  6. package/build/lib/cli/args.d.ts.map +1 -1
  7. package/build/lib/cli/args.js +24 -2
  8. package/build/lib/cli/args.js.map +1 -1
  9. package/build/lib/cli/driver-command.d.ts +16 -0
  10. package/build/lib/cli/driver-command.d.ts.map +1 -1
  11. package/build/lib/cli/driver-command.js +16 -0
  12. package/build/lib/cli/driver-command.js.map +1 -1
  13. package/build/lib/cli/extension-command.d.ts +26 -2
  14. package/build/lib/cli/extension-command.d.ts.map +1 -1
  15. package/build/lib/cli/extension-command.js +135 -4
  16. package/build/lib/cli/extension-command.js.map +1 -1
  17. package/build/lib/cli/parser.d.ts.map +1 -1
  18. package/build/lib/cli/parser.js +11 -7
  19. package/build/lib/cli/parser.js.map +1 -1
  20. package/build/lib/cli/plugin-command.d.ts +16 -0
  21. package/build/lib/cli/plugin-command.d.ts.map +1 -1
  22. package/build/lib/cli/plugin-command.js +16 -0
  23. package/build/lib/cli/plugin-command.js.map +1 -1
  24. package/build/lib/cli/utils.d.ts.map +1 -1
  25. package/build/lib/cli/utils.js +3 -4
  26. package/build/lib/cli/utils.js.map +1 -1
  27. package/build/lib/config-file.d.ts +1 -1
  28. package/build/lib/config.d.ts +8 -7
  29. package/build/lib/config.d.ts.map +1 -1
  30. package/build/lib/config.js +54 -64
  31. package/build/lib/config.js.map +1 -1
  32. package/build/lib/constants.d.ts +10 -0
  33. package/build/lib/constants.d.ts.map +1 -1
  34. package/build/lib/constants.js +11 -1
  35. package/build/lib/constants.js.map +1 -1
  36. package/build/lib/doctor/doctor.d.ts +55 -0
  37. package/build/lib/doctor/doctor.d.ts.map +1 -0
  38. package/build/lib/doctor/doctor.js +201 -0
  39. package/build/lib/doctor/doctor.js.map +1 -0
  40. package/build/lib/extension/driver-config.d.ts +2 -2
  41. package/build/lib/extension/driver-config.d.ts.map +1 -1
  42. package/build/lib/extension/driver-config.js +4 -4
  43. package/build/lib/extension/driver-config.js.map +1 -1
  44. package/build/lib/extension/extension-config.d.ts +10 -3
  45. package/build/lib/extension/extension-config.d.ts.map +1 -1
  46. package/build/lib/extension/extension-config.js +32 -14
  47. package/build/lib/extension/extension-config.js.map +1 -1
  48. package/build/lib/extension/index.d.ts +6 -4
  49. package/build/lib/extension/index.d.ts.map +1 -1
  50. package/build/lib/extension/index.js +74 -32
  51. package/build/lib/extension/index.js.map +1 -1
  52. package/build/lib/extension/manifest.js +1 -1
  53. package/build/lib/extension/manifest.js.map +1 -1
  54. package/build/lib/extension/plugin-config.js +1 -1
  55. package/build/lib/extension/plugin-config.js.map +1 -1
  56. package/build/lib/grid-register.d.ts.map +1 -1
  57. package/build/lib/grid-register.js +1 -2
  58. package/build/lib/grid-register.js.map +1 -1
  59. package/build/lib/main.d.ts +4 -0
  60. package/build/lib/main.d.ts.map +1 -1
  61. package/build/lib/main.js +31 -52
  62. package/build/lib/main.js.map +1 -1
  63. package/build/lib/schema/schema.d.ts +5 -0
  64. package/build/lib/schema/schema.d.ts.map +1 -1
  65. package/build/lib/schema/schema.js +7 -7
  66. package/build/lib/schema/schema.js.map +1 -1
  67. package/build/lib/utils.d.ts +3 -0
  68. package/build/lib/utils.d.ts.map +1 -1
  69. package/build/lib/utils.js +2 -1
  70. package/build/lib/utils.js.map +1 -1
  71. package/build/types/cli.d.ts +1 -1
  72. package/build/types/cli.d.ts.map +1 -1
  73. package/lib/appium.js +388 -2
  74. package/lib/cli/args.js +27 -2
  75. package/lib/cli/driver-command.js +18 -0
  76. package/lib/cli/extension-command.js +160 -9
  77. package/lib/cli/parser.js +22 -8
  78. package/lib/cli/plugin-command.js +18 -0
  79. package/lib/cli/utils.js +5 -7
  80. package/lib/config.js +46 -65
  81. package/lib/constants.js +12 -0
  82. package/lib/doctor/doctor.js +209 -0
  83. package/lib/extension/driver-config.js +3 -3
  84. package/lib/extension/extension-config.js +33 -15
  85. package/lib/extension/index.js +80 -43
  86. package/lib/grid-register.js +1 -2
  87. package/lib/main.js +42 -61
  88. package/lib/utils.js +2 -1
  89. package/package.json +15 -18
  90. package/types/cli.ts +1 -1
package/lib/main.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import {WebSocketServer} from 'ws';
3
4
  import {init as logsinkInit} from './logsink'; // this import needs to come first since it sets up global npmlog
4
5
  import logger from './logger'; // logger needs to remain second
5
6
  import {
@@ -7,7 +8,7 @@ import {
7
8
  server as baseServer,
8
9
  normalizeBasePath,
9
10
  } from '@appium/base-driver';
10
- import {logger as logFactory, util, env, fs} from '@appium/support';
11
+ import {logger as logFactory, util, env} from '@appium/support';
11
12
  import {asyncify} from 'asyncbox';
12
13
  import _ from 'lodash';
13
14
  import {AppiumDriver} from './appium';
@@ -20,15 +21,13 @@ import {
20
21
  getNonDefaultServerArgs,
21
22
  showConfig,
22
23
  showBuildInfo,
23
- validateTmpDir,
24
- warnNodeDeprecations,
25
- checkNpmOk,
24
+ requireDir,
26
25
  } from './config';
27
26
  import {readConfigFile} from './config-file';
28
27
  import {loadExtensions, getActivePlugins, getActiveDrivers} from './extension';
29
28
  import {SERVER_SUBCOMMAND, LONG_STACKTRACE_LIMIT} from './constants';
30
29
  import registerNode from './grid-register';
31
- import {getDefaultsForSchema, validate} from './schema/schema';
30
+ import {getDefaultsForSchema, validate as validateSchema} from './schema/schema';
32
31
  import {
33
32
  inspect,
34
33
  adjustNodePath,
@@ -40,7 +39,6 @@ import {
40
39
  V4_BROADCAST_IP,
41
40
  V6_BROADCAST_IP,
42
41
  } from './utils';
43
- import os from 'node:os';
44
42
  import net from 'node:net';
45
43
 
46
44
  const {resolveAppiumHome} = env;
@@ -53,7 +51,6 @@ const {resolveAppiumHome} = env;
53
51
  async function preflightChecks(args, throwInsteadOfExit = false) {
54
52
  try {
55
53
  checkNodeOk();
56
- await checkNpmOk();
57
54
  if (args.longStacktrace) {
58
55
  Error.stackTraceLimit = LONG_STACKTRACE_LIMIT;
59
56
  }
@@ -61,12 +58,11 @@ async function preflightChecks(args, throwInsteadOfExit = false) {
61
58
  await showBuildInfo();
62
59
  process.exit(0);
63
60
  }
64
- warnNodeDeprecations();
65
61
 
66
- validate(args);
62
+ validateSchema(args);
67
63
 
68
64
  if (args.tmpDir) {
69
- await validateTmpDir(args.tmpDir);
65
+ await requireDir(args.tmpDir, !args.noPermsCheck, 'tmpDir argument value');
70
66
  }
71
67
  } catch (err) {
72
68
  logger.error(err.message.red);
@@ -149,48 +145,16 @@ function getExtraMethodMap(driverClasses, pluginClasses) {
149
145
  }
150
146
 
151
147
  /**
152
- * Prepares and validates appium home path folder
153
- *
154
- * @param {string} name The name of the appium home source (needed for error messages)
155
- * @param {string} appiumHome The actual value to be verified
156
- * @returns {Promise<string>} Same appiumHome value
157
- * @throws {Error} If the validation has failed
148
+ * @param {string?} [appiumHomeFromArgs] - Appium home value retrieved from progrmmatic server args
149
+ * @returns {string}
158
150
  */
159
- async function prepareAppiumHome(name, appiumHome) {
160
- let stat;
161
- try {
162
- stat = await fs.stat(appiumHome);
163
- } catch (e) {
164
- let err = e;
165
- if (e.code === 'ENOENT') {
166
- try {
167
- await fs.mkdir(appiumHome, {recursive: true});
168
- return appiumHome;
169
- } catch (e1) {
170
- err = e1;
171
- }
172
- }
173
- throw new Error(
174
- `The path '${appiumHome}' provided in the ${name} must point ` +
175
- `to a valid folder writeable for the current user account '${os.userInfo().username}'. ` +
176
- `Original error: ${err.message}`,
177
- );
178
- }
179
- if (!stat.isDirectory()) {
180
- throw new Error(
181
- `The path '${appiumHome}' provided in the ${name} must point to a valid folder`,
182
- );
183
- }
184
- try {
185
- await fs.access(appiumHome, fs.constants.W_OK);
186
- } catch (e) {
187
- throw new Error(
188
- `The folder path '${appiumHome}' provided in the ${name} must be ` +
189
- `writeable for the current user account '${os.userInfo().username}. ` +
190
- `Original error: ${e.message}`,
191
- );
151
+ function determineAppiumHomeSource(appiumHomeFromArgs) {
152
+ if (!_.isNil(appiumHomeFromArgs)) {
153
+ return 'appiumHome config value';
154
+ } else if (process.env.APPIUM_HOME) {
155
+ return 'APPIUM_HOME environment variable';
192
156
  }
193
- return appiumHome;
157
+ return 'autodetected Appium home path';
194
158
  }
195
159
 
196
160
  /**
@@ -212,13 +176,10 @@ async function prepareAppiumHome(name, appiumHome) {
212
176
  */
213
177
  async function init(args) {
214
178
  const appiumHome = args?.appiumHome ?? (await resolveAppiumHome());
215
- let appiumHomeSourceName = 'autodetected appium home path';
216
- if (!_.isNil(args?.appiumHome)) {
217
- appiumHomeSourceName = 'appiumHome config value';
218
- } else if (process.env.APPIUM_HOME) {
219
- appiumHomeSourceName = 'APPIUM_HOME environment variable';
220
- }
221
- await prepareAppiumHome(appiumHomeSourceName, appiumHome);
179
+ const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
180
+ // We verify the writeability later based on requested server arguments
181
+ // Here we just need to make sure the path exists and is a folder
182
+ await requireDir(appiumHome, false, appiumHomeSourceName);
222
183
 
223
184
  adjustNodePath();
224
185
 
@@ -295,6 +256,10 @@ async function init(args) {
295
256
  }
296
257
  }
297
258
 
259
+ if (!serverArgs.noPermsCheck) {
260
+ await requireDir(appiumHome, true, appiumHomeSourceName);
261
+ }
262
+
298
263
  const appiumDriver = new AppiumDriver(
299
264
  /** @type {import('@appium/types').DriverOpts<import('./appium').AppiumDriverConstraints>} */ (
300
265
  serverArgs
@@ -309,8 +274,10 @@ async function init(args) {
309
274
  parsedArgs: serverArgs,
310
275
  driverConfig,
311
276
  pluginConfig,
277
+ appiumHome,
312
278
  });
313
279
  } else {
280
+ await requireDir(appiumHome, true, appiumHomeSourceName);
314
281
  if (isExtensionCommandArgs(preConfigArgs)) {
315
282
  // if the user has requested the 'driver' CLI, don't run the normal server,
316
283
  // but instead pass control to the driver CLI
@@ -340,7 +307,7 @@ function logServerAddress(url) {
340
307
  }
341
308
 
342
309
  const interfaces = fetchInterfaces(urlObj.hostname === V4_BROADCAST_IP ? 4 : 6);
343
- const toLabel = (/** @type {os.NetworkInterfaceInfo} */ iface) => {
310
+ const toLabel = (/** @type {import('node:os').NetworkInterfaceInfo} */ iface) => {
344
311
  const href = urlObj.href.replace(urlObj.hostname, iface.address);
345
312
  return iface.internal ? `${href} (only accessible from the same host)` : href;
346
313
  };
@@ -370,17 +337,25 @@ async function main(args) {
370
337
  );
371
338
  }
372
339
 
373
- const {appiumDriver, pluginConfig, driverConfig, parsedArgs} =
340
+ const {appiumDriver, pluginConfig, driverConfig, parsedArgs, appiumHome} =
374
341
  /** @type {InitResult<ServerCommand>} */ (initResult);
375
342
 
376
- const pluginClasses = getActivePlugins(pluginConfig, parsedArgs.usePlugins);
343
+ const pluginClasses = await getActivePlugins(
344
+ pluginConfig, parsedArgs.pluginsImportChunkSize, parsedArgs.usePlugins
345
+ );
377
346
  // set the active plugins on the umbrella driver so it can use them for commands
378
347
  appiumDriver.pluginClasses = pluginClasses;
379
348
 
380
349
  await logStartupInfo(parsedArgs);
350
+
351
+ const appiumHomeSourceName = determineAppiumHomeSource(args?.appiumHome);
352
+ logger.debug(`The ${appiumHomeSourceName}: ${appiumHome}`);
353
+
381
354
  let routeConfiguringFunction = makeRouter(appiumDriver);
382
355
 
383
- const driverClasses = getActiveDrivers(driverConfig, parsedArgs.useDrivers);
356
+ const driverClasses = await getActiveDrivers(
357
+ driverConfig, parsedArgs.driversImportChunkSize, parsedArgs.useDrivers
358
+ );
384
359
  const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
385
360
  const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
386
361
 
@@ -399,8 +374,13 @@ async function main(args) {
399
374
  serverOpts.keepAliveTimeout = parsedArgs.keepAliveTimeout * 1000;
400
375
  }
401
376
  let server;
377
+ const bidiServer = new WebSocketServer({noServer: true});
378
+ bidiServer.on('connection', appiumDriver.onBidiConnection.bind(appiumDriver));
379
+ bidiServer.on('error', appiumDriver.onBidiServerError.bind(appiumDriver));
402
380
  try {
403
381
  server = await baseServer(serverOpts);
382
+ server.addWebSocketHandler('/bidi', bidiServer);
383
+ server.addWebSocketHandler('/bidi/:sessionId', bidiServer);
404
384
  } catch (err) {
405
385
  logger.error(
406
386
  `Could not configure Appium server. It's possible that a driver or plugin tried ` +
@@ -498,6 +478,7 @@ export {main, init, resolveAppiumHome};
498
478
  * @typedef ServerInitData
499
479
  * @property {import('./appium').AppiumDriver} appiumDriver - The Appium driver
500
480
  * @property {import('appium/types').ParsedArgs} parsedArgs - The parsed arguments
481
+ * @property {string} appiumHome - The full path to the Appium home folder
501
482
  */
502
483
 
503
484
  /**
package/lib/utils.js CHANGED
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import logger from './logger';
3
3
  import {processCapabilities, PROTOCOLS, STANDARD_CAPS, errors} from '@appium/base-driver';
4
4
  import {inspect as dump} from 'util';
5
- import {node} from '@appium/support';
5
+ import {node, fs} from '@appium/support';
6
6
  import path from 'path';
7
7
  import {SERVER_SUBCOMMAND, DRIVER_TYPE, PLUGIN_TYPE} from './constants';
8
8
  import os from 'node:os';
@@ -11,6 +11,7 @@ const W3C_APPIUM_PREFIX = 'appium';
11
11
  const STANDARD_CAPS_LOWERCASE = new Set([...STANDARD_CAPS].map((cap) => cap.toLowerCase()));
12
12
  export const V4_BROADCAST_IP = '0.0.0.0';
13
13
  export const V6_BROADCAST_IP = '::';
14
+ export const npmPackage = fs.readPackageJsonFrom(__dirname);
14
15
 
15
16
 
16
17
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium",
3
- "version": "2.2.3",
3
+ "version": "2.4.0",
4
4
  "description": "Automation for Apps.",
5
5
  "keywords": [
6
6
  "automation",
@@ -60,13 +60,13 @@
60
60
  "test:unit": "mocha \"./test/unit/**/*.spec.js\""
61
61
  },
62
62
  "dependencies": {
63
- "@appium/base-driver": "^9.4.3",
64
- "@appium/base-plugin": "^2.2.24",
65
- "@appium/docutils": "^0.4.13",
66
- "@appium/schema": "^0.4.2",
67
- "@appium/support": "^4.1.10",
68
- "@appium/types": "^0.14.3",
69
- "@sidvind/better-ajv-errors": "2.1.0",
63
+ "@appium/base-driver": "^9.5.0",
64
+ "@appium/base-plugin": "^2.2.26",
65
+ "@appium/docutils": "^1.0.2",
66
+ "@appium/schema": "~0.5.0",
67
+ "@appium/support": "^4.2.0",
68
+ "@appium/types": "^0.16.0",
69
+ "@sidvind/better-ajv-errors": "2.1.3",
70
70
  "@types/argparse": "2.0.14",
71
71
  "@types/bluebird": "3.5.42",
72
72
  "@types/fancy-log": "2.0.2",
@@ -76,13 +76,12 @@
76
76
  "ajv": "8.12.0",
77
77
  "ajv-formats": "2.1.1",
78
78
  "argparse": "2.0.1",
79
- "async-lock": "1.4.0",
79
+ "async-lock": "1.4.1",
80
80
  "asyncbox": "3.0.0",
81
- "axios": "1.6.2",
81
+ "axios": "1.6.3",
82
82
  "bluebird": "3.7.2",
83
83
  "cross-env": "7.0.3",
84
- "find-up": "5.0.0",
85
- "lilconfig": "2.1.0",
84
+ "lilconfig": "3.0.0",
86
85
  "lodash": "4.17.21",
87
86
  "npmlog": "7.0.1",
88
87
  "ora": "5.4.1",
@@ -90,10 +89,11 @@
90
89
  "resolve-from": "5.0.0",
91
90
  "semver": "7.5.4",
92
91
  "source-map-support": "0.5.21",
93
- "teen_process": "2.0.101",
94
- "type-fest": "3.13.1",
92
+ "teen_process": "2.1.1",
93
+ "type-fest": "4.9.0",
95
94
  "winston": "3.11.0",
96
95
  "wrap-ansi": "7.0.0",
96
+ "ws": "8.16.0",
97
97
  "yaml": "2.3.4"
98
98
  },
99
99
  "engines": {
@@ -103,8 +103,5 @@
103
103
  "publishConfig": {
104
104
  "access": "public"
105
105
  },
106
- "gitHead": "67504604b7d4602561db2cb3529860b241bec427",
107
- "typedoc": {
108
- "entryPoint": "./lib/main.js"
109
- }
106
+ "gitHead": "76df4d600dcb7c867c37c3d7d302dc7fcc95ae09"
110
107
  }
package/types/cli.ts CHANGED
@@ -19,7 +19,7 @@ export type CliCommand = CliCommandServer | CliExtensionCommand;
19
19
  * Possible subcommands of {@linkcode CliCommandDriver} or
20
20
  * {@linkcode CliCommandPlugin}.
21
21
  */
22
- export type CliExtensionSubcommand = 'install' | 'list' | 'run' | 'uninstall' | 'update';
22
+ export type CliExtensionSubcommand = 'install' | 'list' | 'run' | 'uninstall' | 'update'| 'doctor';
23
23
 
24
24
  export interface CliExtensionSubcommandListArgs {
25
25
  showInstalled?: boolean;