appium-android-driver 7.8.3 → 8.0.1

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 (261) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/build/lib/commands/app-management.d.ts +129 -5
  3. package/build/lib/commands/app-management.d.ts.map +1 -1
  4. package/build/lib/commands/app-management.js +433 -128
  5. package/build/lib/commands/app-management.js.map +1 -1
  6. package/build/lib/commands/appearance.d.ts +17 -4
  7. package/build/lib/commands/appearance.d.ts.map +1 -1
  8. package/build/lib/commands/appearance.js +32 -33
  9. package/build/lib/commands/appearance.js.map +1 -1
  10. package/build/lib/commands/context/cache.d.ts +19 -0
  11. package/build/lib/commands/context/cache.d.ts.map +1 -0
  12. package/build/lib/commands/context/cache.js +32 -0
  13. package/build/lib/commands/context/cache.js.map +1 -0
  14. package/build/lib/commands/context/exports.d.ts +141 -0
  15. package/build/lib/commands/context/exports.d.ts.map +1 -0
  16. package/build/lib/commands/context/exports.js +351 -0
  17. package/build/lib/commands/context/exports.js.map +1 -0
  18. package/build/lib/commands/context/helpers.d.ts +98 -0
  19. package/build/lib/commands/context/helpers.d.ts.map +1 -0
  20. package/build/lib/commands/context/helpers.js +715 -0
  21. package/build/lib/commands/context/helpers.js.map +1 -0
  22. package/build/lib/commands/device/common.d.ts +23 -0
  23. package/build/lib/commands/device/common.d.ts.map +1 -0
  24. package/build/lib/commands/device/common.js +230 -0
  25. package/build/lib/commands/device/common.js.map +1 -0
  26. package/build/lib/commands/device/emulator-actions.d.ts +114 -0
  27. package/build/lib/commands/device/emulator-actions.d.ts.map +1 -0
  28. package/build/lib/commands/device/emulator-actions.js +197 -0
  29. package/build/lib/commands/device/emulator-actions.js.map +1 -0
  30. package/build/lib/commands/device/emulator-console.d.ts +7 -0
  31. package/build/lib/commands/device/emulator-console.d.ts.map +1 -0
  32. package/build/lib/commands/device/emulator-console.js +24 -0
  33. package/build/lib/commands/device/emulator-console.js.map +1 -0
  34. package/build/lib/commands/device/utils.d.ts +50 -0
  35. package/build/lib/commands/device/utils.d.ts.map +1 -0
  36. package/build/lib/commands/device/utils.js +238 -0
  37. package/build/lib/commands/device/utils.js.map +1 -0
  38. package/build/lib/commands/deviceidle.d.ts +8 -5
  39. package/build/lib/commands/deviceidle.d.ts.map +1 -1
  40. package/build/lib/commands/deviceidle.js +31 -37
  41. package/build/lib/commands/deviceidle.js.map +1 -1
  42. package/build/lib/commands/element.d.ts +99 -5
  43. package/build/lib/commands/element.d.ts.map +1 -1
  44. package/build/lib/commands/element.js +152 -116
  45. package/build/lib/commands/element.js.map +1 -1
  46. package/build/lib/commands/execute.d.ts +12 -4
  47. package/build/lib/commands/execute.d.ts.map +1 -1
  48. package/build/lib/commands/execute.js +83 -78
  49. package/build/lib/commands/execute.js.map +1 -1
  50. package/build/lib/commands/file-actions.d.ts +42 -5
  51. package/build/lib/commands/file-actions.d.ts.map +1 -1
  52. package/build/lib/commands/file-actions.js +230 -194
  53. package/build/lib/commands/file-actions.js.map +1 -1
  54. package/build/lib/commands/find.d.ts +5 -4
  55. package/build/lib/commands/find.d.ts.map +1 -1
  56. package/build/lib/commands/find.js +7 -10
  57. package/build/lib/commands/find.js.map +1 -1
  58. package/build/lib/commands/geolocation.d.ts +45 -0
  59. package/build/lib/commands/geolocation.d.ts.map +1 -0
  60. package/build/lib/commands/geolocation.js +182 -0
  61. package/build/lib/commands/geolocation.js.map +1 -0
  62. package/build/lib/commands/ime.d.ts +25 -5
  63. package/build/lib/commands/ime.d.ts.map +1 -1
  64. package/build/lib/commands/ime.js +59 -42
  65. package/build/lib/commands/ime.js.map +1 -1
  66. package/build/lib/commands/intent.d.ts +56 -5
  67. package/build/lib/commands/intent.d.ts.map +1 -1
  68. package/build/lib/commands/intent.js +135 -83
  69. package/build/lib/commands/intent.js.map +1 -1
  70. package/build/lib/commands/keyboard.d.ts +58 -4
  71. package/build/lib/commands/keyboard.d.ts.map +1 -1
  72. package/build/lib/commands/keyboard.js +119 -17
  73. package/build/lib/commands/keyboard.js.map +1 -1
  74. package/build/lib/commands/lock/exports.d.ts +301 -0
  75. package/build/lib/commands/lock/exports.d.ts.map +1 -0
  76. package/build/lib/commands/lock/exports.js +121 -0
  77. package/build/lib/commands/lock/exports.js.map +1 -0
  78. package/build/lib/commands/lock/helpers.d.ts +349 -0
  79. package/build/lib/commands/lock/helpers.d.ts.map +1 -0
  80. package/build/lib/commands/lock/helpers.js +375 -0
  81. package/build/lib/commands/lock/helpers.js.map +1 -0
  82. package/build/lib/commands/log.d.ts +59 -5
  83. package/build/lib/commands/log.d.ts.map +1 -1
  84. package/build/lib/commands/log.js +150 -140
  85. package/build/lib/commands/log.js.map +1 -1
  86. package/build/lib/commands/media-projection.d.ts +16 -5
  87. package/build/lib/commands/media-projection.d.ts.map +1 -1
  88. package/build/lib/commands/media-projection.js +69 -58
  89. package/build/lib/commands/media-projection.js.map +1 -1
  90. package/build/lib/commands/memory.d.ts +9 -5
  91. package/build/lib/commands/memory.d.ts.map +1 -1
  92. package/build/lib/commands/memory.js +19 -24
  93. package/build/lib/commands/memory.js.map +1 -1
  94. package/build/lib/commands/misc.d.ts +42 -0
  95. package/build/lib/commands/misc.d.ts.map +1 -0
  96. package/build/lib/commands/misc.js +100 -0
  97. package/build/lib/commands/misc.js.map +1 -0
  98. package/build/lib/commands/network.d.ts +61 -5
  99. package/build/lib/commands/network.d.ts.map +1 -1
  100. package/build/lib/commands/network.js +196 -189
  101. package/build/lib/commands/network.js.map +1 -1
  102. package/build/lib/commands/performance.d.ts +67 -27
  103. package/build/lib/commands/performance.d.ts.map +1 -1
  104. package/build/lib/commands/performance.js +105 -80
  105. package/build/lib/commands/performance.js.map +1 -1
  106. package/build/lib/commands/permissions.d.ts +12 -6
  107. package/build/lib/commands/permissions.d.ts.map +1 -1
  108. package/build/lib/commands/permissions.js +65 -62
  109. package/build/lib/commands/permissions.js.map +1 -1
  110. package/build/lib/commands/recordscreen.d.ts +44 -5
  111. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  112. package/build/lib/commands/recordscreen.js +131 -126
  113. package/build/lib/commands/recordscreen.js.map +1 -1
  114. package/build/lib/commands/resources.d.ts +16 -0
  115. package/build/lib/commands/resources.d.ts.map +1 -0
  116. package/build/lib/commands/resources.js +91 -0
  117. package/build/lib/commands/resources.js.map +1 -0
  118. package/build/lib/commands/shell.d.ts +8 -5
  119. package/build/lib/commands/shell.d.ts.map +1 -1
  120. package/build/lib/commands/shell.js +29 -33
  121. package/build/lib/commands/shell.js.map +1 -1
  122. package/build/lib/commands/streamscreen.d.ts +34 -6
  123. package/build/lib/commands/streamscreen.d.ts.map +1 -1
  124. package/build/lib/commands/streamscreen.js +166 -162
  125. package/build/lib/commands/streamscreen.js.map +1 -1
  126. package/build/lib/commands/system-bars.d.ts +18 -13
  127. package/build/lib/commands/system-bars.d.ts.map +1 -1
  128. package/build/lib/commands/system-bars.js +68 -64
  129. package/build/lib/commands/system-bars.js.map +1 -1
  130. package/build/lib/commands/time.d.ts +14 -0
  131. package/build/lib/commands/time.d.ts.map +1 -0
  132. package/build/lib/commands/time.js +39 -0
  133. package/build/lib/commands/time.js.map +1 -0
  134. package/build/lib/commands/touch.d.ts +99 -6
  135. package/build/lib/commands/touch.d.ts.map +1 -1
  136. package/build/lib/commands/touch.js +399 -280
  137. package/build/lib/commands/touch.js.map +1 -1
  138. package/build/lib/commands/types.d.ts +110 -2
  139. package/build/lib/commands/types.d.ts.map +1 -1
  140. package/build/lib/doctor/checks.d.ts.map +1 -1
  141. package/build/lib/doctor/checks.js +4 -4
  142. package/build/lib/doctor/checks.js.map +1 -1
  143. package/build/lib/driver.d.ts +224 -27
  144. package/build/lib/driver.d.ts.map +1 -1
  145. package/build/lib/driver.js +232 -7
  146. package/build/lib/driver.js.map +1 -1
  147. package/build/lib/index.d.ts +1 -4
  148. package/build/lib/index.d.ts.map +1 -1
  149. package/build/lib/index.js +1 -13
  150. package/build/lib/index.js.map +1 -1
  151. package/build/lib/logger.js.map +1 -1
  152. package/build/lib/method-map.d.ts +0 -23
  153. package/build/lib/method-map.d.ts.map +1 -1
  154. package/build/lib/method-map.js +0 -11
  155. package/build/lib/method-map.js.map +1 -1
  156. package/build/lib/utils.d.ts +12 -0
  157. package/build/lib/utils.d.ts.map +1 -1
  158. package/build/lib/utils.js +38 -2
  159. package/build/lib/utils.js.map +1 -1
  160. package/lib/commands/app-management.js +470 -145
  161. package/lib/commands/appearance.js +29 -36
  162. package/lib/commands/context/cache.js +29 -0
  163. package/lib/commands/context/exports.js +379 -0
  164. package/lib/commands/context/helpers.js +802 -0
  165. package/lib/commands/device/common.js +264 -0
  166. package/lib/commands/device/emulator-actions.js +194 -0
  167. package/lib/commands/device/emulator-console.js +24 -0
  168. package/lib/commands/device/utils.js +285 -0
  169. package/lib/commands/deviceidle.js +31 -44
  170. package/lib/commands/element.js +149 -142
  171. package/lib/commands/execute.js +86 -87
  172. package/lib/commands/file-actions.js +249 -222
  173. package/lib/commands/find.ts +13 -19
  174. package/lib/commands/geolocation.js +179 -0
  175. package/lib/commands/ime.js +53 -45
  176. package/lib/commands/intent.js +149 -91
  177. package/lib/commands/keyboard.js +114 -17
  178. package/lib/commands/lock/exports.js +139 -0
  179. package/lib/commands/lock/helpers.js +379 -0
  180. package/lib/commands/log.js +170 -166
  181. package/lib/commands/media-projection.js +75 -70
  182. package/lib/commands/memory.js +17 -29
  183. package/lib/commands/misc.js +94 -0
  184. package/lib/commands/network.js +209 -223
  185. package/lib/commands/performance.js +88 -73
  186. package/lib/commands/permissions.js +83 -84
  187. package/lib/commands/recordscreen.js +171 -170
  188. package/lib/commands/resources.js +96 -0
  189. package/lib/commands/shell.js +28 -42
  190. package/lib/commands/streamscreen.js +207 -206
  191. package/lib/commands/system-bars.js +76 -77
  192. package/lib/commands/time.js +36 -0
  193. package/lib/commands/touch.js +442 -346
  194. package/lib/commands/types.ts +123 -2
  195. package/lib/doctor/checks.js +24 -16
  196. package/lib/driver.ts +454 -12
  197. package/lib/index.ts +1 -13
  198. package/lib/logger.js +1 -1
  199. package/lib/method-map.js +0 -11
  200. package/lib/utils.js +40 -3
  201. package/package.json +2 -2
  202. package/build/lib/commands/actions.d.ts +0 -8
  203. package/build/lib/commands/actions.d.ts.map +0 -1
  204. package/build/lib/commands/actions.js +0 -207
  205. package/build/lib/commands/actions.js.map +0 -1
  206. package/build/lib/commands/alert.d.ts +0 -8
  207. package/build/lib/commands/alert.d.ts.map +0 -1
  208. package/build/lib/commands/alert.js +0 -29
  209. package/build/lib/commands/alert.js.map +0 -1
  210. package/build/lib/commands/context.d.ts +0 -10
  211. package/build/lib/commands/context.d.ts.map +0 -1
  212. package/build/lib/commands/context.js +0 -431
  213. package/build/lib/commands/context.js.map +0 -1
  214. package/build/lib/commands/emu-console.d.ts +0 -7
  215. package/build/lib/commands/emu-console.d.ts.map +0 -1
  216. package/build/lib/commands/emu-console.js +0 -27
  217. package/build/lib/commands/emu-console.js.map +0 -1
  218. package/build/lib/commands/general.d.ts +0 -9
  219. package/build/lib/commands/general.d.ts.map +0 -1
  220. package/build/lib/commands/general.js +0 -293
  221. package/build/lib/commands/general.js.map +0 -1
  222. package/build/lib/commands/index.d.ts +0 -28
  223. package/build/lib/commands/index.d.ts.map +0 -1
  224. package/build/lib/commands/index.js +0 -57
  225. package/build/lib/commands/index.js.map +0 -1
  226. package/build/lib/commands/mixins.d.ts +0 -747
  227. package/build/lib/commands/mixins.d.ts.map +0 -1
  228. package/build/lib/commands/mixins.js +0 -19
  229. package/build/lib/commands/mixins.js.map +0 -1
  230. package/build/lib/helpers/android.d.ts +0 -163
  231. package/build/lib/helpers/android.d.ts.map +0 -1
  232. package/build/lib/helpers/android.js +0 -818
  233. package/build/lib/helpers/android.js.map +0 -1
  234. package/build/lib/helpers/index.d.ts +0 -7
  235. package/build/lib/helpers/index.d.ts.map +0 -1
  236. package/build/lib/helpers/index.js +0 -29
  237. package/build/lib/helpers/index.js.map +0 -1
  238. package/build/lib/helpers/types.d.ts +0 -122
  239. package/build/lib/helpers/types.d.ts.map +0 -1
  240. package/build/lib/helpers/types.js +0 -3
  241. package/build/lib/helpers/types.js.map +0 -1
  242. package/build/lib/helpers/unlock.d.ts +0 -32
  243. package/build/lib/helpers/unlock.d.ts.map +0 -1
  244. package/build/lib/helpers/unlock.js +0 -273
  245. package/build/lib/helpers/unlock.js.map +0 -1
  246. package/build/lib/helpers/webview.d.ts +0 -74
  247. package/build/lib/helpers/webview.d.ts.map +0 -1
  248. package/build/lib/helpers/webview.js +0 -448
  249. package/build/lib/helpers/webview.js.map +0 -1
  250. package/lib/commands/actions.js +0 -244
  251. package/lib/commands/alert.js +0 -34
  252. package/lib/commands/context.js +0 -507
  253. package/lib/commands/emu-console.js +0 -31
  254. package/lib/commands/general.js +0 -343
  255. package/lib/commands/index.ts +0 -54
  256. package/lib/commands/mixins.ts +0 -976
  257. package/lib/helpers/android.ts +0 -1153
  258. package/lib/helpers/index.ts +0 -6
  259. package/lib/helpers/types.ts +0 -136
  260. package/lib/helpers/unlock.ts +0 -329
  261. package/lib/helpers/webview.ts +0 -610
