appium-uiautomator2-driver 1.62.0 → 1.65.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,7 +1,9 @@
1
1
  import _ from 'lodash';
2
2
  import log from '../logger';
3
+ import B from 'bluebird';
3
4
  import { errors, BASEDRIVER_HANDLED_SETTINGS } from 'appium-base-driver';
4
5
  import { fs, tempDir } from 'appium-support';
6
+ import { APK_EXTENSION } from '../extensions';
5
7
 
6
8
  let extensions = {},
7
9
  commands = {},
@@ -109,6 +111,7 @@ extensions.executeMobile = async function (mobileCommand, opts = {}) {
109
111
 
110
112
  dragGesture: 'mobileDragGesture',
111
113
  flingGesture: 'mobileFlingGesture',
114
+ doubleClickGesture: 'mobileDoubleClickGesture',
112
115
  longClickGesture: 'mobileLongClickGesture',
113
116
  pinchCloseGesture: 'mobilePinchCloseGesture',
114
117
  pinchOpenGesture: 'mobilePinchOpenGesture',
@@ -154,6 +157,8 @@ extensions.executeMobile = async function (mobileCommand, opts = {}) {
154
157
  stopService: 'mobileStopService',
155
158
 
156
159
  getContexts: 'mobileGetContexts',
160
+
161
+ installMultipleApks: 'mobileInstallMultipleApks',
157
162
  };
158
163
 
159
164
  if (!_.has(mobileCommandsMapping, mobileCommand)) {
@@ -296,6 +301,46 @@ commands.mobileType = async function mobileType (opts = {}) {
296
301
  return await this.adb.typeUnicode(text);
297
302
  };
298
303
 
304
+
305
+ /**
306
+ * @typedef {Object} InstallOptions
307
+ * @property {boolean} allowTestPackages [false] - Set to true in order to allow test
308
+ * packages installation.
309
+ * @property {boolean} useSdcard [false] - Set to true to install the app on sdcard
310
+ * instead of the device memory.
311
+ * @property {boolean} grantPermissions [false] - Set to true in order to grant all the
312
+ * permissions requested in the application's manifest
313
+ * automatically after the installation is completed
314
+ * under Android 6+.
315
+ * @property {boolean} replace [true] - Set it to false if you don't want
316
+ * the application to be upgraded/reinstalled
317
+ * if it is already present on the device.
318
+ * @property {boolean} partialInstall [false] - Install apks partially. It is used for 'install-multiple'.
319
+ * https://android.stackexchange.com/questions/111064/what-is-a-partial-application-install-via-adb
320
+ */
321
+
322
+ /**
323
+ * @typedef {Object} InstallMultipleApksOptions
324
+ * @property {Array<string>} apks - The list of APKs to install. Each APK should be a path to a apk
325
+ * or downloadable URL as HTTP/HTTPS.
326
+ * @property {InstallOptions} options
327
+ */
328
+
329
+ /**
330
+ * Install multiple APKs with `install-multiple` option.
331
+ *
332
+ * @param {InstallMultipleApksOptions} opts
333
+ * @throws {Error} if an error occured while installing the given APKs.
334
+ */
335
+ commands.mobileInstallMultipleApks = async function (opts = {}) {
336
+ if (!_.isArray(opts.apks) || _.isEmpty(opts.apks)) {
337
+ throw new errors.InvalidArgumentError('No apks are given to install');
338
+ }
339
+ const apks = await B.all(opts.apks
340
+ .map((app) => this.helpers.configureApp(app, [APK_EXTENSION])));
341
+ await this.adb.installMultipleApks(apks, opts.options);
342
+ };
343
+
299
344
  Object.assign(extensions, commands, helpers);
300
345
 
301
346
  export default extensions;
@@ -52,6 +52,33 @@ commands.mobileLongClickGesture = async function mobileLongClickGesture (opts =
52
52
  });
53
53
  };
54
54
 
55
+ /**
56
+ * @typedef {Object} DoubleClickOptions
57
+ * @property {?string} elementId - The id of the element to be double clicked.
58
+ * If the element is missing then both click offset coordinates must be provided.
59
+ * If both the element id and offset are provided then the coordinates
60
+ * are parsed as relative offsets from the top left corner of the element.
61
+ * @property {?number} x - The x coordinate to double click on
62
+ * @property {?number} y - The y coordinate to double click on
63
+ */
64
+
65
+ /**
66
+ * Performs a click that lasts for the given duration
67
+ *
68
+ * @param {?DoubleClickOptions} opts
69
+ * @throws {Error} if provided options are not valid
70
+ */
71
+ commands.mobileDoubleClickGesture = async function mobileDoubleClickGesture (opts = {}) {
72
+ const {
73
+ elementId,
74
+ x, y,
75
+ } = opts;
76
+ return await this.uiautomator2.jwproxy.command('/appium/gestures/double_click', 'POST', {
77
+ origin: toOrigin(elementId),
78
+ offset: toPoint(x, y),
79
+ });
80
+ };
81
+
55
82
  /**
56
83
  * @typedef {Object} DragOptions
57
84
  * @property {?string} elementId - The id of the element to be dragged.
@@ -11,6 +11,7 @@ parser.registerAttrEqualityMods('^', '$', '*', '~');
11
11
  parser.enableSubstitutes();
12
12
 
13
13
  const RESOURCE_ID = 'resource-id';
14
+ const ID_LOCATOR_PATTERN = /^[a-zA-Z_][a-zA-Z0-9._]*:id\/[\S]+$/;
14
15
 
15
16
  const BOOLEAN_ATTRS = [
16
17
  'checkable', 'checked', 'clickable', 'enabled', 'focusable',
@@ -115,11 +116,11 @@ function getWordMatcherRegex (word) {
115
116
  /**
116
117
  * Add android:id/ to beginning of string if it's not there already
117
118
  *
118
- * @param {string} str
119
+ * @param {string} locator The initial locator
119
120
  * @returns {string} String with `android:id/` prepended (if it wasn't already)
120
121
  */
