appium-android-driver 14.0.1 → 14.0.3

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.
Files changed (178) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/app-management.d.ts +1 -1
  3. package/build/lib/commands/app-management.d.ts.map +1 -1
  4. package/build/lib/commands/app-management.js +2 -4
  5. package/build/lib/commands/app-management.js.map +1 -1
  6. package/build/lib/commands/appearance.d.ts.map +1 -1
  7. package/build/lib/commands/appearance.js.map +1 -1
  8. package/build/lib/commands/bidi/models.d.ts +1 -1
  9. package/build/lib/commands/bidi/models.d.ts.map +1 -1
  10. package/build/lib/commands/bidi/models.js +1 -1
  11. package/build/lib/commands/bidi/models.js.map +1 -1
  12. package/build/lib/commands/bluetooth.d.ts.map +1 -1
  13. package/build/lib/commands/bluetooth.js.map +1 -1
  14. package/build/lib/commands/context/cache.d.ts +1 -1
  15. package/build/lib/commands/context/cache.d.ts.map +1 -1
  16. package/build/lib/commands/context/cache.js.map +1 -1
  17. package/build/lib/commands/context/exports.d.ts.map +1 -1
  18. package/build/lib/commands/context/exports.js +3 -4
  19. package/build/lib/commands/context/exports.js.map +1 -1
  20. package/build/lib/commands/context/helpers.d.ts.map +1 -1
  21. package/build/lib/commands/context/helpers.js +21 -26
  22. package/build/lib/commands/context/helpers.js.map +1 -1
  23. package/build/lib/commands/device/common.d.ts +1 -1
  24. package/build/lib/commands/device/common.d.ts.map +1 -1
  25. package/build/lib/commands/device/common.js +8 -16
  26. package/build/lib/commands/device/common.js.map +1 -1
  27. package/build/lib/commands/device/emulator-actions.d.ts.map +1 -1
  28. package/build/lib/commands/device/emulator-actions.js +1 -1
  29. package/build/lib/commands/device/emulator-actions.js.map +1 -1
  30. package/build/lib/commands/device/emulator-console.d.ts.map +1 -1
  31. package/build/lib/commands/device/emulator-console.js.map +1 -1
  32. package/build/lib/commands/device/utils.d.ts.map +1 -1
  33. package/build/lib/commands/device/utils.js +5 -6
  34. package/build/lib/commands/device/utils.js.map +1 -1
  35. package/build/lib/commands/deviceidle.d.ts.map +1 -1
  36. package/build/lib/commands/deviceidle.js.map +1 -1
  37. package/build/lib/commands/element.d.ts.map +1 -1
  38. package/build/lib/commands/element.js.map +1 -1
  39. package/build/lib/commands/execute.d.ts.map +1 -1
  40. package/build/lib/commands/execute.js +2 -4
  41. package/build/lib/commands/execute.js.map +1 -1
  42. package/build/lib/commands/file-actions.d.ts.map +1 -1
  43. package/build/lib/commands/file-actions.js +6 -20
  44. package/build/lib/commands/file-actions.js.map +1 -1
  45. package/build/lib/commands/find.d.ts +1 -1
  46. package/build/lib/commands/find.d.ts.map +1 -1
  47. package/build/lib/commands/find.js +1 -1
  48. package/build/lib/commands/find.js.map +1 -1
  49. package/build/lib/commands/geolocation.d.ts.map +1 -1
  50. package/build/lib/commands/geolocation.js +5 -12
  51. package/build/lib/commands/geolocation.js.map +1 -1
  52. package/build/lib/commands/gestures.d.ts.map +1 -1
  53. package/build/lib/commands/gestures.js.map +1 -1
  54. package/build/lib/commands/image-injection.d.ts.map +1 -1
  55. package/build/lib/commands/image-injection.js +2 -2
  56. package/build/lib/commands/image-injection.js.map +1 -1
  57. package/build/lib/commands/ime.d.ts.map +1 -1
  58. package/build/lib/commands/ime.js +1 -7
  59. package/build/lib/commands/ime.js.map +1 -1
  60. package/build/lib/commands/intent.d.ts.map +1 -1
  61. package/build/lib/commands/intent.js +2 -3
  62. package/build/lib/commands/intent.js.map +1 -1
  63. package/build/lib/commands/keyboard.d.ts.map +1 -1
  64. package/build/lib/commands/keyboard.js.map +1 -1
  65. package/build/lib/commands/legacy.d.ts.map +1 -1
  66. package/build/lib/commands/legacy.js.map +1 -1
  67. package/build/lib/commands/lock/exports.d.ts.map +1 -1
  68. package/build/lib/commands/lock/exports.js.map +1 -1
  69. package/build/lib/commands/lock/helpers.d.ts.map +1 -1
  70. package/build/lib/commands/lock/helpers.js +2 -9
  71. package/build/lib/commands/lock/helpers.js.map +1 -1
  72. package/build/lib/commands/log.d.ts +1 -1
  73. package/build/lib/commands/log.d.ts.map +1 -1
  74. package/build/lib/commands/log.js +6 -8
  75. package/build/lib/commands/log.js.map +1 -1
  76. package/build/lib/commands/media-projection.d.ts.map +1 -1
  77. package/build/lib/commands/media-projection.js +2 -2
  78. package/build/lib/commands/media-projection.js.map +1 -1
  79. package/build/lib/commands/memory.d.ts.map +1 -1
  80. package/build/lib/commands/memory.js.map +1 -1
  81. package/build/lib/commands/misc.d.ts.map +1 -1
  82. package/build/lib/commands/misc.js.map +1 -1
  83. package/build/lib/commands/network.d.ts.map +1 -1
  84. package/build/lib/commands/network.js +4 -11
  85. package/build/lib/commands/network.js.map +1 -1
  86. package/build/lib/commands/nfc.d.ts.map +1 -1
  87. package/build/lib/commands/nfc.js.map +1 -1
  88. package/build/lib/commands/performance.d.ts.map +1 -1
  89. package/build/lib/commands/performance.js +4 -21
  90. package/build/lib/commands/performance.js.map +1 -1
  91. package/build/lib/commands/permissions.d.ts.map +1 -1
  92. package/build/lib/commands/permissions.js +4 -7
  93. package/build/lib/commands/permissions.js.map +1 -1
  94. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  95. package/build/lib/commands/recordscreen.js +2 -2
  96. package/build/lib/commands/recordscreen.js.map +1 -1
  97. package/build/lib/commands/resources.d.ts.map +1 -1
  98. package/build/lib/commands/resources.js.map +1 -1
  99. package/build/lib/commands/shell.d.ts.map +1 -1
  100. package/build/lib/commands/shell.js +1 -6
  101. package/build/lib/commands/shell.js.map +1 -1
  102. package/build/lib/commands/streamscreen.d.ts.map +1 -1
  103. package/build/lib/commands/streamscreen.js +6 -9
  104. package/build/lib/commands/streamscreen.js.map +1 -1
  105. package/build/lib/commands/system-bars.d.ts.map +1 -1
  106. package/build/lib/commands/system-bars.js +1 -1
  107. package/build/lib/commands/system-bars.js.map +1 -1
  108. package/build/lib/commands/time.d.ts.map +1 -1
  109. package/build/lib/commands/time.js +1 -1
  110. package/build/lib/commands/time.js.map +1 -1
  111. package/build/lib/commands/types.d.ts +4 -4
  112. package/build/lib/commands/types.d.ts.map +1 -1
  113. package/build/lib/doctor/checks.d.ts.map +1 -1
  114. package/build/lib/doctor/checks.js +2 -2
  115. package/build/lib/doctor/checks.js.map +1 -1
  116. package/build/lib/driver.d.ts +8 -8
  117. package/build/lib/driver.d.ts.map +1 -1
  118. package/build/lib/driver.js +14 -20
  119. package/build/lib/driver.js.map +1 -1
  120. package/build/lib/execute-method-map.d.ts.map +1 -1
  121. package/build/lib/execute-method-map.js +1 -10
  122. package/build/lib/execute-method-map.js.map +1 -1
  123. package/build/lib/index.d.ts +1 -1
  124. package/build/lib/index.d.ts.map +1 -1
  125. package/build/lib/index.js +1 -1
  126. package/build/lib/index.js.map +1 -1
  127. package/build/lib/method-map.d.ts.map +1 -1
  128. package/build/lib/method-map.js.map +1 -1
  129. package/build/lib/utils.d.ts.map +1 -1
  130. package/build/lib/utils.js +1 -1
  131. package/build/lib/utils.js.map +1 -1
  132. package/lib/commands/app-management.ts +15 -43
  133. package/lib/commands/appearance.ts +1 -5
  134. package/lib/commands/bidi/models.ts +5 -12
  135. package/lib/commands/bluetooth.ts +1 -0
  136. package/lib/commands/context/cache.ts +2 -1
  137. package/lib/commands/context/exports.ts +17 -40
  138. package/lib/commands/context/helpers.ts +37 -88
  139. package/lib/commands/device/common.ts +16 -29
  140. package/lib/commands/device/emulator-actions.ts +12 -49
  141. package/lib/commands/device/emulator-console.ts +1 -0
  142. package/lib/commands/device/utils.ts +7 -16
  143. package/lib/commands/deviceidle.ts +1 -0
  144. package/lib/commands/element.ts +6 -20
  145. package/lib/commands/execute.ts +6 -13
  146. package/lib/commands/file-actions.ts +17 -50
  147. package/lib/commands/find.ts +4 -6
  148. package/lib/commands/geolocation.ts +9 -17
  149. package/lib/commands/gestures.ts +2 -1
  150. package/lib/commands/image-injection.ts +9 -19
  151. package/lib/commands/ime.ts +2 -7
  152. package/lib/commands/intent.ts +3 -3
  153. package/lib/commands/keyboard.ts +4 -14
  154. package/lib/commands/legacy.ts +1 -0
  155. package/lib/commands/lock/exports.ts +5 -10
  156. package/lib/commands/lock/helpers.ts +16 -51
  157. package/lib/commands/log.ts +12 -22
  158. package/lib/commands/media-projection.ts +9 -21
  159. package/lib/commands/memory.ts +2 -5
  160. package/lib/commands/misc.ts +3 -5
  161. package/lib/commands/network.ts +9 -27
  162. package/lib/commands/nfc.ts +1 -0
  163. package/lib/commands/performance.ts +12 -48
  164. package/lib/commands/permissions.ts +10 -22
  165. package/lib/commands/recordscreen.ts +16 -41
  166. package/lib/commands/resources.ts +3 -9
  167. package/lib/commands/shell.ts +3 -7
  168. package/lib/commands/streamscreen.ts +17 -37
  169. package/lib/commands/system-bars.ts +7 -13
  170. package/lib/commands/time.ts +4 -8
  171. package/lib/commands/types.ts +9 -10
  172. package/lib/doctor/checks.ts +11 -18
  173. package/lib/driver.ts +43 -65
  174. package/lib/execute-method-map.ts +1 -10
  175. package/lib/index.ts +1 -1
  176. package/lib/method-map.ts +1 -0
  177. package/lib/utils.ts +4 -6
  178. package/package.json +27 -37
