appium-uiautomator2-driver 3.6.1 → 3.7.1
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/CHANGELOG.md +12 -0
- package/README.md +22 -0
- package/build/lib/commands/clipboard.d.ts +30 -0
- package/build/lib/commands/clipboard.d.ts.map +1 -0
- package/build/lib/commands/clipboard.js +48 -0
- package/build/lib/commands/clipboard.js.map +1 -0
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +2 -0
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/misc.d.ts +1 -6
- package/build/lib/commands/misc.d.ts.map +1 -1
- package/build/lib/commands/misc.js +0 -10
- package/build/lib/commands/misc.js.map +1 -1
- package/build/lib/commands/types.d.ts +14 -0
- package/build/lib/commands/types.d.ts.map +1 -1
- package/build/lib/doctor/required-checks.d.ts +2 -2
- package/build/lib/doctor/required-checks.d.ts.map +1 -1
- package/build/lib/driver.d.ts +6 -2
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +5 -1
- package/build/lib/driver.js.map +1 -1
- package/build/lib/uiautomator2.d.ts +3 -0
- package/build/lib/uiautomator2.d.ts.map +1 -1
- package/build/lib/uiautomator2.js +32 -11
- package/build/lib/uiautomator2.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/commands/clipboard.js +55 -0
- package/lib/commands/execute.js +3 -0
- package/lib/commands/misc.js +0 -16
- package/lib/commands/types.ts +15 -0
- package/lib/driver.ts +11 -2
- package/lib/uiautomator2.js +35 -12
- package/npm-shrinkwrap.json +180 -256
- package/package.json +3 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @this {AndroidUiautomator2Driver}
|
|
3
|
+
* @returns {Promise<string>} Base64-encoded content of the clipboard
|
|
4
|
+
* or an empty string if the clipboard is empty.
|
|
5
|
+
*/
|
|
6
|
+
export async function getClipboard() {
|
|
7
|
+
return String(
|
|
8
|
+
(await this.adb.getApiLevel()) < 29
|
|
9
|
+
? await this.uiautomator2.jwproxy.command(
|
|
10
|
+
'/appium/device/get_clipboard',
|
|
11
|
+
'POST',
|
|
12
|
+
{}
|
|
13
|
+
)
|
|
14
|
+
: await this.settingsApp.getClipboard()
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @this {AndroidUiautomator2Driver}
|
|
20
|
+
* @returns {Promise<string>} Base64-encoded content of the clipboard
|
|
21
|
+
* or an empty string if the clipboard is empty.
|
|
22
|
+
*/
|
|
23
|
+
export async function mobileGetClipboard() {
|
|
24
|
+
return await this.getClipboard();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @this {AndroidUiautomator2Driver}
|
|
29
|
+
* @param {string} content Base64-encoded clipboard payload
|
|
30
|
+
* @param {'plaintext'} [contentType='plaintext'] Only a single
|
|
31
|
+
* content type is supported, which is 'plaintext'
|
|
32
|
+
* @param {string} [label] Optinal label to identify the current
|
|
33
|
+
* clipboard payload
|
|
34
|
+
* @returns {Promise<void>}
|
|
35
|
+
*/
|
|
36
|
+
export async function setClipboard(content, contentType, label) {
|
|
37
|
+
await this.uiautomator2.jwproxy.command(
|
|
38
|
+
'/appium/device/set_clipboard',
|
|
39
|
+
'POST',
|
|
40
|
+
{content, contentType, label}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @this {AndroidUiautomator2Driver}
|
|
46
|
+
* @param {import('./types').SetClipboardOpts} opts
|
|
47
|
+
* @returns {Promise<void>}
|
|
48
|
+
*/
|
|
49
|
+
export async function mobileSetClipboard(opts) {
|
|
50
|
+
await this.setClipboard(opts.content, opts.contentType, opts.label);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {import('../driver').AndroidUiautomator2Driver} AndroidUiautomator2Driver
|
|
55
|
+
*/
|
package/lib/commands/execute.js
CHANGED
|
@@ -49,6 +49,9 @@ export function mobileCommandsMapping() {
|
|
|
49
49
|
scheduleAction: 'mobileScheduleAction',
|
|
50
50
|
getActionHistory: 'mobileGetActionHistory',
|
|
51
51
|
unscheduleAction: 'mobileUnscheduleAction',
|
|
52
|
+
|
|
53
|
+
setClipboard: 'mobileSetClipboard',
|
|
54
|
+
getClipboard: 'mobileGetClipboard',
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
|
package/lib/commands/misc.js
CHANGED
|
@@ -40,22 +40,6 @@ export async function setOrientation(orientation) {
|
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* @this {AndroidUiautomator2Driver}
|
|
45
|
-
* @returns {Promise<string>}
|
|
46
|
-
*/
|
|
47
|
-
export async function getClipboard() {
|
|
48
|
-
return String(
|
|
49
|
-
(await this.adb.getApiLevel()) < 29
|
|
50
|
-
? await this.uiautomator2.jwproxy.command(
|
|
51
|
-
'/appium/device/get_clipboard',
|
|
52
|
-
'POST',
|
|
53
|
-
{}
|
|
54
|
-
)
|
|
55
|
-
: await this.settingsApp.getClipboard()
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
43
|
/**
|
|
60
44
|
* @this {AndroidUiautomator2Driver}
|
|
61
45
|
* @returns {Promise<void>}
|
package/lib/commands/types.ts
CHANGED
|
@@ -471,3 +471,18 @@ export interface ActionResult {
|
|
|
471
471
|
export interface ActionArgs {
|
|
472
472
|
name: string;
|
|
473
473
|
}
|
|
474
|
+
|
|
475
|
+
export interface SetClipboardOpts {
|
|
476
|
+
/**
|
|
477
|
+
* Base64-encoded clipboard payload
|
|
478
|
+
*/
|
|
479
|
+
content: string;
|
|
480
|
+
/**
|
|
481
|
+
* Only a single content type is supported, which is 'plaintext'
|
|
482
|
+
*/
|
|
483
|
+
contentType?: 'plaintext';
|
|
484
|
+
/**
|
|
485
|
+
* Optinal label to identify the current clipboard payload
|
|
486
|
+
*/
|
|
487
|
+
label?: string;
|
|
488
|
+
}
|
package/lib/driver.ts
CHANGED
|
@@ -61,6 +61,12 @@ import {
|
|
|
61
61
|
import {
|
|
62
62
|
mobileGetBatteryInfo,
|
|
63
63
|
} from './commands/battery';
|
|
64
|
+
import {
|
|
65
|
+
getClipboard,
|
|
66
|
+
mobileGetClipboard,
|
|
67
|
+
setClipboard,
|
|
68
|
+
mobileSetClipboard,
|
|
69
|
+
} from './commands/clipboard';
|
|
64
70
|
import {
|
|
65
71
|
active,
|
|
66
72
|
getAttribute,
|
|
@@ -111,7 +117,6 @@ import {
|
|
|
111
117
|
getPageSource,
|
|
112
118
|
getOrientation,
|
|
113
119
|
setOrientation,
|
|
114
|
-
getClipboard,
|
|
115
120
|
openNotifications,
|
|
116
121
|
suspendChromedriverProxy,
|
|
117
122
|
mobileGetDeviceInfo,
|
|
@@ -1054,11 +1059,15 @@ class AndroidUiautomator2Driver
|
|
|
1054
1059
|
getPageSource = getPageSource;
|
|
1055
1060
|
getOrientation = getOrientation;
|
|
1056
1061
|
setOrientation = setOrientation;
|
|
1057
|
-
getClipboard = getClipboard;
|
|
1058
1062
|
openNotifications = openNotifications;
|
|
1059
1063
|
suspendChromedriverProxy = suspendChromedriverProxy as any;
|
|
1060
1064
|
mobileGetDeviceInfo = mobileGetDeviceInfo;
|
|
1061
1065
|
|
|
1066
|
+
getClipboard = getClipboard;
|
|
1067
|
+
mobileGetClipboard = mobileGetClipboard;
|
|
1068
|
+
setClipboard = setClipboard;
|
|
1069
|
+
mobileSetClipboard = mobileSetClipboard;
|
|
1070
|
+
|
|
1062
1071
|
setUrl = setUrl;
|
|
1063
1072
|
mobileDeepLink = mobileDeepLink;
|
|
1064
1073
|
back = back;
|
package/lib/uiautomator2.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
TEST_APK_PATH as testApkPath,
|
|
7
7
|
version as serverVersion
|
|
8
8
|
} from 'appium-uiautomator2-server';
|
|
9
|
-
import { util,
|
|
9
|
+
import { util, timing } from 'appium/support';
|
|
10
10
|
import B from 'bluebird';
|
|
11
11
|
import axios from 'axios';
|
|
12
12
|
|
|
@@ -17,7 +17,6 @@ const SERVICES_LAUNCH_TIMEOUT = 30000;
|
|
|
17
17
|
const SERVER_PACKAGE_ID = 'io.appium.uiautomator2.server';
|
|
18
18
|
const SERVER_TEST_PACKAGE_ID = `${SERVER_PACKAGE_ID}.test`;
|
|
19
19
|
const INSTRUMENTATION_TARGET = `${SERVER_TEST_PACKAGE_ID}/androidx.test.runner.AndroidJUnitRunner`;
|
|
20
|
-
const instrumentationLogger = logger.getLogger('Instrumentation');
|
|
21
20
|
|
|
22
21
|
class UIA2Proxy extends JWProxy {
|
|
23
22
|
/** @type {boolean} */
|
|
@@ -50,6 +49,9 @@ class UiAutomator2Server {
|
|
|
50
49
|
/** @type {boolean|undefined} */
|
|
51
50
|
disableSuppressAccessibilityService;
|
|
52
51
|
|
|
52
|
+
/** @type {import('teen_process').SubProcess|null} */
|
|
53
|
+
instrumentationProcess;
|
|
54
|
+
|
|
53
55
|
constructor (log, opts = {}) {
|
|
54
56
|
for (let req of REQD_PARAMS) {
|
|
55
57
|
if (!opts || !util.hasValue(opts[req])) {
|
|
@@ -72,6 +74,7 @@ class UiAutomator2Server {
|
|
|
72
74
|
this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy);
|
|
73
75
|
this.proxyCommand = this.jwproxy.command.bind(this.jwproxy);
|
|
74
76
|
this.jwproxy.didInstrumentationExit = false;
|
|
77
|
+
this.instrumentationProcess = null;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
|
@@ -255,6 +258,9 @@ class UiAutomator2Server {
|
|
|
255
258
|
while (retries < maxRetries) {
|
|
256
259
|
this.log.info(`Waiting up to ${timeout}ms for UiAutomator2 to be online...`);
|
|
257
260
|
this.jwproxy.didInstrumentationExit = false;
|
|
261
|
+
try {
|
|
262
|
+
await this.stopInstrumentationProcess();
|
|
263
|
+
} catch (ign) {}
|
|
258
264
|
await this.startInstrumentationProcess();
|
|
259
265
|
if (!this.jwproxy.didInstrumentationExit) {
|
|
260
266
|
try {
|
|
@@ -312,18 +318,30 @@ class UiAutomator2Server {
|
|
|
312
318
|
// Disable Google analytics to prevent possible fatal exception
|
|
313
319
|
cmd.push('-e', 'disableAnalytics', 'true');
|
|
314
320
|
cmd.push(INSTRUMENTATION_TARGET);
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
instrumentationProcess.on('exit', (code) => {
|
|
323
|
-
instrumentationLogger.debug(`The process has exited with code ${code}`);
|
|
321
|
+
this.instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
|
|
322
|
+
for (const streamName of ['stderr', 'stdout']) {
|
|
323
|
+
this.instrumentationProcess.on(`line-${streamName}`, (line) => this.log.debug(`[Instrumentation] ${line}`));
|
|
324
|
+
}
|
|
325
|
+
this.instrumentationProcess.once('exit', (code, signal) => {
|
|
326
|
+
this.log.debug(`[Instrumentation] The process has exited with code ${code}, signal ${signal}`);
|
|
324
327
|
this.jwproxy.didInstrumentationExit = true;
|
|
325
328
|
});
|
|
326
|
-
await instrumentationProcess.start(0);
|
|
329
|
+
await this.instrumentationProcess.start(0);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async stopInstrumentationProcess () {
|
|
333
|
+
if (!this.instrumentationProcess) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
if (this.instrumentationProcess.isRunning) {
|
|
339
|
+
await this.instrumentationProcess.stop();
|
|
340
|
+
}
|
|
341
|
+
} finally {
|
|
342
|
+
this.instrumentationProcess.removeAllListeners();
|
|
343
|
+
this.instrumentationProcess = null;
|
|
344
|
+
}
|
|
327
345
|
}
|
|
328
346
|
|
|
329
347
|
async deleteSession () {
|
|
@@ -336,6 +354,11 @@ class UiAutomator2Server {
|
|
|
336
354
|
this.log.warn(`Did not get confirmation UiAutomator2 deleteSession worked; ` +
|
|
337
355
|
`Error was: ${err}`);
|
|
338
356
|
}
|
|
357
|
+
try {
|
|
358
|
+
await this.stopInstrumentationProcess();
|
|
359
|
+
} catch (err) {
|
|
360
|
+
this.log.warn(`Could not stop the instrumentation process. Original error: ${err.message}`);
|
|
361
|
+
}
|
|
339
362
|
}
|
|
340
363
|
|
|
341
364
|
async cleanupAutomationLeftovers (strictCleanup = false) {
|