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.
- package/README.md +14 -2
- package/build/lib/commands/general.js +17 -2
- package/build/lib/commands/gestures.js +13 -1
- package/build/lib/css-converter.js +6 -5
- package/build/lib/driver.js +5 -5
- package/build/lib/extensions.js +16 -0
- package/build/lib/uiautomator2.js +2 -1
- package/lib/commands/general.js +45 -0
- package/lib/commands/gestures.js +27 -0
- package/lib/css-converter.js +6 -5
- package/lib/driver.js +1 -2
- package/lib/extensions.js +4 -0
- package/lib/uiautomator2.js +2 -0
- package/package.json +8 -8
- package/lib/.DS_Store +0 -0
package/lib/commands/general.js
CHANGED
|
@@ -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;
|
package/lib/commands/gestures.js
CHANGED
|
@@ -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.
|
package/lib/css-converter.js
CHANGED
|
@@ -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}
|
|
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
|
|
122
|
-
return
|
|
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 =
|
|
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("${
|
|
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',
|
package/lib/uiautomator2.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
49
|
+
"appium-uiautomator2-server": "^4.20.0",
|
|
50
50
|
"asyncbox": "^2.3.1",
|
|
51
|
-
"axios": "^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": "
|
|
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": "^
|
|
99
|
+
"sinon": "^10.0.0",
|
|
100
100
|
"unzipper": "^0.10.0",
|
|
101
101
|
"wd": "^1.10.3",
|
|
102
|
-
"xmldom": "^0.
|
|
103
|
-
"xpath": "^0.
|
|
102
|
+
"xmldom": "^0.x",
|
|
103
|
+
"xpath": "^0.x"
|
|
104
104
|
}
|
|
105
105
|
}
|
package/lib/.DS_Store
DELETED
|
Binary file
|