@@ -1,15 +1,11 @@
1
1
  import {util} from '@appium/support';
2
2
  import {ADB} from 'appium-adb';
3
3
  import {retryInterval} from 'asyncbox';
4
- import {
5
- path as SETTINGS_APK_PATH,
6
- SETTINGS_HELPER_ID,
7
- UNICODE_IME,
8
- EMPTY_IME,
9
- } from 'io.appium.settings';
10
- import {prepareEmulatorForImageInjection} from '../image-injection.js';
11
- import {ADB_LISTEN_ALL_NETWORK_FEATURE} from '../../utils.js';
4
+ import {path as SETTINGS_APK_PATH, SETTINGS_HELPER_ID, UNICODE_IME, EMPTY_IME} from 'io.appium.settings';
5
+
12
6
  import type {AndroidDriver} from '../../driver.js';
7
+ import {ADB_LISTEN_ALL_NETWORK_FEATURE} from '../../utils.js';
8
+ import {prepareEmulatorForImageInjection} from '../image-injection.js';
13
9
 
14
10
  const HELPER_APP_INSTALL_RETRIES = 3;
15
11
  const HELPER_APP_INSTALL_RETRY_DELAY_MS = 5000;
@@ -55,7 +51,7 @@ export function prepareAvdArgs(this: AndroidDriver): string[] {
55
51
  if (Array.isArray(avdArgs)) {
56
52
  result.push(...avdArgs);
57
53
  } else {
58
- result.push(...util.shellParse(`${avdArgs}`));
54
+ result.push(...util.shellParse(`${avdArgs}`).filter((entry): entry is string => typeof entry === 'string'));
59
55
  }
60
56
  }
