appium-uiautomator2-driver 1.65.1 → 1.67.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.
@@ -328,7 +328,7 @@ commands.mobileScrollBackTo = async function (opts = {}) {
328
328
 
329
329
  /**
330
330
  * @typedef {Object} ScrollOpts
331
- * @property {?string} element The identifier of an element. It is required this element
331
+ * @property {?string} elementId The identifier of an element. It is required this element
332
332
  * is a valid scrollable container and it was located by `-android uiautomator`
333
333
  * strategy. If this property is not provided then the first currently available scrollable view
334
334
  * is selected for the interaction.
@@ -356,15 +356,16 @@ commands.mobileScrollBackTo = async function (opts = {}) {
356
356
  * @throws {Error} if the scrolling operation cannot be performed
357
357
  */
358
358
  commands.mobileScroll = async function (opts = {}) {
359
- const {element, strategy, selector, maxSwipes} = opts;
359
+ const {
360
+ element, elementId, // `element` is deprecated, use `elementId` instead
361
+ strategy, selector, maxSwipes
362
+ } = opts;
360
363
  if (!strategy || !selector) {
361
364
  throw new errors.InvalidArgumentError(`Both strategy and selector arguments must be provided`);
362
365
  }
363
366
  return await this.uiautomator2.jwproxy.command('/touch/scroll', 'POST', {
364
- params: {
365
- origin: toOrigin(element),
366
- strategy, selector, maxSwipes
367
- },
367
+ origin: toOrigin(elementId || element),
368
+ params: {strategy, selector, maxSwipes},
368
369
  });
369
370
  };
370
371
 
package/lib/driver.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import _ from 'lodash';
2
2
  import { BaseDriver, DeviceSettings } from 'appium-base-driver';
3
- import { UiAutomator2Server, SERVER_PACKAGE_ID, SERVER_TEST_PACKAGE_ID } from './uiautomator2';
3
+ import {
4
+ UiAutomator2Server, SERVER_PACKAGE_ID, SERVER_TEST_PACKAGE_ID
5
+ } from './uiautomator2';
4
6
  import { fs, util, mjpeg } from 'appium-support';
5
7
  import { retryInterval } from 'asyncbox';
6
8
  import B from 'bluebird';
@@ -8,9 +10,11 @@ import logger from './logger';
8
10
  import commands from './commands/index';
9
11
  import { DEFAULT_ADB_PORT } from 'appium-adb';
10
12
  import uiautomator2Helpers from './helpers';
11
- import { androidHelpers, androidCommands, SETTINGS_HELPER_PKG_ID } from 'appium-android-driver';
13
+ import {
14
+ androidHelpers, androidCommands, SETTINGS_HELPER_PKG_ID
15
+ } from 'appium-android-driver';
12
16
  import desiredCapConstraints from './desired-caps';
13
- import { findAPortNotInUse } from 'portscanner';
17
+ import { findAPortNotInUse, checkPortStatus } from 'portscanner';
14
18
  import os from 'os';
15
19
  import path from 'path';
16
20
  import { APK_EXTENSION, APKS_EXTENSION } from './extensions';
@@ -37,6 +41,8 @@ const DEVICE_PORT = 6790;
37
41
  // device.
38
42
  const MJPEG_SERVER_DEVICE_PORT = 7810;
39
43
 
44
+ const LOCALHOST_IP4 = '127.0.0.1';
45
+
40
46
  // NO_PROXY contains the paths that we never want to proxy to UiAutomator2 server.
41
47
  // TODO: Add the list of paths that we never want to proxy to UiAutomator2 server.
42
48
  // TODO: Need to segregate the paths better way using regular expressions wherever applicable.
@@ -274,6 +280,12 @@ class AndroidUiautomator2Driver extends BaseDriver {
274
280
  async allocateSystemPort () {
275
281
  const forwardPort = async (localPort) => {
276
282
  logger.debug(`Forwarding UiAutomator2 Server port ${DEVICE_PORT} to local port ${localPort}`);
283
+ if ((await checkPortStatus(localPort, LOCALHOST_IP4)) === 'open') {
284
+ logger.errorAndThrow(`UiAutomator2 Server cannot start because the local port #${localPort} is busy. ` +
285
+ `Make sure the port you provide via 'systemPort' capability is not occupied. ` +
286
+ `This situation might often be a result of an inaccurate sessions management, e.g. ` +
287
+ `old automation sessions on the same device must always be closed before starting new ones.`);
288
+ }
277
289
  await this.adb.forwardPort(localPort, DEVICE_PORT);
278
290
  };
279
291
 
@@ -459,7 +471,7 @@ class AndroidUiautomator2Driver extends BaseDriver {
459
471
  async initUiAutomator2Server () {
460
472
  // broken out for readability
461
473
  const uiautomator2Opts = {
462
- host: this.opts.remoteAdbHost || this.opts.host || '127.0.0.1',
474
+ host: this.opts.remoteAdbHost || this.opts.host || LOCALHOST_IP4,
463
475
  systemPort: this.opts.systemPort,
464
476
  devicePort: DEVICE_PORT,
465
477
  adb: this.adb,
@@ -2,8 +2,14 @@ import _ from 'lodash';
2
2
  import { JWProxy, errors } from 'appium-base-driver';
3
3
  import { waitForCondition } from 'asyncbox';
4
4
  import log from './logger';
5
- import { SERVER_APK_PATH as apkPath, TEST_APK_PATH as testApkPath, version as serverVersion } from 'appium-uiautomator2-server';
6
- import { util, logger, tempDir, fs, timing } from 'appium-support';
5
+ import {
6
+ SERVER_APK_PATH as apkPath,
7
+ TEST_APK_PATH as testApkPath,
8
+ version as serverVersion
9
+ } from 'appium-uiautomator2-server';
10
+ import {
11
+ util, logger, tempDir, fs, timing
12
+ } from 'appium-support';
7
13
  import B from 'bluebird';
8
14
  import helpers from './helpers';
9
15
  import axios from 'axios';
@@ -302,13 +308,13 @@ class UiAutomator2Server {
302
308
  url: `http://${this.host}:${this.systemPort}/wd/hub/sessions`,
303
309
  timeout: 500,
304
310
  })).data;
305
- const activeSessionIds = value.map((sess) => sess.id);
311
+ const activeSessionIds = value.map(({id}) => id).filter(Boolean);
306
312
  if (activeSessionIds.length) {
307
313
  log.debug(`The following obsolete sessions are still running: ${JSON.stringify(activeSessionIds)}`);
308
- log.debug('Cleaning up the obsolete sessions');
309
- await B.all(activeSessionIds.map((id) =>
310
- axios.delete(`http://${this.host}:${this.systemPort}/wd/hub/session/${id}`)
311
- ));
314
+ log.debug(`Cleaning up ${util.pluralize('obsolete session', activeSessionIds.length, true)}`);
315
+ await B.all(activeSessionIds
316
+ .map((id) => axios.delete(`http://${this.host}:${this.systemPort}/wd/hub/session/${id}`))
317
+ );
312
318
  // Let all sessions to be properly terminated before continuing
313
319
  await B.delay(1000);
314
320
  } else {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "automated testing",
8
8
  "android"
9
9
  ],
10
- "version": "1.65.1",
10
+ "version": "1.67.0",
11
11
  "author": "appium",
12
12
  "license": "Apache-2.0",
13
13
  "repository": {
@@ -42,11 +42,11 @@
42
42
  "dependencies": {
43
43
  "@babel/runtime": "^7.0.0",
44
44
  "appium-adb": "^8.10.0",
45
- "appium-android-driver": "^4.40.0",
45
+ "appium-android-driver": "^4.47.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.20.0",
49
+ "appium-uiautomator2-server": "^4.23.0",
50
50
  "asyncbox": "^2.3.1",
51
51
  "axios": "^0.x",
52
52
  "bluebird": "^3.5.1",
@@ -89,13 +89,13 @@
89
89
  "eslint-config-appium": "^4.0.1",
90
90
  "gps-demo-app": "^2.1.1",
91
91
  "gulp": "^4.0.0",
92
- "mocha": "^8.2.1",
92
+ "mocha": "^9.0.0",
93
93
  "mocha-junit-reporter": "^2.0.0",
94
94
  "mocha-multi-reporters": "^1.1.7",
95
95
  "pngjs": "^6.0.0",
96
96
  "pre-commit": "^1.2.2",
97
97
  "rimraf": "^3.0.0",
98
- "sinon": "^10.0.0",
98
+ "sinon": "^11.0.0",
99
99
  "unzipper": "^0.10.0",
100
100
  "wd": "^1.10.3",
101
101
  "xmldom": "^0.x",