appium-android-driver 12.4.9 → 12.4.10
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 +6 -0
- package/build/lib/commands/element.d.ts +90 -66
- package/build/lib/commands/element.d.ts.map +1 -1
- package/build/lib/commands/element.js +74 -53
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/log.d.ts +7 -7
- package/build/lib/commands/log.d.ts.map +1 -1
- package/build/lib/commands/log.js +0 -1
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/media-projection.d.ts +32 -36
- package/build/lib/commands/media-projection.d.ts.map +1 -1
- package/build/lib/commands/media-projection.js +27 -54
- package/build/lib/commands/media-projection.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +47 -19
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +21 -36
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/system-bars.d.ts +27 -21
- package/build/lib/commands/system-bars.d.ts.map +1 -1
- package/build/lib/commands/system-bars.js +23 -40
- package/build/lib/commands/system-bars.js.map +1 -1
- package/lib/commands/element.ts +234 -0
- package/lib/commands/log.ts +9 -9
- package/lib/commands/{media-projection.js → media-projection.ts} +69 -68
- package/lib/commands/{permissions.js → permissions.ts} +58 -50
- package/lib/commands/{system-bars.js → system-bars.ts} +59 -50
- package/package.json +1 -1
- package/lib/commands/element.js +0 -158
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import {errors} from 'appium/driver';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
+
import type {StringRecord} from '@appium/types';
|
|
4
|
+
import type {AndroidDriver} from '../driver';
|
|
5
|
+
import type {StatusBarCommand, WindowProperties} from './types';
|
|
3
6
|
|
|
4
7
|
const WINDOW_TITLE_PATTERN = /^\s+Window\s#\d+\sWindow\{[0-9a-f]+\s\w+\s([\w-]+)\}:$/;
|
|
5
8
|
const FRAME_PATTERN = /\bm?[Ff]rame=\[([0-9.-]+),([0-9.-]+)\]\[([0-9.-]+),([0-9.-]+)\]/;
|
|
@@ -11,7 +14,7 @@ const VIEW_VISIBILITY_PATTERN = /\bmViewVisibility=(0x[0-9a-fA-F]+)/;
|
|
|
11
14
|
const VIEW_VISIBLE = 0x0;
|
|
12
15
|
const STATUS_BAR_WINDOW_NAME_PREFIX = 'StatusBar';
|
|
13
16
|
const NAVIGATION_BAR_WINDOW_NAME_PREFIX = 'NavigationBar';
|
|
14
|
-
const DEFAULT_WINDOW_PROPERTIES = {
|
|
17
|
+
const DEFAULT_WINDOW_PROPERTIES: WindowProperties = {
|
|
15
18
|
visible: false,
|
|
16
19
|
x: 0,
|
|
17
20
|
y: 0,
|
|
@@ -20,48 +23,53 @@ const DEFAULT_WINDOW_PROPERTIES = {
|
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
26
|
+
* Gets the system bars (status bar and navigation bar) properties.
|
|
27
|
+
*
|
|
28
|
+
* @returns Promise that resolves to an object containing statusBar and navigationBar properties.
|
|
29
|
+
* @throws {Error} If system bars details cannot be retrieved or parsed.
|
|
25
30
|
*/
|
|
26
|
-
export async function getSystemBars(
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
export async function getSystemBars(
|
|
32
|
+
this: AndroidDriver,
|
|
33
|
+
): Promise<StringRecord> {
|
|
34
|
+
let stdout: string;
|
|
29
35
|
try {
|
|
30
36
|
stdout = await this.adb.shell(['dumpsys', 'window', 'windows']);
|
|
31
37
|
} catch (e) {
|
|
32
38
|
throw new Error(
|
|
33
|
-
`Cannot retrieve system bars details. Original error: ${
|
|
39
|
+
`Cannot retrieve system bars details. Original error: ${(e as Error).message}`,
|
|
34
40
|
);
|
|
35
41
|
}
|
|
36
42
|
return parseWindows.bind(this)(stdout);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @param
|
|
46
|
+
* Performs a status bar command.
|
|
47
|
+
*
|
|
48
|
+
* @param command The status bar command to perform.
|
|
49
|
+
* @param component The name of the tile component.
|
|
44
50
|
* It is only required for `(add|remove|click)Tile` commands.
|
|
45
51
|
* Example value: `com.package.name/.service.QuickSettingsTileComponent`
|
|
46
|
-
* @returns
|
|
52
|
+
* @returns Promise that resolves to the command output string.
|
|
53
|
+
* @throws {errors.InvalidArgumentError} If the command is unknown.
|
|
47
54
|
*/
|
|
48
|
-
export async function mobilePerformStatusBarCommand(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
export async function mobilePerformStatusBarCommand(
|
|
56
|
+
this: AndroidDriver,
|
|
57
|
+
command: StatusBarCommand,
|
|
58
|
+
component?: string,
|
|
59
|
+
): Promise<string> {
|
|
60
|
+
const toStatusBarCommandCallable = (
|
|
61
|
+
cmd: string,
|
|
62
|
+
argsCallable?: () => string[] | string,
|
|
63
|
+
) => async (): Promise<string> =>
|
|
56
64
|
await this.adb.shell([
|
|
57
65
|
'cmd',
|
|
58
66
|
'statusbar',
|
|
59
67
|
cmd,
|
|
60
68
|
...(argsCallable ? _.castArray(argsCallable()) : []),
|
|
61
69
|
]);
|
|
62
|
-
const tileCommandArgsCallable = () =>
|
|
70
|
+
const tileCommandArgsCallable = () => component as string;
|
|
63
71
|
const statusBarCommands = _.fromPairs(
|
|
64
|
-
|
|
72
|
+
([
|
|
65
73
|
['expandNotifications', ['expand-notifications']],
|
|
66
74
|
['expandSettings', ['expand-settings']],
|
|
67
75
|
['collapse', ['collapse']],
|
|
@@ -69,8 +77,8 @@ export async function mobilePerformStatusBarCommand(command, component) {
|
|
|
69
77
|
['removeTile', ['remove-tile', tileCommandArgsCallable]],
|
|
70
78
|
['clickTile', ['click-tile', tileCommandArgsCallable]],
|
|
71
79
|
['getStatusIcons', ['get-status-icons']],
|
|
72
|
-
]).map(([name, args]) => [name, toStatusBarCommandCallable(args[0], args[1])]),
|
|
73
|
-
)
|
|
80
|
+
] as const).map(([name, args]) => [name, toStatusBarCommandCallable(args[0], args[1])]),
|
|
81
|
+
) as Record<StatusBarCommand, () => Promise<string>>;
|
|
74
82
|
|
|
75
83
|
const action = statusBarCommands[command];
|
|
76
84
|
if (!action) {
|
|
@@ -87,14 +95,17 @@ export async function mobilePerformStatusBarCommand(command, component) {
|
|
|
87
95
|
/**
|
|
88
96
|
* Parses window properties from adb dumpsys output
|
|
89
97
|
*
|
|
90
|
-
* @
|
|
91
|
-
* @param
|
|
92
|
-
* @param {Array<string>} props The list of particular window property lines.
|
|
98
|
+
* @param name The name of the window whose properties are being parsed
|
|
99
|
+
* @param props The list of particular window property lines.
|
|
93
100
|
* Check the corresponding unit tests for more details on the input format.
|
|
94
|
-
* @returns
|
|
101
|
+
* @returns Parsed properties object
|
|
95
102
|
* @throws {Error} If there was an issue while parsing the properties string
|
|
96
103
|
*/
|
|
97
|
-
export function parseWindowProperties(
|
|
104
|
+
export function parseWindowProperties(
|
|
105
|
+
this: AndroidDriver,
|
|
106
|
+
name: string,
|
|
107
|
+
props: string[],
|
|
108
|
+
): WindowProperties {
|
|
98
109
|
const result = _.cloneDeep(DEFAULT_WINDOW_PROPERTIES);
|
|
99
110
|
const propLines = props.join('\n');
|
|
100
111
|
const frameMatch = FRAME_PATTERN.exec(propLines);
|
|
@@ -118,19 +129,18 @@ export function parseWindowProperties(name, props) {
|
|
|
118
129
|
/**
|
|
119
130
|
* Extracts status and navigation bar information from the window manager output.
|
|
120
131
|
*
|
|
121
|
-
* @
|
|
122
|
-
* @param {string} lines Output from dumpsys command.
|
|
132
|
+
* @param lines Output from dumpsys command.
|
|
123
133
|
* Check the corresponding unit tests for more details on the input format.
|
|
124
|
-
* @return
|
|
134
|
+
* @return An object containing two items where keys are statusBar and navigationBar,
|
|
125
135
|
* and values are corresponding WindowProperties objects
|
|
126
136
|
* @throws {Error} If no window properties could be parsed
|
|
127
137
|
*/
|
|
128
|
-
export function parseWindows(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const windows = {};
|
|
133
|
-
let currentWindowName = null;
|
|
138
|
+
export function parseWindows(
|
|
139
|
+
this: AndroidDriver,
|
|
140
|
+
lines: string,
|
|
141
|
+
): SystemBarsResult {
|
|
142
|
+
const windows: StringRecord<string[]> = {};
|
|
143
|
+
let currentWindowName: string | null = null;
|
|
134
144
|
for (const line of lines.split('\n').map(_.trimEnd)) {
|
|
135
145
|
const match = WINDOW_TITLE_PATTERN.exec(line);
|
|
136
146
|
if (match) {
|
|
@@ -152,40 +162,39 @@ export function parseWindows(lines) {
|
|
|
152
162
|
throw new Error('Cannot parse any window information from the dumpsys output');
|
|
153
163
|
}
|
|
154
164
|
|
|
155
|
-
|
|
156
|
-
const result = {};
|
|
165
|
+
const result: SystemBarsResult = {};
|
|
157
166
|
for (const [name, props] of _.toPairs(windows)) {
|
|
158
167
|
if (
|
|
159
168
|
name.startsWith(STATUS_BAR_WINDOW_NAME_PREFIX)
|
|
160
|
-
|| props.some((
|
|
169
|
+
|| props.some((line: string) => STATUS_BAR_TYPE_PATTERN.test(line))
|
|
161
170
|
) {
|
|
162
171
|
result.statusBar = parseWindowProperties.bind(this)(name, props);
|
|
163
172
|
} else if (
|
|
164
173
|
name.startsWith(NAVIGATION_BAR_WINDOW_NAME_PREFIX)
|
|
165
|
-
|| props.some((
|
|
174
|
+
|| props.some((line: string) => NAVIGATION_BAR_TYPE_PATTERN.test(line))
|
|
166
175
|
) {
|
|
167
176
|
result.navigationBar = parseWindowProperties.bind(this)(name, props);
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
|
-
const unmatchedWindows =
|
|
179
|
+
const unmatchedWindows = ([
|
|
171
180
|
['statusBar', STATUS_BAR_WINDOW_NAME_PREFIX],
|
|
172
181
|
['navigationBar', NAVIGATION_BAR_WINDOW_NAME_PREFIX],
|
|
173
|
-
]).filter(([name]) => _.isNil(result[name]));
|
|
182
|
+
] as const).filter(([name]) => _.isNil(result[name as keyof SystemBarsResult]));
|
|
174
183
|
for (const [window, namePrefix] of unmatchedWindows) {
|
|
175
184
|
this.log.info(
|
|
176
185
|
`No windows have been found whose title matches to ` +
|
|
177
186
|
`'${namePrefix}'. Assuming it is invisible. ` +
|
|
178
187
|
`Only the following windows are available: ${_.keys(windows)}`,
|
|
179
188
|
);
|
|
180
|
-
result[window] = _.cloneDeep(DEFAULT_WINDOW_PROPERTIES);
|
|
189
|
+
result[window as keyof SystemBarsResult] = _.cloneDeep(DEFAULT_WINDOW_PROPERTIES);
|
|
181
190
|
}
|
|
182
191
|
return result;
|
|
183
192
|
}
|
|
184
193
|
|
|
185
194
|
// #endregion
|
|
186
195
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
196
|
+
interface SystemBarsResult {
|
|
197
|
+
statusBar?: WindowProperties;
|
|
198
|
+
navigationBar?: WindowProperties;
|
|
199
|
+
}
|
|
200
|
+
|
package/package.json
CHANGED
package/lib/commands/element.js
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
|
|
3
|
-
import {errors} from 'appium/driver';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @this {import('../driver').AndroidDriver}
|
|
7
|
-
* @param {string} attribute
|
|
8
|
-
* @param {string} elementId
|
|
9
|
-
* @returns {Promise<string?>}
|
|
10
|
-
*/
|
|
11
|
-
export async function getAttribute(attribute, elementId) {
|
|
12
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @this {import('../driver').AndroidDriver}
|
|
17
|
-
* @param {string} elementId
|
|
18
|
-
* @returns {Promise<void>}
|
|
19
|
-
*/
|
|
20
|
-
export async function click(elementId) {
|
|
21
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @this {import('../driver').AndroidDriver}
|
|
26
|
-
* @param {string} elementId
|
|
27
|
-
* @returns {Promise<string>}
|
|
28
|
-
*/
|
|
29
|
-
export async function getText(elementId) {
|
|
30
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @this {import('../driver').AndroidDriver}
|
|
35
|
-
* @param {string} elementId
|
|
36
|
-
* @returns {Promise<import('@appium/types').Position>}
|
|
37
|
-
*/
|
|
38
|
-
export async function getLocation(elementId) {
|
|
39
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @this {import('../driver').AndroidDriver}
|
|
44
|
-
* @param {string} elementId
|
|
45
|
-
* @returns {Promise<import('@appium/types').Size>}
|
|
46
|
-
*/
|
|
47
|
-
export async function getSize(elementId) {
|
|
48
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @this {import('../driver').AndroidDriver}
|
|
53
|
-
* @param {string} elementId
|
|
54
|
-
* @returns {Promise<string>}
|
|
55
|
-
*/
|
|
56
|
-
export async function getName(elementId) {
|
|
57
|
-
return /** @type {string} */ (await this.getAttribute('className', elementId));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @this {import('../driver').AndroidDriver}
|
|
62
|
-
* @param {string} elementId
|
|
63
|
-
* @returns {Promise<boolean>}
|
|
64
|
-
*/
|
|
65
|
-
export async function elementDisplayed(elementId) {
|
|
66
|
-
return (await this.getAttribute('displayed', elementId)) === 'true';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @this {import('../driver').AndroidDriver}
|
|
71
|
-
* @param {string} elementId
|
|
72
|
-
* @returns {Promise<boolean>}
|
|
73
|
-
*/
|
|
74
|
-
export async function elementEnabled(elementId) {
|
|
75
|
-
return (await this.getAttribute('enabled', elementId)) === 'true';
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @this {import('../driver').AndroidDriver}
|
|
80
|
-
* @param {string} elementId
|
|
81
|
-
* @returns {Promise<boolean>}
|
|
82
|
-
*/
|
|
83
|
-
export async function elementSelected(elementId) {
|
|
84
|
-
return (await this.getAttribute('selected', elementId)) === 'true';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @this {import('../driver').AndroidDriver}
|
|
89
|
-
* @param {string|string[]} keys
|
|
90
|
-
* @param {string} elementId
|
|
91
|
-
* @param {boolean} [replace=false]
|
|
92
|
-
* @returns {Promise<void>}
|
|
93
|
-
*/
|
|
94
|
-
export async function setElementValue(keys, elementId, replace = false) {
|
|
95
|
-
const text = keys instanceof Array ? keys.join('') : keys;
|
|
96
|
-
return await this.doSetElementValue({
|
|
97
|
-
elementId,
|
|
98
|
-
text: String(text),
|
|
99
|
-
replace,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Reason for isolating doSetElementValue from setElementValue is for reusing setElementValue
|
|
105
|
-
* across android-drivers (like appium-uiautomator2-driver) and to avoid code duplication.
|
|
106
|
-
* Other android-drivers (like appium-uiautomator2-driver) need to override doSetElementValue
|
|
107
|
-
* to facilitate setElementValue.
|
|
108
|
-
*
|
|
109
|
-
* @this {import('../driver').AndroidDriver}
|
|
110
|
-
* @param {import('./types').DoSetElementValueOpts} params
|
|
111
|
-
* @returns {Promise<void>}
|
|
112
|
-
*/
|
|
113
|
-
export async function doSetElementValue(params) {
|
|
114
|
-
throw new errors.NotImplementedError('Not implemented');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* @this {import('../driver').AndroidDriver}
|
|
119
|
-
* @param {string|string[]} keys
|
|
120
|
-
* @param {string} elementId
|
|
121
|
-
* @returns {Promise<void>}
|
|
122
|
-
*/
|
|
123
|
-
export async function setValue(keys, elementId) {
|
|
124
|
-
return await this.setElementValue(keys, elementId, false);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* @this {import('../driver').AndroidDriver}
|
|
129
|
-
* @param {string|string[]} keys
|
|
130
|
-
* @param {string} elementId
|
|
131
|
-
* @returns {Promise<void>}
|
|
132
|
-
*/
|
|
133
|
-
export async function replaceValue(keys, elementId) {
|
|
134
|
-
return await this.setElementValue(keys, elementId, true);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @this {import('../driver').AndroidDriver}
|
|
139
|
-
* @param {string|string[]} keys
|
|
140
|
-
* @param {string} elementId
|
|
141
|
-
* @returns {Promise<void>}
|
|
142
|
-
*/
|
|
143
|
-
export async function setValueImmediate(keys, elementId) {
|
|
144
|
-
const text = Array.isArray(keys) ? keys.join('') : keys;
|
|
145
|
-
// first, make sure we are focused on the element
|
|
146
|
-
await this.click(elementId);
|
|
147
|
-
// then send through adb
|
|
148
|
-
await this.adb.inputText(/** @type {string} */ (text));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @this {import('../driver').AndroidDriver}
|
|
153
|
-
* @param {string} elementId
|
|
154
|
-
* @returns {Promise<import('@appium/types').Position>}
|
|
155
|
-
*/
|
|
156
|
-
export async function getLocationInView(elementId) {
|
|
157
|
-
return await this.getLocation(elementId);
|
|
158
|
-
}
|