@@ -1,17 +1,260 @@
1
- // @ts-check
2
-
3
1
  import _ from 'lodash';
4
2
  import {fs, util, zip, tempDir} from '@appium/support';
5
3
  import path from 'path';
6
4
  import {errors} from 'appium/driver';
7
5
  import {requireArgs} from '../utils';
8
- import {mixin} from './mixins';
9
6
 
10
7
  const CONTAINER_PATH_MARKER = '@';
11
8
  // https://regex101.com/r/PLdB0G/2
12
9
  const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`);
13
10
  const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE';
14
11
 
12
+ /**
13
+ * @this {import('../driver').AndroidDriver}
14
+ * @param {string} remotePath
15
+ * @returns {Promise<string>}
16
+ */
17
+ export async function pullFile(remotePath) {
18
+ if (remotePath.endsWith('/')) {
19
+ throw new errors.InvalidArgumentError(
20
+ `It is expected that remote path points to a file and not to a folder. ` +
21
+ `'${remotePath}' is given instead`,
22
+ );
23
+ }
24
+ let tmpDestination = null;
25
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
26
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
27
+ this.log.debug(
28
+ `Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`,
29
+ );
30
+ tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
31
+ try {
32
+ await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
33
+ await this.adb.shell([
34
+ 'run-as',
35
+ packageId,
36
+ `cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`,
37
+ ]);
38
+ } catch (e) {
39
+ this.log.errorAndThrow(
40
+ `Cannot access the container of '${packageId}' application. ` +
41
+ `Is the application installed and has 'debuggable' build option set to true? ` +
42
+ `Original error: ${/** @type {Error} */ (e).message}`,
43
+ );
44
+ }
45
+ }
46
+ const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
47
+ try {
48
+ await this.adb.pull(tmpDestination || remotePath, localFile);
49
+ return (await util.toInMemoryBase64(localFile)).toString();
50
+ } finally {
51
+ if (await fs.exists(localFile)) {
52
+ await fs.unlink(localFile);
53
+ }
54
+ if (tmpDestination) {
55
+ await this.adb.shell(['rm', '-f', tmpDestination]);
56
+ }
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @this {import('../driver').AndroidDriver}
62
+ * @param {import('./types').PullFileOpts} opts
63
+ * @returns {Promise<string>}
64
+ */
65
+ export async function mobilePullFile(opts) {
66
+ const {remotePath} = requireArgs('remotePath', opts);
67
+ return await this.pullFile(remotePath);
68
+ }
69
+
70
+ /**
71
+ * @this {import('../driver').AndroidDriver}
72
+ * @param {string} remotePath
73
+ * @param {string} base64Data
74
+ * @returns {Promise<void>}
75
+ */
76
+ export async function pushFile(remotePath, base64Data) {
77
+ if (remotePath.endsWith('/')) {
78
+ throw new errors.InvalidArgumentError(
79
+ `It is expected that remote path points to a file and not to a folder. ` +
80
+ `'${remotePath}' is given instead`,
81
+ );
82
+ }
83
+ const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
84
+ if (_.isArray(base64Data)) {
85
+ // some clients (ahem) java, send a byte array encoding utf8 characters
86
+ // instead of a string, which would be infinitely better!
87
+ base64Data = Buffer.from(base64Data).toString('utf8');
88
+ }
89
+ const content = Buffer.from(base64Data, 'base64');
90
+ let tmpDestination = null;
91
+ try {
92
+ await fs.writeFile(localFile, content.toString('binary'), 'binary');
93
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
94
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
95
+ this.log.debug(
96
+ `Parsed package identifier '${packageId}' from '${remotePath}'. ` +
97
+ `Will put the data into '${pathInContainer}'`,
98
+ );
99
+ tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
100
+ try {
101
+ await this.adb.shell([
102
+ 'run-as',
103
+ packageId,
104
+ `mkdir -p '${escapePath(path.posix.dirname(pathInContainer))}'`,
105
+ ]);
106
+ await this.adb.shell(['run-as', packageId, `touch '${escapePath(pathInContainer)}'`]);
107
+ await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
108
+ await this.adb.push(localFile, tmpDestination);
109
+ await this.adb.shell([
110
+ 'run-as',
111
+ packageId,
112
+ `cp -f '${escapePath(tmpDestination)}' '${escapePath(pathInContainer)}'`,
113
+ ]);
114
+ } catch (e) {
115
+ this.log.errorAndThrow(
116
+ `Cannot access the container of '${packageId}' application. ` +
117
+ `Is the application installed and has 'debuggable' build option set to true? ` +
118
+ `Original error: ${/** @type {Error} */ (e).message}`,
119
+ );
120
+ }
121
+ } else {
122
+ // adb push creates folders and overwrites existing files.
123
+ await this.adb.push(localFile, remotePath);
124
+
125
+ // if we have pushed a file, it might be a media file, so ensure that
126
+ // apps know about it
127
+ await scanMedia.bind(this)(remotePath);
128
+ }
129
+ } finally {
130
+ if (await fs.exists(localFile)) {
131
+ await fs.unlink(localFile);
132
+ }
133
+ if (tmpDestination) {
134
+ await this.adb.shell(['rm', '-f', tmpDestination]);
135
+ }
136
+ }
137
+ }
138
+
139
+ /**
140
+ * @this {import('../driver').AndroidDriver}
141
+ * @param {import('./types').PushFileOpts} opts
142
+ * @returns {Promise<void>}
143
+ */
144
+ export async function mobilePushFile(opts) {
145
+ const {remotePath, payload} = requireArgs(['remotePath', 'payload'], opts);
146
+ return await this.pushFile(remotePath, payload);
147
+ }
148
+
149
+ /**
150
+ * @this {import('../driver').AndroidDriver}
151
+ * @param {string} remotePath
152
+ * @returns {Promise<string>}
153
+ */
154
+ export async function pullFolder(remotePath) {
155
+ const tmpRoot = await tempDir.openDir();
156
+ try {
157
+ await this.adb.pull(remotePath, tmpRoot);
158
+ return (
159
+ await zip.toInMemoryZip(tmpRoot, {
160
+ encodeToBase64: true,
161
+ })
162
+ ).toString();
163
+ } finally {
164
+ await fs.rimraf(tmpRoot);
165
+ }
166
+ }
167
+
168
+ /**
169
+ * @this {import('../driver').AndroidDriver}
170
+ * @param {import('./types').PullFolderOpts} opts
171
+ * @returns {Promise<string>}
172
+ */
173
+ export async function mobilePullFolder(opts) {
174
+ const {remotePath} = requireArgs('remotePath', opts);
175
+ return await this.pullFolder(remotePath);
176
+ }
177
+
178
+ /**
179
+ * @this {import('../driver').AndroidDriver}
180
+ * @param {import('./types').DeleteFileOpts} opts
181
+ * @returns {Promise<boolean>}
182
+ */
183
+ export async function mobileDeleteFile(opts) {
184
+ const {remotePath} = requireArgs('remotePath', opts);
185
+ if (remotePath.endsWith('/')) {
186
+ throw new errors.InvalidArgumentError(
187
+ `It is expected that remote path points to a folder and not to a file. ` +
188
+ `'${remotePath}' is given instead`,
189
+ );
190
+ }
191
+ return await deleteFileOrFolder.call(this, this.adb, remotePath);
192
+ }
193
+
194
+ /**
195
+ * Deletes the given folder or file from the remote device
196
+ *
197
+ * @param {ADB} adb
198
+ * @param {string} remotePath The full path to the remote folder
199
+ * or file (folder names must end with a single slash)
200
+ * @throws {Error} If the provided remote path is invalid or
201
+ * the package content cannot be accessed
202
+ * @returns {Promise<boolean>} `true` if the remote item has been successfully deleted.
203
+ * If the remote path is valid, but the remote path does not exist
204
+ * this function return `false`.
205
+ * @this {import('../driver').AndroidDriver}
206
+ */
207
+ async function deleteFileOrFolder(adb, remotePath) {
208
+ const {isDir, isPresent, isFile} = createFSTests(adb);
209
+ let dstPath = remotePath;
210
+ /** @type {string|undefined} */
211
+ let pkgId;
212
+ if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
213
+ const [packageId, pathInContainer] = parseContainerPath(remotePath);
214
+ this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'`);
215
+ dstPath = pathInContainer;
216
+ pkgId = packageId;
217
+ }
218
+
219
+ if (pkgId) {
220
+ try {
221
+ await adb.shell(['run-as', pkgId, 'ls']);
222
+ } catch (e) {
223
+ this.log.errorAndThrow(
224
+ `Cannot access the container of '${pkgId}' application. ` +
225
+ `Is the application installed and has 'debuggable' build option set to true? ` +
226
+ `Original error: ${/** @type {Error} */ (e).message}`,
227
+ );
228
+ }
229
+ }
230
+
231
+ if (!(await isPresent(dstPath, pkgId))) {
232
+ this.log.info(`The item at '${dstPath}' does not exist. Perhaps, already deleted?`);
233
+ return false;
234
+ }
235
+
236
+ const expectsFile = !remotePath.endsWith('/');
237
+ if (expectsFile && !(await isFile(dstPath, pkgId))) {
238
+ this.log.errorAndThrow(`The item at '${dstPath}' is not a file`);
239
+ } else if (!expectsFile && !(await isDir(dstPath, pkgId))) {
240
+ this.log.errorAndThrow(`The item at '${dstPath}' is not a folder`);
241
+ }
242
+
243
+ if (pkgId) {
244
+ await adb.shell(['run-as', pkgId, `rm -f${expectsFile ? '' : 'r'} '${escapePath(dstPath)}'`]);
245
+ } else {
246
+ await adb.shell(['rm', `-f${expectsFile ? '' : 'r'}`, dstPath]);
247
+ }
248
+ if (await isPresent(dstPath, pkgId)) {
249
+ this.log.errorAndThrow(
250
+ `The item at '${dstPath}' still exists after being deleted. ` + `Is it writable?`,
251
+ );
252
+ }
253
+ return true;
254
+ }
255
+
256
+ // #region Internal helpers
257
+
15
258
  /**
16
259
  * Parses the actual destination path from the given value
17
260
  *
@@ -26,7 +269,7 @@ function parseContainerPath(remotePath) {
26
269
  if (!match) {
27
270
  throw new Error(
28
271
  `It is expected that package identifier is separated from the relative path with a single slash. ` +
29
- `'${remotePath}' is given instead`
272
+ `'${remotePath}' is given instead`,
30
273
  );
31
274
  }
32
275
  return [match[1], path.posix.resolve(`/data/data/${match[1]}`, match[2])];
@@ -62,7 +305,7 @@ async function scanMedia(remotePath) {
62
305
  this.log.warn(
63
306
  `Ignoring an unexpected error upon media scanning of '${remotePath}': ${
64
307
  err.stderr ?? err.message
65
- }`
308
+ }`,
66
309
  );
67
310
  }
68
311
  }
@@ -78,158 +321,6 @@ function escapePath(p) {
78
321
  return p.replace(/'/g, `\\'`);
79
322
  }
80
323
 
81
- /**
82
- * @type {import('./mixins').FileActionsMixin & ThisType<import('../driver').AndroidDriver>}
83
- * @satisfies {import('@appium/types').ExternalDriver}
84
- */
85
- const FileActionsMixin = {
86
- async pullFile(remotePath) {
87
- if (remotePath.endsWith('/')) {
88
- throw new errors.InvalidArgumentError(
89
- `It is expected that remote path points to a file and not to a folder. ` +
90
- `'${remotePath}' is given instead`
91
- );
92
- }
93
- let tmpDestination = null;
94
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
95
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
96
- this.log.debug(
97
- `Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`
98
- );
99
- tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
100
- try {
101
- await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
102
- await this.adb.shell([
103
- 'run-as',
104
- packageId,
105
- `cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`,
106
- ]);
107
- } catch (e) {
108
- this.log.errorAndThrow(
109
- `Cannot access the container of '${packageId}' application. ` +
110
- `Is the application installed and has 'debuggable' build option set to true? ` +
111
- `Original error: ${/** @type {Error} */ (e).message}`
112
- );
113
- }
114
- }
115
- const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
116
- try {
117
- await this.adb.pull(tmpDestination || remotePath, localFile);
118
- return (await util.toInMemoryBase64(localFile)).toString();
119
- } finally {
120
- if (await fs.exists(localFile)) {
121
- await fs.unlink(localFile);
122
- }
123
- if (tmpDestination) {
124
- await this.adb.shell(['rm', '-f', tmpDestination]);
125
- }
126
- }
127
- },
128
-
129
- async mobilePullFile(opts) {
130
- const {remotePath} = requireArgs('remotePath', opts);
131
- return await this.pullFile(remotePath);
132
- },
133
-
134
- async pushFile(remotePath, base64Data) {
135
- if (remotePath.endsWith('/')) {
136
- throw new errors.InvalidArgumentError(
137
- `It is expected that remote path points to a file and not to a folder. ` +
138
- `'${remotePath}' is given instead`
139
- );
140
- }
141
- const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
142
- if (_.isArray(base64Data)) {
143
- // some clients (ahem) java, send a byte array encoding utf8 characters
144
- // instead of a string, which would be infinitely better!
145
- base64Data = Buffer.from(base64Data).toString('utf8');
146
- }
147
- const content = Buffer.from(base64Data, 'base64');
148
- let tmpDestination = null;
149
- try {
150
- await fs.writeFile(localFile, content.toString('binary'), 'binary');
151
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
152
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
153
- this.log.debug(
154
- `Parsed package identifier '${packageId}' from '${remotePath}'. ` +
155
- `Will put the data into '${pathInContainer}'`
156
- );
157
- tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
158
- try {
159
- await this.adb.shell([
160
- 'run-as',
161
- packageId,
162
- `mkdir -p '${escapePath(path.posix.dirname(pathInContainer))}'`,
163
- ]);
164
- await this.adb.shell(['run-as', packageId, `touch '${escapePath(pathInContainer)}'`]);
165
- await this.adb.shell(['run-as', packageId, `chmod 777 '${escapePath(pathInContainer)}'`]);
166
- await this.adb.push(localFile, tmpDestination);
167
- await this.adb.shell([
168
- 'run-as',
169
- packageId,
170
- `cp -f '${escapePath(tmpDestination)}' '${escapePath(pathInContainer)}'`,
171
- ]);
172
- } catch (e) {
173
- this.log.errorAndThrow(
174
- `Cannot access the container of '${packageId}' application. ` +
175
- `Is the application installed and has 'debuggable' build option set to true? ` +
176
- `Original error: ${/** @type {Error} */ (e).message}`
177
- );
178
- }
179
- } else {
180
- // adb push creates folders and overwrites existing files.
181
- await this.adb.push(localFile, remotePath);
182
-
183
- // if we have pushed a file, it might be a media file, so ensure that
184
- // apps know about it
185
- await scanMedia.bind(this)(remotePath);
186
- }
187
- } finally {
188
- if (await fs.exists(localFile)) {
189
- await fs.unlink(localFile);
190
- }
191
- if (tmpDestination) {
192
- await this.adb.shell(['rm', '-f', tmpDestination]);
193
- }
194
- }
195
- },
196
-
197
- async mobilePushFile(opts) {
198
- const {remotePath, payload} = requireArgs(['remotePath', 'payload'], opts);
199
- return await this.pushFile(remotePath, payload);
200
- },
201
-
202
- async pullFolder(remotePath) {
203
- const tmpRoot = await tempDir.openDir();
204
- try {
205
- await this.adb.pull(remotePath, tmpRoot);
206
- return (
207
- await zip.toInMemoryZip(tmpRoot, {
208
- encodeToBase64: true,
209
- })
210
- ).toString();
211
- } finally {
212
- await fs.rimraf(tmpRoot);
213
- }
214
- },
215
-
216
- async mobilePullFolder(opts) {
217
- const {remotePath} = requireArgs('remotePath', opts);
218
- return await this.pullFolder(remotePath);
219
- },
220
-
221
- async mobileDeleteFile(opts) {
222
- const {remotePath} = requireArgs('remotePath', opts);
223
- if (remotePath.endsWith('/')) {
224
- throw new errors.InvalidArgumentError(
225
- `It is expected that remote path points to a folder and not to a file. ` +
226
- `'${remotePath}' is given instead`
227
- );
228
- }
229
- return await deleteFileOrFolder.call(this, this.adb, remotePath);
230
- },
231
- };
232
-
233
324
  /**
234
325
  * Factory providing filesystem test functions using ADB
235
326
  * @param {ADB} adb
@@ -272,72 +363,8 @@ function createFSTests(adb) {
272
363
  return {isFile, isDir, isPresent};
273
364
  }
274
365
 
275
- /**
276
- * Deletes the given folder or file from the remote device
277
- *
278
- * @param {ADB} adb
279
- * @param {string} remotePath The full path to the remote folder
280
- * or file (folder names must end with a single slash)
281
- * @throws {Error} If the provided remote path is invalid or
282
- * the package content cannot be accessed
283
- * @returns {Promise<boolean>} `true` if the remote item has been successfully deleted.
284
- * If the remote path is valid, but the remote path does not exist
285
- * this function return `false`.
286
- * @this {import('../driver').AndroidDriver}
287
- */
288
- async function deleteFileOrFolder(adb, remotePath) {
289
- const {isDir, isPresent, isFile} = createFSTests(adb);
290
- let dstPath = remotePath;
291
- /** @type {string|undefined} */
292
- let pkgId;
293
- if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
294
- const [packageId, pathInContainer] = parseContainerPath(remotePath);
295
- this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'`);
296
- dstPath = pathInContainer;
297
- pkgId = packageId;
298
- }
299
-
300
- if (pkgId) {
301
- try {
302
- await adb.shell(['run-as', pkgId, 'ls']);
303
- } catch (e) {
304
- this.log.errorAndThrow(
305
- `Cannot access the container of '${pkgId}' application. ` +
306
- `Is the application installed and has 'debuggable' build option set to true? ` +
307
- `Original error: ${/** @type {Error} */ (e).message}`
308
- );
309
- }
310
- }
311
-
312
- if (!(await isPresent(dstPath, pkgId))) {
313
- this.log.info(`The item at '${dstPath}' does not exist. Perhaps, already deleted?`);
314
- return false;
315
- }
316
-
317
- const expectsFile = !remotePath.endsWith('/');
318
- if (expectsFile && !(await isFile(dstPath, pkgId))) {
319
- this.log.errorAndThrow(`The item at '${dstPath}' is not a file`);
320
- } else if (!expectsFile && !(await isDir(dstPath, pkgId))) {
321
- this.log.errorAndThrow(`The item at '${dstPath}' is not a folder`);
322
- }
323
-
324
- if (pkgId) {
325
- await adb.shell(['run-as', pkgId, `rm -f${expectsFile ? '' : 'r'} '${escapePath(dstPath)}'`]);
326
- } else {
327
- await adb.shell(['rm', `-f${expectsFile ? '' : 'r'}`, dstPath]);
328
- }
329
- if (await isPresent(dstPath, pkgId)) {
330
- this.log.errorAndThrow(
331
- `The item at '${dstPath}' still exists after being deleted. ` + `Is it writable?`
332
- );
333
- }
334
- return true;
335
- }
336
-
337
- mixin(FileActionsMixin);
366
+ // #endregion
338
367
 
