appium-android-driver 9.15.0 → 10.0.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/CHANGELOG.md +121 -0
- package/build/lib/commands/app-management.d.ts +39 -26
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js +59 -42
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/appearance.d.ts +10 -4
- package/build/lib/commands/appearance.d.ts.map +1 -1
- package/build/lib/commands/appearance.js +10 -7
- package/build/lib/commands/appearance.js.map +1 -1
- package/build/lib/commands/bluetooth.d.ts +2 -2
- package/build/lib/commands/bluetooth.d.ts.map +1 -1
- package/build/lib/commands/bluetooth.js +2 -3
- package/build/lib/commands/bluetooth.js.map +1 -1
- package/build/lib/commands/context/exports.d.ts +2 -2
- package/build/lib/commands/context/exports.d.ts.map +1 -1
- package/build/lib/commands/context/exports.js +3 -3
- package/build/lib/commands/context/exports.js.map +1 -1
- package/build/lib/commands/device/emulator-actions.d.ts +25 -18
- package/build/lib/commands/device/emulator-actions.d.ts.map +1 -1
- package/build/lib/commands/device/emulator-actions.js +38 -40
- package/build/lib/commands/device/emulator-actions.js.map +1 -1
- package/build/lib/commands/device/emulator-console.d.ts +9 -2
- package/build/lib/commands/device/emulator-console.d.ts.map +1 -1
- package/build/lib/commands/device/emulator-console.js +9 -3
- package/build/lib/commands/device/emulator-console.js.map +1 -1
- package/build/lib/commands/deviceidle.d.ts +3 -2
- package/build/lib/commands/deviceidle.d.ts.map +1 -1
- package/build/lib/commands/deviceidle.js +3 -3
- package/build/lib/commands/deviceidle.js.map +1 -1
- package/build/lib/commands/execute.d.ts +6 -15
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js +36 -93
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-actions.d.ts +13 -24
- package/build/lib/commands/file-actions.d.ts.map +1 -1
- package/build/lib/commands/file-actions.js +13 -38
- package/build/lib/commands/file-actions.js.map +1 -1
- package/build/lib/commands/geolocation.d.ts +9 -4
- package/build/lib/commands/geolocation.d.ts.map +1 -1
- package/build/lib/commands/geolocation.js +14 -6
- package/build/lib/commands/geolocation.js.map +1 -1
- package/build/lib/commands/image-injection.d.ts +2 -2
- package/build/lib/commands/image-injection.d.ts.map +1 -1
- package/build/lib/commands/image-injection.js +2 -3
- package/build/lib/commands/image-injection.js.map +1 -1
- package/build/lib/commands/intent.d.ts +70 -8
- package/build/lib/commands/intent.d.ts.map +1 -1
- package/build/lib/commands/intent.js +118 -16
- package/build/lib/commands/intent.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +2 -2
- package/build/lib/commands/keyboard.d.ts.map +1 -1
- package/build/lib/commands/keyboard.js +2 -4
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/lock/exports.d.ts +12 -8
- package/build/lib/commands/lock/exports.d.ts.map +1 -1
- package/build/lib/commands/lock/exports.js +12 -13
- package/build/lib/commands/lock/exports.js.map +1 -1
- package/build/lib/commands/media-projection.d.ts +41 -4
- package/build/lib/commands/media-projection.d.ts.map +1 -1
- package/build/lib/commands/media-projection.js +52 -11
- package/build/lib/commands/media-projection.js.map +1 -1
- package/build/lib/commands/memory.d.ts +4 -2
- package/build/lib/commands/memory.d.ts.map +1 -1
- package/build/lib/commands/memory.js +4 -3
- package/build/lib/commands/memory.js.map +1 -1
- package/build/lib/commands/network.d.ts +10 -4
- package/build/lib/commands/network.d.ts.map +1 -1
- package/build/lib/commands/network.js +17 -14
- package/build/lib/commands/network.js.map +1 -1
- package/build/lib/commands/nfc.d.ts +2 -2
- package/build/lib/commands/nfc.d.ts.map +1 -1
- package/build/lib/commands/nfc.js +2 -3
- package/build/lib/commands/nfc.js.map +1 -1
- package/build/lib/commands/performance.d.ts +3 -2
- package/build/lib/commands/performance.d.ts.map +1 -1
- package/build/lib/commands/performance.js +3 -4
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +23 -5
- package/build/lib/commands/permissions.d.ts.map +1 -1
- package/build/lib/commands/permissions.js +27 -8
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/shell.d.ts +3 -9
- package/build/lib/commands/shell.d.ts.map +1 -1
- package/build/lib/commands/shell.js +3 -10
- package/build/lib/commands/shell.js.map +1 -1
- package/build/lib/commands/streamscreen.d.ts +56 -6
- package/build/lib/commands/streamscreen.d.ts.map +1 -1
- package/build/lib/commands/streamscreen.js +28 -4
- package/build/lib/commands/streamscreen.js.map +1 -1
- package/build/lib/commands/system-bars.d.ts +6 -2
- package/build/lib/commands/system-bars.d.ts.map +1 -1
- package/build/lib/commands/system-bars.js +7 -7
- package/build/lib/commands/system-bars.js.map +1 -1
- package/build/lib/commands/time.d.ts +2 -2
- package/build/lib/commands/time.d.ts.map +1 -1
- package/build/lib/commands/time.js +3 -3
- package/build/lib/commands/time.js.map +1 -1
- package/build/lib/commands/types.d.ts +0 -588
- package/build/lib/commands/types.d.ts.map +1 -1
- package/build/lib/driver.d.ts +364 -12
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +2 -8
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts +361 -0
- package/build/lib/execute-method-map.d.ts.map +1 -0
- package/build/lib/execute-method-map.js +437 -0
- package/build/lib/execute-method-map.js.map +1 -0
- package/lib/commands/app-management.js +68 -42
- package/lib/commands/appearance.js +10 -8
- package/lib/commands/bluetooth.js +2 -3
- package/lib/commands/context/exports.js +3 -3
- package/lib/commands/device/emulator-actions.js +28 -30
- package/lib/commands/device/emulator-console.js +9 -4
- package/lib/commands/deviceidle.js +3 -4
- package/lib/commands/execute.js +42 -124
- package/lib/commands/file-actions.js +13 -38
- package/lib/commands/geolocation.js +14 -6
- package/lib/commands/image-injection.js +2 -3
- package/lib/commands/intent.js +174 -16
- package/lib/commands/keyboard.js +2 -4
- package/lib/commands/lock/exports.js +12 -13
- package/lib/commands/media-projection.js +62 -11
- package/lib/commands/memory.js +4 -4
- package/lib/commands/network.js +14 -10
- package/lib/commands/nfc.js +2 -3
- package/lib/commands/performance.js +3 -4
- package/lib/commands/permissions.js +33 -14
- package/lib/commands/{shell.js → shell.ts} +8 -11
- package/lib/commands/streamscreen.js +39 -15
- package/lib/commands/system-bars.js +7 -9
- package/lib/commands/time.js +3 -3
- package/lib/commands/types.ts +0 -646
- package/lib/driver.ts +4 -16
- package/lib/execute-method-map.ts +464 -0
- package/package.json +2 -2
package/lib/commands/intent.js
CHANGED
|
@@ -75,11 +75,52 @@ export async function startActivity(
|
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* @this {import('../driver').AndroidDriver}
|
|
78
|
-
* @param {
|
|
78
|
+
* @param {boolean} [wait] Set it to `true` if you want to block the method call
|
|
79
|
+
* until the activity manager's process returns the control to the system.
|
|
80
|
+
* false by default.
|
|
81
|
+
* @param {boolean} [stop] Set it to `true` to force stop the target
|
|
82
|
+
* app before starting the activity
|
|
83
|
+
* false by default.
|
|
84
|
+
* @param {string | number} [windowingMode] The windowing mode to launch the activity into.
|
|
85
|
+
* Check
|
|
86
|
+
* https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/WindowConfiguration.java
|
|
87
|
+
* for more details on possible windowing modes (constants starting with
|
|
88
|
+
* `WINDOWING_MODE_`).
|
|
89
|
+
* @param {string | number} [activityType] The activity type to launch the activity as.
|
|
90
|
+
* Check https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/WindowConfiguration.java
|
|
91
|
+
* for more details on possible activity types (constants starting with `ACTIVITY_TYPE_`).
|
|
92
|
+
* @param {number | string} [display] The display identifier to launch the activity into.
|
|
93
|
+
* @param {string} [user]
|
|
94
|
+
* @param {string} [intent]
|
|
95
|
+
* @param {string} [action]
|
|
96
|
+
* @param {string} [pkg]
|
|
97
|
+
* @param {string} [uri]
|
|
98
|
+
* @param {string} [mimeType]
|
|
99
|
+
* @param {string} [identifier]
|
|
100
|
+
* @param {string} [component]
|
|
101
|
+
* @param {string | string[]} [categories]
|
|
102
|
+
* @param {string[][]} [extras]
|
|
103
|
+
* @param {string} [flags]
|
|
79
104
|
* @returns {Promise<string>}
|
|
80
105
|
*/
|
|
81
|
-
export async function mobileStartActivity(
|
|
82
|
-
|
|
106
|
+
export async function mobileStartActivity(
|
|
107
|
+
wait,
|
|
108
|
+
stop,
|
|
109
|
+
windowingMode,
|
|
110
|
+
activityType,
|
|
111
|
+
display,
|
|
112
|
+
user,
|
|
113
|
+
intent,
|
|
114
|
+
action,
|
|
115
|
+
pkg,
|
|
116
|
+
uri,
|
|
117
|
+
mimeType,
|
|
118
|
+
identifier,
|
|
119
|
+
component,
|
|
120
|
+
categories,
|
|
121
|
+
extras,
|
|
122
|
+
flags,
|
|
123
|
+
) {
|
|
83
124
|
const cmd = [
|
|
84
125
|
'am',
|
|
85
126
|
(await this.adb.getApiLevel()) < API_LEVEL_ANDROID_8 ? 'start' : 'start-activity',
|
|
@@ -102,17 +143,55 @@ export async function mobileStartActivity(opts = {}) {
|
|
|
102
143
|
if (!_.isNil(display)) {
|
|
103
144
|
cmd.push('--display', String(display));
|
|
104
145
|
}
|
|
105
|
-
cmd.push(...parseIntentSpec(
|
|
146
|
+
cmd.push(...parseIntentSpec({
|
|
147
|
+
intent,
|
|
148
|
+
action,
|
|
149
|
+
package: pkg,
|
|
150
|
+
uri,
|
|
151
|
+
mimeType,
|
|
152
|
+
identifier,
|
|
153
|
+
component,
|
|
154
|
+
categories,
|
|
155
|
+
extras,
|
|
156
|
+
flags,
|
|
157
|
+
}));
|
|
106
158
|
return await this.adb.shell(cmd);
|
|
107
159
|
}
|
|
108
160
|
|
|
109
161
|
/**
|
|
110
162
|
* @this {import('../driver').AndroidDriver}
|
|
111
|
-
* @param {
|
|
163
|
+
* @param {string | number} [user] The user ID for which the broadcast is sent.
|
|
164
|
+
* The `current` alias assumes the current user ID.
|
|
165
|
+
* `all` by default.
|
|
166
|
+
* @param {string} [receiverPermission] Require receiver to hold the given permission.
|
|
167
|
+
* @param {boolean} [allowBackgroundActivityStarts] Whether the receiver may start activities even if in the background.
|
|
168
|
+
* @param {string} [intent]
|
|
169
|
+
* @param {string} [action]
|
|
170
|
+
* @param {string} [pkg]
|
|
171
|
+
* @param {string} [uri]
|
|
172
|
+
* @param {string} [mimeType]
|
|
173
|
+
* @param {string} [identifier]
|
|
174
|
+
* @param {string} [component]
|
|
175
|
+
* @param {string | string[]} [categories]
|
|
176
|
+
* @param {string[][]} [extras]
|
|
177
|
+
* @param {string} [flags]
|
|
112
178
|
* @returns {Promise<string>}
|
|
113
179
|
*/
|
|
114
|
-
export async function mobileBroadcast(
|
|
115
|
-
|
|
180
|
+
export async function mobileBroadcast(
|
|
181
|
+
receiverPermission,
|
|
182
|
+
allowBackgroundActivityStarts,
|
|
183
|
+
user,
|
|
184
|
+
intent,
|
|
185
|
+
action,
|
|
186
|
+
pkg,
|
|
187
|
+
uri,
|
|
188
|
+
mimeType,
|
|
189
|
+
identifier,
|
|
190
|
+
component,
|
|
191
|
+
categories,
|
|
192
|
+
extras,
|
|
193
|
+
flags,
|
|
194
|
+
) {
|
|
116
195
|
const cmd = ['am', 'broadcast'];
|
|
117
196
|
if (!_.isNil(user)) {
|
|
118
197
|
cmd.push('--user', String(user));
|
|
@@ -123,17 +202,53 @@ export async function mobileBroadcast(opts = {}) {
|
|
|
123
202
|
if (allowBackgroundActivityStarts) {
|
|
124
203
|
cmd.push('--allow-background-activity-starts');
|
|
125
204
|
}
|
|
126
|
-
cmd.push(...parseIntentSpec(
|
|
205
|
+
cmd.push(...parseIntentSpec({
|
|
206
|
+
intent,
|
|
207
|
+
action,
|
|
208
|
+
package: pkg,
|
|
209
|
+
uri,
|
|
210
|
+
mimeType,
|
|
211
|
+
identifier,
|
|
212
|
+
component,
|
|
213
|
+
categories,
|
|
214
|
+
extras,
|
|
215
|
+
flags,
|
|
216
|
+
}));
|
|
127
217
|
return await this.adb.shell(cmd);
|
|
128
218
|
}
|
|
129
219
|
|
|
130
220
|
/**
|
|
131
221
|
* @this {import('../driver').AndroidDriver}
|
|
132
|
-
* @param {
|
|
222
|
+
* @param {boolean} [foreground] Set it to `true` if your service must be started as foreground service.
|
|
223
|
+
* This option is ignored if the API level of the device under test is below
|
|
224
|
+
* 26 (Android 8).
|
|
225
|
+
* @param {string} [user]
|
|
226
|
+
* @param {string} [intent]
|
|
227
|
+
* @param {string} [action]
|
|
228
|
+
* @param {string} [pkg]
|
|
229
|
+
* @param {string} [uri]
|
|
230
|
+
* @param {string} [mimeType]
|
|
231
|
+
* @param {string} [identifier]
|
|
232
|
+
* @param {string} [component]
|
|
233
|
+
* @param {string | string[]} [categories]
|
|
234
|
+
* @param {string[][]} [extras]
|
|
235
|
+
* @param {string} [flags]
|
|
133
236
|
* @returns {Promise<string>}
|
|
134
237
|
*/
|
|
135
|
-
export async function mobileStartService(
|
|
136
|
-
|
|
238
|
+
export async function mobileStartService(
|
|
239
|
+
foreground,
|
|
240
|
+
user,
|
|
241
|
+
intent,
|
|
242
|
+
action,
|
|
243
|
+
pkg,
|
|
244
|
+
uri,
|
|
245
|
+
mimeType,
|
|
246
|
+
identifier,
|
|
247
|
+
component,
|
|
248
|
+
categories,
|
|
249
|
+
extras,
|
|
250
|
+
flags,
|
|
251
|
+
) {
|
|
137
252
|
const cmd = ['am'];
|
|
138
253
|
if ((await this.adb.getApiLevel()) < API_LEVEL_ANDROID_8) {
|
|
139
254
|
cmd.push('startservice');
|
|
@@ -143,17 +258,49 @@ export async function mobileStartService(opts = {}) {
|
|
|
143
258
|
if (!_.isNil(user)) {
|
|
144
259
|
cmd.push('--user', String(user));
|
|
145
260
|
}
|
|
146
|
-
cmd.push(...parseIntentSpec(
|
|
261
|
+
cmd.push(...parseIntentSpec({
|
|
262
|
+
intent,
|
|
263
|
+
action,
|
|
264
|
+
package: pkg,
|
|
265
|
+
uri,
|
|
266
|
+
mimeType,
|
|
267
|
+
identifier,
|
|
268
|
+
component,
|
|
269
|
+
categories,
|
|
270
|
+
extras,
|
|
271
|
+
flags,
|
|
272
|
+
}));
|
|
147
273
|
return await this.adb.shell(cmd);
|
|
148
274
|
}
|
|
149
275
|
|
|
150
276
|
/**
|
|
151
277
|
* @this {import('../driver').AndroidDriver}
|
|
152
|
-
* @param {
|
|
278
|
+
* @param {string} [user]
|
|
279
|
+
* @param {string} [intent]
|
|
280
|
+
* @param {string} [action]
|
|
281
|
+
* @param {string} [pkg]
|
|
282
|
+
* @param {string} [uri]
|
|
283
|
+
* @param {string} [mimeType]
|
|
284
|
+
* @param {string} [identifier]
|
|
285
|
+
* @param {string} [component]
|
|
286
|
+
* @param {string | string[]} [categories]
|
|
287
|
+
* @param {string[][]} [extras]
|
|
288
|
+
* @param {string} [flags]
|
|
153
289
|
* @returns {Promise<string>}
|
|
154
290
|
*/
|
|
155
|
-
export async function mobileStopService(
|
|
156
|
-
|
|
291
|
+
export async function mobileStopService(
|
|
292
|
+
user,
|
|
293
|
+
intent,
|
|
294
|
+
action,
|
|
295
|
+
pkg,
|
|
296
|
+
uri,
|
|
297
|
+
mimeType,
|
|
298
|
+
identifier,
|
|
299
|
+
component,
|
|
300
|
+
categories,
|
|
301
|
+
extras,
|
|
302
|
+
flags,
|
|
303
|
+
) {
|
|
157
304
|
const cmd = [
|
|
158
305
|
'am',
|
|
159
306
|
(await this.adb.getApiLevel()) < API_LEVEL_ANDROID_8 ? 'stopservice' : 'stop-service',
|
|
@@ -161,7 +308,18 @@ export async function mobileStopService(opts = {}) {
|
|
|
161
308
|
if (!_.isNil(user)) {
|
|
162
309
|
cmd.push('--user', String(user));
|
|
163
310
|
}
|
|
164
|
-
cmd.push(...parseIntentSpec(
|
|
311
|
+
cmd.push(...parseIntentSpec({
|
|
312
|
+
intent,
|
|
313
|
+
action,
|
|
314
|
+
package: pkg,
|
|
315
|
+
uri,
|
|
316
|
+
mimeType,
|
|
317
|
+
identifier,
|
|
318
|
+
component,
|
|
319
|
+
categories,
|
|
320
|
+
extras,
|
|
321
|
+
flags,
|
|
322
|
+
}));
|
|
165
323
|
try {
|
|
166
324
|
return await this.adb.shell(cmd);
|
|
167
325
|
} catch (e) {
|
package/lib/commands/keyboard.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import _ from 'lodash';
|
|
3
3
|
import {errors} from 'appium/driver';
|
|
4
|
-
import {requireArgs} from '../utils';
|
|
5
4
|
import {UNICODE_IME, EMPTY_IME} from 'io.appium.settings';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -80,11 +79,10 @@ export async function longPressKeyCode(keycode, metastate) {
|
|
|
80
79
|
|
|
81
80
|
/**
|
|
82
81
|
* @this {import('../driver').AndroidDriver}
|
|
83
|
-
* @param {
|
|
82
|
+
* @param {string | number} action
|
|
84
83
|
* @returns {Promise<void>}
|
|
85
84
|
*/
|
|
86
|
-
export async function mobilePerformEditorAction(
|
|
87
|
-
const {action} = requireArgs('action', opts);
|
|
85
|
+
export async function mobilePerformEditorAction(action) {
|
|
88
86
|
await this.settingsApp.performEditorAction(action);
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -17,16 +17,6 @@ import {
|
|
|
17
17
|
} from './helpers';
|
|
18
18
|
import _ from 'lodash';
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* @this {AndroidDriver}
|
|
22
|
-
* @param {import('../types').LockOpts} opts
|
|
23
|
-
* @returns {Promise<void>}
|
|
24
|
-
*/
|
|
25
|
-
export async function mobileLock(opts = {}) {
|
|
26
|
-
const {seconds} = opts;
|
|
27
|
-
return await this.lock(seconds);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
20
|
/**
|
|
31
21
|
* @this {AndroidDriver}
|
|
32
22
|
* @param {number} [seconds]
|
|
@@ -64,11 +54,20 @@ export async function unlock() {
|
|
|
64
54
|
|
|
65
55
|
/**
|
|
66
56
|
* @this {AndroidDriver}
|
|
67
|
-
* @param {
|
|
57
|
+
* @param {string} [key] The unlock key. The value of this key depends on the actual unlock type and
|
|
58
|
+
* could be a pin/password/pattern value or a biometric finger id.
|
|
59
|
+
* If not provided then the corresponding value from session capabilities is
|
|
60
|
+
* used.
|
|
61
|
+
* @param {import('../types').UnlockType} [type] The unlock type.
|
|
62
|
+
* If not provided then the corresponding value from session capabilities is used.
|
|
63
|
+
* @param {string} [strategy] Setting it to 'uiautomator' will enforce the driver to avoid using special
|
|
64
|
+
* ADB shortcuts in order to speed up the unlock procedure.
|
|
65
|
+
* 'uiautomator' by default.
|
|
66
|
+
* @param {number} [timeoutMs] The maximum time in milliseconds to wait until the screen gets unlocked
|
|
67
|
+
* 2000ms byde fault.
|
|
68
68
|
* @returns {Promise<void>}
|
|
69
69
|
*/
|
|
70
|
-
export async function mobileUnlock(
|
|
71
|
-
const {key, type, strategy, timeoutMs} = opts;
|
|
70
|
+
export async function mobileUnlock(key, type, strategy, timeoutMs) {
|
|
72
71
|
if (!key && !type) {
|
|
73
72
|
await this.unlock();
|
|
74
73
|
} else {
|
|
@@ -10,13 +10,25 @@ const DEFAULT_FILENAME_FORMAT = 'YYYY-MM-DDTHH-mm-ss';
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @this {import('../driver').AndroidDriver}
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {string} [resolution] Maximum supported resolution on-device (Detected automatically by the app
|
|
14
|
+
* itself), which usually equals to Full HD 1920x1080 on most phones however
|
|
15
|
+
* you can change it to following supported resolutions as well: "1920x1080",
|
|
16
|
+
* "1280x720", "720x480", "320x240", "176x144".
|
|
17
|
+
* @param {'high' | 'normal' | 'low'} [priority] Recording thread priority.
|
|
18
|
+
* If you face performance drops during testing with recording enabled, you
|
|
19
|
+
* can reduce recording priority
|
|
20
|
+
* 'high' by default
|
|
21
|
+
* @param {number} [maxDurationSec] Maximum allowed duration is 15 minutes; you can increase it if your test
|
|
22
|
+
* takes longer than that. 900s by default.
|
|
23
|
+
* @param {string} [filename] You can type recording video file name as you want, but recording currently
|
|
24
|
+
* supports only "mp4" format so your filename must end with ".mp4". An
|
|
25
|
+
* invalid file name will fail to start the recording. If not provided then
|
|
26
|
+
* the current timestamp will be used as file name.
|
|
14
27
|
* @returns {Promise<boolean>}
|
|
15
28
|
*/
|
|
16
|
-
export async function mobileStartMediaProjectionRecording(
|
|
29
|
+
export async function mobileStartMediaProjectionRecording(resolution, priority, maxDurationSec, filename) {
|
|
17
30
|
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
18
31
|
|
|
19
|
-
const {resolution, priority, maxDurationSec, filename} = options;
|
|
20
32
|
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
21
33
|
const fname = adjustMediaExtension(filename || moment().format(DEFAULT_FILENAME_FORMAT));
|
|
22
34
|
const didStart = await recorder.start({
|
|
@@ -48,10 +60,34 @@ export async function mobileIsMediaProjectionRecordingRunning() {
|
|
|
48
60
|
|
|
49
61
|
/**
|
|
50
62
|
* @this {import('../driver').AndroidDriver}
|
|
51
|
-
* @param {
|
|
63
|
+
* @param {string} [remotePath] The path to the remote location, where the resulting video should be
|
|
64
|
+
* uploaded. The following protocols are supported: http/https, ftp. Null or
|
|
65
|
+
* empty string value (the default setting) means the content of resulting
|
|
66
|
+
* file should be encoded as Base64 and passed as the endpoont response value.
|
|
67
|
+
* An exception will be thrown if the generated media file is too big to fit
|
|
68
|
+
* into the available process memory.
|
|
69
|
+
* @param {string} [user] The name of the user for the remote authentication.
|
|
70
|
+
* @param {string} [pass] The password for the remote authentication.
|
|
71
|
+
* @param {import('@appium/types').HTTPMethod} [method] The http multipart upload method name.
|
|
72
|
+
* 'PUT' by default.
|
|
73
|
+
* @param {import('@appium/types').StringRecord} [headers] Additional headers mapping for multipart http(s) uploads
|
|
74
|
+
* @param {string} [fileFieldName] The name of the form field, where the file content BLOB should be stored
|
|
75
|
+
* for http(s) uploads. 'file' by default.
|
|
76
|
+
* @param {import('./types').FormFields} [formFields] Additional form fields for multipart http(s) uploads
|
|
77
|
+
* @param {number} [uploadTimeout] The actual media upload request timeout in milliseconds.
|
|
78
|
+
* Defaults to `@appium/support.net.DEFAULT_TIMEOUT_MS`
|
|
52
79
|
* @returns {Promise<string>}
|
|
53
80
|
*/
|
|
54
|
-
export async function mobileStopMediaProjectionRecording(
|
|
81
|
+
export async function mobileStopMediaProjectionRecording(
|
|
82
|
+
remotePath,
|
|
83
|
+
user,
|
|
84
|
+
pass,
|
|
85
|
+
method,
|
|
86
|
+
headers,
|
|
87
|
+
fileFieldName,
|
|
88
|
+
formFields,
|
|
89
|
+
uploadTimeout,
|
|
90
|
+
) {
|
|
55
91
|
await verifyMediaProjectionRecordingIsSupported(this.adb);
|
|
56
92
|
|
|
57
93
|
const recorder = this.settingsApp.makeMediaProjectionRecorder();
|
|
@@ -65,7 +101,6 @@ export async function mobileStopMediaProjectionRecording(options = {}) {
|
|
|
65
101
|
throw new Error(`No recent media projection recording have been found. Did you start any?`);
|
|
66
102
|
}
|
|
67
103
|
|
|
68
|
-
const {remotePath} = options;
|
|
69
104
|
if (_.isEmpty(remotePath)) {
|
|
70
105
|
const {size} = await fs.stat(recentRecordingPath);
|
|
71
106
|
this.log.debug(
|
|
@@ -73,7 +108,15 @@ export async function mobileStopMediaProjectionRecording(options = {}) {
|
|
|
73
108
|
);
|
|
74
109
|
}
|
|
75
110
|
try {
|
|
76
|
-
return await uploadRecordedMedia(recentRecordingPath, remotePath,
|
|
111
|
+
return await uploadRecordedMedia(recentRecordingPath, remotePath, {
|
|
112
|
+
user,
|
|
113
|
+
pass,
|
|
114
|
+
method,
|
|
115
|
+
headers,
|
|
116
|
+
fileFieldName,
|
|
117
|
+
formFields,
|
|
118
|
+
uploadTimeout,
|
|
119
|
+
});
|
|
77
120
|
} finally {
|
|
78
121
|
await fs.rimraf(path.dirname(recentRecordingPath));
|
|
79
122
|
}
|
|
@@ -85,7 +128,7 @@ export async function mobileStopMediaProjectionRecording(options = {}) {
|
|
|
85
128
|
*
|
|
86
129
|
* @param {string} localFile
|
|
87
130
|
* @param {string} [remotePath]
|
|
88
|
-
* @param {
|
|
131
|
+
* @param {UploadOptions} uploadOptions
|
|
89
132
|
* @returns
|
|
90
133
|
*/
|
|
91
134
|
async function uploadRecordedMedia(localFile, remotePath, uploadOptions = {}) {
|
|
@@ -102,9 +145,6 @@ async function uploadRecordedMedia(localFile, remotePath, uploadOptions = {}) {
|
|
|
102
145
|
formFields,
|
|
103
146
|
uploadTimeout: timeout,
|
|
104
147
|
} = uploadOptions;
|
|
105
|
-
/**
|
|
106
|
-
* @type {Omit<import('./types').StopMediaProjectionRecordingOpts, 'uploadTimeout'> & {auth?: {user: string, pass: string}, timeout?: number}}
|
|
107
|
-
*/
|
|
108
148
|
const options = {
|
|
109
149
|
method: method || 'PUT',
|
|
110
150
|
headers,
|
|
@@ -144,6 +184,17 @@ async function verifyMediaProjectionRecordingIsSupported(adb) {
|
|
|
144
184
|
|
|
145
185
|
// #endregion
|
|
146
186
|
|
|
187
|
+
/**
|
|
188
|
+
* @typedef {Object} UploadOptions
|
|
189
|
+
* @property {string} [user]
|
|
190
|
+
* @property {string} [pass]
|
|
191
|
+
* @property {import('@appium/types').HTTPMethod} [method]
|
|
192
|
+
* @property {import('@appium/types').StringRecord} [headers]
|
|
193
|
+
* @property {string} [fileFieldName]
|
|
194
|
+
* @property {import('./types').FormFields} [formFields]
|
|
195
|
+
* @property {number} [uploadTimeout]
|
|
196
|
+
*/
|
|
197
|
+
|
|
147
198
|
/**
|
|
148
199
|
* @typedef {import('appium-adb').ADB} ADB
|
|
149
200
|
*/
|
package/lib/commands/memory.js
CHANGED
|
@@ -6,12 +6,12 @@ import {errors} from 'appium/driver';
|
|
|
6
6
|
* for more details.
|
|
7
7
|
*
|
|
8
8
|
* @this {import('../driver').AndroidDriver}
|
|
9
|
-
* @param {
|
|
9
|
+
* @param {string} pkg The package name to send the `trimMemory` event to
|
|
10
|
+
* @param {'COMPLETE' | 'MODERATE' | 'BACKGROUND' | 'UI_HIDDEN' | 'RUNNING_CRITICAL' | 'RUNNING_LOW' | 'RUNNING_MODERATE'} level The
|
|
11
|
+
* actual memory trim level to be sent
|
|
10
12
|
* @returns {Promise<void>}
|
|
11
13
|
*/
|
|
12
|
-
export async function mobileSendTrimMemory(
|
|
13
|
-
const {pkg, level} = opts;
|
|
14
|
-
|
|
14
|
+
export async function mobileSendTrimMemory(pkg, level) {
|
|
15
15
|
if (!pkg) {
|
|
16
16
|
throw new errors.InvalidArgumentError(`The 'pkg' argument must be provided`);
|
|
17
17
|
}
|
package/lib/commands/network.js
CHANGED
|
@@ -9,7 +9,7 @@ const DATA_MASK = 0b100;
|
|
|
9
9
|
const WIFI_KEY_NAME = 'wifi';
|
|
10
10
|
const DATA_KEY_NAME = 'data';
|
|
11
11
|
const AIRPLANE_MODE_KEY_NAME = 'airplaneMode';
|
|
12
|
-
const SUPPORTED_SERVICE_NAMES = /** @type {
|
|
12
|
+
const SUPPORTED_SERVICE_NAMES = /** @type {import('./types').ServiceType[]} */ ([
|
|
13
13
|
WIFI_KEY_NAME,
|
|
14
14
|
DATA_KEY_NAME,
|
|
15
15
|
AIRPLANE_MODE_KEY_NAME,
|
|
@@ -46,24 +46,28 @@ export async function isWifiOn() {
|
|
|
46
46
|
/**
|
|
47
47
|
* @since Android 12 (only real devices, emulators work in all APIs)
|
|
48
48
|
* @this {import('../driver').AndroidDriver}
|
|
49
|
-
* @param {
|
|
49
|
+
* @param {boolean} [wifi] Either to enable or disable Wi-Fi.
|
|
50
|
+
* An unset value means to not change the state for the given service.
|
|
51
|
+
* @param {boolean} [data] Either to enable or disable mobile data connection.
|
|
52
|
+
* An unset value means to not change the state for the given service.
|
|
53
|
+
* @param {boolean} [airplaneMode] Either to enable to disable the Airplane Mode
|
|
54
|
+
* An unset value means to not change the state for the given service.
|
|
50
55
|
* @returns {Promise<void>}
|
|
51
56
|
*/
|
|
52
|
-
export async function mobileSetConnectivity(
|
|
53
|
-
const {wifi, data, airplaneMode} = opts;
|
|
57
|
+
export async function mobileSetConnectivity(wifi, data, airplaneMode) {
|
|
54
58
|
if (_.every([wifi, data, airplaneMode], _.isUndefined)) {
|
|
55
59
|
throw new errors.InvalidArgumentError(
|
|
56
60
|
`Either one of ${JSON.stringify(SUPPORTED_SERVICE_NAMES)} options must be provided`,
|
|
57
61
|
);
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
const currentState = await this.mobileGetConnectivity(
|
|
61
|
-
|
|
64
|
+
const currentState = await this.mobileGetConnectivity(
|
|
65
|
+
/** @type {import('./types').ServiceType[]} */ ([
|
|
62
66
|
...(_.isUndefined(wifi) ? [] : [WIFI_KEY_NAME]),
|
|
63
67
|
...(_.isUndefined(data) ? [] : [DATA_KEY_NAME]),
|
|
64
68
|
...(_.isUndefined(airplaneMode) ? [] : [AIRPLANE_MODE_KEY_NAME]),
|
|
65
69
|
]),
|
|
66
|
-
|
|
70
|
+
);
|
|
67
71
|
/** @type {(Promise<any>|(() => Promise<any>))[]} */
|
|
68
72
|
const setters = [];
|
|
69
73
|
if (!_.isUndefined(wifi) && currentState.wifi !== Boolean(wifi)) {
|
|
@@ -87,11 +91,11 @@ export async function mobileSetConnectivity(opts = {}) {
|
|
|
87
91
|
|
|
88
92
|
/**
|
|
89
93
|
* @this {import('../driver').AndroidDriver}
|
|
90
|
-
* @param {import('./types').
|
|
94
|
+
* @param {import('./types').ServiceType[] | import('./types').ServiceType} [services] one or more
|
|
95
|
+
* services to get the connectivity for.
|
|
91
96
|
* @returns {Promise<import('./types').GetConnectivityResult>}
|
|
92
97
|
*/
|
|
93
|
-
export async function mobileGetConnectivity(
|
|
94
|
-
let {services = SUPPORTED_SERVICE_NAMES} = opts;
|
|
98
|
+
export async function mobileGetConnectivity(services = SUPPORTED_SERVICE_NAMES) {
|
|
95
99
|
const svcs = _.castArray(services);
|
|
96
100
|
const unsupportedServices = _.difference(services, SUPPORTED_SERVICE_NAMES);
|
|
97
101
|
if (!_.isEmpty(unsupportedServices)) {
|
package/lib/commands/nfc.js
CHANGED
|
@@ -10,13 +10,12 @@ const SUPPORTED_ACTIONS = /** @type {const} */ ({
|
|
|
10
10
|
* Performs the requested action on the default NFC adapter
|
|
11
11
|
*
|
|
12
12
|
* @this {AndroidDriver}
|
|
13
|
-
* @param {
|
|
13
|
+
* @param { 'enable' | 'disable'} action
|
|
14
14
|
* @returns {Promise<void>}
|
|
15
15
|
* @throws {Error} if the device under test has no default NFC adapter
|
|
16
16
|
* or there was a failure while performing the action.
|
|
17
17
|
*/
|
|
18
|
-
export async function mobileNfc(
|
|
19
|
-
const {action} = opts;
|
|
18
|
+
export async function mobileNfc(action) {
|
|
20
19
|
switch (action) {
|
|
21
20
|
case SUPPORTED_ACTIONS.ENABLE:
|
|
22
21
|
await this.adb.setNfcOn(true);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import {retryInterval} from 'asyncbox';
|
|
3
3
|
import _ from 'lodash';
|
|
4
|
-
import {requireArgs} from '../utils';
|
|
5
4
|
|
|
6
5
|
export const NETWORK_KEYS = [
|
|
7
6
|
[
|
|
@@ -121,11 +120,11 @@ export async function getPerformanceData(packageName, dataType, retries = 2) {
|
|
|
121
120
|
* - cpuinfo: [[user, kernel], [0.9, 1.3]]
|
|
122
121
|
*
|
|
123
122
|
* @this {AndroidDriver}
|
|
124
|
-
* @param {
|
|
123
|
+
* @param {string} packageName The name of the package identifier to fetch the data for
|
|
124
|
+
* @param {import('./types').PerformanceDataType} dataType One of supported subsystem to fetch the data for.
|
|
125
125
|
* @returns {Promise<any[][]>}
|
|
126
126
|
*/
|
|
127
|
-
export async function mobileGetPerformanceData(
|
|
128
|
-
const {packageName, dataType} = requireArgs(['packageName', 'dataType'], opts);
|
|
127
|
+
export async function mobileGetPerformanceData(packageName, dataType) {
|
|
129
128
|
return await this.getPerformanceData(packageName, dataType);
|
|
130
129
|
}
|
|
131
130
|
|
|
@@ -26,18 +26,35 @@ const PERMISSIONS_TYPE = Object.freeze({
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* @this {import('../driver').AndroidDriver}
|
|
29
|
-
* @param {
|
|
30
|
-
*
|
|
29
|
+
* @param {string | string[]} permissions If `target` is set to 'pm':
|
|
30
|
+
* The full name of the permission to be changed
|
|
31
|
+
* or a list of permissions. Check https://developer.android.com/reference/android/Manifest.permission
|
|
32
|
+
* to get the full list of standard Android permssion names. Mandatory argument.
|
|
33
|
+
* If 'all' magic string is passed then the chosen action is going to be applied to all
|
|
34
|
+
* permisisons requested/granted by 'appPackage'.
|
|
35
|
+
* If `target` is set to 'appops':
|
|
36
|
+
* The full name of the appops permission to be changed
|
|
37
|
+
* or a list of permissions. Check AppOpsManager.java sources to get the full list of
|
|
38
|
+
* available appops permission names. Mandatory argument.
|
|
39
|
+
* Examples: 'ACTIVITY_RECOGNITION', 'SMS_FINANCIAL_TRANSACTIONS', 'READ_SMS', 'ACCESS_NOTIFICATIONS'.
|
|
40
|
+
* The 'all' magic string is unsupported.
|
|
41
|
+
* @param {string} [appPackage] The application package to set change permissions on. Defaults to the
|
|
42
|
+
* package name under test
|
|
43
|
+
* @param {string} [action] One of `PM_ACTION` values if `target` is set to 'pm', otherwise
|
|
44
|
+
* one of `APPOPS_ACTION` values
|
|
45
|
+
* @param {'pm' | 'appops'} [target='pm'] Either 'pm' or 'appops'. The 'appops' one requires
|
|
46
|
+
* 'adb_shell' server security option to be enabled.
|
|
31
47
|
*/
|
|
32
|
-
export async function mobileChangePermissions(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
export async function mobileChangePermissions(
|
|
49
|
+
permissions,
|
|
50
|
+
appPackage,
|
|
51
|
+
action,
|
|
52
|
+
target = PERMISSION_TARGET.PM
|
|
53
|
+
) {
|
|
54
|
+
appPackage ??= this.opts.appPackage;
|
|
55
|
+
action ??= _.toLower(target) === PERMISSION_TARGET.APPOPS
|
|
56
|
+
? APPOPS_ACTION.ALLOW
|
|
57
|
+
: PM_ACTION.GRANT;
|
|
41
58
|
if (_.isNil(permissions)) {
|
|
42
59
|
throw new errors.InvalidArgumentError(`'permissions' argument is required`);
|
|
43
60
|
}
|
|
@@ -64,11 +81,13 @@ export async function mobileChangePermissions(opts) {
|
|
|
64
81
|
|
|
65
82
|
/**
|
|
66
83
|
* @this {import('../driver').AndroidDriver}
|
|
67
|
-
* @param {
|
|
84
|
+
* @param {string} [type='requested'] One of possible permission types to get.
|
|
85
|
+
* @param {string} [appPackage] The application package to set change permissions on.
|
|
86
|
+
* Defaults to the package name under test
|
|
68
87
|
* @returns {Promise<string[]>}
|
|
69
88
|
*/
|
|
70
|
-
export async function mobileGetPermissions(
|
|
71
|
-
|
|
89
|
+
export async function mobileGetPermissions(type = PERMISSIONS_TYPE.REQUESTED, appPackage) {
|
|
90
|
+
appPackage ??= this.opts.appPackage;
|
|
72
91
|
/**
|
|
73
92
|
* @type {(pkg: string) => Promise<string[]>}
|
|
74
93
|
*/
|
|
@@ -4,14 +4,13 @@ import _ from 'lodash';
|
|
|
4
4
|
import {exec} from 'teen_process';
|
|
5
5
|
import {ADB_SHELL_FEATURE} from '../utils';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
export async function mobileShell<T extends boolean>(
|
|
8
|
+
command: string,
|
|
9
|
+
args: string[] = [],
|
|
10
|
+
timeout: number = 20000,
|
|
11
|
+
includeStderr?: T,
|
|
12
|
+
): Promise<T extends true ? { stdout: string; stderr: string; } : string> {
|
|
13
13
|
this.assertFeatureEnabled(ADB_SHELL_FEATURE);
|
|
14
|
-
const {command, args = /** @type {string[]} */ ([]), timeout = 20000, includeStderr} = opts ?? {};
|
|
15
14
|
|
|
16
15
|
if (!_.isString(command)) {
|
|
17
16
|
throw new errors.InvalidArgumentError(`The 'command' argument is mandatory`);
|
|
@@ -22,11 +21,13 @@ export async function mobileShell(opts) {
|
|
|
22
21
|
try {
|
|
23
22
|
const {stdout, stderr} = await exec(this.adb.executable.path, adbArgs, {timeout});
|
|
24
23
|
if (includeStderr) {
|
|
24
|
+
// @ts-ignore We know what we are doing here
|
|
25
25
|
return {
|
|
26
26
|
stdout,
|
|
27
27
|
stderr,
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
// @ts-ignore We know what we are doing here
|
|
30
31
|
return stdout;
|
|
31
32
|
} catch (e) {
|
|
32
33
|
const err = /** @type {import('teen_process').ExecError} */ (e);
|
|
@@ -37,7 +38,3 @@ export async function mobileShell(opts) {
|
|
|
37
38
|
);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @typedef {import('appium-adb').ADB} ADB
|
|
43
|
-
*/
|