61
57
  if (networkSpeed) {
@@ -97,10 +93,7 @@ export async function prepareEmulator(this: AndroidDriver, adb: ADB): Promise<vo
97
93
  }
98
94
  const args = prepareAvdArgs.bind(this)();
99
95
  if (isEmulatorRunning) {
100
- if (
101
- (await prepareEmulatorForImageInjection.bind(this)(adb.sdkRoot as string)) ||
102
- args.includes('-wipe-data')
103
- ) {
96
+ if ((await prepareEmulatorForImageInjection.bind(this)(adb.sdkRoot as string)) || args.includes('-wipe-data')) {
104
97
  this.log.debug(`Killing '${avdName}'`);
105
98
  await adb.killEmulator(avdName);
106
99
  } else {
@@ -203,9 +196,7 @@ export async function pushSettingsApp(this: AndroidDriver, throwIfError: boolean
203
196
  // Reinstall would stop the settings helper process anyway, so
204
197
  // there is no need to continue if the application is still running
205
198
  if (await this.settingsApp.isRunningInForeground()) {
206
- this.log.debug(
207
- `${SETTINGS_HELPER_ID} is already running. ` + `There is no need to reset its permissions.`,
208
- );
199
+ this.log.debug(`${SETTINGS_HELPER_ID} is already running. There is no need to reset its permissions.`);
209
200
  return;
210
201
  }
211
202
 
@@ -1,4 +1,5 @@
1
1
  import {errors} from 'appium/driver.js';
2
+
2
3
  import type {AndroidDriver} from '../driver.js';
3
4
 
4
5
  const SUPPORTED_ACTIONS = ['whitelistAdd', 'whitelistRemove'] as const;
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
 
3
- import {errors} from 'appium/driver.js';
4
3
  import type {Position, Size} from '@appium/types';
4
+ import {errors} from 'appium/driver.js';
5
+
5
6
  import type {AndroidDriver} from '../driver.js';
6
7
  import type {DoSetElementValueOpts} from './types.js';
7
8
 
@@ -13,11 +14,7 @@ import type {DoSetElementValueOpts} from './types.js';
13
14
  * @returns Promise that resolves to the attribute value, or `null` if not found.
14
15
  * @throws {errors.NotImplementedError} This method is not implemented.
15
16
  */
16
- export async function getAttribute(
17
- this: AndroidDriver,
18
- attribute: string,
19
- elementId: string,
20
- ): Promise<string | null> {
17
+ export async function getAttribute(this: AndroidDriver, attribute: string, elementId: string): Promise<string | null> {
21
18
  throw new errors.NotImplementedError('Not implemented');
22
19
  }
23
20
 
@@ -139,10 +136,7 @@ export async function setElementValue(
139
136
  * @returns Promise that resolves when the value is set.
140
137
  * @throws {errors.NotImplementedError} This method is not implemented.
141
138
  */
142
- export async function doSetElementValue(
143
- this: AndroidDriver,
144
- params: DoSetElementValueOpts,
145
- ): Promise<void> {
139
+ export async function doSetElementValue(this: AndroidDriver, params: DoSetElementValueOpts): Promise<void> {
146
140
  throw new errors.NotImplementedError('Not implemented');
147
141
  }
148
142
 
@@ -153,11 +147,7 @@ export async function doSetElementValue(
153
147
  * @param elementId The element identifier.
154
148
  * @returns Promise that resolves when the value is set.
155
149
  */
156
- export async function setValue(
157
- this: AndroidDriver,
158
- keys: string | string[],
159
- elementId: string,
160
- ): Promise<void> {
150
+ export async function setValue(this: AndroidDriver, keys: string | string[], elementId: string): Promise<void> {
161
151
  return await this.setElementValue(keys, elementId, false);
162
152
  }
163
153
 
@@ -168,11 +158,7 @@ export async function setValue(
168
158
  * @param elementId The element identifier.
169
159
  * @returns Promise that resolves when the value is replaced.
170
160
  */
171
- export async function replaceValue(
172
- this: AndroidDriver,
173
- keys: string | string[],
174
- elementId: string,
175
- ): Promise<void> {
161
+ export async function replaceValue(this: AndroidDriver, keys: string | string[], elementId: string): Promise<void> {
176
162
  return await this.setElementValue(keys, elementId, true);
177
163
  }
178
164
 
@@ -1,8 +1,9 @@
1
- import {errors, PROTOCOLS} from 'appium/driver.js';
2
1
  import {util} from '@appium/support';
3
2
  import type {StringRecord, Element} from '@appium/types';
4
- import type {AndroidDriver} from '../driver.js';
5
3
  import type {Chromedriver} from 'appium-chromedriver';
4
+ import {errors, PROTOCOLS} from 'appium/driver.js';
5
+
6
+ import type {AndroidDriver} from '../driver.js';
6
7
 
7
8
  const EXECUTE_SCRIPT_PREFIX = 'mobile:';
8
9
 
@@ -17,11 +18,7 @@ type ExecuteMethodArgs = readonly any[] | readonly [StringRecord] | Readonly<Str
17
18
  * @returns Promise that resolves to the script execution result.
18
19
  * @throws {errors.NotImplementedError} If not in a web context and script doesn't start with 'mobile:'.
19
20
  */
20
- export async function execute(
21
- this: AndroidDriver,
22
- script: string,
23
- args?: ExecuteMethodArgs,
24
- ): Promise<any> {
21
+ export async function execute(this: AndroidDriver, script: string, args?: ExecuteMethodArgs): Promise<any> {
25
22
  if (script?.startsWith(EXECUTE_SCRIPT_PREFIX)) {
26
23
  const formattedScript = script.trim().replace(/^mobile:\s*/, `${EXECUTE_SCRIPT_PREFIX} `);
27
24
  const executeMethodArgs = preprocessExecuteMethodArgs(args);
@@ -31,9 +28,7 @@ export async function execute(
31
28
  throw new errors.NotImplementedError();
32
29
  }
33
30
  const endpoint =
34
- (this.chromedriver as Chromedriver).jwproxy.downstreamProtocol === PROTOCOLS.MJSONWP
35
- ? '/execute'
36
- : '/execute/sync';
31
+ (this.chromedriver as Chromedriver).jwproxy.downstreamProtocol === PROTOCOLS.MJSONWP ? '/execute' : '/execute/sync';
37
32
  return await (this.chromedriver as Chromedriver).jwproxy.command(endpoint, 'POST', {
38
33
  script,
39
34
  args,
@@ -62,9 +57,7 @@ function preprocessExecuteMethodArgs(args?: ExecuteMethodArgs): StringRecord {
62
57
  * Automatically unwraps the `elementId` prop _if and only if_ the execute method expects it.
63
58
  */
64
59
  if ('elementId' in executeMethodArgs) {
65
- executeMethodArgs.elementId = util.unwrapElement(
66
- executeMethodArgs.elementId as Element | string,
67
- );
60
+ executeMethodArgs.elementId = util.unwrapElement(executeMethodArgs.elementId as Element | string);
68
61
  }
69
62
 
70
63
  return executeMethodArgs;
@@ -1,8 +1,10 @@
1
- import {fs, util, zip, tempDir} from '@appium/support';
2
1
  import path from 'node:path';
2
+
3
+ import {fs, util, zip, tempDir} from '@appium/support';
4
+ import type {ADB} from 'appium-adb';
3
5
  import {errors} from 'appium/driver.js';
6
+
4
7
  import type {AndroidDriver} from '../driver.js';
5
- import type {ADB} from 'appium-adb';
6
8
 
7
9
  const CONTAINER_PATH_MARKER = '@';
8
10
  // https://regex101.com/r/PLdB0G/2
@@ -27,8 +29,7 @@ const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FI
27
29
  export async function pullFile(this: AndroidDriver, remotePath: string): Promise<string> {
28
30
  if (remotePath.endsWith('/')) {
29
31
  throw new errors.InvalidArgumentError(
30
- `It is expected that remote path points to a file and not to a folder. ` +
31
- `'${remotePath}' is given instead`,
32
+ `It is expected that remote path points to a file and not to a folder. '${remotePath}' is given instead`,
32
33
  );
33
34
  }
34
35
  let tmpDestination: string | null = null;
@@ -84,15 +85,10 @@ export async function pullFile(this: AndroidDriver, remotePath: string): Promise
84
85
  * @returns Promise that resolves when the file is pushed.
85
86
  * @throws {errors.InvalidArgumentError} If the remote path points to a folder instead of a file.
86
87
  */
87
- export async function pushFile(
88
- this: AndroidDriver,
89
- remotePath: string,
90
- base64Data: string | number[],
91
- ): Promise<void> {
88
+ export async function pushFile(this: AndroidDriver, remotePath: string, base64Data: string | number[]): Promise<void> {
92
89
  if (remotePath.endsWith('/')) {
93
90
  throw new errors.InvalidArgumentError(
94
- `It is expected that remote path points to a file and not to a folder. ` +
95
- `'${remotePath}' is given instead`,
91
+ `It is expected that remote path points to a file and not to a folder. '${remotePath}' is given instead`,
96
92
  );
97
93
  }
98
94
  const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
@@ -116,11 +112,7 @@ export async function pushFile(
116
112
  );
117
113
  tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
118
114
  try {
119
- await this.adb.shell([
120
- 'run-as',
121
- packageId,
122
- `mkdir -p '${escapePath(path.posix.dirname(pathInContainer))}'`,
123
- ]);
115
+ await this.adb.shell(['run-as', packageId, `mkdir -p '${escapePath(path.posix.dirname(pathInContainer))}'`]);
124
116
  await this.adb.shell(['run-as', packageId, `touch '${escapePath(pathInContainer)}'`]);
125
117
  await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
126
118
  await this.adb.push(localFile, tmpDestination);
@@ -185,8 +177,7 @@ export async function pullFolder(this: AndroidDriver, remotePath: string): Promi
185
177
  export async function mobileDeleteFile(this: AndroidDriver, remotePath: string): Promise<boolean> {
186
178
  if (remotePath.endsWith('/')) {
187
179
  throw new errors.InvalidArgumentError(
188
- `It is expected that remote path points to a folder and not to a file. ` +
189
- `'${remotePath}' is given instead`,
180
+ `It is expected that remote path points to a folder and not to a file. '${remotePath}' is given instead`,
190
181
  );
191
182
  }
192
183
  return await deleteFileOrFolder.call(this, this.adb, remotePath);
@@ -201,11 +192,7 @@ export async function mobileDeleteFile(this: AndroidDriver, remotePath: string):
201
192
  * If the remote path is valid, but the remote path does not exist
202
193
  * this function return `false`.
203
194
  */
204
- async function deleteFileOrFolder(
205
- this: AndroidDriver,
206
- adb: ADB,
207
- remotePath: string,
208
- ): Promise<boolean> {
195
+ async function deleteFileOrFolder(this: AndroidDriver, adb: ADB, remotePath: string): Promise<boolean> {
209
196
  const {isDir, isPresent, isFile} = createFSTests(adb);
210
197
  let dstPath = remotePath;
211
198
  let pkgId: string | undefined;
@@ -246,9 +233,7 @@ async function deleteFileOrFolder(
246
233
  await adb.shell(['rm', `-f${expectsFile ? '' : 'r'}`, dstPath]);
247
234
  }
248
235
  if (await isPresent(dstPath, pkgId)) {
249
- throw this.log.errorWithException(
250
- `The item at '${dstPath}' still exists after being deleted. Is it writable?`,
251
- );
236
+ throw this.log.errorWithException(`The item at '${dstPath}' still exists after being deleted. Is it writable?`);
252
237
  }
253
238
  return true;
254
239
  }
@@ -285,23 +270,12 @@ async function scanMedia(this: AndroidDriver, remotePath: string): Promise<void>
285
270
  if ((await this.adb.getApiLevel()) >= 29) {
286
271
  await this.settingsApp.scanMedia(remotePath);
287
272
  } else {
288
- await this.adb.shell([
289
- 'am',
290
- 'broadcast',
291
- '-a',
292
- ANDROID_MEDIA_RESCAN_INTENT,
293
- '-d',
294
- `file://${remotePath}`,
295
- ]);
273
+ await this.adb.shell(['am', 'broadcast', '-a', ANDROID_MEDIA_RESCAN_INTENT, '-d', `file://${remotePath}`]);
296
274
  }
297
275
  } catch (e) {
298
276
  const err = e as {stderr?: string; message?: string};
299
277
  // FIXME: what has a `stderr` prop?
300
- this.log.warn(
301
- `Ignoring an unexpected error upon media scanning of '${remotePath}': ${
302
- err.stderr ?? err.message
303
- }`,
304
- );
278
+ this.log.warn(`Ignoring an unexpected error upon media scanning of '${remotePath}': ${err.stderr ?? err.message}`);
305
279
  }
306
280
  }
307
281
 
@@ -317,11 +291,7 @@ function escapePath(p: string): string {
317
291
  * Factory providing filesystem test functions using ADB
318
292
  */
319
293
  function createFSTests(adb: ADB) {
320
- const performRemoteFsCheck = async (
321
- p: string,
322
- op: 'd' | 'f' | 'e',
323
- runAs?: string,
324
- ): Promise<boolean> => {
294
+ const performRemoteFsCheck = async (p: string, op: 'd' | 'f' | 'e', runAs?: string): Promise<boolean> => {
325
295
  const passFlag = '__PASS__';
326
296
  const checkCmd = `[ -${op} '${escapePath(p)}' ] && echo ${passFlag}`;
327
297
  const fullCmd = runAs ? `run-as ${runAs} ${checkCmd}` : checkCmd;
@@ -332,12 +302,9 @@ function createFSTests(adb: ADB) {
332
302
  }
333
303
  };
334
304
 
335
- const isFile = async (p: string, runAs?: string): Promise<boolean> =>
336
- await performRemoteFsCheck(p, 'f', runAs);
337
- const isDir = async (p: string, runAs?: string): Promise<boolean> =>
338
- await performRemoteFsCheck(p, 'd', runAs);
339
- const isPresent = async (p: string, runAs?: string): Promise<boolean> =>
340
- await performRemoteFsCheck(p, 'e', runAs);
305
+ const isFile = async (p: string, runAs?: string): Promise<boolean> => await performRemoteFsCheck(p, 'f', runAs);
306
+ const isDir = async (p: string, runAs?: string): Promise<boolean> => await performRemoteFsCheck(p, 'd', runAs);
307
+ const isPresent = async (p: string, runAs?: string): Promise<boolean> => await performRemoteFsCheck(p, 'e', runAs);
341
308
 
342
309
  return {isFile, isDir, isPresent};
343
310
  }
@@ -1,7 +1,8 @@
1
- import {errors, isErrorType} from 'appium/driver.js';
2
1
  import {util} from '@appium/support';
3
- import type {AndroidDriver} from '../driver.js';
4
2
  import type {Element} from '@appium/types';
3
+ import {errors, isErrorType} from 'appium/driver.js';
4
+
5
+ import type {AndroidDriver} from '../driver.js';
5
6
  import type {FindElementOpts} from './types.js';
6
7
 
7
8
  /**
@@ -103,10 +104,7 @@ export async function findElOrEls(
103
104
  * @returns A single `Element` if `params.multiple` is `false`, or an array of `Element` objects if `true`.
104
105
  * @throws {errors.NotImplementedError} This method must be implemented by the specific context handler.
105
106
  */
106
- export async function doFindElementOrEls(
107
- this: AndroidDriver,
108
- params: FindElementOpts,
109
- ): Promise<Element | Element[]> {
107
+ export async function doFindElementOrEls(this: AndroidDriver, params: FindElementOpts): Promise<Element | Element[]> {
110
108
  void params;
111
109
  throw new errors.NotImplementedError('Not implemented');
112
110
  }
@@ -1,11 +1,13 @@
1
- import {asyncmap} from 'asyncbox';
2
- import {fs, tempDir} from '@appium/support';
3
1
  import path from 'node:path';
2
+
3
+ import {fs, tempDir} from '@appium/support';
4
4
  import type {Location} from '@appium/types';
5
- import {getThirdPartyPackages} from './app-management.js';
6
- import type {AndroidDriver} from '../driver.js';
5
+ import {asyncmap} from 'asyncbox';
7
6
  import {SETTINGS_HELPER_ID} from 'io.appium.settings';
8
7
 
8
+ import type {AndroidDriver} from '../driver.js';
9
+ import {getThirdPartyPackages} from './app-management.js';
10
+
9
11
  // The value close to zero, but not zero, is needed
10
12
  // to trick JSON generation and send a float value instead of an integer,
11
13
  // This allows strictly-typed clients, like Java, to properly
@@ -87,10 +89,7 @@ export async function mobileSetGeolocation(
87
89
  * 20000ms by default.
88
90
  * @returns Promise that resolves when the GPS cache refresh is initiated.
89
91
  */
90
- export async function mobileRefreshGpsCache(
91
- this: AndroidDriver,
92
- timeoutMs?: number,
93
- ): Promise<void> {
92
+ export async function mobileRefreshGpsCache(this: AndroidDriver, timeoutMs?: number): Promise<void> {
94
93
  await this.settingsApp.refreshGeoLocationCache(timeoutMs);
95
94
  }
96
95
 
@@ -135,8 +134,7 @@ export async function toggleLocationServices(this: AndroidDriver): Promise<void>
135
134
  this.log.info('Toggling location services');
136
135
  const isGpsEnabled = await this.isLocationServicesEnabled();
137
136
  this.log.debug(
138
- `Current GPS state: ${isGpsEnabled}. ` +
139
- `The service is going to be ${isGpsEnabled ? 'disabled' : 'enabled'}`,
137
+ `Current GPS state: ${isGpsEnabled}. The service is going to be ${isGpsEnabled ? 'disabled' : 'enabled'}`,
140
138
  );
141
139
  await this.adb.toggleGPSLocationProvider(!isGpsEnabled);
142
140
  }
@@ -211,13 +209,7 @@ async function resetMockLocation(this: AndroidDriver): Promise<void> {
211
209
  // Only include currently installed packages
212
210
  const resultPkgs = pkgIds.filter((pkg) => thirdPartyPkgIds.has(pkg));
213
211
  if (resultPkgs.length <= 1) {
214
- await this.adb.shell([
215
- 'appops',
216
- 'set',
217
- resultPkgs[0] ?? SETTINGS_HELPER_ID,
218
- 'android:mock_location',
219
- 'deny',
220
- ]);
212
+ await this.adb.shell(['appops', 'set', resultPkgs[0] ?? SETTINGS_HELPER_ID, 'android:mock_location', 'deny']);
221
213
  return;
222
214
  }
223
215
 
@@ -1,5 +1,6 @@
1
- import {errors} from 'appium/driver.js';
2
1
  import type {StringRecord} from '@appium/types';
2
+ import {errors} from 'appium/driver.js';
3
+
3
4
  import type {AndroidDriver} from '../driver.js';
4
5
 
5
6
  /**
@@ -1,7 +1,9 @@
1
- import {errors} from 'appium/driver.js';
1
+ import crypto from 'node:crypto';
2
2
  import path from 'node:path';
3
+
3
4
  import {fs, tempDir} from '@appium/support';
4
- import crypto from 'node:crypto';
5
+ import {errors} from 'appium/driver.js';
6
+
5
7
  import type {AndroidDriver} from '../driver.js';
6
8
 
7
9
  const EMULATOR_RESOURCES_ROOT = ['emulator', 'resources'];
@@ -30,10 +32,7 @@ const PNG_MAGIC_LENGTH = 4;
30
32
  * to load the updated config or `false` if the current config is already up to date
31
33
  * or does not need to be updated
32
34
  */
33
- export async function prepareEmulatorForImageInjection(
34
- this: AndroidDriver,
35
- sdkRoot: string,
36
- ): Promise<boolean> {
35
+ export async function prepareEmulatorForImageInjection(this: AndroidDriver, sdkRoot: string): Promise<boolean> {
37
36
  const {injectedImageProperties: props} = this.opts;
38
37
  if (!props) {
39
38
  return false;
@@ -47,9 +46,7 @@ export async function prepareEmulatorForImageInjection(
47
46
  if (await fs.exists(configPath)) {
48
47
  const configPayload = await fs.readFile(configPath, 'utf8');
49
48
  if (configPayload.includes(strProps)) {
50
- this.log.info(
51
- `The image injection config at '${configPath}' is already up to date. Doing nothing`,
52
- );
49
+ this.log.info(`The image injection config at '${configPath}' is already up to date. Doing nothing`);
53
50
  return false;
54
51
  }
55
52
  const updatedPayload = `${DEFAULT_CONFIG_PAYLOAD_PREFIX}
@@ -83,10 +80,7 @@ export async function prepareEmulatorForImageInjection(
83
80
  * @throws {Error} If called on a non-emulator device.
84
81
  * @throws {errors.InvalidArgumentError} If the payload is not a valid base64-encoded PNG.
85
82
  */
86
- export async function mobileInjectEmulatorCameraImage(
87
- this: AndroidDriver,
88
- payload: string,
89
- ): Promise<void> {
83
+ export async function mobileInjectEmulatorCameraImage(this: AndroidDriver, payload: string): Promise<void> {
90
84
  if (!this.isEmulator()) {
91
85
  throw new Error('The image injection feature is only available on emulators');
92
86
  }
@@ -99,9 +93,7 @@ export async function mobileInjectEmulatorCameraImage(
99
93
  const pngBuffer = Buffer.from(payload, 'base64');
100
94
  const magic = pngBuffer.toString('hex', 0, PNG_MAGIC_LENGTH);
101
95
  if (magic !== PNG_MAGIC) {
102
- throw new errors.InvalidArgumentError(
103
- 'The provided image payload must contain a valid base64-encoded .PNG data',
104
- );
96
+ throw new errors.InvalidArgumentError('The provided image payload must contain a valid base64-encoded .PNG data');
105
97
  }
106
98
 
107
99
  const tmpImagePath = await tempDir.path({
@@ -111,9 +103,7 @@ export async function mobileInjectEmulatorCameraImage(
111
103
  });
112
104
  await fs.writeFile(tmpImagePath, pngBuffer);
113
105
  await this.adb.execEmuConsoleCommand(`virtualscene-image table ${tmpImagePath}`);
114
- this.log.info(
115
- `The provided image has been successully injected to the ${this.adb.curDeviceId} emulator`,
116
- );
106
+ this.log.info(`The provided image has been successully injected to the ${this.adb.curDeviceId} emulator`);
117
107
  }
118
108
 
119
109
  // #region Internal helpers
@@ -1,4 +1,5 @@
1
1
  import {errors} from 'appium/driver.js';
2
+
2
3
  import type {AndroidDriver} from '../driver.js';
3
4
  import {SET_STYLUS_HANDWRITING_FEATURE} from '../utils.js';
4
5
 
@@ -76,11 +77,5 @@ export async function deactivateIMEEngine(this: AndroidDriver): Promise<void> {
76
77
  */
77
78
  export async function setStylusHandwriting(this: AndroidDriver, enabled: boolean): Promise<void> {
78
79
  this.assertFeatureEnabled(SET_STYLUS_HANDWRITING_FEATURE);
79
- await this.adb.shell([
80
- 'settings',
81
- 'put',
82
- 'secure',
83
- 'stylus_handwriting_enabled',
84
- enabled ? '1' : '0',
85
- ]);
80
+ await this.adb.shell(['settings', 'put', 'secure', 'stylus_handwriting_enabled', enabled ? '1' : '0']);
86
81
  }
@@ -1,5 +1,6 @@
1
- import {errors} from 'appium/driver.js';
2
1
  import {util} from '@appium/support';
2
+ import {errors} from 'appium/driver.js';
3
+
3
4
  import type {AndroidDriver} from '../driver.js';
4
5
  import type {IntentOpts} from './types.js';
5
6
 
@@ -405,8 +406,7 @@ function parseIntentSpec(opts: IntentOpts = {}): string[] {
405
406
  resultArgs.push(`--e${type}`, key);
406
407
  } else if (value === undefined) {
407
408
  throw new errors.InvalidArgumentError(
408
- `Intent argument type '${type}' in '${JSON.stringify(item)}' requires a ` +
409
- `valid value to be provided`,
409
+ `Intent argument type '${type}' in '${JSON.stringify(item)}' requires a valid value to be provided`,
410
410
  );
411
411
  } else {
412
412
  resultArgs.push(`--e${type}`, key, value);
@@ -1,5 +1,6 @@
1
1
  import {errors} from 'appium/driver.js';
2
2
  import {UNICODE_IME, EMPTY_IME} from 'io.appium.settings';
3
+
3
4
  import type {AndroidDriver} from '../driver.js';
4
5
  import type {SendKeysOpts} from './types.js';
5
6
 
@@ -57,11 +58,7 @@ export async function doSendKeys(this: AndroidDriver, params: SendKeysOpts): Pro
57
58
  * @param metastate Optional meta state flags.
58
59
  * @returns Promise that resolves when the key event is sent.
59
60
  */
60
- export async function keyevent(
61
- this: AndroidDriver,
62
- keycode: string | number,
63
- metastate?: number,
64
- ): Promise<void> {
61
+ export async function keyevent(this: AndroidDriver, keycode: string | number, metastate?: number): Promise<void> {
65
62
  // TODO deprecate keyevent; currently wd only implements keyevent
66
63
  this.log.warn('keyevent will be deprecated use pressKeyCode');
67
64
  return await this.pressKeyCode(keycode, metastate);
@@ -75,11 +72,7 @@ export async function keyevent(
75
72
  * @returns Promise that resolves when the key code is pressed.
76
73
  * @throws {errors.NotImplementedError} This method is not implemented.
77
74
  */
78
- export async function pressKeyCode(
79
- this: AndroidDriver,
80
- keycode: string | number,
81
- metastate?: number,
82
- ): Promise<void> {
75
+ export async function pressKeyCode(this: AndroidDriver, keycode: string | number, metastate?: number): Promise<void> {
83
76
  void keycode;
84
77
  void metastate;
85
78
  throw new errors.NotImplementedError('Not implemented');
@@ -109,10 +102,7 @@ export async function longPressKeyCode(
109
102
  * @param action The editor action to perform (e.g., 'done', 'go', 'next').
110
103
  * @returns Promise that resolves when the editor action is performed.
111
104
  */
112
- export async function mobilePerformEditorAction(
113
- this: AndroidDriver,
114
- action: string | number,
115
- ): Promise<void> {
105
+ export async function mobilePerformEditorAction(this: AndroidDriver, action: string | number): Promise<void> {
116
106
  await this.settingsApp.performEditorAction(action);
117
107
  }
118
108
 
@@ -1,4 +1,5 @@
1
1
  import {errors} from 'appium/driver.js';
2
+
2
3
  import type {AndroidDriver} from '../driver.js';
3
4
 
4
5
  const ISSUE_URL = 'https://github.com/appium/appium/issues/15807';
@@ -1,4 +1,7 @@
1
1
  import {sleep} from 'asyncbox';
2
+
3
+ import type {AndroidDriver, AndroidDriverCaps} from '../../driver.js';
4
+ import type {UnlockType} from '../types.js';
2
5
  import {
3
6
  validateUnlockCapabilities,
4
7
  FINGERPRINT_UNLOCK,
@@ -15,8 +18,6 @@ import {
15
18
  toCredentialType,
16
19
  verifyUnlock,
17
20
  } from './helpers.js';
18
- import type {AndroidDriver, AndroidDriverCaps} from '../../driver.js';
19
- import type {UnlockType} from '../types.js';
20
21
 
21
22
  /**
22
23
  * Locks the device and optionally unlocks it after a specified number of seconds.
@@ -90,10 +91,7 @@ export async function mobileUnlock(
90
91
  *
91
92
  * @param caps - Optional capabilities to use for unlocking. If not provided, uses session capabilities.
92
93
  */
93
- export async function unlockWithOptions(
94
- this: AndroidDriver,
95
- caps: AndroidDriverCaps | null = null,
96
- ): Promise<void> {
94
+ export async function unlockWithOptions(this: AndroidDriver, caps: AndroidDriverCaps | null = null): Promise<void> {
97
95
  if (!(await this.adb.isScreenLocked())) {
98
96
  this.log.info('Screen already unlocked, doing nothing');
99
97
  return;
@@ -126,10 +124,7 @@ export async function unlockWithOptions(
126
124
  credentialType: toCredentialType(unlockType as UnlockType),
127
125
  });
128
126
  } else {
129
- const unlockMethodMap: Record<
130
- string,
131
- (this: AndroidDriver, caps: AndroidDriverCaps) => Promise<void>
132
- > = {
127
+ const unlockMethodMap: Record<string, (this: AndroidDriver, caps: AndroidDriverCaps) => Promise<void>> = {
133
128
  [PIN_UNLOCK]: pinUnlock,
134
129
  [PIN_UNLOCK_KEY_EVENT]: pinUnlockWithKeyEvent,
135
130
  [PASSWORD_UNLOCK]: passwordUnlock,