339
368
  /**
340
369
  * @typedef {import('appium-adb').ADB} ADB
341
370
  */
342
-
343
- export default FileActionsMixin;
@@ -1,35 +1,34 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1
2
  /**
2
- * @privateRemarks This file needed to be converted to TS because the overload of `findElOrEls` is seemingly impossible to express in JS since the value of `this` cannot be bound via a type assertion.
3
3
  * @module
4
4
  */
5
5
 
6
6
  import _ from 'lodash';
7
- import {mixin, type FindMixin} from './mixins';
8
7
  import {errors, isErrorType} from 'appium/driver';
9
8
  import type {AndroidDriver} from '../driver';
10
9
  import type {Element} from '@appium/types';
11
10
  import type {FindElementOpts} from './types';
12
11
 
13
- async function findElOrEls(
12
+ export async function findElOrEls(
14
13
  this: AndroidDriver,
15
14
  strategy: string,
16
15
  selector: string,
17
16
  mult: true,
18
- context?: string
17
+ context?: string,
19
18
  ): Promise<Element[]>;
20
- async function findElOrEls(
19
+ export async function findElOrEls(
21
20
  this: AndroidDriver,
22
21
  strategy: string,
23
22
  selector: string,
24
23
  mult: false,
25
- context?: string
24
+ context?: string,
26
25
  ): Promise<Element>;
27
- async function findElOrEls(
26
+ export async function findElOrEls(
28
27
  this: AndroidDriver,
29
28
  strategy: string,
30
29
  selector: string,
31
30
  mult: boolean,
32
- context = ''
31
+ context = '',
33
32
  ) {
34
33
  if (!selector) {
35
34
  throw new Error('Must provide a selector when finding elements');
@@ -89,14 +88,9 @@ async function findElOrEls(
89
88
  return element as Element;
90
89
  }
91
90
 
92
- const FindMixin: FindMixin & ThisType<AndroidDriver> = {
93
- async doFindElementOrEls(params) {
94
- throw new errors.NotImplementedError('Not implemented');
95
- },
96
-
97
- findElOrEls,
98
- };
99
-
100
- mixin(FindMixin);
101
-
102
- export default FindMixin;
91
+ export async function doFindElementOrEls(
92
+ this: AndroidDriver,
93
+ params: FindElementOpts,
94
+ ): Promise<Element | Element[]> {
95
+ throw new errors.NotImplementedError('Not implemented');
96
+ }