appium-uiautomator2-driver 8.2.0 → 8.2.2
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/build/lib/commands/actions.d.ts.map +1 -1
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts.map +1 -1
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/aut.d.ts.map +1 -1
- package/build/lib/commands/aut.js +1 -2
- package/build/lib/commands/aut.js.map +1 -1
- package/build/lib/commands/battery.d.ts.map +1 -1
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/element.d.ts +1 -1
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/gestures.d.ts.map +1 -1
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +1 -1
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/misc.d.ts.map +1 -1
- package/build/lib/commands/misc.js.map +1 -1
- package/build/lib/commands/screenshot.d.ts +1 -1
- package/build/lib/commands/screenshot.d.ts.map +1 -1
- package/build/lib/commands/screenshot.js +1 -3
- package/build/lib/commands/screenshot.js.map +1 -1
- package/build/lib/commands/viewport.d.ts.map +1 -1
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/lib/commands/windows.d.ts.map +1 -1
- package/build/lib/commands/windows.js.map +1 -1
- package/build/lib/css/index.d.ts.map +1 -1
- package/build/lib/css/index.js.map +1 -1
- package/build/lib/css/ui-automator-emitter.d.ts.map +1 -1
- package/build/lib/css/ui-automator-emitter.js +1 -3
- package/build/lib/css/ui-automator-emitter.js.map +1 -1
- package/build/lib/doctor/optional-checks.d.ts.map +1 -1
- package/build/lib/doctor/optional-checks.js.map +1 -1
- package/build/lib/doctor/required-checks.d.ts.map +1 -1
- package/build/lib/doctor/required-checks.js.map +1 -1
- package/build/lib/driver.d.ts +6 -6
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +9 -20
- package/build/lib/driver.js.map +1 -1
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js.map +1 -1
- package/build/lib/session-claim-handler.d.ts.map +1 -1
- package/build/lib/session-claim-handler.js +1 -1
- package/build/lib/session-claim-handler.js.map +1 -1
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/uiautomator2-server/core.d.ts +1 -1
- package/build/lib/uiautomator2-server/core.d.ts.map +1 -1
- package/build/lib/uiautomator2-server/core.js +8 -22
- package/build/lib/uiautomator2-server/core.js.map +1 -1
- package/build/lib/uiautomator2-server/session.d.ts.map +1 -1
- package/build/lib/uiautomator2-server/session.js +8 -6
- package/build/lib/uiautomator2-server/session.js.map +1 -1
- package/build/lib/utils/app.d.ts.map +1 -1
- package/build/lib/utils/app.js.map +1 -1
- package/build/lib/utils/mjpeg.d.ts.map +1 -1
- package/build/lib/utils/mjpeg.js +1 -1
- package/build/lib/utils/mjpeg.js.map +1 -1
- package/build/lib/utils/object.d.ts.map +1 -1
- package/build/lib/utils/object.js.map +1 -1
- package/lib/commands/actions.ts +4 -12
- package/lib/commands/alert.ts +2 -8
- package/lib/commands/app-management.ts +3 -4
- package/lib/commands/aut.ts +4 -10
- package/lib/commands/battery.ts +1 -5
- package/lib/commands/element.ts +15 -51
- package/lib/commands/find.ts +5 -6
- package/lib/commands/gestures.ts +5 -11
- package/lib/commands/keyboard.ts +10 -19
- package/lib/commands/misc.ts +3 -7
- package/lib/commands/screenshot.ts +8 -15
- package/lib/commands/viewport.ts +3 -10
- package/lib/commands/windows.ts +1 -5
- package/lib/css/index.ts +3 -5
- package/lib/css/ui-automator-emitter.ts +3 -9
- package/lib/doctor/optional-checks.ts +1 -1
- package/lib/doctor/required-checks.ts +1 -1
- package/lib/driver.ts +34 -61
- package/lib/logger.ts +1 -1
- package/lib/session-claim-handler.ts +21 -45
- package/lib/types.ts +2 -2
- package/lib/uiautomator2-server/core.ts +24 -60
- package/lib/uiautomator2-server/session.ts +13 -22
- package/lib/utils/app.ts +1 -0
- package/lib/utils/mjpeg.ts +8 -28
- package/lib/utils/object.ts +1 -4
- package/npm-shrinkwrap.json +74 -95
- package/package.json +21 -35
- package/scripts/reset.mjs +2 -8
package/lib/commands/aut.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {utils} from 'appium-android-driver';
|
|
2
2
|
import {fs} from 'appium/support.js';
|
|
3
3
|
import {SETTINGS_HELPER_ID} from 'io.appium.settings';
|
|
4
|
+
|
|
4
5
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
5
6
|
import {APKS_EXTENSION, APK_EXTENSION} from '../extensions.js';
|
|
6
7
|
import {SERVER_PACKAGE_ID, SERVER_TEST_PACKAGE_ID} from '../uiautomator2-server/index.js';
|
|
@@ -17,10 +18,7 @@ export async function prepareSessionApp(this: AndroidUiautomator2Driver): Promis
|
|
|
17
18
|
// assume is on the device and just launch via the appPackage
|
|
18
19
|
this.log.info(`Starting '${this.opts.appPackage}' directly on the device`);
|
|
19
20
|
} else {
|
|
20
|
-
this.log.info(
|
|
21
|
-
`Neither 'app' nor 'appPackage' was set. Starting UiAutomator2 ` +
|
|
22
|
-
'without the target application',
|
|
23
|
-
);
|
|
21
|
+
this.log.info(`Neither 'app' nor 'appPackage' was set. Starting UiAutomator2 ` + 'without the target application');
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
|
|
@@ -49,9 +47,7 @@ export async function initAUT(this: AndroidUiautomator2Driver): Promise<void> {
|
|
|
49
47
|
try {
|
|
50
48
|
otherApps = utils.parseArray(this.opts.otherApps);
|
|
51
49
|
} catch (e) {
|
|
52
|
-
throw this.log.errorWithException(
|
|
53
|
-
`Could not parse "otherApps" capability: ${(e as Error).message}`,
|
|
54
|
-
);
|
|
50
|
+
throw this.log.errorWithException(`Could not parse "otherApps" capability: ${(e as Error).message}`);
|
|
55
51
|
}
|
|
56
52
|
otherApps = await Promise.all(
|
|
57
53
|
otherApps.map((app) => this.helpers.configureApp(app, [APK_EXTENSION, APKS_EXTENSION])),
|
|
@@ -80,9 +76,7 @@ export async function initAUT(this: AndroidUiautomator2Driver): Promise<void> {
|
|
|
80
76
|
}
|
|
81
77
|
} else {
|
|
82
78
|
if (this.opts.fullReset) {
|
|
83
|
-
throw this.log.errorWithException(
|
|
84
|
-
'Full reset requires an app capability, use fastReset if app is not provided',
|
|
85
|
-
);
|
|
79
|
+
throw this.log.errorWithException('Full reset requires an app capability, use fastReset if app is not provided');
|
|
86
80
|
}
|
|
87
81
|
this.log.debug('No app capability. Assuming it is already on the device');
|
|
88
82
|
if (this.opts.fastReset && this.opts.appPackage) {
|
package/lib/commands/battery.ts
CHANGED
|
@@ -6,11 +6,7 @@ import type {BatteryInfo} from './types.js';
|
|
|
6
6
|
* @returns Battery information including level (0.0-1.0) and state (charging, discharging, etc.).
|
|
7
7
|
*/
|
|
8
8
|
export async function mobileGetBatteryInfo(this: AndroidUiautomator2Driver): Promise<BatteryInfo> {
|
|
9
|
-
const result = (await this.uiautomator2.jwproxy.command(
|
|
10
|
-
'/appium/device/battery_info',
|
|
11
|
-
'GET',
|
|
12
|
-
{},
|
|
13
|
-
)) as {
|
|
9
|
+
const result = (await this.uiautomator2.jwproxy.command('/appium/device/battery_info', 'GET', {})) as {
|
|
14
10
|
status: BatteryInfo['state'];
|
|
15
11
|
level: number;
|
|
16
12
|
};
|
package/lib/commands/element.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {PROTOCOLS} from 'appium/driver.js';
|
|
2
|
-
import type {DoSetElementValueOpts} from 'appium-android-driver';
|
|
3
1
|
import type {Element as AppiumElement, Position, Rect, Size} from '@appium/types';
|
|
4
|
-
import type {
|
|
2
|
+
import type {DoSetElementValueOpts} from 'appium-android-driver';
|
|
5
3
|
import type {Chromedriver} from 'appium-chromedriver';
|
|
4
|
+
import {PROTOCOLS} from 'appium/driver.js';
|
|
5
|
+
|
|
6
|
+
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Gets the currently active element.
|
|
@@ -23,13 +24,7 @@ export async function getAttribute(
|
|
|
23
24
|
attribute: string,
|
|
24
25
|
elementId: string,
|
|
25
26
|
): Promise<string> {
|
|
26
|
-
return String(
|
|
27
|
-
await this.uiautomator2.jwproxy.command(
|
|
28
|
-
`/element/${elementId}/attribute/${attribute}`,
|
|
29
|
-
'GET',
|
|
30
|
-
{},
|
|
31
|
-
),
|
|
32
|
-
);
|
|
27
|
+
return String(await this.uiautomator2.jwproxy.command(`/element/${elementId}/attribute/${attribute}`, 'GET', {}));
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
/**
|
|
@@ -37,10 +32,7 @@ export async function getAttribute(
|
|
|
37
32
|
* @param elementId - ID of the element.
|
|
38
33
|
* @returns True if the element is displayed, false otherwise.
|
|
39
34
|
*/
|
|
40
|
-
export async function elementDisplayed(
|
|
41
|
-
this: AndroidUiautomator2Driver,
|
|
42
|
-
elementId: string,
|
|
43
|
-
): Promise<boolean> {
|
|
35
|
+
export async function elementDisplayed(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
44
36
|
return toBool(await this.getAttribute('displayed', elementId));
|
|
45
37
|
}
|
|
46
38
|
|
|
@@ -49,10 +41,7 @@ export async function elementDisplayed(
|
|
|
49
41
|
* @param elementId - ID of the element.
|
|
50
42
|
* @returns True if the element is enabled, false otherwise.
|
|
51
43
|
*/
|
|
52
|
-
export async function elementEnabled(
|
|
53
|
-
this: AndroidUiautomator2Driver,
|
|
54
|
-
elementId: string,
|
|
55
|
-
): Promise<boolean> {
|
|
44
|
+
export async function elementEnabled(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
56
45
|
return toBool(await this.getAttribute('enabled', elementId));
|
|
57
46
|
}
|
|
58
47
|
|
|
@@ -61,10 +50,7 @@ export async function elementEnabled(
|
|
|
61
50
|
* @param elementId - ID of the element.
|
|
62
51
|
* @returns True if the element is selected, false otherwise.
|
|
63
52
|
*/
|
|
64
|
-
export async function elementSelected(
|
|
65
|
-
this: AndroidUiautomator2Driver,
|
|
66
|
-
elementId: string,
|
|
67
|
-
): Promise<boolean> {
|
|
53
|
+
export async function elementSelected(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
68
54
|
return toBool(await this.getAttribute('selected', elementId));
|
|
69
55
|
}
|
|
70
56
|
|
|
@@ -74,11 +60,7 @@ export async function elementSelected(
|
|
|
74
60
|
* @returns The element tag name.
|
|
75
61
|
*/
|
|
76
62
|
export async function getName(this: AndroidUiautomator2Driver, elementId: string): Promise<string> {
|
|
77
|
-
return (await this.uiautomator2.jwproxy.command(
|
|
78
|
-
`/element/${elementId}/name`,
|
|
79
|
-
'GET',
|
|
80
|
-
{},
|
|
81
|
-
)) as string;
|
|
63
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/name`, 'GET', {})) as string;
|
|
82
64
|
}
|
|
83
65
|
|
|
84
66
|
/**
|
|
@@ -86,15 +68,8 @@ export async function getName(this: AndroidUiautomator2Driver, elementId: string
|
|
|
86
68
|
* @param elementId - ID of the element.
|
|
87
69
|
* @returns The element position coordinates (x, y).
|
|
88
70
|
*/
|
|
89
|
-
export async function getLocation(
|
|
90
|
-
this
|
|
91
|
-
elementId: string,
|
|
92
|
-
): Promise<Position> {
|
|
93
|
-
return (await this.uiautomator2.jwproxy.command(
|
|
94
|
-
`/element/${elementId}/location`,
|
|
95
|
-
'GET',
|
|
96
|
-
{},
|
|
97
|
-
)) as Position;
|
|
71
|
+
export async function getLocation(this: AndroidUiautomator2Driver, elementId: string): Promise<Position> {
|
|
72
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/location`, 'GET', {})) as Position;
|
|
98
73
|
}
|
|
99
74
|
|
|
100
75
|
/**
|
|
@@ -110,10 +85,7 @@ export async function getSize(this: AndroidUiautomator2Driver, elementId: string
|
|
|
110
85
|
* Sets the value of an element using the upstream driver API.
|
|
111
86
|
* @param params - Options containing the element ID and value to set.
|
|
112
87
|
*/
|
|
113
|
-
export async function doSetElementValue(
|
|
114
|
-
this: AndroidUiautomator2Driver,
|
|
115
|
-
params: DoSetElementValueOpts,
|
|
116
|
-
): Promise<void> {
|
|
88
|
+
export async function doSetElementValue(this: AndroidUiautomator2Driver, params: DoSetElementValueOpts): Promise<void> {
|
|
117
89
|
await this.uiautomator2.jwproxy.command(`/element/${params.elementId}/value`, 'POST', params);
|
|
118
90
|
}
|
|
119
91
|
|
|
@@ -156,13 +128,8 @@ export async function click(this: AndroidUiautomator2Driver, element: string): P
|
|
|
156
128
|
* @param element - ID of the element.
|
|
157
129
|
* @returns Base64-encoded PNG screenshot of the element.
|
|
158
130
|
*/
|
|
159
|
-
export async function getElementScreenshot(
|
|
160
|
-
this
|
|
161
|
-
element: string,
|
|
162
|
-
): Promise<string> {
|
|
163
|
-
return String(
|
|
164
|
-
await this.uiautomator2.jwproxy.command(`/element/${element}/screenshot`, 'GET', {}),
|
|
165
|
-
);
|
|
131
|
+
export async function getElementScreenshot(this: AndroidUiautomator2Driver, element: string): Promise<string> {
|
|
132
|
+
return String(await this.uiautomator2.jwproxy.command(`/element/${element}/screenshot`, 'GET', {}));
|
|
166
133
|
}
|
|
167
134
|
|
|
168
135
|
/**
|
|
@@ -178,10 +145,7 @@ export async function clear(this: AndroidUiautomator2Driver, elementId: string):
|
|
|
178
145
|
* @param elementId - ID of the element.
|
|
179
146
|
* @returns The element rectangle (x, y, width, height).
|
|
180
147
|
*/
|
|
181
|
-
export async function getElementRect(
|
|
182
|
-
this: AndroidUiautomator2Driver,
|
|
183
|
-
elementId: string,
|
|
184
|
-
): Promise<Rect> {
|
|
148
|
+
export async function getElementRect(this: AndroidUiautomator2Driver, elementId: string): Promise<Rect> {
|
|
185
149
|
if (!this.isWebContext()) {
|
|
186
150
|
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/rect`, 'GET')) as Rect;
|
|
187
151
|
}
|
package/lib/commands/find.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {cssToNativeLocator} from '../css/index.js';
|
|
2
1
|
import type {Element as AppiumElement} from '@appium/types';
|
|
3
2
|
import type {FindElementOpts} from 'appium-android-driver';
|
|
3
|
+
|
|
4
|
+
import {cssToNativeLocator} from '../css/index.js';
|
|
4
5
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
5
6
|
|
|
6
7
|
// we override the xpath search for this first-visible-child selector, which
|
|
@@ -47,9 +48,7 @@ export async function doFindElementOrEls(
|
|
|
47
48
|
this.opts.appPackage,
|
|
48
49
|
));
|
|
49
50
|
}
|
|
50
|
-
return (await uiautomator2.jwproxy.command(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
params,
|
|
54
|
-
)) as AppiumElement | AppiumElement[];
|
|
51
|
+
return (await uiautomator2.jwproxy.command(`/element${params.multiple ? 's' : ''}`, 'POST', params)) as
|
|
52
|
+
| AppiumElement
|
|
53
|
+
| AppiumElement[];
|
|
55
54
|
}
|
package/lib/commands/gestures.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type {Element as AppiumElement, Position} from '@appium/types';
|
|
1
2
|
import {errors} from 'appium/driver.js';
|
|
2
3
|
import {util} from 'appium/support.js';
|
|
3
|
-
|
|
4
|
-
import type {RelativeRect} from './types.js';
|
|
4
|
+
|
|
5
5
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
6
|
+
import type {RelativeRect} from './types.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Performs a simple click/tap gesture.
|
|
@@ -247,9 +248,7 @@ export async function mobileScrollBackTo(
|
|
|
247
248
|
elementToId?: string,
|
|
248
249
|
): Promise<void> {
|
|
249
250
|
if (!elementId || !elementToId) {
|
|
250
|
-
throw new errors.InvalidArgumentError(
|
|
251
|
-
`Both elementId and elementToId arguments must be provided`,
|
|
252
|
-
);
|
|
251
|
+
throw new errors.InvalidArgumentError(`Both elementId and elementToId arguments must be provided`);
|
|
253
252
|
}
|
|
254
253
|
await this.uiautomator2.jwproxy.command(
|
|
255
254
|
`/appium/element/${util.unwrapElement(elementId)}/scroll_to/${util.unwrapElement(elementToId)}`,
|
|
@@ -290,12 +289,7 @@ function toPoint(x?: number, y?: number): Partial<Position> | undefined {
|
|
|
290
289
|
return Number.isFinite(x) && Number.isFinite(y) ? {x, y} : undefined;
|
|
291
290
|
}
|
|
292
291
|
|
|
293
|
-
function toRect(
|
|
294
|
-
left?: number,
|
|
295
|
-
top?: number,
|
|
296
|
-
width?: number,
|
|
297
|
-
height?: number,
|
|
298
|
-
): RelativeRect | undefined {
|
|
292
|
+
function toRect(left?: number, top?: number, width?: number, height?: number): RelativeRect | undefined {
|
|
299
293
|
return [left, top, width, height].some((v) => !Number.isFinite(v))
|
|
300
294
|
? undefined
|
|
301
295
|
: ({left, top, width, height} as RelativeRect);
|
package/lib/commands/keyboard.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
2
1
|
import type {SendKeysOpts} from 'appium-android-driver';
|
|
3
2
|
|
|
3
|
+
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
4
|
+
|
|
4
5
|
/**
|
|
5
6
|
* Presses a key code with optional metastate and flags.
|
|
6
7
|
* @param keycode - Android key code to press.
|
|
@@ -57,16 +58,12 @@ export async function mobilePressKey(
|
|
|
57
58
|
isLongPress: boolean = false,
|
|
58
59
|
source?: number,
|
|
59
60
|
): Promise<void> {
|
|
60
|
-
await this.uiautomator2.jwproxy.command(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
flags,
|
|
67
|
-
source,
|
|
68
|
-
},
|
|
69
|
-
);
|
|
61
|
+
await this.uiautomator2.jwproxy.command(`/appium/device/${isLongPress ? 'long_' : ''}press_keycode`, 'POST', {
|
|
62
|
+
keycode,
|
|
63
|
+
metastate,
|
|
64
|
+
flags,
|
|
65
|
+
source,
|
|
66
|
+
});
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
/**
|
|
@@ -75,10 +72,7 @@ export async function mobilePressKey(
|
|
|
75
72
|
* @returns True if the input text has been successfully sent to adb.
|
|
76
73
|
* @throws {errors.InvalidArgumentError} If the text argument is not provided.
|
|
77
74
|
*/
|
|
78
|
-
export async function mobileType(
|
|
79
|
-
this: AndroidUiautomator2Driver,
|
|
80
|
-
text: string | number | boolean,
|
|
81
|
-
): Promise<boolean> {
|
|
75
|
+
export async function mobileType(this: AndroidUiautomator2Driver, text: string | number | boolean): Promise<boolean> {
|
|
82
76
|
return await this.settingsApp.typeUnicode(String(text));
|
|
83
77
|
}
|
|
84
78
|
|
|
@@ -86,10 +80,7 @@ export async function mobileType(
|
|
|
86
80
|
* Sends keys to the current element.
|
|
87
81
|
* @param params - Options containing the text to send and optional replace flag.
|
|
88
82
|
*/
|
|
89
|
-
export async function doSendKeys(
|
|
90
|
-
this: AndroidUiautomator2Driver,
|
|
91
|
-
params: SendKeysOpts,
|
|
92
|
-
): Promise<void> {
|
|
83
|
+
export async function doSendKeys(this: AndroidUiautomator2Driver, params: SendKeysOpts): Promise<void> {
|
|
93
84
|
await this.uiautomator2.jwproxy.command('/keys', 'POST', params);
|
|
94
85
|
}
|
|
95
86
|
|
package/lib/commands/misc.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {Orientation, StringRecord} from '@appium/types';
|
|
2
|
+
|
|
2
3
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -21,10 +22,7 @@ export async function getOrientation(this: AndroidUiautomator2Driver): Promise<O
|
|
|
21
22
|
* Sets the device orientation.
|
|
22
23
|
* @param orientation - The desired orientation ('LANDSCAPE' or 'PORTRAIT').
|
|
23
24
|
*/
|
|
24
|
-
export async function setOrientation(
|
|
25
|
-
this: AndroidUiautomator2Driver,
|
|
26
|
-
orientation: Orientation,
|
|
27
|
-
): Promise<void> {
|
|
25
|
+
export async function setOrientation(this: AndroidUiautomator2Driver, orientation: Orientation): Promise<void> {
|
|
28
26
|
const normalizedOrientation = orientation.toUpperCase() as Orientation;
|
|
29
27
|
await this.uiautomator2.jwproxy.command(`/orientation`, 'POST', {
|
|
30
28
|
orientation: normalizedOrientation,
|
|
@@ -63,8 +61,6 @@ export async function mobileGetDeviceInfo(this: AndroidUiautomator2Driver): Prom
|
|
|
63
61
|
/**
|
|
64
62
|
* Resets the accessibility cache on the device.
|
|
65
63
|
*/
|
|
66
|
-
export async function mobileResetAccessibilityCache(
|
|
67
|
-
this: AndroidUiautomator2Driver,
|
|
68
|
-
): Promise<void> {
|
|
64
|
+
export async function mobileResetAccessibilityCache(this: AndroidUiautomator2Driver): Promise<void> {
|
|
69
65
|
await this.uiautomator2.jwproxy.command('/appium/reset_ax_cache', 'POST', {});
|
|
70
66
|
}
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
+
import type {StringRecord} from '@appium/types';
|
|
1
2
|
import {imageUtil} from 'appium/support.js';
|
|
2
|
-
|
|
3
|
+
|
|
3
4
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
5
|
+
import {isEmpty} from '../utils/index.js';
|
|
4
6
|
import type {Screenshot} from './types.js';
|
|
5
|
-
import type {StringRecord} from '@appium/types';
|
|
6
7
|
|
|
7
8
|
// Matches SurfaceFlinger output format:
|
|
8
9
|
// Physical: Display 4619827259835644672 (HWC display 0): port=0 pnpId=GGL displayName="EMU_display_0"
|
|
9
10
|
// Virtual: Display 11529215049243506835 (Virtual display): displayName="Emulator 2D Display" uniqueId="..."
|
|
10
|
-
const DISPLAY_PATTERN =
|
|
11
|
-
/^Display\s+(\d+)\s+\((?:HWC\s+display\s+(\d+)|Virtual\s+display)\):.*?displayName="([^"]*)"/gm;
|
|
11
|
+
const DISPLAY_PATTERN = /^Display\s+(\d+)\s+\((?:HWC\s+display\s+(\d+)|Virtual\s+display)\):.*?displayName="([^"]*)"/gm;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Parses SurfaceFlinger display output to extract display information.
|
|
15
15
|
* @param displaysInfo - The raw output from `adb shell dumpsys SurfaceFlinger --display-id`
|
|
16
16
|
* @returns A record mapping display IDs to their information (without payload)
|
|
17
17
|
*/
|
|
18
|
-
export function parseSurfaceFlingerDisplays(
|
|
19
|
-
displaysInfo: string,
|
|
20
|
-
): Record<string, Partial<Screenshot>> {
|
|
18
|
+
export function parseSurfaceFlingerDisplays(displaysInfo: string): Record<string, Partial<Screenshot>> {
|
|
21
19
|
const infos: Record<string, Partial<Screenshot>> = {};
|
|
22
20
|
const lines = displaysInfo.split('\n');
|
|
23
21
|
|
|
@@ -30,9 +28,7 @@ export function parseSurfaceFlingerDisplays(
|
|
|
30
28
|
|
|
31
29
|
// Determine if default: HWC display 0 is default, or first physical display if no HWC info
|
|
32
30
|
const isDefault =
|
|
33
|
-
hwcId !== undefined
|
|
34
|
-
? hwcId === '0'
|
|
35
|
-
: !line.includes('Virtual') && Object.keys(infos).length === 0;
|
|
31
|
+
hwcId !== undefined ? hwcId === '0' : !line.includes('Virtual') && Object.keys(infos).length === 0;
|
|
36
32
|
|
|
37
33
|
infos[matchedDisplayId] = {
|
|
38
34
|
id: matchedDisplayId,
|
|
@@ -103,8 +99,7 @@ export async function mobileScreenshots(
|
|
|
103
99
|
const toB64Screenshot = async (dispId: string): Promise<string> =>
|
|
104
100
|
(await this.adb.takeScreenshot(dispId)).toString('base64');
|
|
105
101
|
|
|
106
|
-
const displayIdStr: string | null =
|
|
107
|
-
displayId == null || displayId === '' ? null : String(displayId);
|
|
102
|
+
const displayIdStr: string | null = displayId == null || displayId === '' ? null : String(displayId);
|
|
108
103
|
|
|
109
104
|
if (displayIdStr) {
|
|
110
105
|
if (!infos[displayIdStr]) {
|
|
@@ -121,9 +116,7 @@ export async function mobileScreenshots(
|
|
|
121
116
|
};
|
|
122
117
|
}
|
|
123
118
|
|
|
124
|
-
const allInfos = Object.values(infos).filter(
|
|
125
|
-
(info): info is Partial<Screenshot> & {id: string} => !!info?.id,
|
|
126
|
-
);
|
|
119
|
+
const allInfos = Object.values(infos).filter((info): info is Partial<Screenshot> & {id: string} => !!info?.id);
|
|
127
120
|
const screenshots = await Promise.all(allInfos.map((info) => toB64Screenshot(info.id)));
|
|
128
121
|
for (let i = 0; i < allInfos.length; i++) {
|
|
129
122
|
const info = allInfos[i];
|
package/lib/commands/viewport.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {Rect, Size} from '@appium/types';
|
|
2
|
+
|
|
2
3
|
import type {AndroidUiautomator2Driver} from '../driver.js';
|
|
3
4
|
import type {RelativeRect} from './types.js';
|
|
4
5
|
|
|
@@ -7,11 +8,7 @@ import type {RelativeRect} from './types.js';
|
|
|
7
8
|
* @returns The status bar height in pixels.
|
|
8
9
|
*/
|
|
9
10
|
export async function getStatusBarHeight(this: AndroidUiautomator2Driver): Promise<number> {
|
|
10
|
-
const {statusBar} = (await this.uiautomator2.jwproxy.command(
|
|
11
|
-
`/appium/device/system_bars`,
|
|
12
|
-
'GET',
|
|
13
|
-
{},
|
|
14
|
-
)) as {
|
|
11
|
+
const {statusBar} = (await this.uiautomator2.jwproxy.command(`/appium/device/system_bars`, 'GET', {})) as {
|
|
15
12
|
statusBar: number;
|
|
16
13
|
};
|
|
17
14
|
return statusBar;
|
|
@@ -69,11 +66,7 @@ export async function getWindowRect(this: AndroidUiautomator2Driver): Promise<Re
|
|
|
69
66
|
* @returns The display density value.
|
|
70
67
|
*/
|
|
71
68
|
export async function getDisplayDensity(this: AndroidUiautomator2Driver): Promise<number> {
|
|
72
|
-
return (await this.uiautomator2.jwproxy.command(
|
|
73
|
-
'/appium/device/display_density',
|
|
74
|
-
'GET',
|
|
75
|
-
{},
|
|
76
|
-
)) as number;
|
|
69
|
+
return (await this.uiautomator2.jwproxy.command('/appium/device/display_density', 'GET', {})) as number;
|
|
77
70
|
}
|
|
78
71
|
|
|
79
72
|
/**
|
package/lib/commands/windows.ts
CHANGED
|
@@ -21,9 +21,5 @@ export async function mobileListWindows(
|
|
|
21
21
|
* Gets a list of all displays available on the device.
|
|
22
22
|
*/
|
|
23
23
|
export async function mobileListDisplays(this: AndroidUiautomator2Driver): Promise<DisplayInfo[]> {
|
|
24
|
-
return (await this.uiautomator2.jwproxy.command(
|
|
25
|
-
'/appium/list_displays',
|
|
26
|
-
'POST',
|
|
27
|
-
{},
|
|
28
|
-
)) as DisplayInfo[];
|
|
24
|
+
return (await this.uiautomator2.jwproxy.command('/appium/list_displays', 'POST', {})) as DisplayInfo[];
|
|
29
25
|
}
|
package/lib/css/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type {CssTransformer, NativeLocator, StrategyKey} from '@appium/css-locator-to-native';
|
|
1
2
|
import {errors} from 'appium/driver.js';
|
|
3
|
+
|
|
2
4
|
import {memoize} from '../utils/index.js';
|
|
3
5
|
import {UI_AUTOMATOR_EMITTER_KEY, UI_AUTOMATOR_STRATEGY} from './constants.js';
|
|
4
6
|
import {ATTRIBUTE_SCHEMA} from './schema.js';
|
|
5
7
|
import {UiAutomatorEmitter} from './ui-automator-emitter.js';
|
|
6
|
-
import type {CssTransformer, NativeLocator, StrategyKey} from '@appium/css-locator-to-native';
|
|
7
8
|
|
|
8
9
|
export {UI_AUTOMATOR_STRATEGY} from './constants.js';
|
|
9
10
|
|
|
@@ -29,10 +30,7 @@ const getTransformCss = memoize(async function loadTransformCss(): Promise<CssTr
|
|
|
29
30
|
* @param appPackage - Optional application package used to qualify resource ids
|
|
30
31
|
* @returns Native locator strategy name and selector string
|
|
31
32
|
*/
|
|
32
|
-
export async function cssToNativeLocator(
|
|
33
|
-
css: string,
|
|
34
|
-
appPackage?: string | null,
|
|
35
|
-
): Promise<NativeLocator> {
|
|
33
|
+
export async function cssToNativeLocator(css: string, appPackage?: string | null): Promise<NativeLocator> {
|
|
36
34
|
try {
|
|
37
35
|
const transformCss = await getTransformCss();
|
|
38
36
|
return transformCss(css, {appPackage});
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
+
import type {ParsedAttribute, ParsedRule, ParsedSelector, StrategyEmitter} from '@appium/css-locator-to-native';
|
|
2
|
+
|
|
1
3
|
import {escapeRegExp} from '../utils/index.js';
|
|
2
|
-
import type {
|
|
3
|
-
ParsedAttribute,
|
|
4
|
-
ParsedRule,
|
|
5
|
-
ParsedSelector,
|
|
6
|
-
StrategyEmitter,
|
|
7
|
-
} from '@appium/css-locator-to-native';
|
|
8
4
|
|
|
9
5
|
const BOOLEAN_ATTRS = new Set([
|
|
10
6
|
'checkable',
|
|
@@ -136,9 +132,7 @@ export class UiAutomatorEmitter implements StrategyEmitter<UiAutomatorEmitterCon
|
|
|
136
132
|
}
|
|
137
133
|
|
|
138
134
|
function toSnakeCase(str: string): string {
|
|
139
|
-
const tokens = str
|
|
140
|
-
.split('-')
|
|
141
|
-
.map((token) => token.charAt(0).toUpperCase() + token.slice(1).toLowerCase());
|
|
135
|
+
const tokens = str.split('-').map((token) => token.charAt(0).toUpperCase() + token.slice(1).toLowerCase());
|
|
142
136
|
const out = tokens.join('');
|
|
143
137
|
return out.charAt(0).toLowerCase() + out.slice(1);
|
|
144
138
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {doctor} from 'appium-android-driver';
|
|
2
1
|
import type {IDoctorCheck} from '@appium/types';
|
|
2
|
+
import {doctor} from 'appium-android-driver';
|
|
3
3
|
|
|
4
4
|
export const optionalBundletoolCheck: IDoctorCheck = doctor.optionalBundletoolCheck;
|
|
5
5
|
export const optionalGstreamerCheck: IDoctorCheck = doctor.optionalGstreamerCheck;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {doctor} from 'appium-android-driver';
|
|
2
1
|
import type {IDoctorCheck} from '@appium/types';
|
|
2
|
+
import {doctor} from 'appium-android-driver';
|
|
3
3
|
|
|
4
4
|
export const androidHomeCheck: IDoctorCheck = doctor.androidHomeCheck;
|
|
5
5
|
export const javaHomeCheck: IDoctorCheck = doctor.javaHomeCheck;
|
package/lib/driver.ts
CHANGED
|
@@ -12,30 +12,7 @@ import {DEFAULT_ADB_PORT, type ADB} from 'appium-adb';
|
|
|
12
12
|
import {AndroidDriver, utils} from 'appium-android-driver';
|
|
13
13
|
import {BaseDriver, DeviceSettings} from 'appium/driver.js';
|
|
14
14
|
import {util} from 'appium/support.js';
|
|
15
|
-
|
|
16
|
-
import {newMethodMap} from './method-map.js';
|
|
17
|
-
import {assignDefaults, memoize, MJpegStream} from './utils/index.js';
|
|
18
|
-
import type {
|
|
19
|
-
Uiautomator2Settings,
|
|
20
|
-
Uiautomator2DeviceDetails,
|
|
21
|
-
Uiautomator2DriverCaps,
|
|
22
|
-
Uiautomator2DriverOpts,
|
|
23
|
-
Uiautomator2StartSessionOpts,
|
|
24
|
-
W3CUiautomator2DriverCaps,
|
|
25
|
-
} from './types.js';
|
|
26
|
-
import type {UiAutomator2Server} from './uiautomator2-server/index.js';
|
|
27
|
-
import {
|
|
28
|
-
allocateMjpegServerPort,
|
|
29
|
-
allocateSystemPort,
|
|
30
|
-
initServer,
|
|
31
|
-
performExecution,
|
|
32
|
-
performPostExecSetup,
|
|
33
|
-
performPreExecSetup,
|
|
34
|
-
releaseMjpegServerPort,
|
|
35
|
-
releaseSystemPort,
|
|
36
|
-
requireServer,
|
|
37
|
-
startSession,
|
|
38
|
-
} from './uiautomator2-server/index.js';
|
|
15
|
+
|
|
39
16
|
import {
|
|
40
17
|
mobileGetActionHistory,
|
|
41
18
|
mobileScheduleAction,
|
|
@@ -86,14 +63,7 @@ import {
|
|
|
86
63
|
mobileScrollGesture,
|
|
87
64
|
mobileSwipeGesture,
|
|
88
65
|
} from './commands/gestures.js';
|
|
89
|
-
import {
|
|
90
|
-
pressKeyCode,
|
|
91
|
-
longPressKeyCode,
|
|
92
|
-
mobilePressKey,
|
|
93
|
-
mobileType,
|
|
94
|
-
doSendKeys,
|
|
95
|
-
keyevent,
|
|
96
|
-
} from './commands/keyboard.js';
|
|
66
|
+
import {pressKeyCode, longPressKeyCode, mobilePressKey, mobileType, doSendKeys, keyevent} from './commands/keyboard.js';
|
|
97
67
|
import {
|
|
98
68
|
getPageSource,
|
|
99
69
|
getOrientation,
|
|
@@ -103,7 +73,6 @@ import {
|
|
|
103
73
|
mobileGetDeviceInfo,
|
|
104
74
|
mobileResetAccessibilityCache,
|
|
105
75
|
} from './commands/misc.js';
|
|
106
|
-
import {mobileListWindows, mobileListDisplays} from './commands/windows.js';
|
|
107
76
|
import {setUrl, mobileDeepLink, back} from './commands/navigation.js';
|
|
108
77
|
import {
|
|
109
78
|
mobileScreenshots,
|
|
@@ -120,8 +89,33 @@ import {
|
|
|
120
89
|
getWindowSize,
|
|
121
90
|
mobileViewPortRect,
|
|
122
91
|
} from './commands/viewport.js';
|
|
92
|
+
import {mobileListWindows, mobileListDisplays} from './commands/windows.js';
|
|
93
|
+
import UIAUTOMATOR2_CONSTRAINTS, {type Uiautomator2Constraints} from './constraints.js';
|
|
123
94
|
import {executeMethodMap} from './execute-method-map.js';
|
|
95
|
+
import {newMethodMap} from './method-map.js';
|
|
124
96
|
import {sessionClaimHandler} from './session-claim-handler.js';
|
|
97
|
+
import type {
|
|
98
|
+
Uiautomator2Settings,
|
|
99
|
+
Uiautomator2DeviceDetails,
|
|
100
|
+
Uiautomator2DriverCaps,
|
|
101
|
+
Uiautomator2DriverOpts,
|
|
102
|
+
Uiautomator2StartSessionOpts,
|
|
103
|
+
W3CUiautomator2DriverCaps,
|
|
104
|
+
} from './types.js';
|
|
105
|
+
import type {UiAutomator2Server} from './uiautomator2-server/index.js';
|
|
106
|
+
import {
|
|
107
|
+
allocateMjpegServerPort,
|
|
108
|
+
allocateSystemPort,
|
|
109
|
+
initServer,
|
|
110
|
+
performExecution,
|
|
111
|
+
performPostExecSetup,
|
|
112
|
+
performPreExecSetup,
|
|
113
|
+
releaseMjpegServerPort,
|
|
114
|
+
releaseSystemPort,
|
|
115
|
+
requireServer,
|
|
116
|
+
startSession,
|
|
117
|
+
} from './uiautomator2-server/index.js';
|
|
118
|
+
import {assignDefaults, memoize, MJpegStream} from './utils/index.js';
|
|
125
119
|
|
|
126
120
|
// NO_PROXY contains the paths that we never want to proxy to UiAutomator2 server.
|
|
127
121
|
// TODO: Add the list of paths that we never want to proxy to UiAutomator2 server.
|
|
@@ -348,14 +342,7 @@ class AndroidUiautomator2Driver
|
|
|
348
342
|
|
|
349
343
|
super(opts, shouldValidateCaps);
|
|
350
344
|
|
|
351
|
-
this.locatorStrategies = [
|
|
352
|
-
'xpath',
|
|
353
|
-
'id',
|
|
354
|
-
'class name',
|
|
355
|
-
'accessibility id',
|
|
356
|
-
'css selector',
|
|
357
|
-
'-android uiautomator',
|
|
358
|
-
];
|
|
345
|
+
this.locatorStrategies = ['xpath', 'id', 'class name', 'accessibility id', 'css selector', '-android uiautomator'];
|
|
359
346
|
this.desiredCapConstraints = structuredClone(UIAUTOMATOR2_CONSTRAINTS);
|
|
360
347
|
this.jwpProxyActive = false;
|
|
361
348
|
this.jwpProxyAvoid = NO_PROXY;
|
|
@@ -442,9 +429,7 @@ class AndroidUiautomator2Driver
|
|
|
442
429
|
try {
|
|
443
430
|
activity = await this.adb.resolveLaunchableActivity(pkg);
|
|
444
431
|
} catch (e) {
|
|
445
|
-
this.log.warn(
|
|
446
|
-
`Using the default ${pkg} activity ${activity}. Original error: ${(e as Error).message}`,
|
|
447
|
-
);
|
|
432
|
+
this.log.warn(`Using the default ${pkg} activity ${activity}. Original error: ${(e as Error).message}`);
|
|
448
433
|
}
|
|
449
434
|
this.opts.appPackage = this.caps.appPackage = pkg;
|
|
450
435
|
this.opts.appActivity = this.caps.appActivity = activity;
|
|
@@ -496,11 +481,7 @@ class AndroidUiautomator2Driver
|
|
|
496
481
|
override async getSession(): Promise<SingularSessionData<Uiautomator2Constraints>> {
|
|
497
482
|
const sessionData = await BaseDriver.prototype.getSession.call(this);
|
|
498
483
|
this.log.debug('Getting session details from server to mix in');
|
|
499
|
-
const uia2Data = (await this.requireUiautomator2().jwproxy.command(
|
|
500
|
-
'/',
|
|
501
|
-
'GET',
|
|
502
|
-
{},
|
|
503
|
-
)) as StringRecord;
|
|
484
|
+
const uia2Data = (await this.requireUiautomator2().jwproxy.command('/', 'GET', {})) as StringRecord;
|
|
504
485
|
return {...sessionData, ...uia2Data};
|
|
505
486
|
}
|
|
506
487
|
|
|
@@ -560,8 +541,7 @@ class AndroidUiautomator2Driver
|
|
|
560
541
|
if (this.opts.appPackage) {
|
|
561
542
|
if (
|
|
562
543
|
!this.isChromeSession &&
|
|
563
|
-
((!this.opts.dontStopAppOnReset && !this.opts.noReset) ||
|
|
564
|
-
(this.opts.noReset && this.opts.shouldTerminateApp))
|
|
544
|
+
((!this.opts.dontStopAppOnReset && !this.opts.noReset) || (this.opts.noReset && this.opts.shouldTerminateApp))
|
|
565
545
|
) {
|
|
566
546
|
try {
|
|
567
547
|
await this.adb.forceStop(this.opts.appPackage);
|
|
@@ -570,9 +550,7 @@ class AndroidUiautomator2Driver
|
|
|
570
550
|
}
|
|
571
551
|
}
|
|
572
552
|
if (this.opts.fullReset && !this.opts.skipUninstall) {
|
|
573
|
-
this.log.debug(
|
|
574
|
-
`Capability 'fullReset' set to 'true', Uninstalling '${this.opts.appPackage}'`,
|
|
575
|
-
);
|
|
553
|
+
this.log.debug(`Capability 'fullReset' set to 'true', Uninstalling '${this.opts.appPackage}'`);
|
|
576
554
|
try {
|
|
577
555
|
await this.adb.uninstallApk(this.opts.appPackage);
|
|
578
556
|
} catch (err) {
|
|
@@ -647,10 +625,7 @@ class AndroidUiautomator2Driver
|
|
|
647
625
|
this.jwpProxyAvoid = NO_PROXY;
|
|
648
626
|
}
|
|
649
627
|
if (this.opts.nativeWebScreenshot) {
|
|
650
|
-
this.jwpProxyAvoid = [
|
|
651
|
-
...this.jwpProxyAvoid,
|
|
652
|
-
['GET', new RegExp('^/session/[^/]+/screenshot')],
|
|
653
|
-
];
|
|
628
|
+
this.jwpProxyAvoid = [...this.jwpProxyAvoid, ['GET', new RegExp('^/session/[^/]+/screenshot')]];
|
|
654
629
|
}
|
|
655
630
|
|
|
656
631
|
return this.jwpProxyAvoid;
|
|
@@ -672,9 +647,7 @@ class AndroidUiautomator2Driver
|
|
|
672
647
|
}
|
|
673
648
|
|
|
674
649
|
// needed to make the typechecker happy
|
|
675
|
-
override async getAppiumSessionCapabilities(): Promise<
|
|
676
|
-
SessionCapabilities<Uiautomator2Constraints>
|
|
677
|
-
> {
|
|
650
|
+
override async getAppiumSessionCapabilities(): Promise<SessionCapabilities<Uiautomator2Constraints>> {
|
|
678
651
|
return (await super.getAppiumSessionCapabilities()) as SessionCapabilities<Uiautomator2Constraints>;
|
|
679
652
|
}
|
|
680
653
|
|