appium-android-driver 5.14.7 → 6.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 (210) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/lib/commands/actions.d.ts +6 -224
  3. package/build/lib/commands/actions.d.ts.map +1 -1
  4. package/build/lib/commands/actions.js +306 -405
  5. package/build/lib/commands/actions.js.map +1 -1
  6. package/build/lib/commands/alert.d.ts +7 -9
  7. package/build/lib/commands/alert.d.ts.map +1 -1
  8. package/build/lib/commands/alert.js +24 -18
  9. package/build/lib/commands/alert.js.map +1 -1
  10. package/build/lib/commands/app-management.d.ts +7 -313
  11. package/build/lib/commands/app-management.d.ts.map +1 -1
  12. package/build/lib/commands/app-management.js +135 -293
  13. package/build/lib/commands/app-management.js.map +1 -1
  14. package/build/lib/commands/context.d.ts +8 -92
  15. package/build/lib/commands/context.d.ts.map +1 -1
  16. package/build/lib/commands/context.js +381 -439
  17. package/build/lib/commands/context.js.map +1 -1
  18. package/build/lib/commands/element.d.ts +8 -35
  19. package/build/lib/commands/element.d.ts.map +1 -1
  20. package/build/lib/commands/element.js +153 -136
  21. package/build/lib/commands/element.js.map +1 -1
  22. package/build/lib/commands/emu-console.d.ts +6 -48
  23. package/build/lib/commands/emu-console.d.ts.map +1 -1
  24. package/build/lib/commands/emu-console.js +19 -34
  25. package/build/lib/commands/emu-console.js.map +1 -1
  26. package/build/lib/commands/execute.d.ts +6 -5
  27. package/build/lib/commands/execute.d.ts.map +1 -1
  28. package/build/lib/commands/execute.js +77 -66
  29. package/build/lib/commands/execute.js.map +1 -1
  30. package/build/lib/commands/file-actions.d.ts +7 -128
  31. package/build/lib/commands/file-actions.d.ts.map +1 -1
  32. package/build/lib/commands/file-actions.js +183 -219
  33. package/build/lib/commands/file-actions.js.map +1 -1
  34. package/build/lib/commands/find.d.ts +8 -12
  35. package/build/lib/commands/find.d.ts.map +1 -1
  36. package/build/lib/commands/find.js +19 -23
  37. package/build/lib/commands/find.js.map +1 -1
  38. package/build/lib/commands/general.d.ts +9 -132
  39. package/build/lib/commands/general.d.ts.map +1 -1
  40. package/build/lib/commands/general.js +281 -312
  41. package/build/lib/commands/general.js.map +1 -1
  42. package/build/lib/commands/ime.d.ts +7 -10
  43. package/build/lib/commands/ime.d.ts.map +1 -1
  44. package/build/lib/commands/ime.js +47 -35
  45. package/build/lib/commands/ime.js.map +1 -1
  46. package/build/lib/commands/index.d.ts +27 -2
  47. package/build/lib/commands/index.d.ts.map +1 -1
  48. package/build/lib/commands/index.js +41 -19
  49. package/build/lib/commands/index.js.map +1 -1
  50. package/build/lib/commands/intent.d.ts +7 -417
  51. package/build/lib/commands/intent.d.ts.map +1 -1
  52. package/build/lib/commands/intent.js +104 -216
  53. package/build/lib/commands/intent.js.map +1 -1
  54. package/build/lib/commands/keyboard.d.ts +6 -5
  55. package/build/lib/commands/keyboard.d.ts.map +1 -1
  56. package/build/lib/commands/keyboard.js +16 -8
  57. package/build/lib/commands/keyboard.js.map +1 -1
  58. package/build/lib/commands/log.d.ts +7 -44
  59. package/build/lib/commands/log.d.ts.map +1 -1
  60. package/build/lib/commands/log.js +146 -108
  61. package/build/lib/commands/log.js.map +1 -1
  62. package/build/lib/commands/media-projection.d.ts +7 -143
  63. package/build/lib/commands/media-projection.d.ts.map +1 -1
  64. package/build/lib/commands/media-projection.js +113 -140
  65. package/build/lib/commands/media-projection.js.map +1 -1
  66. package/build/lib/commands/mixins.d.ts +740 -0
  67. package/build/lib/commands/mixins.d.ts.map +1 -0
  68. package/build/lib/commands/mixins.js +19 -0
  69. package/build/lib/commands/mixins.js.map +1 -0
  70. package/build/lib/commands/network.d.ts +7 -138
  71. package/build/lib/commands/network.d.ts.map +1 -1
  72. package/build/lib/commands/network.js +212 -254
  73. package/build/lib/commands/network.js.map +1 -1
  74. package/build/lib/commands/performance.d.ts +24 -70
  75. package/build/lib/commands/performance.d.ts.map +1 -1
  76. package/build/lib/commands/performance.js +144 -100
  77. package/build/lib/commands/performance.js.map +1 -1
  78. package/build/lib/commands/permissions.d.ts +8 -92
  79. package/build/lib/commands/permissions.d.ts.map +1 -1
  80. package/build/lib/commands/permissions.js +75 -87
  81. package/build/lib/commands/permissions.js.map +1 -1
  82. package/build/lib/commands/recordscreen.d.ts +7 -193
  83. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  84. package/build/lib/commands/recordscreen.js +151 -182
  85. package/build/lib/commands/recordscreen.js.map +1 -1
  86. package/build/lib/commands/shell.d.ts +7 -7
  87. package/build/lib/commands/shell.d.ts.map +1 -1
  88. package/build/lib/commands/shell.js +40 -33
  89. package/build/lib/commands/shell.js.map +1 -1
  90. package/build/lib/commands/streamscreen.d.ts +9 -103
  91. package/build/lib/commands/streamscreen.d.ts.map +1 -1
  92. package/build/lib/commands/streamscreen.js +261 -218
  93. package/build/lib/commands/streamscreen.js.map +1 -1
  94. package/build/lib/commands/system-bars.d.ts +22 -90
  95. package/build/lib/commands/system-bars.d.ts.map +1 -1
  96. package/build/lib/commands/system-bars.js +76 -74
  97. package/build/lib/commands/system-bars.js.map +1 -1
  98. package/build/lib/commands/touch.d.ts +10 -29
  99. package/build/lib/commands/touch.d.ts.map +1 -1
  100. package/build/lib/commands/touch.js +301 -285
  101. package/build/lib/commands/touch.js.map +1 -1
  102. package/build/lib/commands/types.d.ts +978 -0
  103. package/build/lib/commands/types.d.ts.map +1 -0
  104. package/build/lib/commands/types.js +3 -0
  105. package/build/lib/commands/types.js.map +1 -0
  106. package/build/lib/constraints.d.ts +291 -0
  107. package/build/lib/constraints.d.ts.map +1 -0
  108. package/build/lib/{desired-caps.js → constraints.js} +103 -102
  109. package/build/lib/constraints.js.map +1 -0
  110. package/build/lib/driver.d.ts +68 -37
  111. package/build/lib/driver.d.ts.map +1 -1
  112. package/build/lib/driver.js +123 -80
  113. package/build/lib/driver.js.map +1 -1
  114. package/build/lib/helpers/android.d.ts +164 -0
  115. package/build/lib/helpers/android.d.ts.map +1 -0
  116. package/build/lib/helpers/android.js +819 -0
  117. package/build/lib/helpers/android.js.map +1 -0
  118. package/build/lib/helpers/index.d.ts +7 -0
  119. package/build/lib/helpers/index.d.ts.map +1 -0
  120. package/build/lib/helpers/index.js +29 -0
  121. package/build/lib/helpers/index.js.map +1 -0
  122. package/build/lib/helpers/types.d.ts +121 -0
  123. package/build/lib/helpers/types.d.ts.map +1 -0
  124. package/build/lib/helpers/types.js +3 -0
  125. package/build/lib/helpers/types.js.map +1 -0
  126. package/build/lib/helpers/unlock.d.ts +32 -0
  127. package/build/lib/helpers/unlock.d.ts.map +1 -0
  128. package/build/lib/helpers/unlock.js +273 -0
  129. package/build/lib/helpers/unlock.js.map +1 -0
  130. package/build/lib/helpers/webview.d.ts +74 -0
  131. package/build/lib/helpers/webview.d.ts.map +1 -0
  132. package/build/lib/helpers/webview.js +421 -0
  133. package/build/lib/helpers/webview.js.map +1 -0
  134. package/build/lib/index.d.ts +9 -0
  135. package/build/lib/index.d.ts.map +1 -0
  136. package/build/lib/index.js +37 -0
  137. package/build/lib/index.js.map +1 -0
  138. package/build/lib/method-map.d.ts +0 -8
  139. package/build/lib/method-map.d.ts.map +1 -1
  140. package/build/lib/method-map.js +63 -74
  141. package/build/lib/method-map.js.map +1 -1
  142. package/build/lib/stubs.d.ts +0 -1
  143. package/build/lib/stubs.d.ts.map +1 -1
  144. package/build/lib/stubs.js +1 -0
  145. package/build/lib/stubs.js.map +1 -1
  146. package/build/lib/utils.d.ts +1 -1
  147. package/build/lib/utils.d.ts.map +1 -1
  148. package/lib/commands/actions.js +351 -464
  149. package/lib/commands/alert.js +27 -17
  150. package/lib/commands/app-management.js +156 -314
  151. package/lib/commands/context.js +457 -441
  152. package/lib/commands/element.js +201 -157
  153. package/lib/commands/emu-console.js +25 -45
  154. package/lib/commands/execute.js +106 -90
  155. package/lib/commands/file-actions.js +222 -240
  156. package/lib/commands/find.ts +103 -0
  157. package/lib/commands/general.js +327 -339
  158. package/lib/commands/ime.js +50 -34
  159. package/lib/commands/{index.js → index.ts} +20 -24
  160. package/lib/commands/intent.js +108 -249
  161. package/lib/commands/keyboard.js +20 -8
  162. package/lib/commands/log.js +172 -116
  163. package/lib/commands/media-projection.js +134 -161
  164. package/lib/commands/mixins.ts +966 -0
  165. package/lib/commands/network.js +252 -281
  166. package/lib/commands/performance.js +203 -132
  167. package/lib/commands/permissions.js +108 -109
  168. package/lib/commands/recordscreen.js +212 -209
  169. package/lib/commands/shell.js +51 -40
  170. package/lib/commands/streamscreen.js +355 -289
  171. package/lib/commands/system-bars.js +92 -83
  172. package/lib/commands/touch.js +357 -294
  173. package/lib/commands/types.ts +1097 -0
  174. package/lib/{desired-caps.js → constraints.ts} +106 -103
  175. package/lib/{driver.js → driver.ts} +278 -132
  176. package/lib/helpers/android.ts +1143 -0
  177. package/lib/helpers/index.ts +6 -0
  178. package/lib/helpers/types.ts +134 -0
  179. package/lib/helpers/unlock.ts +329 -0
  180. package/lib/helpers/webview.ts +582 -0
  181. package/lib/index.ts +18 -0
  182. package/lib/method-map.js +87 -98
  183. package/lib/stubs.ts +0 -1
  184. package/package.json +26 -19
  185. package/build/index.js +0 -51
  186. package/build/lib/android-helpers.d.ts +0 -136
  187. package/build/lib/android-helpers.d.ts.map +0 -1
  188. package/build/lib/android-helpers.js +0 -855
  189. package/build/lib/android-helpers.js.map +0 -1
  190. package/build/lib/commands/coverage.d.ts +0 -5
  191. package/build/lib/commands/coverage.d.ts.map +0 -1
  192. package/build/lib/commands/coverage.js +0 -19
  193. package/build/lib/commands/coverage.js.map +0 -1
  194. package/build/lib/desired-caps.d.ts +0 -353
  195. package/build/lib/desired-caps.d.ts.map +0 -1
  196. package/build/lib/desired-caps.js.map +0 -1
  197. package/build/lib/unlock-helpers.d.ts +0 -38
  198. package/build/lib/unlock-helpers.d.ts.map +0 -1
  199. package/build/lib/unlock-helpers.js +0 -266
  200. package/build/lib/unlock-helpers.js.map +0 -1
  201. package/build/lib/webview-helpers.d.ts +0 -224
  202. package/build/lib/webview-helpers.d.ts.map +0 -1
  203. package/build/lib/webview-helpers.js +0 -528
  204. package/build/lib/webview-helpers.js.map +0 -1
  205. package/index.js +0 -24
  206. package/lib/android-helpers.js +0 -983
  207. package/lib/commands/coverage.js +0 -18
  208. package/lib/commands/find.js +0 -82
  209. package/lib/unlock-helpers.js +0 -278
  210. package/lib/webview-helpers.js +0 -602
