appium-uiautomator2-driver 6.7.5 → 6.7.7
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 +26 -29
- package/build/lib/commands/actions.d.ts.map +1 -1
- package/build/lib/commands/actions.js +19 -27
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts +14 -22
- package/build/lib/commands/alert.d.ts.map +1 -1
- package/build/lib/commands/alert.js +8 -19
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-management.d.ts +7 -10
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +4 -14
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/battery.d.ts +4 -5
- package/build/lib/commands/battery.d.ts.map +1 -1
- package/build/lib/commands/battery.js +4 -9
- package/build/lib/commands/battery.js.map +1 -1
- package/build/lib/commands/clipboard.d.ts +9 -13
- package/build/lib/commands/clipboard.d.ts.map +1 -1
- package/build/lib/commands/clipboard.js +7 -14
- package/build/lib/commands/clipboard.js.map +1 -1
- package/build/lib/commands/element.d.ts +64 -69
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +64 -84
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/find.d.ts +13 -9
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js +4 -16
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/gestures.d.ts +87 -189
- package/build/lib/commands/gestures.d.ts.map +1 -1
- package/build/lib/commands/gestures.js +77 -204
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +30 -41
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +22 -37
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/misc.d.ts +19 -35
- package/build/lib/commands/misc.d.ts.map +1 -1
- package/build/lib/commands/misc.js +15 -30
- package/build/lib/commands/misc.js.map +1 -1
- package/build/lib/commands/navigation.d.ts +11 -16
- package/build/lib/commands/navigation.d.ts.map +1 -1
- package/build/lib/commands/navigation.js +9 -17
- package/build/lib/commands/navigation.js.map +1 -1
- package/build/lib/commands/viewport.d.ts +23 -22
- package/build/lib/commands/viewport.d.ts.map +1 -1
- package/build/lib/commands/viewport.js +17 -24
- package/build/lib/commands/viewport.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/commands/actions.ts +95 -0
- package/lib/commands/alert.ts +46 -0
- package/lib/commands/app-management.ts +25 -0
- package/lib/commands/battery.ts +19 -0
- package/lib/commands/clipboard.ts +29 -0
- package/lib/commands/element.ts +180 -0
- package/lib/commands/find.ts +48 -0
- package/lib/commands/gestures.ts +297 -0
- package/lib/commands/keyboard.ts +102 -0
- package/lib/commands/misc.ts +67 -0
- package/lib/commands/navigation.ts +32 -0
- package/lib/commands/viewport.ts +78 -0
- package/npm-shrinkwrap.json +16 -46
- package/package.json +1 -1
- package/lib/commands/actions.js +0 -107
- package/lib/commands/alert.js +0 -63
- package/lib/commands/app-management.js +0 -32
- package/lib/commands/battery.js +0 -23
- package/lib/commands/clipboard.js +0 -37
- package/lib/commands/element.js +0 -261
- package/lib/commands/find.js +0 -47
- package/lib/commands/gestures.js +0 -446
- package/lib/commands/keyboard.js +0 -108
- package/lib/commands/misc.js +0 -109
- package/lib/commands/navigation.js +0 -33
- package/lib/commands/viewport.js +0 -100
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type {StringRecord} from '@appium/types';
|
|
2
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
3
|
+
import type {ActionResult} from './types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Schedules a recurring action to be performed at specified intervals.
|
|
7
|
+
* @param name - Unique name for the scheduled action.
|
|
8
|
+
* @param steps - Array of action steps to be executed.
|
|
9
|
+
* @param maxPass - Maximum number of successful executions before stopping.
|
|
10
|
+
* @param maxFail - Maximum number of failed executions before stopping.
|
|
11
|
+
* @param times - Total number of times to execute the action.
|
|
12
|
+
* @param intervalMs - Interval in milliseconds between action executions.
|
|
13
|
+
* @param maxHistoryItems - Maximum number of history items to keep.
|
|
14
|
+
* @returns The result of scheduling the action.
|
|
15
|
+
*/
|
|
16
|
+
export async function mobileScheduleAction(
|
|
17
|
+
this: AndroidUiautomator2Driver,
|
|
18
|
+
name: string,
|
|
19
|
+
steps: StringRecord[],
|
|
20
|
+
maxPass?: number,
|
|
21
|
+
maxFail?: number,
|
|
22
|
+
times?: number,
|
|
23
|
+
intervalMs?: number,
|
|
24
|
+
maxHistoryItems?: number,
|
|
25
|
+
): Promise<any> {
|
|
26
|
+
return await this.uiautomator2.jwproxy.command('/appium/schedule_action', 'POST', {
|
|
27
|
+
name,
|
|
28
|
+
steps,
|
|
29
|
+
maxFail,
|
|
30
|
+
maxPass,
|
|
31
|
+
times,
|
|
32
|
+
intervalMs,
|
|
33
|
+
maxHistoryItems,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Gets the execution history for a scheduled action.
|
|
39
|
+
* @param name - Name of the scheduled action.
|
|
40
|
+
* @returns The action execution history containing repeats and step results.
|
|
41
|
+
*/
|
|
42
|
+
export async function mobileGetActionHistory(
|
|
43
|
+
this: AndroidUiautomator2Driver,
|
|
44
|
+
name: string,
|
|
45
|
+
): Promise<ActionResult> {
|
|
46
|
+
return (await this.uiautomator2.jwproxy.command('/appium/action_history', 'POST', {name})) as ActionResult;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Unschedules a previously scheduled action.
|
|
51
|
+
* @param name - Name of the scheduled action to unschedule.
|
|
52
|
+
* @returns The result of unscheduling the action.
|
|
53
|
+
*/
|
|
54
|
+
export async function mobileUnscheduleAction(
|
|
55
|
+
this: AndroidUiautomator2Driver,
|
|
56
|
+
name: string,
|
|
57
|
+
): Promise<any> {
|
|
58
|
+
return await this.uiautomator2.jwproxy.command('/appium/unschedule_action', 'POST', {name});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Performs a sequence of actions.
|
|
63
|
+
* @param actions - Array of action objects to perform. Pointer actions are automatically converted to touch type.
|
|
64
|
+
*/
|
|
65
|
+
export async function performActions(
|
|
66
|
+
this: AndroidUiautomator2Driver,
|
|
67
|
+
actions: StringRecord[],
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
// This is mandatory, since Selenium API uses MOUSE as the default pointer type
|
|
70
|
+
const preprocessedActions = actions.map((action) =>
|
|
71
|
+
Object.assign(
|
|
72
|
+
{},
|
|
73
|
+
action,
|
|
74
|
+
action.type === 'pointer'
|
|
75
|
+
? {
|
|
76
|
+
parameters: {
|
|
77
|
+
pointerType: 'touch',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
: {}
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
|
|
84
|
+
await this.uiautomator2.jwproxy.command('/actions', 'POST', {
|
|
85
|
+
actions: preprocessedActions,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Releases all currently pressed keys and buttons.
|
|
91
|
+
*/
|
|
92
|
+
export async function releaseActions(this: AndroidUiautomator2Driver): Promise<void> {
|
|
93
|
+
this.log.info('On this platform, releaseActions is a no-op');
|
|
94
|
+
}
|
|
95
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gets the text of the currently displayed alert.
|
|
5
|
+
* @returns The alert text as a string.
|
|
6
|
+
*/
|
|
7
|
+
export async function getAlertText(this: AndroidUiautomator2Driver): Promise<string> {
|
|
8
|
+
return String(await this.uiautomator2.jwproxy.command('/alert/text', 'GET', {}));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Accepts the currently displayed alert.
|
|
13
|
+
* @param buttonLabel - Optional label of the button to click. If not provided, the button will be detected automatically.
|
|
14
|
+
*/
|
|
15
|
+
export async function mobileAcceptAlert(
|
|
16
|
+
this: AndroidUiautomator2Driver,
|
|
17
|
+
buttonLabel?: string,
|
|
18
|
+
): Promise<void> {
|
|
19
|
+
await this.uiautomator2.jwproxy.command('/alert/accept', 'POST', {buttonLabel});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accepts the currently displayed alert (W3C endpoint).
|
|
24
|
+
*/
|
|
25
|
+
export async function postAcceptAlert(this: AndroidUiautomator2Driver): Promise<void> {
|
|
26
|
+
await this.mobileAcceptAlert();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Dismisses the currently displayed alert.
|
|
31
|
+
* @param buttonLabel - Optional label of the button to click. If not provided, the button will be detected automatically.
|
|
32
|
+
*/
|
|
33
|
+
export async function mobileDismissAlert(
|
|
34
|
+
this: AndroidUiautomator2Driver,
|
|
35
|
+
buttonLabel?: string,
|
|
36
|
+
): Promise<void> {
|
|
37
|
+
await this.uiautomator2.jwproxy.command('/alert/dismiss', 'POST', {buttonLabel});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Dismisses the currently displayed alert (W3C endpoint).
|
|
42
|
+
*/
|
|
43
|
+
export async function postDismissAlert(this: AndroidUiautomator2Driver): Promise<void> {
|
|
44
|
+
await this.mobileDismissAlert();
|
|
45
|
+
}
|
|
46
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import B from 'bluebird';
|
|
3
|
+
import {errors} from 'appium/driver';
|
|
4
|
+
import {APK_EXTENSION} from '../extensions';
|
|
5
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
6
|
+
import type {InstallOptions} from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Installs multiple APKs with `install-multiple` option.
|
|
10
|
+
* @param apks - Array of APK file paths or URLs to install.
|
|
11
|
+
* @param options - Optional installation options (allowTestPackages, useSdcard, grantPermissions, etc.).
|
|
12
|
+
* @throws {errors.InvalidArgumentError} If the apks array is empty or invalid.
|
|
13
|
+
*/
|
|
14
|
+
export async function mobileInstallMultipleApks(
|
|
15
|
+
this: AndroidUiautomator2Driver,
|
|
16
|
+
apks: string[],
|
|
17
|
+
options?: InstallOptions,
|
|
18
|
+
): Promise<void> {
|
|
19
|
+
if (!_.isArray(apks) || _.isEmpty(apks)) {
|
|
20
|
+
throw new errors.InvalidArgumentError('No apks are given to install');
|
|
21
|
+
}
|
|
22
|
+
const configuredApks = await B.all(apks.map((app) => this.helpers.configureApp(app, [APK_EXTENSION])));
|
|
23
|
+
await this.adb.installMultipleApks(configuredApks, options);
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
2
|
+
import type {BatteryInfo} from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reads the battery information from the device under test.
|
|
6
|
+
* @returns Battery information including level (0.0-1.0) and state (charging, discharging, etc.).
|
|
7
|
+
*/
|
|
8
|
+
export async function mobileGetBatteryInfo(this: AndroidUiautomator2Driver): Promise<BatteryInfo> {
|
|
9
|
+
const result = (await this.uiautomator2.jwproxy.command('/appium/device/battery_info', 'GET', {})) as {
|
|
10
|
+
status: BatteryInfo['state'];
|
|
11
|
+
level: number;
|
|
12
|
+
};
|
|
13
|
+
const batteryInfo = result as any;
|
|
14
|
+
// Give it the same name as in iOS
|
|
15
|
+
batteryInfo.state = result.status;
|
|
16
|
+
delete batteryInfo.status;
|
|
17
|
+
return batteryInfo as BatteryInfo;
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gets the clipboard content as a base64-encoded string.
|
|
5
|
+
* @returns Base64-encoded clipboard content, or an empty string if the clipboard is empty.
|
|
6
|
+
*/
|
|
7
|
+
export async function getClipboard(this: AndroidUiautomator2Driver): Promise<string> {
|
|
8
|
+
return String(
|
|
9
|
+
(await this.adb.getApiLevel()) < 29
|
|
10
|
+
? await this.uiautomator2.jwproxy.command('/appium/device/get_clipboard', 'POST', {})
|
|
11
|
+
: await this.settingsApp.getClipboard()
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sets the clipboard content.
|
|
17
|
+
* @param content - Base64-encoded clipboard payload.
|
|
18
|
+
* @param contentType - Content type. Only 'plaintext' is supported. Defaults to 'plaintext'.
|
|
19
|
+
* @param label - Optional label to identify the current clipboard payload.
|
|
20
|
+
*/
|
|
21
|
+
export async function setClipboard(
|
|
22
|
+
this: AndroidUiautomator2Driver,
|
|
23
|
+
content: string,
|
|
24
|
+
contentType: 'plaintext' = 'plaintext',
|
|
25
|
+
label?: string,
|
|
26
|
+
): Promise<void> {
|
|
27
|
+
await this.uiautomator2.jwproxy.command('/appium/device/set_clipboard', 'POST', {content, contentType, label});
|
|
28
|
+
}
|
|
29
|
+
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {PROTOCOLS} from 'appium/driver';
|
|
2
|
+
import B from 'bluebird';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import type {DoSetElementValueOpts} from 'appium-android-driver';
|
|
5
|
+
import type {Element as AppiumElement, Position, Rect, Size} from '@appium/types';
|
|
6
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
7
|
+
import type {Chromedriver} from 'appium-chromedriver';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Gets the currently active element.
|
|
11
|
+
* @returns The currently active element.
|
|
12
|
+
*/
|
|
13
|
+
export async function active(this: AndroidUiautomator2Driver): Promise<AppiumElement> {
|
|
14
|
+
return (await this.uiautomator2.jwproxy.command('/element/active', 'GET')) as AppiumElement;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Gets an element attribute value.
|
|
19
|
+
* @param attribute - Name of the attribute to retrieve.
|
|
20
|
+
* @param elementId - ID of the element.
|
|
21
|
+
* @returns The attribute value as a string.
|
|
22
|
+
*/
|
|
23
|
+
export async function getAttribute(this: AndroidUiautomator2Driver, attribute: string, elementId: string): Promise<string> {
|
|
24
|
+
return String(await this.uiautomator2.jwproxy.command(`/element/${elementId}/attribute/${attribute}`, 'GET', {}));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns whether the element is displayed.
|
|
29
|
+
* @param elementId - ID of the element.
|
|
30
|
+
* @returns True if the element is displayed, false otherwise.
|
|
31
|
+
*/
|
|
32
|
+
export async function elementDisplayed(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
33
|
+
return toBool(await this.getAttribute('displayed', elementId));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns whether the element is enabled.
|
|
38
|
+
* @param elementId - ID of the element.
|
|
39
|
+
* @returns True if the element is enabled, false otherwise.
|
|
40
|
+
*/
|
|
41
|
+
export async function elementEnabled(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
42
|
+
return toBool(await this.getAttribute('enabled', elementId));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Returns whether the element is selected.
|
|
47
|
+
* @param elementId - ID of the element.
|
|
48
|
+
* @returns True if the element is selected, false otherwise.
|
|
49
|
+
*/
|
|
50
|
+
export async function elementSelected(this: AndroidUiautomator2Driver, elementId: string): Promise<boolean> {
|
|
51
|
+
return toBool(await this.getAttribute('selected', elementId));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Gets the element tag name.
|
|
56
|
+
* @param elementId - ID of the element.
|
|
57
|
+
* @returns The element tag name.
|
|
58
|
+
*/
|
|
59
|
+
export async function getName(this: AndroidUiautomator2Driver, elementId: string): Promise<string> {
|
|
60
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/name`, 'GET', {})) as string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the element location.
|
|
65
|
+
* @param elementId - ID of the element.
|
|
66
|
+
* @returns The element position coordinates (x, y).
|
|
67
|
+
*/
|
|
68
|
+
export async function getLocation(this: AndroidUiautomator2Driver, elementId: string): Promise<Position> {
|
|
69
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/location`, 'GET', {})) as Position;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Gets the element size.
|
|
74
|
+
* @param elementId - ID of the element.
|
|
75
|
+
* @returns The element size (width, height).
|
|
76
|
+
*/
|
|
77
|
+
export async function getSize(this: AndroidUiautomator2Driver, elementId: string): Promise<Size> {
|
|
78
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/size`, 'GET', {})) as Size;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Sets the value of an element using the upstream driver API.
|
|
83
|
+
* @param params - Options containing the element ID and value to set.
|
|
84
|
+
*/
|
|
85
|
+
export async function doSetElementValue(this: AndroidUiautomator2Driver, params: DoSetElementValueOpts): Promise<void> {
|
|
86
|
+
await this.uiautomator2.jwproxy.command(`/element/${params.elementId}/value`, 'POST', params);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Sends text to an element without replacement.
|
|
91
|
+
* @param keys - Text to send, either as a string or array of strings (which will be joined).
|
|
92
|
+
* @param elementId - ID of the element.
|
|
93
|
+
*/
|
|
94
|
+
export async function setValueImmediate(
|
|
95
|
+
this: AndroidUiautomator2Driver,
|
|
96
|
+
keys: string | string[],
|
|
97
|
+
elementId: string,
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
await this.uiautomator2.jwproxy.command(`/element/${elementId}/value`, 'POST', {
|
|
100
|
+
elementId,
|
|
101
|
+
text: _.isArray(keys) ? keys.join('') : keys,
|
|
102
|
+
replace: false,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets the element text.
|
|
108
|
+
* @param elementId - ID of the element.
|
|
109
|
+
* @returns The element text content.
|
|
110
|
+
*/
|
|
111
|
+
export async function getText(this: AndroidUiautomator2Driver, elementId: string): Promise<string> {
|
|
112
|
+
return String(await this.uiautomator2.jwproxy.command(`/element/${elementId}/text`, 'GET', {}));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Clicks the given element.
|
|
117
|
+
* @param element - ID of the element to click.
|
|
118
|
+
*/
|
|
119
|
+
export async function click(this: AndroidUiautomator2Driver, element: string): Promise<void> {
|
|
120
|
+
await this.uiautomator2.jwproxy.command(`/element/${element}/click`, 'POST', {element});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Takes a screenshot of the element.
|
|
125
|
+
* @param element - ID of the element.
|
|
126
|
+
* @returns Base64-encoded PNG screenshot of the element.
|
|
127
|
+
*/
|
|
128
|
+
export async function getElementScreenshot(this: AndroidUiautomator2Driver, element: string): Promise<string> {
|
|
129
|
+
return String(await this.uiautomator2.jwproxy.command(`/element/${element}/screenshot`, 'GET', {}));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Clears the element text.
|
|
134
|
+
* @param elementId - ID of the element to clear.
|
|
135
|
+
*/
|
|
136
|
+
export async function clear(this: AndroidUiautomator2Driver, elementId: string): Promise<void> {
|
|
137
|
+
await this.uiautomator2.jwproxy.command(`/element/${elementId}/clear`, 'POST', {elementId});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Gets the element rectangle.
|
|
142
|
+
* @param elementId - ID of the element.
|
|
143
|
+
* @returns The element rectangle (x, y, width, height).
|
|
144
|
+
*/
|
|
145
|
+
export async function getElementRect(this: AndroidUiautomator2Driver, elementId: string): Promise<Rect> {
|
|
146
|
+
if (!this.isWebContext()) {
|
|
147
|
+
return (await this.uiautomator2.jwproxy.command(`/element/${elementId}/rect`, 'GET')) as Rect;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const chromedriver = this.chromedriver as Chromedriver;
|
|
151
|
+
if (chromedriver.jwproxy.downstreamProtocol === PROTOCOLS.MJSONWP) {
|
|
152
|
+
const [{x, y}, {width, height}] = (await B.all([
|
|
153
|
+
chromedriver.jwproxy.command(`/element/${elementId}/location`, 'GET'),
|
|
154
|
+
chromedriver.jwproxy.command(`/element/${elementId}/size`, 'GET'),
|
|
155
|
+
])) as [Position, Size];
|
|
156
|
+
return {x, y, width, height};
|
|
157
|
+
}
|
|
158
|
+
return (await chromedriver.jwproxy.command(`/element/${elementId}/rect`, 'GET')) as Rect;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Replaces the element text.
|
|
163
|
+
* @param elementId - ID of the element.
|
|
164
|
+
* @param text - Text to replace the current element value with.
|
|
165
|
+
*/
|
|
166
|
+
export async function mobileReplaceElementValue(
|
|
167
|
+
this: AndroidUiautomator2Driver,
|
|
168
|
+
elementId: string,
|
|
169
|
+
text: string,
|
|
170
|
+
): Promise<void> {
|
|
171
|
+
await this.uiautomator2.jwproxy.command(`/element/${elementId}/value`, 'POST', {
|
|
172
|
+
text,
|
|
173
|
+
replace: true,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function toBool(value: any): boolean {
|
|
178
|
+
return _.isString(value) ? value.toLowerCase() === 'true' : !!value;
|
|
179
|
+
}
|
|
180
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {CssConverter} from '../css-converter';
|
|
2
|
+
import type {Element as AppiumElement} from '@appium/types';
|
|
3
|
+
import type {FindElementOpts} from 'appium-android-driver';
|
|
4
|
+
import type {AndroidUiautomator2Driver} from '../driver';
|
|
5
|
+
|
|
6
|
+
// we override the xpath search for this first-visible-child selector, which
|
|
7
|
+
// looks like /*[@firstVisible="true"]
|
|
8
|
+
const MAGIC_FIRST_VIS_CHILD_SEL = /\/\*\[@firstVisible ?= ?('|")true\1\]/;
|
|
9
|
+
|
|
10
|
+
const MAGIC_SCROLLABLE_SEL = /\/\/\*\[@scrollable ?= ?('|")true\1\]/;
|
|
11
|
+
const MAGIC_SCROLLABLE_BY = 'new UiSelector().scrollable(true)';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Overrides helpers.doFindElementOrEls functionality of appium-android-driver.
|
|
15
|
+
* Handles special xpath selectors and CSS selector conversion.
|
|
16
|
+
* @param params - Element finding options including strategy, selector, context, and multiple flag.
|
|
17
|
+
* @returns A single element if `params.multiple` is false, or an array of elements if true.
|
|
18
|
+
*/
|
|
19
|
+
export async function doFindElementOrEls(
|
|
20
|
+
this: AndroidUiautomator2Driver,
|
|
21
|
+
params: FindElementOpts & {multiple: true},
|
|
22
|
+
): Promise<AppiumElement[]>;
|
|
23
|
+
export async function doFindElementOrEls(
|
|
24
|
+
this: AndroidUiautomator2Driver,
|
|
25
|
+
params: FindElementOpts & {multiple: false},
|
|
26
|
+
): Promise<AppiumElement>;
|
|
27
|
+
export async function doFindElementOrEls(
|
|
28
|
+
this: AndroidUiautomator2Driver,
|
|
29
|
+
params: FindElementOpts,
|
|
30
|
+
): Promise<AppiumElement | AppiumElement[]> {
|
|
31
|
+
const uiautomator2 = this.uiautomator2;
|
|
32
|
+
if (params.strategy === 'xpath' && MAGIC_FIRST_VIS_CHILD_SEL.test(params.selector)) {
|
|
33
|
+
const elementId = params.context;
|
|
34
|
+
return (await uiautomator2.jwproxy.command(`/appium/element/${elementId}/first_visible`, 'GET', {})) as AppiumElement;
|
|
35
|
+
}
|
|
36
|
+
if (params.strategy === 'xpath' && MAGIC_SCROLLABLE_SEL.test(params.selector)) {
|
|
37
|
+
params.strategy = '-android uiautomator';
|
|
38
|
+
params.selector = MAGIC_SCROLLABLE_BY;
|
|
39
|
+
}
|
|
40
|
+
if (params.strategy === 'css selector') {
|
|
41
|
+
params.strategy = '-android uiautomator';
|
|
42
|
+
params.selector = new CssConverter(params.selector, this.opts.appPackage).toUiAutomatorSelector();
|
|
43
|
+
}
|
|
44
|
+
return (await uiautomator2.jwproxy.command(`/element${params.multiple ? 's' : ''}`, 'POST', params)) as
|
|
45
|
+
| AppiumElement
|
|
46
|
+
| AppiumElement[];
|
|
47
|
+
}
|
|
48
|
+
|