appium-xcuitest-driver 10.3.0 → 10.4.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 (257) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/active-app-info.d.ts +9 -0
  3. package/build/lib/commands/active-app-info.d.ts.map +1 -0
  4. package/build/lib/commands/active-app-info.js +14 -0
  5. package/build/lib/commands/active-app-info.js.map +1 -0
  6. package/build/lib/commands/alert.d.ts +42 -45
  7. package/build/lib/commands/alert.d.ts.map +1 -1
  8. package/build/lib/commands/alert.js +66 -62
  9. package/build/lib/commands/alert.js.map +1 -1
  10. package/build/lib/commands/app-management.d.ts +150 -153
  11. package/build/lib/commands/app-management.d.ts.map +1 -1
  12. package/build/lib/commands/app-management.js +300 -286
  13. package/build/lib/commands/app-management.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +14 -17
  15. package/build/lib/commands/app-strings.d.ts.map +1 -1
  16. package/build/lib/commands/app-strings.js +23 -24
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/appearance.d.ts +19 -22
  19. package/build/lib/commands/appearance.d.ts.map +1 -1
  20. package/build/lib/commands/appearance.js +56 -56
  21. package/build/lib/commands/appearance.js.map +1 -1
  22. package/build/lib/commands/audit.d.ts +22 -17
  23. package/build/lib/commands/audit.d.ts.map +1 -1
  24. package/build/lib/commands/audit.js +17 -18
  25. package/build/lib/commands/audit.js.map +1 -1
  26. package/build/lib/commands/battery.d.ts +11 -14
  27. package/build/lib/commands/battery.d.ts.map +1 -1
  28. package/build/lib/commands/battery.js +36 -37
  29. package/build/lib/commands/battery.js.map +1 -1
  30. package/build/lib/commands/biometric.d.ts +30 -33
  31. package/build/lib/commands/biometric.d.ts.map +1 -1
  32. package/build/lib/commands/biometric.js +42 -41
  33. package/build/lib/commands/biometric.js.map +1 -1
  34. package/build/lib/commands/certificate.d.ts +48 -45
  35. package/build/lib/commands/certificate.d.ts.map +1 -1
  36. package/build/lib/commands/certificate.js +218 -205
  37. package/build/lib/commands/certificate.js.map +1 -1
  38. package/build/lib/commands/clipboard.d.ts +19 -22
  39. package/build/lib/commands/clipboard.d.ts.map +1 -1
  40. package/build/lib/commands/clipboard.js +30 -30
  41. package/build/lib/commands/clipboard.js.map +1 -1
  42. package/build/lib/commands/condition.d.ts +49 -26
  43. package/build/lib/commands/condition.d.ts.map +1 -1
  44. package/build/lib/commands/condition.js +87 -86
  45. package/build/lib/commands/condition.js.map +1 -1
  46. package/build/lib/commands/content-size.d.ts +26 -29
  47. package/build/lib/commands/content-size.d.ts.map +1 -1
  48. package/build/lib/commands/content-size.js +36 -36
  49. package/build/lib/commands/content-size.js.map +1 -1
  50. package/build/lib/commands/context.d.ts +161 -108
  51. package/build/lib/commands/context.d.ts.map +1 -1
  52. package/build/lib/commands/context.js +530 -517
  53. package/build/lib/commands/context.js.map +1 -1
  54. package/build/lib/commands/deviceInfo.d.ts +9 -12
  55. package/build/lib/commands/deviceInfo.d.ts.map +1 -1
  56. package/build/lib/commands/deviceInfo.js +17 -18
  57. package/build/lib/commands/deviceInfo.js.map +1 -1
  58. package/build/lib/commands/element.d.ts +102 -105
  59. package/build/lib/commands/element.d.ts.map +1 -1
  60. package/build/lib/commands/element.js +337 -323
  61. package/build/lib/commands/element.js.map +1 -1
  62. package/build/lib/commands/execute.d.ts +24 -19
  63. package/build/lib/commands/execute.d.ts.map +1 -1
  64. package/build/lib/commands/execute.js +63 -62
  65. package/build/lib/commands/execute.js.map +1 -1
  66. package/build/lib/commands/file-movement.d.ts +77 -80
  67. package/build/lib/commands/file-movement.d.ts.map +1 -1
  68. package/build/lib/commands/file-movement.js +130 -124
  69. package/build/lib/commands/file-movement.js.map +1 -1
  70. package/build/lib/commands/find.d.ts +18 -21
  71. package/build/lib/commands/find.d.ts.map +1 -1
  72. package/build/lib/commands/find.js +158 -156
  73. package/build/lib/commands/find.js.map +1 -1
  74. package/build/lib/commands/general.d.ts +124 -116
  75. package/build/lib/commands/general.d.ts.map +1 -1
  76. package/build/lib/commands/general.js +248 -232
  77. package/build/lib/commands/general.js.map +1 -1
  78. package/build/lib/commands/geolocation.d.ts +43 -46
  79. package/build/lib/commands/geolocation.d.ts.map +1 -1
  80. package/build/lib/commands/geolocation.js +10 -11
  81. package/build/lib/commands/geolocation.js.map +1 -1
  82. package/build/lib/commands/gesture.d.ts +273 -276
  83. package/build/lib/commands/gesture.d.ts.map +1 -1
  84. package/build/lib/commands/gesture.js +506 -492
  85. package/build/lib/commands/gesture.js.map +1 -1
  86. package/build/lib/commands/increase-contrast.d.ts +20 -23
  87. package/build/lib/commands/increase-contrast.d.ts.map +1 -1
  88. package/build/lib/commands/increase-contrast.js +30 -30
  89. package/build/lib/commands/increase-contrast.js.map +1 -1
  90. package/build/lib/commands/iohid.d.ts +1370 -1373
  91. package/build/lib/commands/iohid.d.ts.map +1 -1
  92. package/build/lib/commands/iohid.js +30 -31
  93. package/build/lib/commands/iohid.js.map +1 -1
  94. package/build/lib/commands/keyboard.d.ts +29 -32
  95. package/build/lib/commands/keyboard.d.ts.map +1 -1
  96. package/build/lib/commands/keyboard.js +53 -51
  97. package/build/lib/commands/keyboard.js.map +1 -1
  98. package/build/lib/commands/keychains.d.ts +9 -12
  99. package/build/lib/commands/keychains.d.ts.map +1 -1
  100. package/build/lib/commands/keychains.js +13 -14
  101. package/build/lib/commands/keychains.js.map +1 -1
  102. package/build/lib/commands/localization.d.ts +16 -19
  103. package/build/lib/commands/localization.d.ts.map +1 -1
  104. package/build/lib/commands/localization.js +25 -26
  105. package/build/lib/commands/localization.js.map +1 -1
  106. package/build/lib/commands/location.d.ts +36 -39
  107. package/build/lib/commands/location.d.ts.map +1 -1
  108. package/build/lib/commands/location.js +99 -98
  109. package/build/lib/commands/location.js.map +1 -1
  110. package/build/lib/commands/lock.d.ts +21 -24
  111. package/build/lib/commands/lock.d.ts.map +1 -1
  112. package/build/lib/commands/lock.js +39 -38
  113. package/build/lib/commands/lock.js.map +1 -1
  114. package/build/lib/commands/log.d.ts +43 -37
  115. package/build/lib/commands/log.d.ts.map +1 -1
  116. package/build/lib/commands/log.js +174 -171
  117. package/build/lib/commands/log.js.map +1 -1
  118. package/build/lib/commands/memory.d.ts +9 -12
  119. package/build/lib/commands/memory.d.ts.map +1 -1
  120. package/build/lib/commands/memory.js +37 -38
  121. package/build/lib/commands/memory.js.map +1 -1
  122. package/build/lib/commands/navigation.d.ts +30 -33
  123. package/build/lib/commands/navigation.d.ts.map +1 -1
  124. package/build/lib/commands/navigation.js +92 -92
  125. package/build/lib/commands/navigation.js.map +1 -1
  126. package/build/lib/commands/notifications.d.ts +26 -29
  127. package/build/lib/commands/notifications.d.ts.map +1 -1
  128. package/build/lib/commands/notifications.js +53 -53
  129. package/build/lib/commands/notifications.js.map +1 -1
  130. package/build/lib/commands/pasteboard.d.ts +21 -24
  131. package/build/lib/commands/pasteboard.d.ts.map +1 -1
  132. package/build/lib/commands/pasteboard.js +37 -37
  133. package/build/lib/commands/pasteboard.js.map +1 -1
  134. package/build/lib/commands/pcap.d.ts +39 -26
  135. package/build/lib/commands/pcap.d.ts.map +1 -1
  136. package/build/lib/commands/pcap.js +81 -81
  137. package/build/lib/commands/pcap.js.map +1 -1
  138. package/build/lib/commands/performance.d.ts +63 -44
  139. package/build/lib/commands/performance.d.ts.map +1 -1
  140. package/build/lib/commands/performance.js +105 -105
  141. package/build/lib/commands/performance.js.map +1 -1
  142. package/build/lib/commands/permissions.d.ts +33 -36
  143. package/build/lib/commands/permissions.d.ts.map +1 -1
  144. package/build/lib/commands/permissions.js +66 -65
  145. package/build/lib/commands/permissions.js.map +1 -1
  146. package/build/lib/commands/proxy-helper.d.ts +12 -15
  147. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  148. package/build/lib/commands/proxy-helper.js +53 -54
  149. package/build/lib/commands/proxy-helper.js.map +1 -1
  150. package/build/lib/commands/record-audio.d.ts +49 -29
  151. package/build/lib/commands/record-audio.d.ts.map +1 -1
  152. package/build/lib/commands/record-audio.js +100 -104
  153. package/build/lib/commands/record-audio.js.map +1 -1
  154. package/build/lib/commands/recordscreen.d.ts +54 -18
  155. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  156. package/build/lib/commands/recordscreen.js +127 -129
  157. package/build/lib/commands/recordscreen.js.map +1 -1
  158. package/build/lib/commands/screenshots.d.ts +14 -17
  159. package/build/lib/commands/screenshots.d.ts.map +1 -1
  160. package/build/lib/commands/screenshots.js +108 -107
  161. package/build/lib/commands/screenshots.js.map +1 -1
  162. package/build/lib/commands/simctl.d.ts +11 -14
  163. package/build/lib/commands/simctl.d.ts.map +1 -1
  164. package/build/lib/commands/simctl.js +23 -26
  165. package/build/lib/commands/simctl.js.map +1 -1
  166. package/build/lib/commands/source.d.ts +14 -17
  167. package/build/lib/commands/source.d.ts.map +1 -1
  168. package/build/lib/commands/source.js +40 -43
  169. package/build/lib/commands/source.js.map +1 -1
  170. package/build/lib/commands/timeouts.d.ts +44 -33
  171. package/build/lib/commands/timeouts.d.ts.map +1 -1
  172. package/build/lib/commands/timeouts.js +65 -63
  173. package/build/lib/commands/timeouts.js.map +1 -1
  174. package/build/lib/commands/web.d.ts +275 -197
  175. package/build/lib/commands/web.d.ts.map +1 -1
  176. package/build/lib/commands/web.js +866 -785
  177. package/build/lib/commands/web.js.map +1 -1
  178. package/build/lib/commands/xctest-record-screen.d.ts +63 -66
  179. package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
  180. package/build/lib/commands/xctest-record-screen.js +103 -102
  181. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  182. package/build/lib/commands/xctest.d.ts +55 -51
  183. package/build/lib/commands/xctest.d.ts.map +1 -1
  184. package/build/lib/commands/xctest.js +116 -117
  185. package/build/lib/commands/xctest.js.map +1 -1
  186. package/build/lib/driver.d.ts +277 -1597
  187. package/build/lib/driver.d.ts.map +1 -1
  188. package/build/lib/driver.js +318 -235
  189. package/build/lib/driver.js.map +1 -1
  190. package/build/lib/execute-method-map.d.ts.map +1 -1
  191. package/build/lib/execute-method-map.js +9 -0
  192. package/build/lib/execute-method-map.js.map +1 -1
  193. package/lib/commands/active-app-info.js +12 -0
  194. package/lib/commands/alert.js +68 -65
  195. package/lib/commands/app-management.js +308 -301
  196. package/lib/commands/app-strings.js +24 -26
  197. package/lib/commands/appearance.js +54 -56
  198. package/lib/commands/audit.js +18 -20
  199. package/lib/commands/battery.js +35 -37
  200. package/lib/commands/biometric.js +44 -46
  201. package/lib/commands/certificate.js +226 -215
  202. package/lib/commands/clipboard.js +30 -32
  203. package/lib/commands/condition.js +98 -100
  204. package/lib/commands/content-size.js +36 -38
  205. package/lib/commands/context.js +495 -490
  206. package/lib/commands/deviceInfo.js +19 -20
  207. package/lib/commands/element.js +367 -357
  208. package/lib/commands/execute.js +72 -72
  209. package/lib/commands/file-movement.js +132 -134
  210. package/lib/commands/find.js +160 -159
  211. package/lib/commands/general.js +238 -231
  212. package/lib/commands/geolocation.js +6 -14
  213. package/lib/commands/gesture.js +525 -515
  214. package/lib/commands/increase-contrast.js +30 -32
  215. package/lib/commands/iohid.js +32 -34
  216. package/lib/commands/keyboard.js +49 -51
  217. package/lib/commands/keychains.js +12 -14
  218. package/lib/commands/localization.js +24 -26
  219. package/lib/commands/location.js +102 -104
  220. package/lib/commands/lock.js +38 -38
  221. package/lib/commands/log.js +197 -198
  222. package/lib/commands/memory.js +40 -42
  223. package/lib/commands/navigation.js +96 -100
  224. package/lib/commands/notifications.js +57 -59
  225. package/lib/commands/pasteboard.js +37 -39
  226. package/lib/commands/pcap.js +84 -86
  227. package/lib/commands/performance.js +132 -133
  228. package/lib/commands/permissions.js +67 -69
  229. package/lib/commands/proxy-helper.js +60 -61
  230. package/lib/commands/record-audio.js +115 -120
  231. package/lib/commands/recordscreen.js +145 -149
  232. package/lib/commands/screenshots.js +116 -116
  233. package/lib/commands/simctl.js +25 -29
  234. package/lib/commands/source.js +42 -46
  235. package/lib/commands/timeouts.js +59 -63
  236. package/lib/commands/web.js +932 -859
  237. package/lib/commands/xctest-record-screen.js +103 -105
  238. package/lib/commands/xctest.js +134 -139
  239. package/lib/driver.js +286 -235
  240. package/lib/execute-method-map.ts +9 -0
  241. package/npm-shrinkwrap.json +8 -8
  242. package/package.json +1 -1
  243. package/build/lib/commands/activeAppInfo.d.ts +0 -12
  244. package/build/lib/commands/activeAppInfo.d.ts.map +0 -1
  245. package/build/lib/commands/activeAppInfo.js +0 -15
  246. package/build/lib/commands/activeAppInfo.js.map +0 -1
  247. package/build/lib/commands/index.d.ts +0 -96
  248. package/build/lib/commands/index.d.ts.map +0 -1
  249. package/build/lib/commands/index.js +0 -100
  250. package/build/lib/commands/index.js.map +0 -1
  251. package/build/lib/cookies.d.ts +0 -15
  252. package/build/lib/cookies.d.ts.map +0 -1
  253. package/build/lib/cookies.js +0 -84
  254. package/build/lib/cookies.js.map +0 -1
  255. package/lib/commands/activeAppInfo.js +0 -14
  256. package/lib/commands/index.js +0 -95
  257. package/lib/cookies.js +0 -92