121
- function prependAndroidId (str) {
122
- return str.startsWith('android:id/') ? str : `android:id/${str}`;
122
+ function formatIdLocator (locator) {
123
+ return ID_LOCATOR_PATTERN.test(locator) ? locator : `android:id/${locator}`;
123
124
  }
124
125
 
125
126
  /**
@@ -157,7 +158,7 @@ function parseAttr (cssAttr) {
157
158
  // Otherwise parse as string
158
159
  let value = cssAttr.value || '';
159
160
  if (attrName === RESOURCE_ID) {
160
- value = prependAndroidId(value);
161
+ value = formatIdLocator(value);
161
162
  }
162
163
  if (value === '') {
163
164
  return `.${methodName}Matches("")`;
@@ -254,7 +255,7 @@ function parseCssRule (cssRule) {
254
255
  uiAutomatorSelector += `.classNameMatches("${cssRule.classNames.join('\\.')}")`;
255
256
  }
256
257
  if (cssRule.id) {
257
- uiAutomatorSelector += `.resourceId("${prependAndroidId(cssRule.id)}")`;
258
+ uiAutomatorSelector += `.resourceId("${formatIdLocator(cssRule.id)}")`;
258
259
  }
259
260
  if (cssRule.attrs) {
260
261
  for (const attr of cssRule.attrs) {
package/lib/driver.js CHANGED
@@ -13,6 +13,7 @@ import desiredCapConstraints from './desired-caps';
13
13
  import { findAPortNotInUse } from 'portscanner';
14
14
  import os from 'os';
15
15
  import path from 'path';
16
+ import { APK_EXTENSION, APKS_EXTENSION } from './extensions';
16
17
 
17
18
 
18
19
  const helpers = Object.assign({}, uiautomator2Helpers, androidHelpers);
@@ -121,8 +122,6 @@ const CHROME_NO_PROXY = [
121
122
  ['POST', new RegExp('^/session/[^/]+/execute$')],
122
123
  ['POST', new RegExp('^/session/[^/]+/execute/sync')],
123
124
  ];
124
- const APK_EXTENSION = '.apk';
125
- const APKS_EXTENSION = '.apks';
126
125
 
127
126
  const MEMOIZED_FUNCTIONS = [
128
127
  'getStatusBarHeight',
@@ -0,0 +1,4 @@
1
+ const APK_EXTENSION = '.apk';
2
+ const APKS_EXTENSION = '.apks';
3
+
4
+ export { APK_EXTENSION, APKS_EXTENSION };
@@ -265,6 +265,8 @@ class UiAutomator2Server {
265
265
  if (_.isBoolean(this.disableSuppressAccessibilityService)) {
266
266
  cmd.push('-e', 'DISABLE_SUPPRESS_ACCESSIBILITY_SERVICES', this.disableSuppressAccessibilityService);
267
267
  }
268
+ // Disable Google analytics to prevent possible fatal exception
269
+ cmd.push('-e', 'disableAnalytics', true);
268
270
  cmd.push(INSTRUMENTATION_TARGET);
269
271
  const instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
270
272
  instrumentationProcess.on('output', (stdout, stderr) => {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "automated testing",
8
8
  "android"
9
9
  ],
10
- "version": "1.62.0",
10
+ "version": "1.65.0",
11
11
  "author": "appium",
12
12
  "license": "Apache-2.0",
13
13
  "repository": {
@@ -41,14 +41,14 @@
41
41
  ],
42
42
  "dependencies": {
43
43
  "@babel/runtime": "^7.0.0",
44
- "appium-adb": "^8.9.0",
44
+ "appium-adb": "^8.10.0",
45
45
  "appium-android-driver": "^4.40.0",
46
46
  "appium-base-driver": "^7.0.0",
47
47
  "appium-chromedriver": "^4.23.1",
48
48
  "appium-support": "^2.49.0",
49
- "appium-uiautomator2-server": "^4.17.4",
49
+ "appium-uiautomator2-server": "^4.20.0",
50
50
  "asyncbox": "^2.3.1",
51
- "axios": "^0.21.0",
51
+ "axios": "^0.x",
52
52
  "bluebird": "^3.5.1",
53
53
  "css-selector-parser": "^1.4.1",
54
54
  "lodash": "^4.17.4",
@@ -90,16 +90,16 @@
90
90
  "eslint-config-appium": "^4.0.1",
91
91
  "gps-demo-app": "^2.1.1",
92
92
  "gulp": "^4.0.0",
93
- "mocha": "~8.2.1",
93
+ "mocha": "^8.2.1",
94
94
  "mocha-junit-reporter": "^2.0.0",
95
95
  "mocha-multi-reporters": "^1.1.7",
96
96
  "pngjs": "^6.0.0",
97
97
  "pre-commit": "^1.2.2",
98
98
  "rimraf": "^3.0.0",
99
- "sinon": "^9.0.0",
99
+ "sinon": "^10.0.0",
100
100
  "unzipper": "^0.10.0",
101
101
  "wd": "^1.10.3",
102
- "xmldom": "^0.4.0",
103
- "xpath": "^0.0.32"
102
+ "xmldom": "^0.x",
103
+ "xpath": "^0.x"
104
104
  }
105
105
  }
package/lib/.DS_Store DELETED
Binary file