appium-webdriveragent 14.2.1 → 15.0.0
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 +11 -0
- package/WebDriverAgentLib/Info.plist +2 -2
- package/build/lib/types.d.ts +44 -4
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/utils/index.d.ts +11 -0
- package/build/lib/utils/index.d.ts.map +1 -0
- package/build/lib/utils/index.js +27 -0
- package/build/lib/utils/index.js.map +1 -0
- package/build/lib/utils/module.d.ts +6 -0
- package/build/lib/utils/module.d.ts.map +1 -0
- package/build/lib/utils/module.js +31 -0
- package/build/lib/utils/module.js.map +1 -0
- package/build/lib/utils/platform.d.ts +7 -0
- package/build/lib/utils/platform.d.ts.map +1 -0
- package/build/lib/utils/platform.js +13 -0
- package/build/lib/utils/platform.js.map +1 -0
- package/build/lib/utils/processes.d.ts +23 -0
- package/build/lib/utils/processes.d.ts.map +1 -0
- package/build/lib/utils/processes.js +132 -0
- package/build/lib/utils/processes.js.map +1 -0
- package/build/lib/utils/security.d.ts +5 -0
- package/build/lib/utils/security.d.ts.map +1 -0
- package/build/lib/utils/security.js +15 -0
- package/build/lib/utils/security.js.map +1 -0
- package/build/lib/utils/xctestrun.d.ts +51 -0
- package/build/lib/utils/xctestrun.d.ts.map +1 -0
- package/build/lib/utils/xctestrun.js +120 -0
- package/build/lib/utils/xctestrun.js.map +1 -0
- package/build/lib/wda-strategies.d.ts +69 -0
- package/build/lib/wda-strategies.d.ts.map +1 -0
- package/build/lib/wda-strategies.js +253 -0
- package/build/lib/wda-strategies.js.map +1 -0
- package/build/lib/webdriveragent.d.ts +3 -14
- package/build/lib/webdriveragent.d.ts.map +1 -1
- package/build/lib/webdriveragent.js +78 -127
- package/build/lib/webdriveragent.js.map +1 -1
- package/build/lib/xcodebuild.d.ts.map +1 -1
- package/build/lib/xcodebuild.js +29 -7
- package/build/lib/xcodebuild.js.map +1 -1
- package/lib/types.ts +58 -4
- package/lib/utils/index.ts +20 -0
- package/lib/utils/module.ts +29 -0
- package/lib/utils/platform.ts +10 -0
- package/lib/utils/processes.ts +135 -0
- package/lib/utils/security.ts +15 -0
- package/lib/utils/xctestrun.ts +160 -0
- package/lib/wda-strategies.ts +340 -0
- package/lib/webdriveragent.ts +89 -163
- package/lib/xcodebuild.ts +34 -17
- package/package.json +2 -3
- package/build/lib/utils.d.ts +0 -105
- package/build/lib/utils.d.ts.map +0 -1
- package/build/lib/utils.js +0 -413
- package/build/lib/utils.js.map +0 -1
- package/lib/utils.ts +0 -442
package/lib/webdriveragent.ts
CHANGED
|
@@ -5,15 +5,9 @@ import {fs, util} from '@appium/support';
|
|
|
5
5
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
6
6
|
import {log as defaultLogger} from './logger';
|
|
7
7
|
import {NoSessionProxy} from './no-session-proxy';
|
|
8
|
-
import {
|
|
9
|
-
getWDAUpgradeTimestamp,
|
|
10
|
-
resetTestProcesses,
|
|
11
|
-
getPIDsListeningOnPort,
|
|
12
|
-
BOOTSTRAP_PATH,
|
|
13
|
-
} from './utils';
|
|
8
|
+
import {BOOTSTRAP_PATH, getWDAUpgradeTimestamp} from './utils';
|
|
14
9
|
import {XcodeBuild} from './xcodebuild';
|
|
15
10
|
import AsyncLock from 'async-lock';
|
|
16
|
-
import {exec} from 'teen_process';
|
|
17
11
|
import {
|
|
18
12
|
WDA_RUNNER_BUNDLE_ID,
|
|
19
13
|
WDA_BASE_URL,
|
|
@@ -26,9 +20,14 @@ import type {
|
|
|
26
20
|
AppleDevice,
|
|
27
21
|
XcodeBuildSettings,
|
|
28
22
|
RetrieveBuildSettingsOptions,
|
|
23
|
+
WdaHostOps,
|
|
29
24
|
} from './types';
|
|
30
|
-
import
|
|
31
|
-
|
|
25
|
+
import {
|
|
26
|
+
createDefaultWdaHostOps,
|
|
27
|
+
createWdaStartupStrategy,
|
|
28
|
+
type WdaStartupStrategy,
|
|
29
|
+
type WdaStartupStrategyContext,
|
|
30
|
+
} from './wda-strategies';
|
|
32
31
|
|
|
33
32
|
const WDA_LAUNCH_TIMEOUT = 60 * 1000;
|
|
34
33
|
const WDA_AGENT_PORT = 8100;
|
|
@@ -66,6 +65,8 @@ export class WebDriverAgent {
|
|
|
66
65
|
private readonly wdaLaunchTimeout: number;
|
|
67
66
|
private readonly usePreinstalledWDA?: boolean;
|
|
68
67
|
private readonly updatedWDABundleIdSuffix: string;
|
|
68
|
+
private readonly hostOps: Required<WdaHostOps>;
|
|
69
|
+
private activeStartupStrategy?: WdaStartupStrategy;
|
|
69
70
|
private _xcodebuild?: XcodeBuild | null;
|
|
70
71
|
private _url?: URL;
|
|
71
72
|
|
|
@@ -113,6 +114,21 @@ export class WebDriverAgent {
|
|
|
113
114
|
this.wdaLaunchTimeout = args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT;
|
|
114
115
|
this.usePreinstalledWDA = args.usePreinstalledWDA;
|
|
115
116
|
this.updatedWDABundleIdSuffix = args.updatedWDABundleIdSuffix ?? DEFAULT_TEST_BUNDLE_SUFFIX;
|
|
117
|
+
const defaultHostOps = createDefaultWdaHostOps();
|
|
118
|
+
this.hostOps = {
|
|
119
|
+
simulator: {
|
|
120
|
+
...defaultHostOps.simulator,
|
|
121
|
+
...args.hostOps?.simulator,
|
|
122
|
+
},
|
|
123
|
+
realDevicePreinstalled: {
|
|
124
|
+
...defaultHostOps.realDevicePreinstalled,
|
|
125
|
+
...args.hostOps?.realDevicePreinstalled,
|
|
126
|
+
},
|
|
127
|
+
realDeviceXcodebuild: {
|
|
128
|
+
...defaultHostOps.realDeviceXcodebuild,
|
|
129
|
+
...args.hostOps?.realDeviceXcodebuild,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
116
132
|
|
|
117
133
|
this._xcodebuild = this.canSkipXcodebuild
|
|
118
134
|
? null
|
|
@@ -244,32 +260,14 @@ export class WebDriverAgent {
|
|
|
244
260
|
* that are listening on the same port but belong to different devices.
|
|
245
261
|
*/
|
|
246
262
|
async cleanupObsoleteProcesses(): Promise<void> {
|
|
247
|
-
const obsoletePids = await getPIDsListeningOnPort(
|
|
248
|
-
this.url.port as string,
|
|
249
|
-
(cmdLine) =>
|
|
250
|
-
cmdLine.includes('/WebDriverAgentRunner') &&
|
|
251
|
-
!cmdLine.toLowerCase().includes(this.device.udid.toLowerCase()),
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
if (obsoletePids.length === 0) {
|
|
255
|
-
this.log.debug(
|
|
256
|
-
`No obsolete cached processes from previous WDA sessions ` +
|
|
257
|
-
`listening on port ${this.url.port} have been found`,
|
|
258
|
-
);
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
this.log.info(
|
|
263
|
-
`Detected ${obsoletePids.length} obsolete cached process${obsoletePids.length === 1 ? '' : 'es'} ` +
|
|
264
|
-
`from previous WDA sessions. Cleaning them up`,
|
|
265
|
-
);
|
|
266
263
|
try {
|
|
267
|
-
await
|
|
264
|
+
await this.hostOps.realDeviceXcodebuild.cleanupObsoleteProcesses?.({
|
|
265
|
+
udid: this.device.udid,
|
|
266
|
+
port: this.url.port as string,
|
|
267
|
+
commandLineIncludes: '/WebDriverAgentRunner',
|
|
268
|
+
});
|
|
268
269
|
} catch (e: any) {
|
|
269
|
-
this.log.warn(
|
|
270
|
-
`Failed to kill obsolete cached process${obsoletePids.length === 1 ? '' : 'es'} '${obsoletePids}'. ` +
|
|
271
|
-
`Original error: ${e.message}`,
|
|
272
|
-
);
|
|
270
|
+
this.log.warn(`Failed to clean obsolete cached processes. Original error: ${e.message}`);
|
|
273
271
|
}
|
|
274
272
|
}
|
|
275
273
|
|
|
@@ -298,53 +296,10 @@ export class WebDriverAgent {
|
|
|
298
296
|
* @param sessionId Launch WDA and establish the session with this sessionId
|
|
299
297
|
*/
|
|
300
298
|
async launch(sessionId: string): Promise<StringRecord | null> {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return await this.getStatus();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (this.usePreinstalledWDA) {
|
|
309
|
-
return await this.launchWithPreinstalledWDA(sessionId);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
this.log.info('Launching WebDriverAgent on the device');
|
|
313
|
-
|
|
314
|
-
this.setupProxies(sessionId);
|
|
315
|
-
|
|
316
|
-
if (!this.useXctestrunFile && !(await fs.exists(this.agentPath))) {
|
|
317
|
-
throw new Error(
|
|
318
|
-
`Trying to use WebDriverAgent project at '${this.agentPath}' but the ` +
|
|
319
|
-
'file does not exist',
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// useXctestrunFile and usePrebuiltWDA use existing dependencies
|
|
324
|
-
// It depends on user side
|
|
325
|
-
if (this.useXctestrunFile || this.usePrebuiltWDA) {
|
|
326
|
-
this.log.info('Skipped WDA project cleanup according to the provided capabilities');
|
|
327
|
-
} else {
|
|
328
|
-
const synchronizationKey = path.normalize(this.bootstrapPath);
|
|
329
|
-
await SHARED_RESOURCES_GUARD.acquire(
|
|
330
|
-
synchronizationKey,
|
|
331
|
-
async () => await this._cleanupProjectIfFresh(),
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// We need to provide WDA local port, because it might be occupied
|
|
336
|
-
await resetTestProcesses(this.device.udid, !this.isRealDevice);
|
|
337
|
-
|
|
338
|
-
if (!this.noSessionProxy) {
|
|
339
|
-
throw new Error('noSessionProxy is not available');
|
|
340
|
-
}
|
|
341
|
-
await this.xcodebuild.init(this.noSessionProxy);
|
|
342
|
-
|
|
343
|
-
// Start the xcodebuild process
|
|
344
|
-
if (this.prebuildWDA) {
|
|
345
|
-
await this.xcodebuild.prebuild();
|
|
346
|
-
}
|
|
347
|
-
return (await this.xcodebuild.start()) as StringRecord | null;
|
|
299
|
+
const startupStrategy = this.createStartupStrategy();
|
|
300
|
+
this.log.info(`Selected '${startupStrategy.name}' WebDriverAgent startup strategy`);
|
|
301
|
+
this.activeStartupStrategy = startupStrategy;
|
|
302
|
+
return await startupStrategy.launch(sessionId);
|
|
348
303
|
}
|
|
349
304
|
|
|
350
305
|
/**
|
|
@@ -364,27 +319,7 @@ export class WebDriverAgent {
|
|
|
364
319
|
* Handles both preinstalled WDA and xcodebuild-based sessions.
|
|
365
320
|
*/
|
|
366
321
|
async quit(): Promise<void> {
|
|
367
|
-
|
|
368
|
-
this.log.info('Stopping the XCTest session');
|
|
369
|
-
try {
|
|
370
|
-
if (this.device.simctl) {
|
|
371
|
-
await this.device.simctl.terminateApp(this.bundleIdForXctest);
|
|
372
|
-
} else if (this.device.devicectl) {
|
|
373
|
-
await this.device.devicectl.terminateApp(this.bundleIdForXctest);
|
|
374
|
-
}
|
|
375
|
-
} catch (e: any) {
|
|
376
|
-
this.log.warn(e.message);
|
|
377
|
-
}
|
|
378
|
-
} else if (!this.args.webDriverAgentUrl) {
|
|
379
|
-
this.log.info('Shutting down sub-processes');
|
|
380
|
-
if (this._xcodebuild) {
|
|
381
|
-
await this.xcodebuild.quit();
|
|
382
|
-
}
|
|
383
|
-
} else {
|
|
384
|
-
this.log.debug(
|
|
385
|
-
'Stopping neither xcodebuild nor XCTest session since WDA lifecycle is not managed by this driver',
|
|
386
|
-
);
|
|
387
|
-
}
|
|
322
|
+
await (this.activeStartupStrategy ?? this.createStartupStrategy()).quit();
|
|
388
323
|
|
|
389
324
|
if (this.jwproxy) {
|
|
390
325
|
this.jwproxy.sessionId = null;
|
|
@@ -397,6 +332,7 @@ export class WebDriverAgent {
|
|
|
397
332
|
// then clean that up. If the url was supplied, we want to keep it
|
|
398
333
|
this.webDriverAgentUrl = undefined;
|
|
399
334
|
}
|
|
335
|
+
this.activeStartupStrategy = undefined;
|
|
400
336
|
}
|
|
401
337
|
|
|
402
338
|
/**
|
|
@@ -487,6 +423,58 @@ export class WebDriverAgent {
|
|
|
487
423
|
return cachedUrl;
|
|
488
424
|
}
|
|
489
425
|
|
|
426
|
+
private createStartupStrategy(): WdaStartupStrategy {
|
|
427
|
+
const context: WdaStartupStrategyContext = {
|
|
428
|
+
argsWebDriverAgentUrl: this.args.webDriverAgentUrl,
|
|
429
|
+
webDriverAgentUrl: this.webDriverAgentUrl,
|
|
430
|
+
usePreinstalledWDA: this.usePreinstalledWDA,
|
|
431
|
+
useXctestrunFile: this.useXctestrunFile,
|
|
432
|
+
usePrebuiltWDA: this.usePrebuiltWDA,
|
|
433
|
+
prebuildWDA: this.prebuildWDA,
|
|
434
|
+
isRealDevice: this.isRealDevice,
|
|
435
|
+
device: this.device,
|
|
436
|
+
agentPath: this.agentPath,
|
|
437
|
+
bootstrapPath: this.bootstrapPath,
|
|
438
|
+
bundleIdForXctest: this.bundleIdForXctest,
|
|
439
|
+
wdaLocalPort: this.wdaLocalPort,
|
|
440
|
+
wdaRemotePort: this.wdaRemotePort,
|
|
441
|
+
wdaBindingIP: this.wdaBindingIP,
|
|
442
|
+
wdaLaunchTimeout: this.wdaLaunchTimeout,
|
|
443
|
+
mjpegServerPort: this.mjpegServerPort,
|
|
444
|
+
maxHttpRequestBodySize: this.maxHttpRequestBodySize,
|
|
445
|
+
platformName: this.platformName,
|
|
446
|
+
platformVersion: this.platformVersion,
|
|
447
|
+
log: this.log,
|
|
448
|
+
hostOps: this.hostOps,
|
|
449
|
+
setWebDriverAgentUrl: (value) => {
|
|
450
|
+
this.webDriverAgentUrl = value;
|
|
451
|
+
},
|
|
452
|
+
setUrl: (value) => {
|
|
453
|
+
this.url = value;
|
|
454
|
+
},
|
|
455
|
+
setupProxies: (sessionId) => this.setupProxies(sessionId),
|
|
456
|
+
getStatus: async (timeoutMs) => await this.getStatus(timeoutMs),
|
|
457
|
+
cleanupProjectIfFresh: async () => {
|
|
458
|
+
const synchronizationKey = path.normalize(this.bootstrapPath);
|
|
459
|
+
await SHARED_RESOURCES_GUARD.acquire(
|
|
460
|
+
synchronizationKey,
|
|
461
|
+
async () => await this._cleanupProjectIfFresh(),
|
|
462
|
+
);
|
|
463
|
+
},
|
|
464
|
+
xcodebuild: () => this.xcodebuild,
|
|
465
|
+
noSessionProxy: () => {
|
|
466
|
+
if (!this.noSessionProxy) {
|
|
467
|
+
throw new Error('noSessionProxy is not available');
|
|
468
|
+
}
|
|
469
|
+
return this.noSessionProxy;
|
|
470
|
+
},
|
|
471
|
+
setStarted: (started) => {
|
|
472
|
+
this.started = started;
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
return createWdaStartupStrategy(context);
|
|
476
|
+
}
|
|
477
|
+
|
|
490
478
|
private setupProxies(sessionId: string): void {
|
|
491
479
|
const proxyOpts: any = {
|
|
492
480
|
log: this.log,
|
|
@@ -671,66 +659,4 @@ export class WebDriverAgent {
|
|
|
671
659
|
this.log.warn(`Cannot perform WebDriverAgent project cleanup. Original error: ${e.message}`);
|
|
672
660
|
}
|
|
673
661
|
}
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Launch WDA with preinstalled package with 'xcrun devicectl device process launch'.
|
|
677
|
-
* The WDA package must be prepared properly like published via
|
|
678
|
-
* https://github.com/appium/WebDriverAgent/releases
|
|
679
|
-
* with proper sign for this case.
|
|
680
|
-
*
|
|
681
|
-
* @param opts launching WDA with devicectl command options.
|
|
682
|
-
*/
|
|
683
|
-
private async _launchViaDevicectl(
|
|
684
|
-
opts: {env?: Record<string, string | number>} = {},
|
|
685
|
-
): Promise<void> {
|
|
686
|
-
const {env} = opts;
|
|
687
|
-
|
|
688
|
-
await (this.device.devicectl as Devicectl).launchApp(this.bundleIdForXctest, {
|
|
689
|
-
env,
|
|
690
|
-
terminateExisting: true,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
/**
|
|
695
|
-
* Launch WDA with preinstalled package without xcodebuild.
|
|
696
|
-
* @param sessionId Launch WDA and establish the session with this sessionId
|
|
697
|
-
*/
|
|
698
|
-
private async launchWithPreinstalledWDA(sessionId: string): Promise<StringRecord | null> {
|
|
699
|
-
const xctestEnv: Record<string, string | number> = {
|
|
700
|
-
USE_PORT: this.wdaLocalPort || WDA_AGENT_PORT,
|
|
701
|
-
WDA_PRODUCT_BUNDLE_IDENTIFIER: this.bundleIdForXctest,
|
|
702
|
-
};
|
|
703
|
-
if (this.mjpegServerPort) {
|
|
704
|
-
xctestEnv.MJPEG_SERVER_PORT = this.mjpegServerPort;
|
|
705
|
-
}
|
|
706
|
-
if (this.wdaBindingIP) {
|
|
707
|
-
xctestEnv.USE_IP = this.wdaBindingIP;
|
|
708
|
-
}
|
|
709
|
-
if (this.maxHttpRequestBodySize) {
|
|
710
|
-
xctestEnv.MAX_HTTP_REQUEST_BODY_SIZE = this.maxHttpRequestBodySize;
|
|
711
|
-
}
|
|
712
|
-
this.log.info('Launching WebDriverAgent on the device without xcodebuild');
|
|
713
|
-
if (this.isRealDevice) {
|
|
714
|
-
await this._launchViaDevicectl({env: xctestEnv});
|
|
715
|
-
} else {
|
|
716
|
-
await (this.device.simctl as Simctl).exec('launch', {
|
|
717
|
-
args: ['--terminate-running-process', this.device.udid, this.bundleIdForXctest],
|
|
718
|
-
env: xctestEnv,
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
this.setupProxies(sessionId);
|
|
723
|
-
let status: StringRecord | null;
|
|
724
|
-
try {
|
|
725
|
-
status = await this.getStatus(this.wdaLaunchTimeout);
|
|
726
|
-
} catch {
|
|
727
|
-
throw new Error(
|
|
728
|
-
`Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` +
|
|
729
|
-
`The WebDriverAgent might not be properly built or the device might be locked. ` +
|
|
730
|
-
`The 'appium:wdaLaunchTimeout' capability modifies the timeout.`,
|
|
731
|
-
);
|
|
732
|
-
}
|
|
733
|
-
this.started = true;
|
|
734
|
-
return status;
|
|
735
|
-
}
|
|
736
662
|
}
|
package/lib/xcodebuild.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import {retryInterval} from 'asyncbox';
|
|
2
2
|
import {SubProcess, exec} from 'teen_process';
|
|
3
|
-
import {logger, timing} from '@appium/support';
|
|
3
|
+
import {logger, timing, util} from '@appium/support';
|
|
4
4
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
5
5
|
import {log as defaultLogger} from './logger';
|
|
6
|
-
import {
|
|
7
|
-
setRealDeviceSecurity,
|
|
8
|
-
setXctestrunFile,
|
|
9
|
-
killProcess,
|
|
10
|
-
getWDAUpgradeTimestamp,
|
|
11
|
-
isTvOS,
|
|
12
|
-
escapeRegExp,
|
|
13
|
-
truncateString,
|
|
14
|
-
} from './utils';
|
|
6
|
+
import {getWDAUpgradeTimestamp, isTvOS, setRealDeviceSecurity, setXctestrunFile} from './utils';
|
|
15
7
|
import path from 'node:path';
|
|
16
8
|
import {WDA_RUNNER_BUNDLE_ID} from './constants';
|
|
17
9
|
import type {
|
|
@@ -36,7 +28,7 @@ const IGNORED_ERRORS = [
|
|
|
36
28
|
'Failed to remove screenshot at path',
|
|
37
29
|
];
|
|
38
30
|
const IGNORED_ERRORS_PATTERN = new RegExp(
|
|
39
|
-
'(' + IGNORED_ERRORS.map((errStr) => escapeRegExp(errStr)).join('|') + ')',
|
|
31
|
+
'(' + IGNORED_ERRORS.map((errStr) => util.escapeRegExp(errStr)).join('|') + ')',
|
|
40
32
|
);
|
|
41
33
|
|
|
42
34
|
const RUNNER_SCHEME_TV = 'WebDriverAgentRunner_tvOS';
|
|
@@ -308,7 +300,34 @@ export class XcodeBuild {
|
|
|
308
300
|
* Stops the xcodebuild process and cleans up resources.
|
|
309
301
|
*/
|
|
310
302
|
async quit(): Promise<void> {
|
|
311
|
-
|
|
303
|
+
const xcodebuild = this.xcodebuild;
|
|
304
|
+
if (!xcodebuild || !xcodebuild.isRunning) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
this.log.info(`Shutting down 'xcodebuild' process (pid '${xcodebuild.proc?.pid}')`);
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
await xcodebuild.stop('SIGTERM', 1000);
|
|
312
|
+
return;
|
|
313
|
+
} catch (err: unknown) {
|
|
314
|
+
if (!(err as Error)?.message?.includes(`Process didn't end after`)) {
|
|
315
|
+
throw err;
|
|
316
|
+
}
|
|
317
|
+
this.log.debug(
|
|
318
|
+
`xcodebuild process did not end in a timely fashion: '${(err as Error)?.message}'.`,
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
await xcodebuild.stop('SIGKILL');
|
|
324
|
+
} catch (err: unknown) {
|
|
325
|
+
if ((err as Error)?.message?.includes('not currently running')) {
|
|
326
|
+
// The process ended but for some reason we were not informed.
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
throw err;
|
|
330
|
+
}
|
|
312
331
|
}
|
|
313
332
|
|
|
314
333
|
private async fetchBuildSettings(
|
|
@@ -336,7 +355,7 @@ export class XcodeBuild {
|
|
|
336
355
|
entries = JSON.parse(stdout) as XcodeShowBuildSettingsEntry[];
|
|
337
356
|
} catch (err: any) {
|
|
338
357
|
this.log.warn(
|
|
339
|
-
`Cannot parse WDA build settings for scheme '${schemeLabel}' from ${truncateString(stdout, 300)}. ` +
|
|
358
|
+
`Cannot parse WDA build settings for scheme '${schemeLabel}' from ${util.truncateString(stdout, 300)}. ` +
|
|
340
359
|
`Original error: ${err.message}`,
|
|
341
360
|
);
|
|
342
361
|
return;
|
|
@@ -433,10 +452,8 @@ export class XcodeBuild {
|
|
|
433
452
|
}
|
|
434
453
|
|
|
435
454
|
private async createSubProcess(buildOnly: boolean = false): Promise<SubProcess> {
|
|
436
|
-
if (!this.useXctestrunFile && this.realDevice) {
|
|
437
|
-
|
|
438
|
-
await setRealDeviceSecurity(this.keychainPath, this.keychainPassword);
|
|
439
|
-
}
|
|
455
|
+
if (!this.useXctestrunFile && this.realDevice && this.keychainPath && this.keychainPassword) {
|
|
456
|
+
await setRealDeviceSecurity(this.keychainPath, this.keychainPassword);
|
|
440
457
|
}
|
|
441
458
|
|
|
442
459
|
const {cmd, args} = this.getCommand(buildOnly);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-webdriveragent",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "Package bundling WebDriverAgent",
|
|
5
5
|
"main": "./build/lib/index.js",
|
|
6
6
|
"types": "./build/lib/index.d.ts",
|
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
"chai-as-promised": "^8.0.0",
|
|
66
66
|
"conventional-changelog-conventionalcommits": "^9.0.0",
|
|
67
67
|
"mocha": "^11.0.1",
|
|
68
|
-
"node-devicectl": "^1.4.0",
|
|
69
68
|
"node-simctl": "^8.0.0",
|
|
70
69
|
"prettier": "^3.0.0",
|
|
71
70
|
"semantic-release": "^25.0.2",
|
|
@@ -77,7 +76,7 @@
|
|
|
77
76
|
"dependencies": {
|
|
78
77
|
"@appium/base-driver": "^10.3.0",
|
|
79
78
|
"@appium/strongbox": "^1.0.0-rc.1",
|
|
80
|
-
"@appium/support": "^7.
|
|
79
|
+
"@appium/support": "^7.2.1",
|
|
81
80
|
"appium-ios-simulator": "^8.0.0",
|
|
82
81
|
"async-lock": "^1.0.0",
|
|
83
82
|
"asyncbox": "^6.1.0",
|
package/build/lib/utils.d.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import type { SubProcess } from 'teen_process';
|
|
2
|
-
import type { DeviceInfo } from './types';
|
|
3
|
-
export declare const BOOTSTRAP_PATH: string;
|
|
4
|
-
/**
|
|
5
|
-
* Arguments for setting xctestrun file
|
|
6
|
-
*/
|
|
7
|
-
export interface XctestrunFileArgs {
|
|
8
|
-
deviceInfo: DeviceInfo;
|
|
9
|
-
sdkVersion: string;
|
|
10
|
-
bootstrapPath: string;
|
|
11
|
-
wdaRemotePort: number | string;
|
|
12
|
-
wdaBindingIP?: string;
|
|
13
|
-
maxHttpRequestBodySize?: number | string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Find and terminate all processes matching the given pgrep pattern.
|
|
17
|
-
*/
|
|
18
|
-
export declare function killAppUsingPattern(pgrepPattern: string): Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Return true if the platformName is tvOS
|
|
21
|
-
* @param platformName The name of the platorm
|
|
22
|
-
* @returns Return true if the platformName is tvOS
|
|
23
|
-
*/
|
|
24
|
-
export declare function isTvOS(platformName: string): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Configure keychain access required for real-device code signing.
|
|
27
|
-
*/
|
|
28
|
-
export declare function setRealDeviceSecurity(keychainPath: string, keychainPassword: string): Promise<void>;
|
|
29
|
-
/**
|
|
30
|
-
* Creates xctestrun file per device & platform version.
|
|
31
|
-
* We expects to have WebDriverAgentRunner_iphoneos${sdkVersion|platformVersion}-arm64.xctestrun for real device
|
|
32
|
-
* and WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-${x86_64|arm64}.xctestrun for simulator located @bootstrapPath
|
|
33
|
-
* Newer Xcode (Xcode 10.0 at least) generate xctestrun file following sdkVersion.
|
|
34
|
-
* e.g. Xcode which has iOS SDK Version 12.2 on an intel Mac host machine generates WebDriverAgentRunner_iphonesimulator.2-x86_64.xctestrun
|
|
35
|
-
* even if the cap has platform version 11.4
|
|
36
|
-
*
|
|
37
|
-
* @param args
|
|
38
|
-
* @return returns xctestrunFilePath for given device
|
|
39
|
-
* @throws if WebDriverAgentRunner_iphoneos${sdkVersion|platformVersion}-arm64.xctestrun for real device
|
|
40
|
-
* or WebDriverAgentRunner_iphonesimulator${sdkVersion|platformVersion}-x86_64.xctestrun for simulator is not found @bootstrapPath,
|
|
41
|
-
* then it will throw a file not found exception
|
|
42
|
-
*/
|
|
43
|
-
export declare function setXctestrunFile(args: XctestrunFileArgs): Promise<string>;
|
|
44
|
-
/**
|
|
45
|
-
* Return the WDA object which appends existing xctest runner content
|
|
46
|
-
* @param platformName - The name of the platform
|
|
47
|
-
* @param wdaRemotePort - The remote port number
|
|
48
|
-
* @param wdaBindingIP - The IP address to bind to. If not given, it binds to all interfaces.
|
|
49
|
-
* @param maxHttpRequestBodySize - The maximum HTTP request body size in bytes.
|
|
50
|
-
* @return returns a runner object which has USE_PORT and optionally USE_IP
|
|
51
|
-
*/
|
|
52
|
-
export declare function getAdditionalRunContent(platformName: string, wdaRemotePort: number | string, wdaBindingIP?: string, maxHttpRequestBodySize?: number | string): Record<string, any>;
|
|
53
|
-
/**
|
|
54
|
-
* Return the path of xctestrun if it exists
|
|
55
|
-
* @param deviceInfo
|
|
56
|
-
* @param sdkVersion - The Xcode SDK version of OS.
|
|
57
|
-
* @param bootstrapPath - The folder path containing xctestrun file.
|
|
58
|
-
*/
|
|
59
|
-
export declare function getXctestrunFilePath(deviceInfo: DeviceInfo, sdkVersion: string, bootstrapPath: string): Promise<string>;
|
|
60
|
-
/**
|
|
61
|
-
* Return the name of xctestrun file
|
|
62
|
-
* @param deviceInfo
|
|
63
|
-
* @param version - The Xcode SDK version of OS.
|
|
64
|
-
* @return returns xctestrunFilePath for given device
|
|
65
|
-
*/
|
|
66
|
-
export declare function getXctestrunFileName(deviceInfo: DeviceInfo, version: string): string;
|
|
67
|
-
/**
|
|
68
|
-
* Ensures the process is killed after the timeout
|
|
69
|
-
*/
|
|
70
|
-
export declare function killProcess(name: string, proc: SubProcess | null | undefined): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Generate a random integer in range [low, high). `low` is inclusive and `high` is exclusive.
|
|
73
|
-
*/
|
|
74
|
-
export declare function randomInt(low: number, high: number): number;
|
|
75
|
-
/**
|
|
76
|
-
* Retrieves WDA upgrade timestamp. The manifest only gets modified on package upgrade.
|
|
77
|
-
*/
|
|
78
|
-
export declare function getWDAUpgradeTimestamp(): Promise<number | null>;
|
|
79
|
-
/**
|
|
80
|
-
* Escape regular expression metacharacters in a string.
|
|
81
|
-
*/
|
|
82
|
-
export declare function escapeRegExp(value: string): string;
|
|
83
|
-
/**
|
|
84
|
-
* Truncate a string to the given length and append ellipsis if needed.
|
|
85
|
-
*/
|
|
86
|
-
export declare function truncateString(value: string, length: number): string;
|
|
87
|
-
/**
|
|
88
|
-
* Kills running XCTest processes for the particular device.
|
|
89
|
-
*/
|
|
90
|
-
export declare function resetTestProcesses(udid: string, isSimulator: boolean): Promise<void>;
|
|
91
|
-
/**
|
|
92
|
-
* Get the IDs of processes listening on the particular system port.
|
|
93
|
-
* It is also possible to apply additional filtering based on the
|
|
94
|
-
* process command line.
|
|
95
|
-
*
|
|
96
|
-
* @param port - The port number.
|
|
97
|
-
* @param filteringFunc - Optional lambda function, which
|
|
98
|
-
* receives command line string of the particular process
|
|
99
|
-
* listening on given port, and is expected to return
|
|
100
|
-
* either true or false to include/exclude the corresponding PID
|
|
101
|
-
* from the resulting array.
|
|
102
|
-
* @returns - the list of matched process ids.
|
|
103
|
-
*/
|
|
104
|
-
export declare function getPIDsListeningOnPort(port: string | number, filteringFunc?: ((cmdline: string) => boolean | Promise<boolean>) | null): Promise<string[]>;
|
|
105
|
-
//# sourceMappingURL=utils.d.ts.map
|
package/build/lib/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../lib/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AAQ7C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,SAAS,CAAC;AAyCxC,eAAO,MAAM,cAAc,QAAkB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB/E;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GAAG,MAAM,EAC9B,YAAY,CAAC,EAAE,MAAM,EACrB,sBAAsB,CAAC,EAAE,MAAM,GAAG,MAAM,GACvC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAcrB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC,CAmCjB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKpF;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAClC,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOrE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,aAAa,GAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,IAAW,GAC7E,OAAO,CAAC,MAAM,EAAE,CAAC,CAiCnB"}
|