@@ -1,13 +1,13 @@
1
- import _ from 'lodash';
2
- import { waitForCondition } from 'asyncbox';
3
- import { util, fs, net, tempDir } from '@appium/support';
4
- import path from 'path';
1
+ // @ts-check
2
+
3
+ import {fs, net, tempDir, util} from '@appium/support';
4
+ import {waitForCondition} from 'asyncbox';
5
5
  import B from 'bluebird';
6
- import { SETTINGS_HELPER_PKG_ID } from '../android-helpers';
6
+ import _ from 'lodash';
7
7
  import moment from 'moment';
8
-
9
-
10
- const commands = {};
8
+ import path from 'node:path';
9
+ import {SETTINGS_HELPER_PKG_ID} from '../helpers';
10
+ import {mixin} from './mixins';
11
11
 
12
12
  // https://github.com/appium/io.appium.settings#internal-audio--video-recording
13
13
  const DEFAULT_EXT = '.mp4';
@@ -21,8 +21,14 @@ const RECORDING_ACTION_STOP = `${SETTINGS_HELPER_PKG_ID}.recording.ACTION_STOP`;
21
21
  const RECORDINGS_ROOT = `/storage/emulated/0/Android/data/${SETTINGS_HELPER_PKG_ID}/files`;
22
22
  const DEFAULT_FILENAME_FORMAT = 'YYYY-MM-DDTHH-mm-ss';
