appium-mac2-driver 4.0.4 → 4.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/build/lib/commands/app-management.d.ts +1 -1
- package/build/lib/commands/app-management.d.ts.map +1 -1
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/applescript.d.ts.map +1 -1
- package/build/lib/commands/applescript.js +1 -1
- package/build/lib/commands/applescript.js.map +1 -1
- package/build/lib/commands/bidi/models.d.ts.map +1 -1
- package/build/lib/commands/bidi/models.js.map +1 -1
- package/build/lib/commands/clipboard.d.ts.map +1 -1
- package/build/lib/commands/clipboard.js.map +1 -1
- package/build/lib/commands/execute.d.ts +1 -1
- package/build/lib/commands/execute.d.ts.map +1 -1
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/find.d.ts.map +1 -1
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/gestures.d.ts.map +1 -1
- package/build/lib/commands/gestures.js +5 -13
- package/build/lib/commands/gestures.js.map +1 -1
- package/build/lib/commands/helpers.d.ts +1 -1
- package/build/lib/commands/helpers.d.ts.map +1 -1
- package/build/lib/commands/helpers.js.map +1 -1
- package/build/lib/commands/native-record-screen.d.ts +2 -2
- package/build/lib/commands/native-record-screen.d.ts.map +1 -1
- package/build/lib/commands/native-record-screen.js +4 -5
- package/build/lib/commands/native-record-screen.js.map +1 -1
- package/build/lib/commands/navigation.d.ts.map +1 -1
- package/build/lib/commands/navigation.js.map +1 -1
- package/build/lib/commands/record-screen.d.ts +1 -1
- package/build/lib/commands/record-screen.d.ts.map +1 -1
- package/build/lib/commands/record-screen.js +2 -2
- package/build/lib/commands/record-screen.js.map +1 -1
- package/build/lib/commands/screenshots.d.ts.map +1 -1
- package/build/lib/commands/screenshots.js.map +1 -1
- package/build/lib/commands/source.d.ts.map +1 -1
- package/build/lib/commands/source.js.map +1 -1
- package/build/lib/doctor/optional-checks.d.ts.map +1 -1
- package/build/lib/doctor/optional-checks.js +2 -2
- package/build/lib/doctor/optional-checks.js.map +1 -1
- package/build/lib/doctor/required-checks.d.ts.map +1 -1
- package/build/lib/doctor/required-checks.js +1 -1
- package/build/lib/doctor/required-checks.js.map +1 -1
- package/build/lib/driver.d.ts +5 -5
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +9 -10
- package/build/lib/driver.js.map +1 -1
- package/build/lib/execute-method-map.d.ts.map +1 -1
- package/build/lib/execute-method-map.js +4 -37
- package/build/lib/execute-method-map.js.map +1 -1
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +2 -2
- package/build/lib/utils.js.map +1 -1
- package/build/lib/wda-mac.d.ts +1 -1
- package/build/lib/wda-mac.d.ts.map +1 -1
- package/build/lib/wda-mac.js +8 -12
- package/build/lib/wda-mac.js.map +1 -1
- package/lib/commands/app-management.ts +5 -16
- package/lib/commands/applescript.ts +3 -1
- package/lib/commands/bidi/models.ts +2 -5
- package/lib/commands/clipboard.ts +1 -4
- package/lib/commands/execute.ts +3 -6
- package/lib/commands/find.ts +1 -0
- package/lib/commands/gestures.ts +10 -44
- package/lib/commands/helpers.ts +3 -4
- package/lib/commands/native-record-screen.ts +15 -28
- package/lib/commands/navigation.ts +1 -5
- package/lib/commands/record-screen.ts +10 -30
- package/lib/commands/screenshots.ts +1 -4
- package/lib/commands/source.ts +1 -4
- package/lib/doctor/optional-checks.ts +10 -19
- package/lib/doctor/required-checks.ts +3 -5
- package/lib/driver.ts +12 -21
- package/lib/execute-method-map.ts +4 -37
- package/lib/utils.ts +3 -2
- package/lib/wda-mac.ts +19 -31
- package/npm-shrinkwrap.json +169 -198
- package/package.json +66 -77
- package/scripts/open-wda.mjs +2 -1
package/lib/commands/gestures.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {util} from 'appium/support.js';
|
|
2
1
|
import {errors} from 'appium/driver.js';
|
|
2
|
+
import {util} from 'appium/support.js';
|
|
3
|
+
|
|
3
4
|
import type {Mac2Driver} from '../driver.js';
|
|
4
5
|
import type {KeyOptions} from '../types.js';
|
|
5
6
|
|
|
@@ -257,18 +258,9 @@ export async function macosClickAndDrag(
|
|
|
257
258
|
endY?: number,
|
|
258
259
|
keyModifierFlags?: number,
|
|
259
260
|
): Promise<unknown> {
|
|
260
|
-
requireSourceDestWithElementsOrCoordinates(
|
|
261
|
-
sourceElementId,
|
|
262
|
-
destinationElementId,
|
|
263
|
-
startX,
|
|
264
|
-
startY,
|
|
265
|
-
endX,
|
|
266
|
-
endY,
|
|
267
|
-
);
|
|
261
|
+
requireSourceDestWithElementsOrCoordinates(sourceElementId, destinationElementId, startX, startY, endX, endY);
|
|
268
262
|
const url =
|
|
269
|
-
sourceElementId && destinationElementId
|
|
270
|
-
? `/wda/element/${sourceElementId}/clickAndDrag`
|
|
271
|
-
: '/wda/clickAndDrag';
|
|
263
|
+
sourceElementId && destinationElementId ? `/wda/element/${sourceElementId}/clickAndDrag` : '/wda/clickAndDrag';
|
|
272
264
|
const dest = destinationElementId && util.wrapElement(destinationElementId);
|
|
273
265
|
return await this.wda.proxy.command(url, 'POST', {
|
|
274
266
|
startX,
|
|
@@ -318,14 +310,7 @@ export async function macosClickAndDragAndHold(
|
|
|
318
310
|
velocity?: number,
|
|
319
311
|
keyModifierFlags?: number,
|
|
320
312
|
): Promise<unknown> {
|
|
321
|
-
requireSourceDestWithElementsOrCoordinates(
|
|
322
|
-
sourceElementId,
|
|
323
|
-
destinationElementId,
|
|
324
|
-
startX,
|
|
325
|
-
startY,
|
|
326
|
-
endX,
|
|
327
|
-
endY,
|
|
328
|
-
);
|
|
313
|
+
requireSourceDestWithElementsOrCoordinates(sourceElementId, destinationElementId, startX, startY, endX, endY);
|
|
329
314
|
const url =
|
|
330
315
|
sourceElementId && destinationElementId
|
|
331
316
|
? `/wda/element/${sourceElementId}/clickAndDragAndHold`
|
|
@@ -356,11 +341,7 @@ export async function macosClickAndDragAndHold(
|
|
|
356
341
|
* If unset then keys are sent to the current application
|
|
357
342
|
* under test.
|
|
358
343
|
*/
|
|
359
|
-
export async function macosKeys(
|
|
360
|
-
this: Mac2Driver,
|
|
361
|
-
keys: (KeyOptions | string)[],
|
|
362
|
-
elementId?: string,
|
|
363
|
-
): Promise<unknown> {
|
|
344
|
+
export async function macosKeys(this: Mac2Driver, keys: (KeyOptions | string)[], elementId?: string): Promise<unknown> {
|
|
364
345
|
const url = elementId ? `/wda/element/${elementId}/keys` : '/wda/keys';
|
|
365
346
|
return await this.wda.proxy.command(url, 'POST', {keys});
|
|
366
347
|
}
|
|
@@ -492,9 +473,7 @@ export async function macosPressAndDrag(
|
|
|
492
473
|
// startX, startY, endX, endY,
|
|
493
474
|
// );
|
|
494
475
|
const url =
|
|
495
|
-
sourceElementId && destinationElementId
|
|
496
|
-
? `/wda/element/${sourceElementId}/pressAndDrag`
|
|
497
|
-
: '/wda/pressAndDrag';
|
|
476
|
+
sourceElementId && destinationElementId ? `/wda/element/${sourceElementId}/pressAndDrag` : '/wda/pressAndDrag';
|
|
498
477
|
const dest = destinationElementId && util.wrapElement(destinationElementId);
|
|
499
478
|
return await this.wda.proxy.command(url, 'POST', {
|
|
500
479
|
startX,
|
|
@@ -544,14 +523,7 @@ export async function macosPressAndDragAndHold(
|
|
|
544
523
|
velocity?: number,
|
|
545
524
|
keyModifierFlags?: number,
|
|
546
525
|
): Promise<unknown> {
|
|
547
|
-
requireSourceDestWithElementsOrCoordinates(
|
|
548
|
-
sourceElementId,
|
|
549
|
-
destinationElementId,
|
|
550
|
-
startX,
|
|
551
|
-
startY,
|
|
552
|
-
endX,
|
|
553
|
-
endY,
|
|
554
|
-
);
|
|
526
|
+
requireSourceDestWithElementsOrCoordinates(sourceElementId, destinationElementId, startX, startY, endX, endY);
|
|
555
527
|
const url =
|
|
556
528
|
sourceElementId && destinationElementId
|
|
557
529
|
? `/wda/element/${sourceElementId}/pressAndDragAndHold`
|
|
@@ -602,16 +574,10 @@ function requireSourceDestWithElementsOrCoordinates(
|
|
|
602
574
|
): void {
|
|
603
575
|
if (
|
|
604
576
|
!(typeof sourceElementId === 'string' && typeof destinationElementId === 'string') &&
|
|
605
|
-
!(
|
|
606
|
-
typeof startX === 'number' &&
|
|
607
|
-
typeof startY === 'number' &&
|
|
608
|
-
typeof endX === 'number' &&
|
|
609
|
-
typeof endY === 'number'
|
|
610
|
-
)
|
|
577
|
+
!(typeof startX === 'number' && typeof startY === 'number' && typeof endX === 'number' && typeof endY === 'number')
|
|
611
578
|
) {
|
|
612
579
|
throw new errors.InvalidArgumentError(
|
|
613
|
-
`'sourceElementId' and 'destinationElementId'
|
|
614
|
-
`or 'startX', 'startY', 'endX' and 'endY' are required.`,
|
|
580
|
+
`'sourceElementId' and 'destinationElementId' or 'startX', 'startY', 'endX' and 'endY' are required.`,
|
|
615
581
|
);
|
|
616
582
|
}
|
|
617
583
|
}
|
package/lib/commands/helpers.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type {StringRecord} from '@appium/types';
|
|
1
2
|
import {util, fs, net} from 'appium/support.js';
|
|
3
|
+
|
|
2
4
|
import type {Mac2Driver} from '../driver.js';
|
|
3
|
-
import type {StringRecord} from '@appium/types';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Uploads the given local file to the specified remote path or returns
|
|
@@ -19,9 +20,7 @@ export async function uploadRecordedMedia(
|
|
|
19
20
|
): Promise<string> {
|
|
20
21
|
if (remotePath == null || remotePath.length === 0) {
|
|
21
22
|
const {size} = await fs.stat(localFile);
|
|
22
|
-
this.log.debug(
|
|
23
|
-
`The size of the resulting screen recording is ${util.toReadableSizeString(size)}`,
|
|
24
|
-
);
|
|
23
|
+
this.log.debug(`The size of the resulting screen recording is ${util.toReadableSizeString(size)}`);
|
|
25
24
|
return (await util.toInMemoryBase64(localFile)).toString();
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import type EventEmitter from 'node:events';
|
|
2
|
+
import os from 'node:os';
|
|
1
3
|
import path from 'node:path';
|
|
2
|
-
|
|
3
|
-
import type {Mac2Driver} from '../driver.js';
|
|
4
|
-
import {uploadRecordedMedia} from './helpers.js';
|
|
4
|
+
|
|
5
5
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
6
|
-
import
|
|
6
|
+
import {fs, util} from 'appium/support.js';
|
|
7
7
|
import type {CancellablePromise} from 'asyncbox';
|
|
8
8
|
import {TimeoutError, sleep, waitForCondition, withTimeout} from 'asyncbox';
|
|
9
9
|
import {exec} from 'teen_process';
|
|
10
|
+
|
|
11
|
+
import type {Mac2Driver} from '../driver.js';
|
|
12
|
+
import {isPlainObject} from '../utils.js';
|
|
10
13
|
import {BIDI_EVENT_NAME} from './bidi/constants.js';
|
|
11
14
|
import {toNativeVideoChunkAddedEvent} from './bidi/models.js';
|
|
12
|
-
import {
|
|
13
|
-
import os from 'node:os';
|
|
15
|
+
import {uploadRecordedMedia} from './helpers.js';
|
|
14
16
|
|
|
15
17
|
const RECORDING_STARTUP_TIMEOUT_MS = 5000;
|
|
16
18
|
const BUFFER_SIZE = 0xffff;
|
|
@@ -196,9 +198,7 @@ export class NativeVideoChunksBroadcaster {
|
|
|
196
198
|
const handle = await fs.open(fullPath, 'r');
|
|
197
199
|
try {
|
|
198
200
|
while (bytesRead < size) {
|
|
199
|
-
const bufferSize = Number(
|
|
200
|
-
size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead,
|
|
201
|
-
);
|
|
201
|
+
const bufferSize = Number(size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead);
|
|
202
202
|
const buf = Buffer.alloc(bufferSize);
|
|
203
203
|
await fs.read(handle, buf as any, 0, bufferSize, bytesRead as any);
|
|
204
204
|
this._ee.emit(BIDI_EVENT_NAME, toNativeVideoChunkAddedEvent(uuid, buf));
|
|
@@ -210,9 +210,7 @@ export class NativeVideoChunksBroadcaster {
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
if (isCompleted) {
|
|
213
|
-
this._log.debug(
|
|
214
|
-
`The native video recording identified by ${uuid} has been detected as completed`,
|
|
215
|
-
);
|
|
213
|
+
this._log.debug(`The native video recording identified by ${uuid} has been detected as completed`);
|
|
216
214
|
return;
|
|
217
215
|
}
|
|
218
216
|
|
|
@@ -242,10 +240,7 @@ export class NativeVideoChunksBroadcaster {
|
|
|
242
240
|
return;
|
|
243
241
|
}
|
|
244
242
|
|
|
245
|
-
this._log.warn(
|
|
246
|
-
`Stopped monitoring of the native video recording identified by ${uuid} ` +
|
|
247
|
-
`because of the timeout`,
|
|
248
|
-
);
|
|
243
|
+
this._log.warn(`Stopped monitoring of the native video recording identified by ${uuid} because of the timeout`);
|
|
249
244
|
}
|
|
250
245
|
|
|
251
246
|
private async _wait(timeoutMs: number): Promise<void> {
|
|
@@ -284,13 +279,9 @@ export class NativeVideoChunksBroadcaster {
|
|
|
284
279
|
}
|
|
285
280
|
try {
|
|
286
281
|
await Promise.all(tasks);
|
|
287
|
-
this._log.debug(
|
|
288
|
-
`Successfully deleted ${util.pluralize('leftover video recording', tasks.length, true)}`,
|
|
289
|
-
);
|
|
282
|
+
this._log.debug(`Successfully deleted ${util.pluralize('leftover video recording', tasks.length, true)}`);
|
|
290
283
|
} catch (e) {
|
|
291
|
-
this._log.warn(
|
|
292
|
-
`Could not cleanup some leftover video recordings: ${e instanceof Error ? e.message : String(e)}`,
|
|
293
|
-
);
|
|
284
|
+
this._log.warn(`Could not cleanup some leftover video recordings: ${e instanceof Error ? e.message : String(e)}`);
|
|
294
285
|
}
|
|
295
286
|
}
|
|
296
287
|
|
|
@@ -352,9 +343,7 @@ export async function macosStartNativeScreenRecording(
|
|
|
352
343
|
* @returns The information about the asynchronously running video recording or
|
|
353
344
|
* null if no native video recording has been started.
|
|
354
345
|
*/
|
|
355
|
-
export async function macosGetNativeScreenRecordingInfo(
|
|
356
|
-
this: Mac2Driver,
|
|
357
|
-
): Promise<ActiveVideoInfo | null> {
|
|
346
|
+
export async function macosGetNativeScreenRecordingInfo(this: Mac2Driver): Promise<ActiveVideoInfo | null> {
|
|
358
347
|
return (await this.wda.proxy.command('/wda/video', 'GET')) as ActiveVideoInfo | null;
|
|
359
348
|
}
|
|
360
349
|
|
|
@@ -402,9 +391,7 @@ export async function macosStopNativeScreenRecording(
|
|
|
402
391
|
{},
|
|
403
392
|
)) as ActiveVideoInfo | null;
|
|
404
393
|
if (!response || !isPlainObject(response)) {
|
|
405
|
-
throw new Error(
|
|
406
|
-
'There is no active screen recording, thus nothing to stop. Did you start it before?',
|
|
407
|
-
);
|
|
394
|
+
throw new Error('There is no active screen recording, thus nothing to stop. Did you start it before?');
|
|
408
395
|
}
|
|
409
396
|
|
|
410
397
|
const {uuid} = response;
|
|
@@ -9,10 +9,6 @@ import type {Mac2Driver} from '../driver.js';
|
|
|
9
9
|
* the given url with. If not provided then the default application
|
|
10
10
|
* for the given url scheme is going to be used.
|
|
11
11
|
*/
|
|
12
|
-
export async function macosDeepLink(
|
|
13
|
-
this: Mac2Driver,
|
|
14
|
-
url: string,
|
|
15
|
-
bundleId?: string,
|
|
16
|
-
): Promise<unknown> {
|
|
12
|
+
export async function macosDeepLink(this: Mac2Driver, url: string, bundleId?: string): Promise<unknown> {
|
|
17
13
|
return await this.wda.proxy.command('/url', 'POST', {url, bundleId});
|
|
18
14
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
2
2
|
import {util, fs, tempDir} from 'appium/support.js';
|
|
3
|
+
import {waitForCondition} from 'asyncbox';
|
|
3
4
|
import {SubProcess} from 'teen_process';
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
import type {Mac2Driver} from '../driver.js';
|
|
6
|
-
import
|
|
7
|
+
import {uploadRecordedMedia} from './helpers.js';
|
|
7
8
|
|
|
8
9
|
const RETRY_PAUSE = 300;
|
|
9
10
|
const RETRY_TIMEOUT = 5000;
|
|
@@ -14,16 +15,7 @@ const FFMPEG_BINARY = 'ffmpeg';
|
|
|
14
15
|
const DEFAULT_FPS = 15;
|
|
15
16
|
const DEFAULT_PRESET = 'veryfast';
|
|
16
17
|
|
|
17
|
-
type Preset =
|
|
18
|
-
| 'ultrafast'
|
|
19
|
-
| 'superfast'
|
|
20
|
-
| 'veryfast'
|
|
21
|
-
| 'faster'
|
|
22
|
-
| 'fast'
|
|
23
|
-
| 'medium'
|
|
24
|
-
| 'slow'
|
|
25
|
-
| 'slower'
|
|
26
|
-
| 'veryslow';
|
|
18
|
+
type Preset = 'ultrafast' | 'superfast' | 'veryfast' | 'faster' | 'fast' | 'medium' | 'slow' | 'slower' | 'veryslow';
|
|
27
19
|
|
|
28
20
|
interface ScreenRecorderOptions {
|
|
29
21
|
fps?: number;
|
|
@@ -192,9 +184,7 @@ export class ScreenRecorder {
|
|
|
192
184
|
void (async () => {
|
|
193
185
|
try {
|
|
194
186
|
await this._enforceTermination();
|
|
195
|
-
reject(
|
|
196
|
-
new Error(`Screen recording has failed to exit after ${PROCESS_SHUTDOWN_TIMEOUT}ms`),
|
|
197
|
-
);
|
|
187
|
+
reject(new Error(`Screen recording has failed to exit after ${PROCESS_SHUTDOWN_TIMEOUT}ms`));
|
|
198
188
|
} catch (err) {
|
|
199
189
|
reject(err);
|
|
200
190
|
}
|
|
@@ -208,9 +198,7 @@ export class ScreenRecorder {
|
|
|
208
198
|
if (code === 0) {
|
|
209
199
|
resolve(await this.getVideoPath());
|
|
210
200
|
} else {
|
|
211
|
-
reject(
|
|
212
|
-
new Error(`Screen recording exited with error code ${code}, signal ${signal}`),
|
|
213
|
-
);
|
|
201
|
+
reject(new Error(`Screen recording exited with error code ${code}, signal ${signal}`));
|
|
214
202
|
}
|
|
215
203
|
} catch (err) {
|
|
216
204
|
reject(err);
|
|
@@ -329,10 +317,7 @@ export async function macosStartRecordingScreen(
|
|
|
329
317
|
*
|
|
330
318
|
* @see macosStartRecordingScreen
|
|
331
319
|
*/
|
|
332
|
-
export async function startRecordingScreen(
|
|
333
|
-
this: Mac2Driver,
|
|
334
|
-
options: StartRecordingScreenOptions = {},
|
|
335
|
-
): Promise<void> {
|
|
320
|
+
export async function startRecordingScreen(this: Mac2Driver, options: StartRecordingScreenOptions = {}): Promise<void> {
|
|
336
321
|
return await this.macosStartRecordingScreen(
|
|
337
322
|
options.deviceId,
|
|
338
323
|
options.timeLimit,
|
|
@@ -405,10 +390,7 @@ export async function macosStopRecordingScreen(
|
|
|
405
390
|
*
|
|
406
391
|
* @see macosStopRecordingScreen
|
|
407
392
|
*/
|
|
408
|
-
export async function stopRecordingScreen(
|
|
409
|
-
this: Mac2Driver,
|
|
410
|
-
options: StopRecordingScreenOptions = {},
|
|
411
|
-
): Promise<string> {
|
|
393
|
+
export async function stopRecordingScreen(this: Mac2Driver, options: StopRecordingScreenOptions = {}): Promise<string> {
|
|
412
394
|
return await this.macosStopRecordingScreen(
|
|
413
395
|
options.remotePath,
|
|
414
396
|
options.user,
|
|
@@ -427,8 +409,6 @@ async function requireFfmpegPath(log: AppiumLogger): Promise<string> {
|
|
|
427
409
|
try {
|
|
428
410
|
return await fs.which(FFMPEG_BINARY);
|
|
429
411
|
} catch {
|
|
430
|
-
throw log.errorWithException(
|
|
431
|
-
`${FFMPEG_BINARY} has not been found in PATH. ` + `Please make sure it is installed`,
|
|
432
|
-
);
|
|
412
|
+
throw log.errorWithException(`${FFMPEG_BINARY} has not been found in PATH. Please make sure it is installed`);
|
|
433
413
|
}
|
|
434
414
|
}
|
|
@@ -9,9 +9,6 @@ import type {ScreenshotsInfo} from '../types.js';
|
|
|
9
9
|
* If no matches were found then an error is thrown.
|
|
10
10
|
* @returns Screenshots information for the requested display(s)
|
|
11
11
|
*/
|
|
12
|
-
export async function macosScreenshots(
|
|
13
|
-
this: Mac2Driver,
|
|
14
|
-
displayId?: number,
|
|
15
|
-
): Promise<ScreenshotsInfo> {
|
|
12
|
+
export async function macosScreenshots(this: Mac2Driver, displayId?: number): Promise<ScreenshotsInfo> {
|
|
16
13
|
return (await this.wda.proxy.command('/wda/screenshots', 'POST', {displayId})) as ScreenshotsInfo;
|
|
17
14
|
}
|
package/lib/commands/source.ts
CHANGED
|
@@ -12,8 +12,5 @@ import type {Mac2Driver} from '../driver.js';
|
|
|
12
12
|
* @returns the page source in the requested format
|
|
13
13
|
*/
|
|
14
14
|
export async function macosSource(this: Mac2Driver, format: string = 'xml'): Promise<string> {
|
|
15
|
-
return (await this.wda.proxy.command(
|
|
16
|
-
`/source?format=${encodeURIComponent(format)}`,
|
|
17
|
-
'GET',
|
|
18
|
-
)) as string;
|
|
15
|
+
return (await this.wda.proxy.command(`/source?format=${encodeURIComponent(format)}`, 'GET')) as string;
|
|
19
16
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import os from 'node:os';
|
|
3
|
-
import
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import type {IDoctorCheck, AppiumLogger, DoctorCheckResult} from '@appium/types';
|
|
4
5
|
import {doctor, fs, util} from 'appium/support.js';
|
|
5
6
|
import {exec} from 'teen_process';
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
import {resolveExecutablePath} from './utils.js';
|
|
7
9
|
import '@colors/colors';
|
|
8
10
|
|
|
9
11
|
export class OptionalFfmpegCheck implements IDoctorCheck {
|
|
@@ -45,9 +47,7 @@ export class OptionalAutomationModeCheck implements IDoctorCheck {
|
|
|
45
47
|
try {
|
|
46
48
|
({stdout} = await exec('automationmodetool'));
|
|
47
49
|
} catch (err) {
|
|
48
|
-
return doctor.nokOptional(
|
|
49
|
-
`Cannot run 'automationmodetool': ${(err as any).stderr || (err as Error).message}`,
|
|
50
|
-
);
|
|
50
|
+
return doctor.nokOptional(`Cannot run 'automationmodetool': ${(err as any).stderr || (err as Error).message}`);
|
|
51
51
|
}
|
|
52
52
|
if (stdout.includes('DOES NOT REQUIRE')) {
|
|
53
53
|
return doctor.okOptional(`Automation Mode does not require user authentication`);
|
|
@@ -83,11 +83,7 @@ export class OptionalFullDiskAccessDaemonContainersCheck implements IDoctorCheck
|
|
|
83
83
|
return `*/Data/{,tmp/}Attachments/${uuid}`;
|
|
84
84
|
})();
|
|
85
85
|
private readonly ANY_ATTACHMENT_GLOB = '*/Data/{,tmp/}Attachments/*';
|
|
86
|
-
private readonly DAEMON_CONTAINERS_ROOT = path.resolve(
|
|
87
|
-
os.homedir(),
|
|
88
|
-
'Library',
|
|
89
|
-
'Daemon Containers',
|
|
90
|
-
);
|
|
86
|
+
private readonly DAEMON_CONTAINERS_ROOT = path.resolve(os.homedir(), 'Library', 'Daemon Containers');
|
|
91
87
|
|
|
92
88
|
async diagnose(): Promise<DoctorCheckResult> {
|
|
93
89
|
const nonDarwin = this.checkIfNotDarwin();
|
|
@@ -136,9 +132,7 @@ export class OptionalFullDiskAccessDaemonContainersCheck implements IDoctorCheck
|
|
|
136
132
|
if (process.platform === 'darwin') {
|
|
137
133
|
return null;
|
|
138
134
|
}
|
|
139
|
-
return doctor.okOptional(
|
|
140
|
-
`Full Disk Access to ${this.DAEMON_CONTAINERS_ROOT} can only be checked on macOS`,
|
|
141
|
-
);
|
|
135
|
+
return doctor.okOptional(`Full Disk Access to ${this.DAEMON_CONTAINERS_ROOT} can only be checked on macOS`);
|
|
142
136
|
}
|
|
143
137
|
|
|
144
138
|
private async tryAccessDaemonContainers(): Promise<DoctorCheckResult | null> {
|
|
@@ -146,9 +140,7 @@ export class OptionalFullDiskAccessDaemonContainersCheck implements IDoctorCheck
|
|
|
146
140
|
await fs.access(this.DAEMON_CONTAINERS_ROOT);
|
|
147
141
|
return null;
|
|
148
142
|
} catch (e) {
|
|
149
|
-
return doctor.nokOptional(
|
|
150
|
-
`Cannot access "${this.DAEMON_CONTAINERS_ROOT}": ${(e as Error).message}`,
|
|
151
|
-
);
|
|
143
|
+
return doctor.nokOptional(`Cannot access "${this.DAEMON_CONTAINERS_ROOT}": ${(e as Error).message}`);
|
|
152
144
|
}
|
|
153
145
|
}
|
|
154
146
|
|
|
@@ -189,5 +181,4 @@ export class OptionalFullDiskAccessDaemonContainersCheck implements IDoctorCheck
|
|
|
189
181
|
);
|
|
190
182
|
}
|
|
191
183
|
}
|
|
192
|
-
export const optionalFullDiskAccessDaemonContainersCheck =
|
|
193
|
-
new OptionalFullDiskAccessDaemonContainersCheck();
|
|
184
|
+
export const optionalFullDiskAccessDaemonContainersCheck = new OptionalFullDiskAccessDaemonContainersCheck();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type {IDoctorCheck, AppiumLogger, DoctorCheckResult} from '@appium/types';
|
|
2
|
+
import {getPath as getXcodePath} from 'appium-xcode';
|
|
1
3
|
import {doctor} from 'appium/support.js';
|
|
2
4
|
import {exec} from 'teen_process';
|
|
3
|
-
import {getPath as getXcodePath} from 'appium-xcode';
|
|
4
|
-
import type {IDoctorCheck, AppiumLogger, DoctorCheckResult} from '@appium/types';
|
|
5
5
|
import '@colors/colors';
|
|
6
6
|
|
|
7
7
|
export class XcodeCheck implements IDoctorCheck {
|
|
@@ -44,9 +44,7 @@ export class XcodebuildCheck implements IDoctorCheck {
|
|
|
44
44
|
({stdout, stderr} = await exec('xcodebuild', ['-version']));
|
|
45
45
|
xcodeVerMatch = XcodebuildCheck.XCODE_VER_PATTERN.exec(stdout);
|
|
46
46
|
} catch (err) {
|
|
47
|
-
return doctor.nok(
|
|
48
|
-
`Cannot run 'xcodebuild': ${(err as any).stderr || (err as Error).message}`,
|
|
49
|
-
);
|
|
47
|
+
return doctor.nok(`Cannot run 'xcodebuild': ${(err as any).stderr || (err as Error).message}`);
|
|
50
48
|
}
|
|
51
49
|
if (!xcodeVerMatch) {
|
|
52
50
|
return doctor.nok(`Cannot determine Xcode version. stdout: ${stdout}; stderr: ${stderr}`);
|
package/lib/driver.ts
CHANGED
|
@@ -12,23 +12,24 @@ import type {
|
|
|
12
12
|
W3CDriverCaps,
|
|
13
13
|
} from '@appium/types';
|
|
14
14
|
import {BaseDriver, DeviceSettings} from 'appium/driver.js';
|
|
15
|
-
|
|
16
|
-
import MAC2_CONSTRAINTS, {type Mac2Constraints} from './constraints.js';
|
|
15
|
+
|
|
17
16
|
import * as appManagemenetCommands from './commands/app-management.js';
|
|
18
17
|
import * as appleScriptCommands from './commands/applescript.js';
|
|
19
|
-
import * as executeCommands from './commands/execute.js';
|
|
20
18
|
import * as auditCommands from './commands/audit.js';
|
|
19
|
+
import * as clipboardCommands from './commands/clipboard.js';
|
|
20
|
+
import * as executeCommands from './commands/execute.js';
|
|
21
21
|
import * as findCommands from './commands/find.js';
|
|
22
22
|
import * as gesturesCommands from './commands/gestures.js';
|
|
23
|
+
import * as nativeScreenRecordingCommands from './commands/native-record-screen.js';
|
|
23
24
|
import * as navigationCommands from './commands/navigation.js';
|
|
24
25
|
import * as recordScreenCommands from './commands/record-screen.js';
|
|
25
26
|
import * as screenshotCommands from './commands/screenshots.js';
|
|
26
27
|
import * as sourceCommands from './commands/source.js';
|
|
27
|
-
import
|
|
28
|
-
import
|
|
28
|
+
import MAC2_CONSTRAINTS, {type Mac2Constraints} from './constraints.js';
|
|
29
|
+
import {executeMethodMap} from './execute-method-map.js';
|
|
29
30
|
import log from './logger.js';
|
|
30
31
|
import {newMethodMap} from './method-map.js';
|
|
31
|
-
import {
|
|
32
|
+
import {WDA_MAC_SERVER, type WDAMacServer} from './wda-mac.js';
|
|
32
33
|
|
|
33
34
|
const NO_PROXY: RouteMatcher[] = [
|
|
34
35
|
['GET', new RegExp('^/session/[^/]+/appium')],
|
|
@@ -101,8 +102,7 @@ export class Mac2Driver
|
|
|
101
102
|
macosStopRecordingScreen = recordScreenCommands.macosStopRecordingScreen;
|
|
102
103
|
|
|
103
104
|
macosStartNativeScreenRecording = nativeScreenRecordingCommands.macosStartNativeScreenRecording;
|
|
104
|
-
macosGetNativeScreenRecordingInfo =
|
|
105
|
-
nativeScreenRecordingCommands.macosGetNativeScreenRecordingInfo;
|
|
105
|
+
macosGetNativeScreenRecordingInfo = nativeScreenRecordingCommands.macosGetNativeScreenRecordingInfo;
|
|
106
106
|
macosStopNativeScreenRecording = nativeScreenRecordingCommands.macosStopNativeScreenRecording;
|
|
107
107
|
macosListDisplays = nativeScreenRecordingCommands.macosListDisplays;
|
|
108
108
|
|
|
@@ -200,15 +200,13 @@ export class Mac2Driver
|
|
|
200
200
|
const [sessionId, caps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
|
|
201
201
|
this._wda = WDA_MAC_SERVER;
|
|
202
202
|
this.caps = caps as Mac2DriverCaps;
|
|
203
|
+
// oxlint-disable-next-line no-self-assign -- narrows this.opts' type for the rest of the method
|
|
203
204
|
this.opts = this.opts as Mac2DriverOpts;
|
|
204
205
|
try {
|
|
205
206
|
const prerun = caps.prerun as PrerunCapability | undefined;
|
|
206
207
|
if (prerun) {
|
|
207
208
|
if (typeof prerun.command !== 'string' && typeof prerun.script !== 'string') {
|
|
208
|
-
throw new Error(
|
|
209
|
-
`'prerun' capability value must either contain ` +
|
|
210
|
-
`'script' or 'command' entry of string type`,
|
|
211
|
-
);
|
|
209
|
+
throw new Error(`'prerun' capability value must either contain 'script' or 'command' entry of string type`);
|
|
212
210
|
}
|
|
213
211
|
log.info('Executing prerun AppleScript');
|
|
214
212
|
const output = await this.macosExecAppleScript(prerun.script, undefined, prerun.command);
|
|
@@ -245,18 +243,11 @@ export class Mac2Driver
|
|
|
245
243
|
const postrun = this.opts.postrun as PostrunCapability | undefined;
|
|
246
244
|
if (postrun) {
|
|
247
245
|
if (typeof postrun.command !== 'string' && typeof postrun.script !== 'string') {
|
|
248
|
-
log.error(
|
|
249
|
-
`'postrun' capability value must either contain ` +
|
|
250
|
-
`'script' or 'command' entry of string type`,
|
|
251
|
-
);
|
|
246
|
+
log.error(`'postrun' capability value must either contain 'script' or 'command' entry of string type`);
|
|
252
247
|
} else {
|
|
253
248
|
log.info('Executing postrun AppleScript');
|
|
254
249
|
try {
|
|
255
|
-
const output = await this.macosExecAppleScript(
|
|
256
|
-
postrun.script,
|
|
257
|
-
undefined,
|
|
258
|
-
postrun.command,
|
|
259
|
-
);
|
|
250
|
+
const output = await this.macosExecAppleScript(postrun.script, undefined, postrun.command);
|
|
260
251
|
if (output.trim()) {
|
|
261
252
|
log.info(`Postrun script output: ${output}`);
|
|
262
253
|
}
|
|
@@ -43,15 +43,7 @@ export const executeMethodMap = {
|
|
|
43
43
|
command: 'macosClickAndDrag',
|
|
44
44
|
params: {
|
|
45
45
|
required: ['duration'],
|
|
46
|
-
optional: [
|
|
47
|
-
'sourceElementId',
|
|
48
|
-
'destinationElementId',
|
|
49
|
-
'startX',
|
|
50
|
-
'startY',
|
|
51
|
-
'endX',
|
|
52
|
-
'endY',
|
|
53
|
-
'keyModifierFlags',
|
|
54
|
-
],
|
|
46
|
+
optional: ['sourceElementId', 'destinationElementId', 'startX', 'startY', 'endX', 'endY', 'keyModifierFlags'],
|
|
55
47
|
},
|
|
56
48
|
},
|
|
57
49
|
'macos: clickAndDragAndHold': {
|
|
@@ -100,15 +92,7 @@ export const executeMethodMap = {
|
|
|
100
92
|
command: 'macosPressAndDrag',
|
|
101
93
|
params: {
|
|
102
94
|
required: ['duration'],
|
|
103
|
-
optional: [
|
|
104
|
-
'sourceElementId',
|
|
105
|
-
'destinationElementId',
|
|
106
|
-
'startX',
|
|
107
|
-
'startY',
|
|
108
|
-
'endX',
|
|
109
|
-
'endY',
|
|
110
|
-
'keyModifierFlags',
|
|
111
|
-
],
|
|
95
|
+
optional: ['sourceElementId', 'destinationElementId', 'startX', 'startY', 'endX', 'endY', 'keyModifierFlags'],
|
|
112
96
|
},
|
|
113
97
|
},
|
|
114
98
|
'macos: pressAndDragAndHold': {
|
|
@@ -180,15 +164,7 @@ export const executeMethodMap = {
|
|
|
180
164
|
command: 'macosStartRecordingScreen',
|
|
181
165
|
params: {
|
|
182
166
|
required: ['deviceId'],
|
|
183
|
-
optional: [
|
|
184
|
-
'timeLimit',
|
|
185
|
-
'videoFilter',
|
|
186
|
-
'fps',
|
|
187
|
-
'preset',
|
|
188
|
-
'captureCursor',
|
|
189
|
-
'captureClicks',
|
|
190
|
-
'forceRestart',
|
|
191
|
-
],
|
|
167
|
+
optional: ['timeLimit', 'videoFilter', 'fps', 'preset', 'captureCursor', 'captureClicks', 'forceRestart'],
|
|
192
168
|
},
|
|
193
169
|
},
|
|
194
170
|
'macos: stopRecordingScreen': {
|
|
@@ -209,16 +185,7 @@ export const executeMethodMap = {
|
|
|
209
185
|
'macos: stopNativeScreenRecording': {
|
|
210
186
|
command: 'macosStopNativeScreenRecording',
|
|
211
187
|
params: {
|
|
212
|
-
optional: [
|
|
213
|
-
'remotePath',
|
|
214
|
-
'user',
|
|
215
|
-
'pass',
|
|
216
|
-
'method',
|
|
217
|
-
'headers',
|
|
218
|
-
'fileFieldName',
|
|
219
|
-
'formFields',
|
|
220
|
-
'ignorePayload',
|
|
221
|
-
],
|
|
188
|
+
optional: ['remotePath', 'user', 'pass', 'method', 'headers', 'fileFieldName', 'formFields', 'ignorePayload'],
|
|
222
189
|
},
|
|
223
190
|
},
|
|
224
191
|
'macos: listDisplays': {
|
package/lib/utils.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {exec} from 'teen_process';
|
|
2
|
-
import {node} from 'appium/support.js';
|
|
3
1
|
import {fileURLToPath} from 'node:url';
|
|
4
2
|
|
|
3
|
+
import {node} from 'appium/support.js';
|
|
4
|
+
import {exec} from 'teen_process';
|
|
5
|
+
|
|
5
6
|
const MODULE_NAME = 'appium-mac2-driver';
|
|
6
7
|
const currentFilename = fileURLToPath(import.meta.url);
|
|
7
8
|
|