appium-uiautomator2-driver 3.4.0 → 3.5.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.
@@ -1,120 +1,89 @@
1
1
  import _ from 'lodash';
2
- import {errors, PROTOCOLS} from 'appium/driver';
3
- import {AndroidUiautomator2Driver} from '../driver';
4
-
5
- const MOBILE_SCRIPT_NAME_PREFIX = 'mobile:';
2
+ import {AndroidDriver} from 'appium-android-driver';
6
3
 
7
4
  /**
8
- * @override
9
- * @privateRemarks Because the "mobile" commands (execute methods) in this
10
- * driver universally accept an options object, this method will _not_ call
11
- * into `BaseDriver.executeMethod`.
12
5
  * @this {AndroidUiautomator2Driver}
13
- * @param {string} script
14
- * @param {any[]} [args]
15
- * @returns {Promise<any>}
6
+ * @returns {import('@appium/types').StringRecord<string>}
16
7
  */
17
- export async function execute(script, args) {
18
- const mobileScriptName = toExecuteMethodName(script);
19
- const isWebContext = this.isWebContext();
20
- if (mobileScriptName && isWebContext || !isWebContext) {
21
- if (mobileScriptName) {
22
- const executeMethodArgs = preprocessExecuteMethodArgs(args);
23
- this.log.info(`Executing method '${mobileScriptName}'`);
24
- return await this.executeMobile(mobileScriptName, executeMethodArgs);
25
- }
26
- // Just pass the script name through and let it fail with a proper error message
27
- return await this.executeMobile(`${script}`, {});
28
- }
29
- const endpoint =
30
- /** @type {import('appium-chromedriver').Chromedriver} */ (this.chromedriver).jwproxy
31
- .downstreamProtocol === PROTOCOLS.MJSONWP
32
- ? '/execute'
33
- : '/execute/sync';
34
- return await /** @type {import('appium-chromedriver').Chromedriver} */ (
35
- this.chromedriver
36
- ).jwproxy.command(endpoint, 'POST', {
37
- script,
38
- args,
39
- });
8
+ export function mobileCommandsMapping() {
9
+ const commonMapping = new AndroidDriver().mobileCommandsMapping.call(this);
10
+ return {
11
+ ...commonMapping,
12
+ dragGesture: 'mobileDragGesture',
13
+ flingGesture: 'mobileFlingGesture',
14
+ doubleClickGesture: 'mobileDoubleClickGesture',
15
+ clickGesture: 'mobileClickGesture',
16
+ longClickGesture: 'mobileLongClickGesture',
17
+ pinchCloseGesture: 'mobilePinchCloseGesture',
18
+ pinchOpenGesture: 'mobilePinchOpenGesture',
19
+ swipeGesture: 'mobileSwipeGesture',
20
+ scrollGesture: 'mobileScrollGesture',
21
+ scrollBackTo: 'mobileScrollBackTo',
22
+ scroll: 'mobileScroll',
23
+ viewportScreenshot: 'mobileViewportScreenshot',
24
+ viewportRect: 'mobileViewPortRect',
25
+
26
+ deepLink: 'mobileDeepLink',
27
+
28
+ acceptAlert: 'mobileAcceptAlert',
29
+ dismissAlert: 'mobileDismissAlert',
30
+
31
+ batteryInfo: 'mobileGetBatteryInfo',
32
+
33
+ deviceInfo: 'mobileGetDeviceInfo',
34
+
35
+ openNotifications: 'openNotifications',
36
+
37
+ type: 'mobileType',
38
+ replaceElementValue: 'mobileReplaceElementValue',
39
+
40
+ getAppStrings: 'mobileGetAppStrings',
41
+
42
+ installMultipleApks: 'mobileInstallMultipleApks',
43
+
44
+ pressKey: 'mobilePressKey',
45
+
46
+ screenshots: 'mobileScreenshots',
47
+
48
+ scheduleAction: 'mobileScheduleAction',
49
+ getActionHistory: 'mobileGetActionHistory',
50
+ unscheduleAction: 'mobileUnscheduleAction',
51
+ };
40
52
  }
41
53
 
42
54
  /**
43
55
  * @override
44
56
  * @this {AndroidUiautomator2Driver}
45
- * @param {string} script Must be of the form `mobile: <something>`, which
46
- * differs from its parent class implementation.
57
+ * @param {string} mobileCommand
47
58
  * @param {import('@appium/types').StringRecord} [opts={}]
48
59
  * @returns {Promise<any>}
49
60
  */
50
- export async function executeMobile(script, opts = {}) {
51
- if (!(script in AndroidUiautomator2Driver.executeMethodMap)) {
52
- const commandNames = _.map(
53
- _.keys(AndroidUiautomator2Driver.executeMethodMap),
54
- (value) => value.slice(8)
55
- );
56
- throw new errors.UnknownCommandError(
57
- `Unknown mobile command "${script}". ` +
58
- `Only ${commandNames.join(', ')} commands are supported.`
59
- );
60
- }
61
- const methodName =
62
- AndroidUiautomator2Driver.executeMethodMap[
63
- /** @type {keyof import('../execute-method-map').Uiautomator2ExecuteMethodMap} */ (script)
64
- ].command;
65
-
66
- return await /** @type {(opts?: any) => Promise<unknown>} */ (this[methodName])(opts);
61
+ export async function executeMobile(mobileCommand, opts = {}) {
62
+ return await new AndroidDriver().executeMobile.call(this, mobileCommand, preprocessOptions(opts));
67
63
  }
68
64
 
69
65
  // #region Internal Helpers
70
66
 
71
67
  /**
72
- * Messages the arguments going into an execute method.
73
- * @remarks A similar method is implemented in `appium-xcuitest-driver`, but it
74
- * appears the methods in here handle unwrapping of `Element` objects, so we do
75
- * not do that here.
76
- * @param {readonly any[] | readonly [StringRecord] | Readonly<StringRecord>} [args]
68
+ * Renames the deprecated `element` key to `elementId`. Historically,
69
+ * all of the pre-Execute-Method-Map execute methods accepted an `element` _or_ and `elementId` param.
70
+ * This assigns the `element` value to `elementId` if `elementId` is not already present.
71
+ *
72
+ * @param {import('@appium/types').StringRecord} [opts={}]
77
73
  * @internal
78
- * @returns {StringRecord<unknown>}
74
+ * @returns {import('@appium/types').StringRecord|undefined}
79
75
  */
80
- function preprocessExecuteMethodArgs(args) {
81
- if (_.isArray(args)) {
82
- args = _.first(args);
76
+ function preprocessOptions(opts = {}) {
77
+ if (_.isPlainObject(opts) && !('elementId' in opts) && 'element' in opts) {
78
+ opts.elementId = opts.element;
79
+ delete opts.element;
80
+ this.log.debug(`Replaced the obsolete 'element' key with 'elementId'`);
83
81
  }
84
- const executeMethodArgs = /** @type {StringRecord<unknown>} */ (args ?? {});
85
- /**
86
- * Renames the deprecated `element` key to `elementId`. Historically,
87
- * all of the pre-Execute-Method-Map execute methods accepted an `element` _or_ and `elementId` param.
88
- * This assigns the `element` value to `elementId` if `elementId` is not already present.
89
- */
90
- if (!('elementId' in executeMethodArgs) && 'element' in executeMethodArgs) {
91
- executeMethodArgs.elementId = executeMethodArgs.element;
92
- delete executeMethodArgs.element;
93
- }
94
-
95
- return executeMethodArgs;
96
- }
97
-
98
- /**
99
- * Type guard to check if a script is an execute method.
100
- * @param {any} script
101
- * @internal
102
- * @returns {string?}
103
- */
104
- function toExecuteMethodName(script) {
105
- return _.startsWith(script, MOBILE_SCRIPT_NAME_PREFIX)
106
- ? script.replace(new RegExp(`${MOBILE_SCRIPT_NAME_PREFIX}\\s*`), `${MOBILE_SCRIPT_NAME_PREFIX} `)
107
- : null;
82
+ return opts;
108
83
  }
109
84
 
110
85
  // #endregion
111
86
 
112
87
  /**
113
- * @typedef {import('../uiautomator2').UiAutomator2Server} UiAutomator2Server
114
- * @typedef {import('appium-adb').ADB} ADB
115
- */
116
-
117
- /**
118
- * @template [T=any]
119
- * @typedef {import('@appium/types').StringRecord<T>} StringRecord
88
+ * @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
120
89
  */
@@ -238,8 +238,7 @@ export async function mobileScrollBackTo(opts) {
238
238
  */
239
239
  export async function mobileScroll(opts) {
240
240
  const {
241
- element,
242
- elementId, // `element` is deprecated, use `elementId` instead
241
+ elementId,
243
242
  strategy,
244
243
  selector,
245
244
  maxSwipes,
@@ -253,7 +252,7 @@ export async function mobileScroll(opts) {
253
252
  '/gestures/scroll_to',
254
253
  'POST',
255
254
  {
256
- origin: toOrigin(elementId || element),
255
+ origin: toOrigin(elementId),
257
256
  params: {strategy, selector, maxSwipes},
258
257
  }
259
258
  );
package/lib/driver.ts CHANGED
@@ -22,7 +22,6 @@ import path from 'node:path';
22
22
  import {checkPortStatus, findAPortNotInUse} from 'portscanner';
23
23
  import type {ExecError} from 'teen_process';
24
24
  import UIAUTOMATOR2_CONSTRAINTS, {type Uiautomator2Constraints} from './constraints';
25
- import {executeMethodMap} from './execute-method-map';
26
25
  import {APKS_EXTENSION, APK_EXTENSION} from './extensions';
27
26
  import {newMethodMap} from './method-map';
28
27
  import { signApp } from './helpers';
@@ -81,8 +80,8 @@ import {
81
80
  mobileReplaceElementValue,
82
81
  } from './commands/element';
83
82
  import {
84
- execute,
85
83
  executeMobile,
84
+ mobileCommandsMapping,
86
85
  } from './commands/execute';
87
86
  import {
88
87
  doFindElementOrEls,
@@ -266,8 +265,6 @@ class AndroidUiautomator2Driver
266
265
  {
267
266
  static newMethodMap = newMethodMap;
268
267
 
269
- static executeMethodMap = executeMethodMap;
270
-
271
268
  uiautomator2: UiAutomator2Server;
272
269
 
273
270
  systemPort: number | undefined;
@@ -1030,8 +1027,8 @@ class AndroidUiautomator2Driver
1030
1027
  clear = clear;
1031
1028
  mobileReplaceElementValue = mobileReplaceElementValue;
1032
1029
 
1033
- execute = execute;
1034
1030
  executeMobile = executeMobile;
1031
+ mobileCommandsMapping = mobileCommandsMapping;
1035
1032
 
1036
1033
  doFindElementOrEls = doFindElementOrEls;
1037
1034
 
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "appium-uiautomator2-driver",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-uiautomator2-driver",
9
- "version": "3.4.0",
9
+ "version": "3.5.0",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "appium-adb": "^12.2.0",
13
- "appium-android-driver": "^9.5.0",
13
+ "appium-android-driver": "^9.6.0",
14
14
  "appium-chromedriver": "^5.6.28",
15
15
  "appium-uiautomator2-server": "^7.0.1",
16
16
  "asyncbox": "^3.0.0",
@@ -1035,9 +1035,9 @@
1035
1035
  }
1036
1036
  },
1037
1037
  "node_modules/appium-android-driver": {
1038
- "version": "9.5.0",
1039
- "resolved": "https://registry.npmjs.org/appium-android-driver/-/appium-android-driver-9.5.0.tgz",
1040
- "integrity": "sha512-J0VYaAM7j3Z03o3Ykf38HYxnmpbKClnScjmKuJFOq1yTPdXnv1VSRNScPdogDoEvAc+3+wHdTuopFJowV3NM+Q==",
1038
+ "version": "9.6.0",
1039
+ "resolved": "https://registry.npmjs.org/appium-android-driver/-/appium-android-driver-9.6.0.tgz",
1040
+ "integrity": "sha512-BVZ6zhc1xQmjXE75t3G1Z3lpJEubiO7fhjhfkzA7SeBBNadCJg/D6r/Fm9SpMuT6+IwuCv6onFOsAkgQW8zNnA==",
1041
1041
  "dependencies": {
1042
1042
  "@appium/support": "^4.2.0",
1043
1043
  "@colors/colors": "^1.6.0",
@@ -3353,15 +3353,15 @@
3353
3353
  "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
3354
3354
  },
3355
3355
  "node_modules/path-scurry": {
3356
- "version": "1.11.0",
3357
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.0.tgz",
3358
- "integrity": "sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==",
3356
+ "version": "1.11.1",
3357
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
3358
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
3359
3359
  "dependencies": {
3360
3360
  "lru-cache": "^10.2.0",
3361
3361
  "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
3362
3362
  },
3363
3363
  "engines": {
3364
- "node": ">=16 || 14 >=14.17"
3364
+ "node": ">=16 || 14 >=14.18"
3365
3365
  },
3366
3366
  "funding": {
3367
3367
  "url": "https://github.com/sponsors/isaacs"
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "automated testing",
8
8
  "android"
9
9
  ],
10
- "version": "3.4.0",
10
+ "version": "3.5.0",
11
11
  "bugs": {
12
12
  "url": "https://github.com/appium/appium-uiautomator2-driver/issues"
13
13
  },
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "appium-adb": "^12.2.0",
60
- "appium-android-driver": "^9.5.0",
60
+ "appium-android-driver": "^9.6.0",
61
61
  "appium-chromedriver": "^5.6.28",
62
62
  "appium-uiautomator2-server": "^7.0.1",
63
63
  "asyncbox": "^3.0.0",