23
23
 
24
-
25
- async function uploadRecordedMedia (localFile, remotePath = null, uploadOptions = {}) {
24
+ /**
25
+ *
26
+ * @param {string} localFile
27
+ * @param {string} [remotePath]
28
+ * @param {import('./types').StopMediaProjectionRecordingOpts} uploadOptions
29
+ * @returns
30
+ */
31
+ async function uploadRecordedMedia(localFile, remotePath, uploadOptions = {}) {
26
32
  if (_.isEmpty(remotePath)) {
27
33
  return (await util.toInMemoryBase64(localFile)).toString();
28
34
  }
@@ -36,6 +42,9 @@ async function uploadRecordedMedia (localFile, remotePath = null, uploadOptions
36
42
  formFields,
37
43
  uploadTimeout: timeout,
38
44
  } = uploadOptions;
45
+ /**
46
+ * @type {Omit<import('./types').StopMediaProjectionRecordingOpts, 'uploadTimeout'> & {auth?: {user: string, pass: string}, timeout?: number}}
47
+ */
39
48
  const options = {
40
49
  method: method || 'PUT',
41
50
  headers,
@@ -46,52 +55,64 @@ async function uploadRecordedMedia (localFile, remotePath = null, uploadOptions
46
55
  if (user && pass) {
47
56
  options.auth = {user, pass};
48
57
  }
49
- await net.uploadFile(localFile, remotePath, options);
58
+ await net.uploadFile(localFile, /** @type {string} */ (remotePath), options);
50
59
  return '';
51
60
  }
52
61
 
53
- function adjustMediaExtension (name) {
62
+ /**
63
+ *
64
+ * @param {string} name
65
+ * @returns {string}
66
+ */
67
+ function adjustMediaExtension(name) {
54
68
  return _.toLower(name).endsWith(DEFAULT_EXT) ? name : `${name}${DEFAULT_EXT}`;
55
69
  }
56
70
 
57
- async function verifyMediaProjectionRecordingIsSupported (adb) {
71
+ /**
72
+ *
73
+ * @param {ADB} adb
74
+ */
75
+ async function verifyMediaProjectionRecordingIsSupported(adb) {
58
76
  const apiLevel = await adb.getApiLevel();
59
77
  if (apiLevel < MIN_API_LEVEL) {
60
- throw new Error(`Media projection-based recording is not available on API Level ${apiLevel}. ` +
61
- `Minimum required API Level is ${MIN_API_LEVEL}.`);
78
+ throw new Error(
79
+ `Media projection-based recording is not available on API Level ${apiLevel}. ` +
80
+ `Minimum required API Level is ${MIN_API_LEVEL}.`
81
+ );
62
82
  }
63
83
  }
64
84
 
65
-
66
85
  class MediaProjectionRecorder {
67
- constructor (adb) {
86
+ /**
87
+ * @param {ADB} adb
88
+ */
89
+ constructor(adb) {
68
90
  this.adb = adb;
69
91
  }
70
92
 
71
- async isRunning () {
93
+ async isRunning() {
72
94
  const stdout = await this.adb.shell([
73
- 'dumpsys', 'activity', 'services', RECORDING_SERVICE_NAME
95
+ 'dumpsys',
96
+ 'activity',
97
+ 'services',
98
+ RECORDING_SERVICE_NAME,
74
99
  ]);
75
100
  return stdout.includes(RECORDING_SERVICE_NAME);
76
101
  }
77
102
 
78
- async start (opts = {}) {
103
+ /**
104
+ *
105
+ * @param {import('./types').StartMediaProjectionRecordingOpts} opts
106
+ * @returns {Promise<boolean>}
107
+ */
108
+ async start(opts = {}) {
79
109
  if (await this.isRunning()) {
80
110
  return false;
81
111
  }
82
112
 
83
113
  await this.cleanup();
84
- const {
85
- filename,
86
- maxDurationSec,
87
- priority,
88
- resolution,
89
- } = opts;
90
- const args = [
91
- 'am', 'start',
92
- '-n', RECORDING_ACTIVITY_NAME,
93
- '-a', RECORDING_ACTION_START,
94
- ];
114
+ const {filename, maxDurationSec, priority, resolution} = opts;
115
+ const args = ['am', 'start', '-n', RECORDING_ACTIVITY_NAME, '-a', RECORDING_ACTION_START];
95
116
  if (filename) {
96
117
  args.push('--es', 'filename', filename);
97
118
  }
@@ -107,11 +128,13 @@ class MediaProjectionRecorder {
107
128
  await this.adb.shell(args);
108
129
  await new B((resolve, reject) => {
109
130
  setTimeout(async () => {
110
- if (!await this.isRunning()) {
111
- return reject(new Error(
112
- `The media projection recording is not running after ${RECORDING_STARTUP_TIMEOUT_MS}ms. ` +
113
- `Please check the logcat output for more details.`
114
- ));
131
+ if (!(await this.isRunning())) {
132
+ return reject(
133
+ new Error(
134
+ `The media projection recording is not running after ${RECORDING_STARTUP_TIMEOUT_MS}ms. ` +
135
+ `Please check the logcat output for more details.`
136
+ )
137
+ );
115
138
  }
116
139
  resolve();
117
140
  }, RECORDING_STARTUP_TIMEOUT_MS);
@@ -119,11 +142,11 @@ class MediaProjectionRecorder {
119
142
  return true;
120
143
  }
121
144
 
122
- async cleanup () {
145
+ async cleanup() {
123
146
  await this.adb.shell([`rm -f ${RECORDINGS_ROOT}/*`]);
124
147
  }
125
148
 
126
- async pullRecent () {
149
+ async pullRecent() {
127
150
  const recordings = await this.adb.ls(RECORDINGS_ROOT, ['-tr']);
128
151
  if (_.isEmpty(recordings)) {
129
152
  return null;
@@ -135,15 +158,18 @@ class MediaProjectionRecorder {
135
158
  return dstPath;
136
159
  }
137
160
 
138
- async stop () {
139
- if (!await this.isRunning()) {
161
+ async stop() {
162
+ if (!(await this.isRunning())) {
140
163
  return false;
141
164
  }
142
165
 
143
166
  await this.adb.shell([
144
- 'am', 'start',
145
- '-n', RECORDING_ACTIVITY_NAME,
146
- '-a', RECORDING_ACTION_STOP,
167
+ 'am',
168
+ 'start',
169
+ '-n',
170
+ RECORDING_ACTIVITY_NAME,
171
+ '-a',
172
+ RECORDING_ACTION_STOP,
147
173
  ]);
148
174
  try {
149
175
  await waitForCondition(async () => !(await this.isRunning()), {
@@ -153,137 +179,84 @@ class MediaProjectionRecorder {
153
179
  } catch (e) {
154
180
  throw new Error(
155
181
  `The attempt to stop the current media projection recording timed out after ` +
156
- `${RECORDING_STOP_TIMEOUT_MS}ms`
182
+ `${RECORDING_STOP_TIMEOUT_MS}ms`
157
183
  );
158
184
  }
159
185
  return true;
160
186
  }
161
187
  }
162
-
163
-
164
188
  /**
165
- * @typedef {Object} StartRecordingOptions
166
- *
167
- * @property {string?} resolution Maximum supported resolution on-device (Detected
168
- * automatically by the app itself), which usually equals to Full HD 1920x1080 on most
169
- * phones however you can change it to following supported resolutions
170
- * as well: "1920x1080", "1280x720", "720x480", "320x240", "176x144".
171
- * @property {number?} maxDurationSec [900] Default value: 900 seconds which means
172
- * maximum allowed duration is 15 minute, you can increase it if your test takes
173
- * longer than that.
174
- * @property {string?} priority [high] Means recording thread priority is maximum
175
- * however if you face performance drops during testing with recording enabled, you
176
- * can reduce recording priority to "normal" or "low".
177
- * @property {string?} filename You can type recording video file name as you want,
178
- * but recording currently supports only "mp4" format so your filename must end with ".mp4".
179
- * An invalid file name will fail to start the recording.
180
- * If not provided then the current timestamp will be used as file name.
189
+ * @type {import('./mixins').MediaProjectionMixin & ThisType<import('../driver').AndroidDriver>}
190
+ * @satisfies {import('@appium/types').ExternalDriver}
181
191
  */
192
+ const MediaProjectionMixin = {
193
+ async mobileStartMediaProjectionRecording(options = {}) {
194
+ const adb = /** @type {ADB} */ (this.adb);
195
+ await verifyMediaProjectionRecordingIsSupported(adb);
182
196
 
183
- /**
184
- * Record the display of a real devices running Android 10 (API level 29) and higher.
185
- * The screen activity is recorded to a MPEG-4 file. Audio is also recorded by default
186
- * (only for apps that allow it in their manifests).
187
- * If another recording has been already started then the command will exit silently.
188
- * The previously recorded video file is deleted when a new recording session is started.
189
- * Recording continues it is stopped explicitly or until the timeout happens.
190
- *
191
- * @param {?StartRecordingOptions} options Available options.
192
- * @returns {boolean} True if a new recording has successfully started.
193
- * @throws {Error} If recording has failed to start or is not supported on the device under test.
194
- */
195
- commands.mobileStartMediaProjectionRecording = async function mobileStartMediaProjectionRecording (options = {}) {
196
- await verifyMediaProjectionRecordingIsSupported(this.adb);
197
-
198
- const {resolution, priority, maxDurationSec, filename} = options;
199
- const recorder = new MediaProjectionRecorder(this.adb);
200
- const fname = adjustMediaExtension(filename || moment().format(DEFAULT_FILENAME_FORMAT));
201
- const didStart = await recorder.start({
202
- resolution,
203
- priority,
204
- maxDurationSec,
205
- filename: fname,
206
- });
207
- if (didStart) {
208
- this.log.info(`A new media projection recording '${fname}' has been successfully started`);
209
- } else {
210
- this.log.info('Another media projection recording is already in progress. There is nothing to start');
211
- }
212
- return didStart;
213
- };
214
-
215
- /**
216
- * Checks if a media projection-based recording is currently running.
217
- *
218
- * @returns {boolean} True if a recording is in progress.
219
- * @throws {Error} If a recording is not supported on the device under test.
220
- */
221
- commands.mobileIsMediaProjectionRecordingRunning = async function mobileIsMediaProjectionRecordingRunning () {
222
- await verifyMediaProjectionRecordingIsSupported(this.adb);
197
+ const {resolution, priority, maxDurationSec, filename} = options;
198
+ const recorder = new MediaProjectionRecorder(adb);
199
+ const fname = adjustMediaExtension(filename || moment().format(DEFAULT_FILENAME_FORMAT));
200
+ const didStart = await recorder.start({
201
+ resolution,
202
+ priority,
203
+ maxDurationSec,
204
+ filename: fname,
205
+ });
206
+ if (didStart) {
207
+ this.log.info(`A new media projection recording '${fname}' has been successfully started`);
208
+ } else {
209
+ this.log.info(
210
+ 'Another media projection recording is already in progress. There is nothing to start'
211
+ );
212
+ }
213
+ return didStart;
214
+ },
223
215
 
224
- const recorder = new MediaProjectionRecorder(this.adb);
225
- return await recorder.isRunning();
226
- };
216
+ async mobileIsMediaProjectionRecordingRunning() {
217
+ const adb = /** @type {ADB} */ (this.adb);
218
+ await verifyMediaProjectionRecordingIsSupported(adb);
227
219
 
228
- /**
229
- * @typedef {Object} StopRecordingOptions
230
- *
231
- * @property {string?} remotePath The path to the remote location, where the resulting video should be uploaded.
232
- * The following protocols are supported: http/https, ftp.
233
- * Null or empty string value (the default setting) means the content of resulting
234
- * file should be encoded as Base64 and passed as the endpoont response value.
235
- * An exception will be thrown if the generated media file is too big to
236
- * fit into the available process memory.
237
- * @property {string?} user The name of the user for the remote authentication.
238
- * @property {string?} pass The password for the remote authentication.
239
- * @property {string?} method The http multipart upload method name. The 'PUT' one is used by default.
240
- * @property {Object?} headers Additional headers mapping for multipart http(s) uploads
241
- * @property {string?} fileFieldName [file] The name of the form field, where the file content BLOB should be stored for
242
- * http(s) uploads
243
- * @property {Object|Array<Pair>?} formFields Additional form fields for multipart http(s) uploads
244
- * @property {number?} uploadTimeout - The actual media upload request timeout in milliseconds;
245
- * defaults to @appium/support net DEFAULT_TIMEOUT_MS
246
- */
220
+ const recorder = new MediaProjectionRecorder(adb);
221
+ return await recorder.isRunning();
222
+ },
247
223
 
248
- /**
249
- * Stop a media projection-based recording.
250
- * If no recording has been started before then an error is thrown.
251
- * If the recording has been already finished before this API has been called
252
- * then the most recent recorded file is returned.
253
- *
254
- * @param {?StopRecordingOptions} options Available options.
255
- * @returns {string} Base64-encoded content of the recorded media file if 'remotePath'
256
- * parameter is falsy or an empty string.
257
- * @throws {Error} If there was an error while stopping a recording,
258
- * fetching the content of the remote media file,
259
- * or if a recording is not supported on the device under test.
260
- */
261
- commands.mobileStopMediaProjectionRecording = async function mobileStopMediaProjectionRecording (options = {}) {
262
- await verifyMediaProjectionRecordingIsSupported(this.adb);
224
+ async mobileStopMediaProjectionRecording(options = {}) {
225
+ const adb = /** @type {ADB} */ (this.adb);
226
+ await verifyMediaProjectionRecordingIsSupported(adb);
263
227
 
264
- const recorder = new MediaProjectionRecorder(this.adb);
265
- if (await recorder.stop()) {
266
- this.log.info('Successfully stopped a media projection recording. Pulling the recorded media');
267
- } else {
268
- this.log.info('Media projection recording is not running. There is nothing to stop');
269
- }
270
- const recentRecordingPath = await recorder.pullRecent();
271
- if (!recentRecordingPath) {
272
- throw new Error(`No recent media projection recording have been found. Did you start any?`);
273
- }
228
+ const recorder = new MediaProjectionRecorder(adb);
229
+ if (await recorder.stop()) {
230
+ this.log.info(
231
+ 'Successfully stopped a media projection recording. Pulling the recorded media'
232
+ );
233
+ } else {
234
+ this.log.info('Media projection recording is not running. There is nothing to stop');
235
+ }
236
+ const recentRecordingPath = await recorder.pullRecent();
237
+ if (!recentRecordingPath) {
238
+ throw new Error(`No recent media projection recording have been found. Did you start any?`);
239
+ }
274
240
 
275
- const {remotePath} = options;
276
- if (_.isEmpty(remotePath)) {
277
- const {size} = await fs.stat(recentRecordingPath);
278
- this.log.debug(`The size of the resulting media projection recording is ${util.toReadableSizeString(size)}`);
279
- }
280
- try {
281
- return await uploadRecordedMedia(recentRecordingPath, remotePath, options);
282
- } finally {
283
- await fs.rimraf(path.dirname(recentRecordingPath));
284
- }
241
+ const {remotePath} = options;
242
+ if (_.isEmpty(remotePath)) {
243
+ const {size} = await fs.stat(recentRecordingPath);
244
+ this.log.debug(
245
+ `The size of the resulting media projection recording is ${util.toReadableSizeString(size)}`
246
+ );
247
+ }
248
+ try {
249
+ return await uploadRecordedMedia(recentRecordingPath, remotePath, options);
250
+ } finally {
251
+ await fs.rimraf(path.dirname(recentRecordingPath));
252
+ }
253
+ },
285
254
  };
286
255
 
256
+ mixin(MediaProjectionMixin);
287
257
 
288
- export { commands };
289
- export default commands;
258
+ export default MediaProjectionMixin;
259
+
260
+ /**
261
+ * @typedef {import('appium-adb').ADB} ADB
262
+ */