appium-mac2-driver 4.0.4 → 4.0.5
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 +6 -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 +150 -191
- package/package.json +66 -77
- package/scripts/open-wda.mjs +2 -1
|
@@ -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
|
|
package/lib/wda-mac.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import url from 'node:url';
|
|
3
|
-
import axios from 'axios';
|
|
4
2
|
import {setTimeout as delay} from 'node:timers/promises';
|
|
3
|
+
import url from 'node:url';
|
|
4
|
+
|
|
5
|
+
import {strongbox} from '@appium/strongbox';
|
|
6
|
+
import type {HTTPMethod, HTTPBody, ProxyResponse, ProxyOptions} from '@appium/types';
|
|
5
7
|
import {JWProxy, errors} from 'appium/driver.js';
|
|
6
8
|
import {fs, logger, util, timing} from 'appium/support.js';
|
|
7
|
-
import {strongbox} from '@appium/strongbox';
|
|
8
|
-
import {SubProcess, exec} from 'teen_process';
|
|
9
9
|
import {waitForCondition} from 'asyncbox';
|
|
10
|
+
import axios from 'axios';
|
|
10
11
|
import {checkPortStatus} from 'portscanner';
|
|
11
|
-
import
|
|
12
|
+
import {SubProcess, exec} from 'teen_process';
|
|
13
|
+
|
|
12
14
|
import {listChildrenProcessIds, getModuleRoot, clearArray, removeAllOccurrences} from './utils.js';
|
|
13
15
|
|
|
14
16
|
const log = logger.getLogger('WebDriverAgentMac');
|
|
@@ -51,9 +53,10 @@ class WDAMacProcess {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
async cleanupProjectIfFresh(): Promise<void> {
|
|
54
|
-
const packageInfo = JSON.parse(
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
const packageInfo = JSON.parse(await fs.readFile(path.join(getModuleRoot(), 'package.json'), 'utf8')) as {
|
|
57
|
+
name: string;
|
|
58
|
+
version: string;
|
|
59
|
+
};
|
|
57
60
|
const box = strongbox(packageInfo.name);
|
|
58
61
|
let boxItem = box.getItem(RECENT_MODULE_VERSION_ITEM_NAME);
|
|
59
62
|
if (!boxItem) {
|
|
@@ -69,9 +72,7 @@ class WDAMacProcess {
|
|
|
69
72
|
return;
|
|
70
73
|
}
|
|
71
74
|
} else {
|
|
72
|
-
log.info(
|
|
73
|
-
'There is no need to perform the project cleanup. A fresh install has been detected',
|
|
74
|
-
);
|
|
75
|
+
log.info('There is no need to perform the project cleanup. A fresh install has been detected');
|
|
75
76
|
try {
|
|
76
77
|
await box.createItemWithValue(RECENT_MODULE_VERSION_ITEM_NAME, packageInfo.version);
|
|
77
78
|
} catch (e: any) {
|
|
@@ -86,9 +87,7 @@ class WDAMacProcess {
|
|
|
86
87
|
recentModuleVersion = util.coerceVersion(recentModuleVersion, true);
|
|
87
88
|
} catch (e: any) {
|
|
88
89
|
log.warn(`The persisted module version string has been damaged: ${e.message}`);
|
|
89
|
-
log.info(
|
|
90
|
-
`Updating it to '${packageInfo.version}' assuming the project cleanup is not needed`,
|
|
91
|
-
);
|
|
90
|
+
log.info(`Updating it to '${packageInfo.version}' assuming the project cleanup is not needed`);
|
|
92
91
|
await boxItem.write(packageInfo.version);
|
|
93
92
|
return;
|
|
94
93
|
}
|
|
@@ -137,8 +136,7 @@ class WDAMacProcess {
|
|
|
137
136
|
xcodebuild = await fs.which(XCODEBUILD);
|
|
138
137
|
} catch {
|
|
139
138
|
throw new Error(
|
|
140
|
-
`${XCODEBUILD} binary cannot be found in PATH.
|
|
141
|
-
`Please make sure that Xcode is installed on your system`,
|
|
139
|
+
`${XCODEBUILD} binary cannot be found in PATH. Please make sure that Xcode is installed on your system`,
|
|
142
140
|
);
|
|
143
141
|
}
|
|
144
142
|
log.debug(`Using ${XCODEBUILD} binary at '${xcodebuild}'`);
|
|
@@ -147,8 +145,7 @@ class WDAMacProcess {
|
|
|
147
145
|
|
|
148
146
|
log.debug(`Using ${this.host} as server host`);
|
|
149
147
|
log.debug(`Using port ${this.port}`);
|
|
150
|
-
const isPortBusy = async (): Promise<boolean> =>
|
|
151
|
-
(await checkPortStatus(this.port, this.host)) === 'open';
|
|
148
|
+
const isPortBusy = async (): Promise<boolean> => (await checkPortStatus(this.port, this.host)) === 'open';
|
|
152
149
|
if (await isPortBusy()) {
|
|
153
150
|
log.warn(
|
|
154
151
|
`The port #${this.port} at ${this.host} is busy. ` +
|
|
@@ -256,16 +253,10 @@ class WDAMacProcess {
|
|
|
256
253
|
) {
|
|
257
254
|
return false;
|
|
258
255
|
}
|
|
259
|
-
if (
|
|
260
|
-
(systemPort && this.port !== systemPort) ||
|
|
261
|
-
(!systemPort && this.port !== DEFAULT_SYSTEM_PORT)
|
|
262
|
-
) {
|
|
256
|
+
if ((systemPort && this.port !== systemPort) || (!systemPort && this.port !== DEFAULT_SYSTEM_PORT)) {
|
|
263
257
|
return false;
|
|
264
258
|
}
|
|
265
|
-
if (
|
|
266
|
-
(systemHost && this.host !== systemHost) ||
|
|
267
|
-
(!systemHost && this.host !== DEFAULT_SYSTEM_HOST)
|
|
268
|
-
) {
|
|
259
|
+
if ((systemHost && this.host !== systemHost) || (!systemHost && this.host !== DEFAULT_SYSTEM_HOST)) {
|
|
269
260
|
return false;
|
|
270
261
|
}
|
|
271
262
|
if (
|
|
@@ -385,9 +376,7 @@ export class WDAMacServer {
|
|
|
385
376
|
removeAllOccurrences(RUNNING_PROCESS_IDS, pid);
|
|
386
377
|
});
|
|
387
378
|
}
|
|
388
|
-
log.info(
|
|
389
|
-
`The host process is ready within ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
|
|
390
|
-
);
|
|
379
|
+
log.info(`The host process is ready within ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
391
380
|
}
|
|
392
381
|
} else {
|
|
393
382
|
log.info('The host process has already been listening. Proceeding with session creation');
|
|
@@ -455,8 +444,7 @@ export class WDAMacServer {
|
|
|
455
444
|
parsedUrl = new url.URL(caps.webDriverAgentMacUrl);
|
|
456
445
|
} catch (e: any) {
|
|
457
446
|
throw new Error(
|
|
458
|
-
`webDriverAgentMacUrl, '${caps.webDriverAgentMacUrl}',
|
|
459
|
-
`in the capabilities is invalid. ${e.message}`,
|
|
447
|
+
`webDriverAgentMacUrl, '${caps.webDriverAgentMacUrl}', in the capabilities is invalid. ${e.message}`,
|
|
460
448
|
{cause: e},
|
|
461
449
|
);
|
|
462
450
|
}
|