@@ -11,6 +11,7 @@ const PROCESS_STARTUP_TIMEOUT_MS = 5000;
11
11
  const DEFAULT_EXT = '.mp4';
12
12
  const FFMPEG_BINARY = 'ffmpeg';
13
13
  const ffmpegLogger = logger.getLogger(FFMPEG_BINARY);
14
+
14
15
  export class AudioRecorder {
15
16
  constructor(input, log, audioPath, opts = {}) {
16
17
  this.input = input;
@@ -134,135 +135,129 @@ export class AudioRecorder {
134
135
  }
135
136
  }
136
137
 
137
- export default {
138
- /**
139
- * @type {AudioRecorder|null}
140
- */
141
- _audioRecorder: null,
142
- /**
143
- * Records the given hardware audio input and saves it into an `.mp4` file.
144
- *
145
- * **To use this command, the `audio_record` security feature must be enabled _and_ [FFMpeg](https://ffmpeg.org/) must be installed on the Appium server.**
146
- *
147
- * @param {string|number} audioInput - The name of the corresponding audio input device to use for the capture. The full list of capture devices could be shown by executing `ffmpeg -f avfoundation -list_devices true -i ""`
148
- * @param {string|number} timeLimit - The maximum recording time, in seconds.
149
- * @param {string} audioCodec - The name of the audio codec.
150
- * @param {string} audioBitrate - The bitrate of the resulting audio stream.
151
- * @param {string|number} audioChannels - The count of audio channels in the resulting stream. Setting it to `1` will create a single channel (mono) audio stream.
152
- * @param {string|number} audioRate - The sampling rate of the resulting audio stream (in Hz).
153
- * @param {boolean} forceRestart - Whether to restart audio capture process forcefully when `mobile: startRecordingAudio` is called (`true`) or ignore the call until the current audio recording is completed (`false`).
154
- * @group Real Device Only
155
- * @this {XCUITestDriver}
156
- * @returns {Promise<void>}
157
- * @privateRemarks Using string literals for the default parameters makes better documentation.
158
- */
159
- async startAudioRecording(
160
- audioInput,
161
- timeLimit = 180,
162
- audioCodec = 'aac',
163
- audioBitrate = '128k',
164
- audioChannels = 2,
165
- audioRate = 44100,
166
- forceRestart = false,
167
- ) {
168
- if (!this.isFeatureEnabled(AUDIO_RECORD_FEAT_NAME)) {
169
- throw this.log.errorWithException(
170
- `Audio capture feature must be enabled on the server side. ` +
171
- `Please set '--relaxed-security' or '--allow-insecure' with '${AUDIO_RECORD_FEAT_NAME}' option. ` +
172
- `Read https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/security.md for more details.`,
173
- );
174
- }
175
- if (!audioInput) {
176
- throw this.log.errorWithException(
177
- `The mandatory audioInput option is not provided. Please set it ` +
178
- `to a correct value (e. g. ':1'). Use 'ffmpeg -f avfoundation -list_devices true -i ""' ` +
179
- `command to list available input sources`,
180
- );
181
- }
138
+ /**
139
+ * Records the given hardware audio input and saves it into an `.mp4` file.
140
+ *
141
+ * **To use this command, the `audio_record` security feature must be enabled _and_ [FFMpeg](https://ffmpeg.org/) must be installed on the Appium server.**
142
+ *
143
+ * @param {string|number} audioInput - The name of the corresponding audio input device to use for the capture. The full list of capture devices could be shown by executing `ffmpeg -f avfoundation -list_devices true -i ""`
144
+ * @param {string|number} timeLimit - The maximum recording time, in seconds.
145
+ * @param {string} audioCodec - The name of the audio codec.
146
+ * @param {string} audioBitrate - The bitrate of the resulting audio stream.
147
+ * @param {string|number} audioChannels - The count of audio channels in the resulting stream. Setting it to `1` will create a single channel (mono) audio stream.
148
+ * @param {string|number} audioRate - The sampling rate of the resulting audio stream (in Hz).
149
+ * @param {boolean} forceRestart - Whether to restart audio capture process forcefully when `mobile: startRecordingAudio` is called (`true`) or ignore the call until the current audio recording is completed (`false`).
150
+ * @group Real Device Only
151
+ * @this {XCUITestDriver}
152
+ * @returns {Promise<void>}
153
+ * @privateRemarks Using string literals for the default parameters makes better documentation.
154
+ */
155
+ export async function startAudioRecording(
156
+ audioInput,
157
+ timeLimit = 180,
158
+ audioCodec = 'aac',
159
+ audioBitrate = '128k',
160
+ audioChannels = 2,
161
+ audioRate = 44100,
162
+ forceRestart = false,
163
+ ) {
164
+ if (!this.isFeatureEnabled(AUDIO_RECORD_FEAT_NAME)) {
165
+ throw this.log.errorWithException(
166
+ `Audio capture feature must be enabled on the server side. ` +
167
+ `Please set '--relaxed-security' or '--allow-insecure' with '${AUDIO_RECORD_FEAT_NAME}' option. ` +
168
+ `Read https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/security.md for more details.`,
169
+ );
170
+ }
171
+ if (!audioInput) {
172
+ throw this.log.errorWithException(
173
+ `The mandatory audioInput option is not provided. Please set it ` +
174
+ `to a correct value (e. g. ':1'). Use 'ffmpeg -f avfoundation -list_devices true -i ""' ` +
175
+ `command to list available input sources`,
176
+ );
177
+ }
182
178
 
183
- if (this._audioRecorder?.isRecording()) {
184
- this.log.info(`There is an active audio recording process`);
185
- if (forceRestart) {
186
- this.log.info(`Stopping it because 'forceRestart' option is set to true`);
187
- await this._audioRecorder.interrupt(true);
188
- } else {
189
- this.log.info(
190
- `Doing nothing. ` +
191
- `Set 'forceRestart' option to true if you'd like to start a new audio recording session`,
192
- );
193
- return;
194
- }
195
- }
196
- if (this._audioRecorder) {
197
- await this._audioRecorder.cleanup();
198
- this._audioRecorder = null;
179
+ if (this._audioRecorder?.isRecording()) {
180
+ this.log.info(`There is an active audio recording process`);
181
+ if (forceRestart) {
182
+ this.log.info(`Stopping it because 'forceRestart' option is set to true`);
183
+ await this._audioRecorder.interrupt(true);
184
+ } else {
185
+ this.log.info(
186
+ `Doing nothing. ` +
187
+ `Set 'forceRestart' option to true if you'd like to start a new audio recording session`,
188
+ );
189
+ return;
199
190
  }
191
+ }
192
+ if (this._audioRecorder) {
193
+ await this._audioRecorder.cleanup();
194
+ this._audioRecorder = null;
195
+ }
200
196
 
201
- const audioPath = await tempDir.path({
202
- prefix: `appium_${util.uuidV4().substring(0, 8)}`,
203
- suffix: DEFAULT_EXT,
204
- });
197
+ const audioPath = await tempDir.path({
198
+ prefix: `appium_${util.uuidV4().substring(0, 8)}`,
199
+ suffix: DEFAULT_EXT,
200
+ });
205
201
 
206
- const audioRecorder = new AudioRecorder(audioInput, this.log, audioPath, {
207
- audioSource: DEFAULT_SOURCE,
208
- audioCodec,
209
- audioBitrate,
210
- audioChannels,
211
- audioRate,
212
- });
202
+ const audioRecorder = new AudioRecorder(audioInput, this.log, audioPath, {
203
+ audioSource: DEFAULT_SOURCE,
204
+ audioCodec,
205
+ audioBitrate,
206
+ audioChannels,
207
+ audioRate,
208
+ });
213
209
 
214
- const timeoutSeconds = parseInt(String(timeLimit), 10);
215
- if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {
216
- throw this.log.errorWithException(
217
- `The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +
218
- `The value of '${timeLimit}' has been passed instead.`,
219
- );
220
- }
210
+ const timeoutSeconds = parseInt(String(timeLimit), 10);
211
+ if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {
212
+ throw this.log.errorWithException(
213
+ `The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +
214
+ `The value of '${timeLimit}' has been passed instead.`,
215
+ );
216
+ }
221
217
 
222
- try {
223
- await audioRecorder.start(timeoutSeconds);
224
- } catch (e) {
225
- await audioRecorder.interrupt(true);
226
- await audioRecorder.cleanup();
227
- throw e;
228
- }
229
- this._audioRecorder = audioRecorder;
230
- },
218
+ try {
219
+ await audioRecorder.start(timeoutSeconds);
220
+ } catch (e) {
221
+ await audioRecorder.interrupt(true);
222
+ await audioRecorder.cleanup();
223
+ throw e;
224
+ }
225
+ this._audioRecorder = audioRecorder;
226
+ }
231
227
 
232
- /**
233
- * Stop recording of the audio input. If no audio recording process is running then
234
- * the endpoint will try to get the recently recorded file.
235
- * If no previously recorded file is found and no active audio recording
236
- * processes are running then the method returns an empty string.
237
- *
238
- * @returns {Promise<string>} Base64-encoded content of the recorded media file or an
239
- * empty string if no audio recording has been started before.
240
- * @throws {Error} If there was an error while getting the recorded file.
241
- * @this {XCUITestDriver}
242
- */
243
- async stopAudioRecording() {
244
- if (!this._audioRecorder) {
245
- this.log.info('Audio recording has not been started. There is nothing to stop');
246
- return '';
247
- }
228
+ /**
229
+ * Stop recording of the audio input. If no audio recording process is running then
230
+ * the endpoint will try to get the recently recorded file.
231
+ * If no previously recorded file is found and no active audio recording
232
+ * processes are running then the method returns an empty string.
233
+ *
234
+ * @returns {Promise<string>} Base64-encoded content of the recorded media file or an
235
+ * empty string if no audio recording has been started before.
236
+ * @throws {Error} If there was an error while getting the recorded file.
237
+ * @this {XCUITestDriver}
238
+ */
239
+ export async function stopAudioRecording() {
240
+ if (!this._audioRecorder) {
241
+ this.log.info('Audio recording has not been started. There is nothing to stop');
242
+ return '';
243
+ }
248
244
 
249
- let resultPath;
250
- try {
251
- resultPath = await this._audioRecorder.finish();
252
- if (!(await fs.exists(resultPath))) {
253
- throw this.log.errorWithException(
254
- `${FFMPEG_BINARY} has failed ` + `to store the actual audio recording at '${resultPath}'`,
255
- );
256
- }
257
- } catch (e) {
258
- await this._audioRecorder.interrupt(true);
259
- await this._audioRecorder.cleanup();
260
- this._audioRecorder = null;
261
- throw e;
245
+ let resultPath;
246
+ try {
247
+ resultPath = await this._audioRecorder.finish();
248
+ if (!(await fs.exists(resultPath))) {
249
+ throw this.log.errorWithException(
250
+ `${FFMPEG_BINARY} has failed ` + `to store the actual audio recording at '${resultPath}'`,
251
+ );
262
252
  }
263
- return await encodeBase64OrUpload(resultPath);
264
- },
265
- };
253
+ } catch (e) {
254
+ await this._audioRecorder.interrupt(true);
255
+ await this._audioRecorder.cleanup();
256
+ this._audioRecorder = null;
257
+ throw e;
258
+ }
259
+ return await encodeBase64OrUpload(resultPath);
260
+ }
266
261
 
267
262
  /**
268
263
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
@@ -226,169 +226,165 @@ export class ScreenRecorder {
226
226
  }
227
227
  }
228
228
 
229
- export default {
230
- /** @type {ScreenRecorder?} */
231
- _recentScreenRecorder: null,
232
- /**
233
- * Direct Appium to start recording the device screen
234
- *
235
- * Record the display of devices running iOS Simulator since Xcode 9 or real devices since iOS 11
236
- * (ffmpeg utility is required: 'brew install ffmpeg').
237
- * It records screen activity to a MPEG-4 file. Audio is not recorded with the video file.
238
- * If screen recording has been already started then the command will stop it forcefully and start a new one.
239
- * The previously recorded video file will be deleted.
240
- *
241
- * @param {import('./types').StartRecordingScreenOptions} [options] - The available options.
242
- * @returns {Promise<string>} Base64-encoded content of the recorded media file if
243
- * any screen recording is currently running or an empty string.
244
- * @throws {Error} If screen recording has failed to start.
245
- * @this {XCUITestDriver}
246
- */
247
- async startRecordingScreen(options = {}) {
248
- const {
249
- videoType = DEFAULT_VCODEC,
250
- timeLimit = DEFAULT_RECORDING_TIME_SEC,
251
- videoQuality = DEFAULT_QUALITY,
252
- videoFps = DEFAULT_FPS,
253
- videoFilters,
254
- videoScale,
255
- forceRestart,
256
- pixelFormat,
257
- hardwareAcceleration
258
- } = options;
229
+ /**
230
+ * Direct Appium to start recording the device screen
231
+ *
232
+ * Record the display of devices running iOS Simulator since Xcode 9 or real devices since iOS 11
233
+ * (ffmpeg utility is required: 'brew install ffmpeg').
234
+ * It records screen activity to a MPEG-4 file. Audio is not recorded with the video file.
235
+ * If screen recording has been already started then the command will stop it forcefully and start a new one.
236
+ * The previously recorded video file will be deleted.
237
+ *
238
+ * @param {import('./types').StartRecordingScreenOptions} [options] - The available options.
239
+ * @returns {Promise<string>} Base64-encoded content of the recorded media file if
240
+ * any screen recording is currently running or an empty string.
241
+ * @throws {Error} If screen recording has failed to start.
242
+ * @this {XCUITestDriver}
243
+ */
244
+ export async function startRecordingScreen(options = {}) {
245
+ const {
246
+ videoType = DEFAULT_VCODEC,
247
+ timeLimit = DEFAULT_RECORDING_TIME_SEC,
248
+ videoQuality = DEFAULT_QUALITY,
249
+ videoFps = DEFAULT_FPS,
250
+ videoFilters,
251
+ videoScale,
252
+ forceRestart,
253
+ pixelFormat,
254
+ hardwareAcceleration
255
+ } = options;
259
256
 
260
- let result = '';
261
- if (!forceRestart) {
262
- this.log.info(
263
- `Checking if there is/was a previous screen recording. ` +
264
- `Set 'forceRestart' option to 'true' if you'd like to skip this step.`
265
- );
266
- result = (await this.stopRecordingScreen(options)) ?? result;
267
- }
257
+ let result = '';
258
+ if (!forceRestart) {
259
+ this.log.info(
260
+ `Checking if there is/was a previous screen recording. ` +
261
+ `Set 'forceRestart' option to 'true' if you'd like to skip this step.`
262
+ );
263
+ result = (await this.stopRecordingScreen(options)) ?? result;
264
+ }
268
265
 
269
- const videoPath = await tempDir.path({
270
- prefix: `appium_${Math.random().toString(16).substring(2, 8)}`,
271
- suffix: MP4_EXT
272
- });
266
+ const videoPath = await tempDir.path({
267
+ prefix: `appium_${Math.random().toString(16).substring(2, 8)}`,
268
+ suffix: MP4_EXT
269
+ });
273
270
 
274
- const wdaBaseUrl = this.opts.wdaBaseUrl || WDA_BASE_URL;
275
- const screenRecorder = new ScreenRecorder(this.device.udid, this.log, videoPath, {
276
- remotePort: this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT,
277
- remoteUrl: wdaBaseUrl,
278
- videoType,
279
- videoFilters,
280
- videoScale,
281
- videoFps,
282
- pixelFormat,
283
- hardwareAcceleration
284
- });
285
- if (!(await screenRecorder.interrupt(true))) {
286
- throw this.log.errorWithException('Unable to stop screen recording process');
287
- }
288
- if (this._recentScreenRecorder) {
289
- await this._recentScreenRecorder.cleanup();
290
- this._recentScreenRecorder = null;
291
- }
271
+ const wdaBaseUrl = this.opts.wdaBaseUrl || WDA_BASE_URL;
272
+ const screenRecorder = new ScreenRecorder(this.device.udid, this.log, videoPath, {
273
+ remotePort: this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT,
274
+ remoteUrl: wdaBaseUrl,
275
+ videoType,
276
+ videoFilters,
277
+ videoScale,
278
+ videoFps,
279
+ pixelFormat,
280
+ hardwareAcceleration
281
+ });
282
+ if (!(await screenRecorder.interrupt(true))) {
283
+ throw this.log.errorWithException('Unable to stop screen recording process');
284
+ }
285
+ if (this._recentScreenRecorder) {
286
+ await this._recentScreenRecorder.cleanup();
287
+ this._recentScreenRecorder = null;
288
+ }
292
289
 
293
- const timeoutSeconds = parseFloat(String(timeLimit));
294
- if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {
295
- throw this.log.errorWithException(
296
- `The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +
297
- `The value of '${timeLimit}' has been passed instead.`,
290
+ const timeoutSeconds = parseFloat(String(timeLimit));
291
+ if (isNaN(timeoutSeconds) || timeoutSeconds > MAX_RECORDING_TIME_SEC || timeoutSeconds <= 0) {
292
+ throw this.log.errorWithException(
293
+ `The timeLimit value must be in range [1, ${MAX_RECORDING_TIME_SEC}] seconds. ` +
294
+ `The value of '${timeLimit}' has been passed instead.`,
295
+ );
296
+ }
297
+
298
+ let {mjpegServerScreenshotQuality, mjpegServerFramerate} =
299
+ /** @type {import('appium-webdriveragent').WDASettings} */ (
300
+ await this.proxyCommand('/appium/settings', 'GET')
301
+ );
302
+ if (videoQuality) {
303
+ const quality = _.isInteger(videoQuality)
304
+ ? videoQuality
305
+ : QUALITY_MAPPING[_.toLower(String(videoQuality))];
306
+ if (!quality) {
307
+ throw new Error(
308
+ `videoQuality value should be one of ${JSON.stringify(
309
+ _.keys(QUALITY_MAPPING)
310
+ )} or a number in range 1..100. ` + `'${videoQuality}' is given instead`
298
311
  );
299
312
  }
300
-
301
- let {mjpegServerScreenshotQuality, mjpegServerFramerate} =
302
- /** @type {import('appium-webdriveragent').WDASettings} */ (
303
- await this.proxyCommand('/appium/settings', 'GET')
304
- );
305
- if (videoQuality) {
306
- const quality = _.isInteger(videoQuality)
307
- ? videoQuality
308
- : QUALITY_MAPPING[_.toLower(String(videoQuality))];
309
- if (!quality) {
310
- throw new Error(
311
- `videoQuality value should be one of ${JSON.stringify(
312
- _.keys(QUALITY_MAPPING)
313
- )} or a number in range 1..100. ` + `'${videoQuality}' is given instead`
314
- );
315
- }
316
- mjpegServerScreenshotQuality = mjpegServerScreenshotQuality !== quality ? quality : undefined;
317
- } else {
318
- mjpegServerScreenshotQuality = undefined;
313
+ mjpegServerScreenshotQuality = mjpegServerScreenshotQuality !== quality ? quality : undefined;
314
+ } else {
315
+ mjpegServerScreenshotQuality = undefined;
316
+ }
317
+ if (videoFps) {
318
+ const fps = parseInt(String(videoFps), 10);
319
+ if (isNaN(fps)) {
320
+ throw new Error(
321
+ `videoFps value should be a valid number in range 1..60. ` +
322
+ `'${videoFps}' is given instead`
323
+ );
319
324
  }
320
- if (videoFps) {
321
- const fps = parseInt(String(videoFps), 10);
322
- if (isNaN(fps)) {
323
- throw new Error(
324
- `videoFps value should be a valid number in range 1..60. ` +
325
- `'${videoFps}' is given instead`
326
- );
325
+ mjpegServerFramerate = mjpegServerFramerate !== fps ? fps : undefined;
326
+ } else {
327
+ mjpegServerFramerate = undefined;
328
+ }
329
+ if (util.hasValue(mjpegServerScreenshotQuality) || util.hasValue(mjpegServerFramerate)) {
330
+ await this.proxyCommand('/appium/settings', 'POST', {
331
+ settings: {
332
+ mjpegServerScreenshotQuality,
333
+ mjpegServerFramerate
327
334
  }
328
- mjpegServerFramerate = mjpegServerFramerate !== fps ? fps : undefined;
329
- } else {
330
- mjpegServerFramerate = undefined;
331
- }
332
- if (util.hasValue(mjpegServerScreenshotQuality) || util.hasValue(mjpegServerFramerate)) {
333
- await this.proxyCommand('/appium/settings', 'POST', {
334
- settings: {
335
- mjpegServerScreenshotQuality,
336
- mjpegServerFramerate
337
- }
338
- });
339
- }
335
+ });
336
+ }
340
337
 
341
- try {
342
- await screenRecorder.start(timeoutSeconds * 1000);
343
- } catch (e) {
344
- await screenRecorder.interrupt(true);
345
- await screenRecorder.cleanup();
346
- throw e;
347
- }
348
- this._recentScreenRecorder = screenRecorder;
338
+ try {
339
+ await screenRecorder.start(timeoutSeconds * 1000);
340
+ } catch (e) {
341
+ await screenRecorder.interrupt(true);
342
+ await screenRecorder.cleanup();
343
+ throw e;
344
+ }
345
+ this._recentScreenRecorder = screenRecorder;
349
346
 
350
- return result;
351
- },
347
+ return result;
348
+ }
352
349
 
353
- /**
354
- * Direct Appium to stop screen recording and return the video
355
- *
356
- * If no screen recording process is running then the endpoint will try to get
357
- * the recently recorded file. If no previously recorded file is found and no
358
- * active screen recording processes are running then the method returns an
359
- * empty string.
360
- *
361
- * @param {import('./types').StopRecordingScreenOptions} options - The available
362
- * options.
363
- * @returns {Promise<string?>} Base64-encoded content of the recorded media
364
- * file if `remotePath` parameter is empty or null or an empty string.
365
- * @throws {Error} If there was an error while getting the name of a media
366
- * file or the file content cannot be uploaded to the remote
367
- * location.
368
- * @this {XCUITestDriver}
369
- */
370
- async stopRecordingScreen(options = {}) {
371
- if (!this._recentScreenRecorder) {
372
- this.log.info('Screen recording is not running. There is nothing to stop.');
373
- return '';
374
- }
350
+ /**
351
+ * Direct Appium to stop screen recording and return the video
352
+ *
353
+ * If no screen recording process is running then the endpoint will try to get
354
+ * the recently recorded file. If no previously recorded file is found and no
355
+ * active screen recording processes are running then the method returns an
356
+ * empty string.
357
+ *
358
+ * @param {import('./types').StopRecordingScreenOptions} options - The available
359
+ * options.
360
+ * @returns {Promise<string?>} Base64-encoded content of the recorded media
361
+ * file if `remotePath` parameter is empty or null or an empty string.
362
+ * @throws {Error} If there was an error while getting the name of a media
363
+ * file or the file content cannot be uploaded to the remote
364
+ * location.
365
+ * @this {XCUITestDriver}
366
+ */
367
+ export async function stopRecordingScreen(options = {}) {
368
+ if (!this._recentScreenRecorder) {
369
+ this.log.info('Screen recording is not running. There is nothing to stop.');
370
+ return '';
371
+ }
375
372
 
376
- try {
377
- const videoPath = await this._recentScreenRecorder.finish();
378
- if (!(await fs.exists(videoPath))) {
379
- throw this.log.errorWithException(
380
- `The screen recorder utility has failed ` +
381
- `to store the actual screen recording at '${videoPath}'`
382
- );
383
- }
384
- return await encodeBase64OrUpload(videoPath, options.remotePath, options);
385
- } finally {
386
- await this._recentScreenRecorder.interrupt(true);
387
- await this._recentScreenRecorder.cleanup();
388
- this._recentScreenRecorder = null;
373
+ try {
374
+ const videoPath = await this._recentScreenRecorder.finish();
375
+ if (!(await fs.exists(videoPath))) {
376
+ throw this.log.errorWithException(
377
+ `The screen recorder utility has failed ` +
378
+ `to store the actual screen recording at '${videoPath}'`
379
+ );
389
380
  }
381
+ return await encodeBase64OrUpload(videoPath, options.remotePath, options);
382
+ } finally {
383
+ await this._recentScreenRecorder.interrupt(true);
384
+ await this._recentScreenRecorder.cleanup();
385
+ this._recentScreenRecorder = null;
390
386
  }
391
- };
387
+ }
392
388
 
393
389
  /**
394
390
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver