appium-webdriveragent 15.1.6 → 16.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/Scripts/build-webdriveragent.mjs +8 -9
- package/Scripts/fetch-prebuilt-wda.mjs +16 -14
- package/Scripts/update-wda-version.mjs +12 -10
- package/WebDriverAgentLib/Info.plist +2 -2
- package/build/lib/check-dependencies.d.ts +1 -1
- package/build/lib/check-dependencies.d.ts.map +1 -1
- package/build/lib/check-dependencies.js +12 -18
- package/build/lib/check-dependencies.js.map +1 -1
- package/build/lib/constants.js +13 -19
- package/build/lib/constants.js.map +1 -1
- package/build/lib/index.d.ts +6 -6
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +6 -32
- package/build/lib/index.js.map +1 -1
- package/build/lib/logger.js +2 -5
- package/build/lib/logger.js.map +1 -1
- package/build/lib/no-session-proxy.js +2 -6
- package/build/lib/no-session-proxy.js.map +1 -1
- package/build/lib/types.d.ts.map +1 -1
- package/build/lib/types.js +1 -2
- package/build/lib/utils/index.d.ts +6 -6
- package/build/lib/utils/index.d.ts.map +1 -1
- package/build/lib/utils/index.js +8 -22
- package/build/lib/utils/index.js.map +1 -1
- package/build/lib/utils/module.d.ts.map +1 -1
- package/build/lib/utils/module.js +9 -20
- package/build/lib/utils/module.js.map +1 -1
- package/build/lib/utils/platform.js +3 -6
- package/build/lib/utils/platform.js.map +1 -1
- package/build/lib/utils/processes.d.ts.map +1 -1
- package/build/lib/utils/processes.js +16 -21
- package/build/lib/utils/processes.js.map +1 -1
- package/build/lib/utils/security.d.ts.map +1 -1
- package/build/lib/utils/security.js +7 -10
- package/build/lib/utils/security.js.map +1 -1
- package/build/lib/utils/xctestrun.d.ts +1 -1
- package/build/lib/utils/xctestrun.d.ts.map +1 -1
- package/build/lib/utils/xctestrun.js +26 -37
- package/build/lib/utils/xctestrun.js.map +1 -1
- package/build/lib/wda-strategies.d.ts +3 -3
- package/build/lib/wda-strategies.d.ts.map +1 -1
- package/build/lib/wda-strategies.js +15 -24
- package/build/lib/wda-strategies.js.map +1 -1
- package/build/lib/webdriveragent.d.ts +3 -8
- package/build/lib/webdriveragent.d.ts.map +1 -1
- package/build/lib/webdriveragent.js +45 -63
- package/build/lib/webdriveragent.js.map +1 -1
- package/build/lib/xcodebuild.d.ts +2 -2
- package/build/lib/xcodebuild.d.ts.map +1 -1
- package/build/lib/xcodebuild.js +29 -43
- package/build/lib/xcodebuild.js.map +1 -1
- package/lib/check-dependencies.ts +7 -11
- package/lib/index.ts +6 -6
- package/lib/types.ts +5 -3
- package/lib/utils/index.ts +7 -12
- package/lib/utils/module.ts +2 -7
- package/lib/utils/platform.ts +1 -1
- package/lib/utils/processes.ts +3 -4
- package/lib/utils/security.ts +3 -5
- package/lib/utils/xctestrun.ts +11 -24
- package/lib/wda-strategies.ts +10 -17
- package/lib/webdriveragent.ts +22 -48
- package/lib/xcodebuild.ts +20 -41
- package/package.json +66 -67
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
1
3
|
import {fs} from '@appium/support';
|
|
2
4
|
import {exec} from 'teen_process';
|
|
3
|
-
|
|
4
|
-
import {WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP} from './constants';
|
|
5
|
-
import {BOOTSTRAP_PATH} from './utils';
|
|
6
|
-
import type {XcodeBuild} from './xcodebuild';
|
|
5
|
+
|
|
6
|
+
import {WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP} from './constants.js';
|
|
7
|
+
import {BOOTSTRAP_PATH} from './utils/index.js';
|
|
8
|
+
import type {XcodeBuild} from './xcodebuild.js';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Ensure simulator WDA is built and return the resulting app bundle path.
|
|
@@ -13,13 +15,7 @@ export async function bundleWDASim(xcodebuild: XcodeBuild): Promise<string> {
|
|
|
13
15
|
if (!derivedDataPath) {
|
|
14
16
|
throw new Error('Cannot retrieve the path to the Xcode derived data folder');
|
|
15
17
|
}
|
|
16
|
-
const wdaBundlePath = path.join(
|
|
17
|
-
derivedDataPath,
|
|
18
|
-
'Build',
|
|
19
|
-
'Products',
|
|
20
|
-
'Debug-iphonesimulator',
|
|
21
|
-
WDA_RUNNER_APP,
|
|
22
|
-
);
|
|
18
|
+
const wdaBundlePath = path.join(derivedDataPath, 'Build', 'Products', 'Debug-iphonesimulator', WDA_RUNNER_APP);
|
|
23
19
|
if (await fs.exists(wdaBundlePath)) {
|
|
24
20
|
return wdaBundlePath;
|
|
25
21
|
}
|
package/lib/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export {bundleWDASim} from './check-dependencies';
|
|
2
|
-
export {NoSessionProxy} from './no-session-proxy';
|
|
3
|
-
export {WebDriverAgent} from './webdriveragent';
|
|
4
|
-
export {WDA_BASE_URL, WDA_RUNNER_APP, WDA_RUNNER_BUNDLE_ID, PROJECT_FILE} from './constants';
|
|
5
|
-
export {resetTestProcesses, BOOTSTRAP_PATH} from './utils';
|
|
1
|
+
export {bundleWDASim} from './check-dependencies.js';
|
|
2
|
+
export {NoSessionProxy} from './no-session-proxy.js';
|
|
3
|
+
export {WebDriverAgent} from './webdriveragent.js';
|
|
4
|
+
export {WDA_BASE_URL, WDA_RUNNER_APP, WDA_RUNNER_BUNDLE_ID, PROJECT_FILE} from './constants.js';
|
|
5
|
+
export {resetTestProcesses, BOOTSTRAP_PATH} from './utils/index.js';
|
|
6
6
|
|
|
7
|
-
export * from './types';
|
|
7
|
+
export * from './types.js';
|
package/lib/types.ts
CHANGED
|
@@ -23,8 +23,7 @@ export interface WDASettings {
|
|
|
23
23
|
defaultAlertAction?: 'accept' | 'dismiss';
|
|
24
24
|
acceptAlertButtonSelector?: string;
|
|
25
25
|
dismissAlertButtonSelector?: string;
|
|
26
|
-
screenshotOrientation?:
|
|
27
|
-
'auto' | 'portrait' | 'portraitUpsideDown' | 'landscapeRight' | 'landscapeLeft';
|
|
26
|
+
screenshotOrientation?: 'auto' | 'portrait' | 'portraitUpsideDown' | 'landscapeRight' | 'landscapeLeft';
|
|
28
27
|
waitForIdleTimeout?: number;
|
|
29
28
|
animationCoolOffTimeout?: number;
|
|
30
29
|
maxTypingFrequency?: number;
|
|
@@ -100,7 +99,10 @@ export interface AppleDevice {
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
export type WdaStartupStrategyName =
|
|
103
|
-
'existing-url'
|
|
102
|
+
| 'existing-url'
|
|
103
|
+
| 'simulator'
|
|
104
|
+
| 'real-device-xcodebuild'
|
|
105
|
+
| 'real-device-preinstalled';
|
|
104
106
|
|
|
105
107
|
export type WdaLaunchEnvironment = Record<string, string | number>;
|
|
106
108
|
|
package/lib/utils/index.ts
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {getWDAUpgradeTimestamp as getWDAUpgradeTimestampImpl} from './module';
|
|
1
|
+
import {getWDAUpgradeTimestamp as getWDAUpgradeTimestampImpl} from './module.js';
|
|
2
2
|
|
|
3
|
-
export {BOOTSTRAP_PATH} from './module';
|
|
4
|
-
export {isTvOS} from './platform';
|
|
5
|
-
export {getPIDsListeningOnPort, killAppUsingPattern, resetTestProcesses} from './processes';
|
|
6
|
-
export {setRealDeviceSecurity} from './security';
|
|
7
|
-
export {
|
|
8
|
-
|
|
9
|
-
getXctestrunFileName,
|
|
10
|
-
getXctestrunFilePath,
|
|
11
|
-
setXctestrunFile,
|
|
12
|
-
} from './xctestrun';
|
|
13
|
-
export type {XctestrunFileArgs} from './xctestrun';
|
|
3
|
+
export {BOOTSTRAP_PATH} from './module.js';
|
|
4
|
+
export {isTvOS} from './platform.js';
|
|
5
|
+
export {getPIDsListeningOnPort, killAppUsingPattern, resetTestProcesses} from './processes.js';
|
|
6
|
+
export {setRealDeviceSecurity} from './security.js';
|
|
7
|
+
export {getAdditionalRunContent, getXctestrunFileName, getXctestrunFilePath, setXctestrunFile} from './xctestrun.js';
|
|
8
|
+
export type {XctestrunFileArgs} from './xctestrun.js';
|
|
14
9
|
|
|
15
10
|
/**
|
|
16
11
|
* Retrieves WDA upgrade timestamp. The manifest only gets modified on package upgrade.
|
package/lib/utils/module.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {fs, node as supportNode} from '@appium/support';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import {fileURLToPath} from 'node:url';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
const currentFilename =
|
|
7
|
-
typeof __filename !== 'undefined'
|
|
8
|
-
? __filename
|
|
9
|
-
: fileURLToPath(new Function('return import.meta.url')());
|
|
4
|
+
import {fs, node as supportNode} from '@appium/support';
|
|
10
5
|
|
|
11
|
-
const moduleRoot = supportNode.getModuleRootSync('appium-webdriveragent',
|
|
6
|
+
const moduleRoot = supportNode.getModuleRootSync('appium-webdriveragent', fileURLToPath(import.meta.url));
|
|
12
7
|
|
|
13
8
|
if (!moduleRoot) {
|
|
14
9
|
throw new Error('Cannot find the root folder of the appium-webdriveragent Node.js module');
|
package/lib/utils/platform.ts
CHANGED
package/lib/utils/processes.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {waitForCondition} from 'asyncbox';
|
|
2
2
|
import {exec} from 'teen_process';
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
import {log} from '../logger.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Find and terminate all processes matching the given pgrep pattern.
|
|
@@ -127,9 +128,7 @@ async function getPIDsUsingPattern(pattern: string): Promise<string[]> {
|
|
|
127
128
|
.filter(Number.isInteger)
|
|
128
129
|
.map((x) => `${x}`);
|
|
129
130
|
} catch (err: any) {
|
|
130
|
-
log.debug(
|
|
131
|
-
`'pgrep ${args.join(' ')}' didn't detect any matching processes. Return code: ${err.code}`,
|
|
132
|
-
);
|
|
131
|
+
log.debug(`'pgrep ${args.join(' ')}' didn't detect any matching processes. Return code: ${err.code}`);
|
|
133
132
|
return [];
|
|
134
133
|
}
|
|
135
134
|
}
|
package/lib/utils/security.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {exec} from 'teen_process';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import {log} from '../logger.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Configure keychain access required for real-device code signing.
|
|
6
7
|
*/
|
|
7
|
-
export async function setRealDeviceSecurity(
|
|
8
|
-
keychainPath: string,
|
|
9
|
-
keychainPassword: string,
|
|
10
|
-
): Promise<void> {
|
|
8
|
+
export async function setRealDeviceSecurity(keychainPath: string, keychainPassword: string): Promise<void> {
|
|
11
9
|
log.debug('Setting security for iOS device');
|
|
12
10
|
await exec('security', ['-v', 'list-keychains', '-s', keychainPath]);
|
|
13
11
|
await exec('security', ['-v', 'unlock-keychain', '-p', keychainPassword, keychainPath]);
|
package/lib/utils/xctestrun.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {fs, plist, util} from '@appium/support';
|
|
2
|
-
import path from 'node:path';
|
|
3
1
|
import {arch} from 'node:os';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
import {
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import {fs, plist, util} from '@appium/support';
|
|
5
|
+
|
|
6
|
+
import {log} from '../logger.js';
|
|
7
|
+
import type {DeviceInfo} from '../types.js';
|
|
8
|
+
import {isTvOS} from './platform.js';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Arguments for setting xctestrun file
|
|
@@ -32,14 +34,7 @@ export interface XctestrunFileArgs {
|
|
|
32
34
|
* then it will throw a file not found exception
|
|
33
35
|
*/
|
|
34
36
|
export async function setXctestrunFile(args: XctestrunFileArgs): Promise<string> {
|
|
35
|
-
const {
|
|
36
|
-
deviceInfo,
|
|
37
|
-
sdkVersion,
|
|
38
|
-
bootstrapPath,
|
|
39
|
-
wdaRemotePort,
|
|
40
|
-
wdaBindingIP,
|
|
41
|
-
maxHttpRequestBodySize,
|
|
42
|
-
} = args;
|
|
37
|
+
const {deviceInfo, sdkVersion, bootstrapPath, wdaRemotePort, wdaBindingIP, maxHttpRequestBodySize} = args;
|
|
43
38
|
const xctestrunFilePath = await getXctestrunFilePath(deviceInfo, sdkVersion, bootstrapPath);
|
|
44
39
|
const xctestRunContent = await plist.parsePlistFile(xctestrunFilePath);
|
|
45
40
|
const updateWDAPort = getAdditionalRunContent(
|
|
@@ -75,9 +70,7 @@ export function getAdditionalRunContent(
|
|
|
75
70
|
// USE_PORT must be 'string'
|
|
76
71
|
USE_PORT: `${wdaRemotePort}`,
|
|
77
72
|
...(wdaBindingIP ? {USE_IP: wdaBindingIP} : {}),
|
|
78
|
-
...(maxHttpRequestBodySize
|
|
79
|
-
? {MAX_HTTP_REQUEST_BODY_SIZE: `${maxHttpRequestBodySize}`}
|
|
80
|
-
: {}),
|
|
73
|
+
...(maxHttpRequestBodySize ? {MAX_HTTP_REQUEST_BODY_SIZE: `${maxHttpRequestBodySize}`} : {}),
|
|
81
74
|
},
|
|
82
75
|
},
|
|
83
76
|
};
|
|
@@ -110,10 +103,7 @@ export async function getXctestrunFilePath(
|
|
|
110
103
|
log.info(`Using '${filePath}' as xctestrun file`);
|
|
111
104
|
return filePath;
|
|
112
105
|
}
|
|
113
|
-
const originalXctestrunFile = path.resolve(
|
|
114
|
-
bootstrapPath,
|
|
115
|
-
getXctestrunFileName(deviceInfo, version),
|
|
116
|
-
);
|
|
106
|
+
const originalXctestrunFile = path.resolve(bootstrapPath, getXctestrunFileName(deviceInfo, version));
|
|
117
107
|
if (await fs.exists(originalXctestrunFile)) {
|
|
118
108
|
// If this is first time run for given device, then first generate xctestrun file for device.
|
|
119
109
|
// We need to have a xctestrun file **per device** because we cannot have same wda port for all devices.
|
|
@@ -143,10 +133,7 @@ export function getXctestrunFileName(deviceInfo: DeviceInfo, version: string): s
|
|
|
143
133
|
return `WebDriverAgentRunner_${isTvOS(deviceInfo.platformName) ? 'tvOS_appletv' : 'iphone'}${archSuffix}.xctestrun`;
|
|
144
134
|
}
|
|
145
135
|
|
|
146
|
-
function mergeObjects<T extends Record<string, any>, U extends Record<string, any>>(
|
|
147
|
-
target: T,
|
|
148
|
-
source: U,
|
|
149
|
-
): T & U {
|
|
136
|
+
function mergeObjects<T extends Record<string, any>, U extends Record<string, any>>(target: T, source: U): T & U {
|
|
150
137
|
const output: Record<string, any> = {...target};
|
|
151
138
|
for (const [key, sourceValue] of Object.entries(source)) {
|
|
152
139
|
const targetValue = output[key];
|
package/lib/wda-strategies.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {exec} from 'teen_process';
|
|
2
1
|
import {fs} from '@appium/support';
|
|
3
2
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import type {
|
|
3
|
+
import {exec} from 'teen_process';
|
|
4
|
+
|
|
5
|
+
import type {NoSessionProxy} from './no-session-proxy.js';
|
|
7
6
|
import type {
|
|
8
7
|
AppleDevice,
|
|
9
8
|
RealDevicePreinstalledHostOps,
|
|
@@ -12,11 +11,12 @@ import type {
|
|
|
12
11
|
WdaHostOps,
|
|
13
12
|
WdaLaunchEnvironment,
|
|
14
13
|
WdaStartupStrategyName,
|
|
15
|
-
} from './types';
|
|
14
|
+
} from './types.js';
|
|
15
|
+
import {getPIDsListeningOnPort, resetTestProcesses} from './utils/index.js';
|
|
16
|
+
import type {XcodeBuild} from './xcodebuild.js';
|
|
16
17
|
|
|
17
18
|
const WDA_AGENT_PORT = 8100;
|
|
18
|
-
const HOST_OPS_REQUIRED_MESSAGE =
|
|
19
|
-
'Host operations must be provided to launch or terminate preinstalled WebDriverAgent';
|
|
19
|
+
const HOST_OPS_REQUIRED_MESSAGE = 'Host operations must be provided to launch or terminate preinstalled WebDriverAgent';
|
|
20
20
|
|
|
21
21
|
export interface WdaStartupStrategy {
|
|
22
22
|
readonly name: WdaStartupStrategyName;
|
|
@@ -220,9 +220,7 @@ export function createDefaultRealDeviceXcodebuildHostOps(): RealDeviceXcodebuild
|
|
|
220
220
|
async cleanupObsoleteProcesses({udid, port, commandLineIncludes}) {
|
|
221
221
|
const obsoletePids = await getPIDsListeningOnPort(
|
|
222
222
|
port,
|
|
223
|
-
(cmdLine) =>
|
|
224
|
-
cmdLine.includes(commandLineIncludes) &&
|
|
225
|
-
!cmdLine.toLowerCase().includes(udid.toLowerCase()),
|
|
223
|
+
(cmdLine) => cmdLine.includes(commandLineIncludes) && !cmdLine.toLowerCase().includes(udid.toLowerCase()),
|
|
226
224
|
);
|
|
227
225
|
|
|
228
226
|
if (obsoletePids.length > 0) {
|
|
@@ -232,18 +230,13 @@ export function createDefaultRealDeviceXcodebuildHostOps(): RealDeviceXcodebuild
|
|
|
232
230
|
};
|
|
233
231
|
}
|
|
234
232
|
|
|
235
|
-
async function launchWithXcodebuild(
|
|
236
|
-
ctx: WdaStartupStrategyContext,
|
|
237
|
-
sessionId: string,
|
|
238
|
-
): Promise<StringRecord | null> {
|
|
233
|
+
async function launchWithXcodebuild(ctx: WdaStartupStrategyContext, sessionId: string): Promise<StringRecord | null> {
|
|
239
234
|
ctx.log.info('Launching WebDriverAgent on the device');
|
|
240
235
|
|
|
241
236
|
ctx.setupProxies(sessionId);
|
|
242
237
|
|
|
243
238
|
if (!ctx.useXctestrunFile && !(await fs.exists(ctx.agentPath))) {
|
|
244
|
-
throw new Error(
|
|
245
|
-
`Trying to use WebDriverAgent project at '${ctx.agentPath}' but the ` + 'file does not exist',
|
|
246
|
-
);
|
|
239
|
+
throw new Error(`Trying to use WebDriverAgent project at '${ctx.agentPath}' but the file does not exist`);
|
|
247
240
|
}
|
|
248
241
|
|
|
249
242
|
if (ctx.useXctestrunFile || ctx.usePrebuiltWDA) {
|
package/lib/webdriveragent.ts
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
|
-
import {waitForCondition} from 'asyncbox';
|
|
2
1
|
import path from 'node:path';
|
|
2
|
+
|
|
3
3
|
import {JWProxy} from '@appium/base-driver';
|
|
4
|
+
import {strongbox} from '@appium/strongbox';
|
|
4
5
|
import {fs, util} from '@appium/support';
|
|
5
6
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
6
|
-
import {log as defaultLogger} from './logger';
|
|
7
|
-
import {NoSessionProxy} from './no-session-proxy';
|
|
8
|
-
import {BOOTSTRAP_PATH, getWDAUpgradeTimestamp} from './utils';
|
|
9
|
-
import {XcodeBuild} from './xcodebuild';
|
|
10
7
|
import AsyncLock from 'async-lock';
|
|
8
|
+
import {waitForCondition} from 'asyncbox';
|
|
9
|
+
|
|
11
10
|
import {
|
|
12
11
|
WDA_RUNNER_BUNDLE_ID,
|
|
13
12
|
WDA_BASE_URL,
|
|
14
13
|
WDA_UPGRADE_TIMESTAMP_PATH,
|
|
15
14
|
DEFAULT_TEST_BUNDLE_SUFFIX,
|
|
16
|
-
} from './constants';
|
|
17
|
-
import {
|
|
15
|
+
} from './constants.js';
|
|
16
|
+
import {log as defaultLogger} from './logger.js';
|
|
17
|
+
import {NoSessionProxy} from './no-session-proxy.js';
|
|
18
18
|
import type {
|
|
19
19
|
WebDriverAgentArgs,
|
|
20
20
|
AppleDevice,
|
|
21
21
|
XcodeBuildSettings,
|
|
22
22
|
RetrieveBuildSettingsOptions,
|
|
23
23
|
WdaHostOps,
|
|
24
|
-
} from './types';
|
|
24
|
+
} from './types.js';
|
|
25
|
+
import {BOOTSTRAP_PATH, getWDAUpgradeTimestamp} from './utils/index.js';
|
|
25
26
|
import {
|
|
26
27
|
createDefaultWdaHostOps,
|
|
27
28
|
createWdaStartupStrategy,
|
|
28
29
|
type WdaStartupStrategy,
|
|
29
30
|
type WdaStartupStrategyContext,
|
|
30
|
-
} from './wda-strategies';
|
|
31
|
+
} from './wda-strategies.js';
|
|
32
|
+
import {XcodeBuild} from './xcodebuild.js';
|
|
31
33
|
|
|
32
34
|
const WDA_LAUNCH_TIMEOUT = 60 * 1000;
|
|
33
35
|
const WDA_AGENT_PORT = 8100;
|
|
@@ -89,8 +91,7 @@ export class WebDriverAgent {
|
|
|
89
91
|
this.setWDAPaths(args.bootstrapPath, args.agentPath);
|
|
90
92
|
|
|
91
93
|
this.wdaLocalPort = args.wdaLocalPort;
|
|
92
|
-
this.wdaRemotePort =
|
|
93
|
-
((this.isRealDevice ? args.wdaRemotePort : null) ?? args.wdaLocalPort) || WDA_AGENT_PORT;
|
|
94
|
+
this.wdaRemotePort = ((this.isRealDevice ? args.wdaRemotePort : null) ?? args.wdaLocalPort) || WDA_AGENT_PORT;
|
|
94
95
|
this.wdaBaseUrl = args.wdaBaseUrl || WDA_BASE_URL;
|
|
95
96
|
this.wdaBindingIP = args.wdaBindingIP;
|
|
96
97
|
this.prebuildWDA = args.prebuildWDA;
|
|
@@ -223,9 +224,7 @@ export class WebDriverAgent {
|
|
|
223
224
|
} else {
|
|
224
225
|
const port = this.wdaLocalPort || WDA_AGENT_PORT;
|
|
225
226
|
const parsedBaseUrl = this.toUrl(this.wdaBaseUrl || WDA_BASE_URL);
|
|
226
|
-
this._url = new URL(
|
|
227
|
-
`${parsedBaseUrl.protocol}//${this.wdaBindingIP || parsedBaseUrl.hostname}:${port}`,
|
|
228
|
-
);
|
|
227
|
+
this._url = new URL(`${parsedBaseUrl.protocol}//${this.wdaBindingIP || parsedBaseUrl.hostname}:${port}`);
|
|
229
228
|
}
|
|
230
229
|
}
|
|
231
230
|
return this._url;
|
|
@@ -308,8 +307,8 @@ export class WebDriverAgent {
|
|
|
308
307
|
* @returns `true` if source is fresh (all required files exist), `false` otherwise
|
|
309
308
|
*/
|
|
310
309
|
async isSourceFresh(): Promise<boolean> {
|
|
311
|
-
const existsPromises = ['Resources', path.join('Resources', 'WebDriverAgent.bundle')].map(
|
|
312
|
-
|
|
310
|
+
const existsPromises = ['Resources', path.join('Resources', 'WebDriverAgent.bundle')].map((subPath) =>
|
|
311
|
+
fs.exists(path.resolve(this.bootstrapPath, subPath)),
|
|
313
312
|
);
|
|
314
313
|
return (await Promise.all(existsPromises)).every((v) => v === true);
|
|
315
314
|
}
|
|
@@ -340,26 +339,13 @@ export class WebDriverAgent {
|
|
|
340
339
|
* @param options - Optional scheme, SDK, configuration, or destination
|
|
341
340
|
* @returns Build settings, or `undefined` if xcodebuild is skipped or settings cannot be determined
|
|
342
341
|
*/
|
|
343
|
-
async retrieveBuildSettings(
|
|
344
|
-
options?: RetrieveBuildSettingsOptions,
|
|
345
|
-
): Promise<XcodeBuildSettings | undefined> {
|
|
342
|
+
async retrieveBuildSettings(options?: RetrieveBuildSettingsOptions): Promise<XcodeBuildSettings | undefined> {
|
|
346
343
|
if (this.canSkipXcodebuild) {
|
|
347
344
|
return;
|
|
348
345
|
}
|
|
349
346
|
return await this.xcodebuild.retrieveBuildSettings(options);
|
|
350
347
|
}
|
|
351
348
|
|
|
352
|
-
/**
|
|
353
|
-
* @deprecated Use {@link retrieveBuildSettings} instead. Will be removed in a future release.
|
|
354
|
-
* @returns The derived data path, or `undefined` if xcodebuild is skipped
|
|
355
|
-
*/
|
|
356
|
-
async retrieveDerivedDataPath(): Promise<string | undefined> {
|
|
357
|
-
if (this.canSkipXcodebuild) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
return await this.xcodebuild.retrieveDerivedDataPath();
|
|
361
|
-
}
|
|
362
|
-
|
|
363
349
|
/**
|
|
364
350
|
* Reuse running WDA if it has the same bundle id with updatedWDABundleId.
|
|
365
351
|
* Or reuse it if it has the default id without updatedWDABundleId.
|
|
@@ -456,10 +442,7 @@ export class WebDriverAgent {
|
|
|
456
442
|
getStatus: async (timeoutMs) => await this.getStatus(timeoutMs),
|
|
457
443
|
cleanupProjectIfFresh: async () => {
|
|
458
444
|
const synchronizationKey = path.normalize(this.bootstrapPath);
|
|
459
|
-
await SHARED_RESOURCES_GUARD.acquire(
|
|
460
|
-
synchronizationKey,
|
|
461
|
-
async () => await this._cleanupProjectIfFresh(),
|
|
462
|
-
);
|
|
445
|
+
await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => await this._cleanupProjectIfFresh());
|
|
463
446
|
},
|
|
464
447
|
xcodebuild: () => this.xcodebuild,
|
|
465
448
|
noSessionProxy: () => {
|
|
@@ -551,16 +534,13 @@ export class WebDriverAgent {
|
|
|
551
534
|
headers: this.args.extraRequestHeaders,
|
|
552
535
|
});
|
|
553
536
|
|
|
554
|
-
const sendGetStatus = async () =>
|
|
555
|
-
(await noSessionProxy.command('/status', 'GET')) as StringRecord;
|
|
537
|
+
const sendGetStatus = async () => (await noSessionProxy.command('/status', 'GET')) as StringRecord;
|
|
556
538
|
|
|
557
539
|
if (timeoutMs == null || timeoutMs <= 0) {
|
|
558
540
|
try {
|
|
559
541
|
return await sendGetStatus();
|
|
560
542
|
} catch (err: any) {
|
|
561
|
-
this.log.debug(
|
|
562
|
-
`WDA is not listening at '${this.url.href}'. Original error:: ${err.message}`,
|
|
563
|
-
);
|
|
543
|
+
this.log.debug(`WDA is not listening at '${this.url.href}'. Original error:: ${err.message}`);
|
|
564
544
|
return null;
|
|
565
545
|
}
|
|
566
546
|
}
|
|
@@ -598,9 +578,7 @@ export class WebDriverAgent {
|
|
|
598
578
|
return;
|
|
599
579
|
}
|
|
600
580
|
|
|
601
|
-
const packageInfo = JSON.parse(
|
|
602
|
-
await fs.readFile(path.join(BOOTSTRAP_PATH, 'package.json'), 'utf8'),
|
|
603
|
-
);
|
|
581
|
+
const packageInfo = JSON.parse(await fs.readFile(path.join(BOOTSTRAP_PATH, 'package.json'), 'utf8'));
|
|
604
582
|
const box = strongbox(packageInfo.name);
|
|
605
583
|
let boxItem = box.getItem(RECENT_MODULE_VERSION_ITEM_NAME);
|
|
606
584
|
if (!boxItem) {
|
|
@@ -616,9 +594,7 @@ export class WebDriverAgent {
|
|
|
616
594
|
return;
|
|
617
595
|
}
|
|
618
596
|
} else {
|
|
619
|
-
this.log.info(
|
|
620
|
-
'There is no need to perform the project cleanup. A fresh install has been detected',
|
|
621
|
-
);
|
|
597
|
+
this.log.info('There is no need to perform the project cleanup. A fresh install has been detected');
|
|
622
598
|
try {
|
|
623
599
|
await box.createItemWithValue(RECENT_MODULE_VERSION_ITEM_NAME, packageInfo.version);
|
|
624
600
|
} catch (e: any) {
|
|
@@ -633,9 +609,7 @@ export class WebDriverAgent {
|
|
|
633
609
|
recentModuleVersion = util.coerceVersion(recentModuleVersion, true);
|
|
634
610
|
} catch (e: any) {
|
|
635
611
|
this.log.warn(`The persisted module version string has been damaged: ${e.message}`);
|
|
636
|
-
this.log.info(
|
|
637
|
-
`Updating it to '${packageInfo.version}' assuming the project clenup is not needed`,
|
|
638
|
-
);
|
|
612
|
+
this.log.info(`Updating it to '${packageInfo.version}' assuming the project clenup is not needed`);
|
|
639
613
|
await boxItem.write(packageInfo.version);
|
|
640
614
|
return;
|
|
641
615
|
}
|
package/lib/xcodebuild.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
3
|
import {logger, timing, util} from '@appium/support';
|
|
4
4
|
import type {AppiumLogger, StringRecord} from '@appium/types';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import {WDA_RUNNER_BUNDLE_ID} from './constants';
|
|
5
|
+
import {retryInterval} from 'asyncbox';
|
|
6
|
+
import {SubProcess, exec} from 'teen_process';
|
|
7
|
+
|
|
8
|
+
import {WDA_RUNNER_BUNDLE_ID} from './constants.js';
|
|
9
|
+
import {log as defaultLogger} from './logger.js';
|
|
10
|
+
import type {NoSessionProxy} from './no-session-proxy.js';
|
|
9
11
|
import type {
|
|
10
12
|
AppleDevice,
|
|
11
13
|
RetrieveBuildSettingsOptions,
|
|
12
14
|
XcodeBuildArgs,
|
|
13
15
|
XcodeBuildSettings,
|
|
14
16
|
XcodeShowBuildSettingsEntry,
|
|
15
|
-
} from './types';
|
|
16
|
-
import
|
|
17
|
+
} from './types.js';
|
|
18
|
+
import {getWDAUpgradeTimestamp, isTvOS, setRealDeviceSecurity, setXctestrunFile} from './utils/index.js';
|
|
17
19
|
|
|
18
20
|
const DEFAULT_SIGNING_ID = 'iPhone Developer';
|
|
19
21
|
const PREBUILD_DELAY = 0;
|
|
@@ -22,11 +24,7 @@ const LIB_SCHEME_IOS = 'WebDriverAgentLib';
|
|
|
22
24
|
|
|
23
25
|
const ERROR_WRITING_ATTACHMENT = 'Error writing attachment data to file';
|
|
24
26
|
const ERROR_COPYING_ATTACHMENT = 'Error copying testing attachment';
|
|
25
|
-
const IGNORED_ERRORS = [
|
|
26
|
-
ERROR_WRITING_ATTACHMENT,
|
|
27
|
-
ERROR_COPYING_ATTACHMENT,
|
|
28
|
-
'Failed to remove screenshot at path',
|
|
29
|
-
];
|
|
27
|
+
const IGNORED_ERRORS = [ERROR_WRITING_ATTACHMENT, ERROR_COPYING_ATTACHMENT, 'Failed to remove screenshot at path'];
|
|
30
28
|
const IGNORED_ERRORS_PATTERN = new RegExp(
|
|
31
29
|
'(' + IGNORED_ERRORS.map((errStr) => util.escapeRegExp(errStr)).join('|') + ')',
|
|
32
30
|
);
|
|
@@ -71,10 +69,7 @@ export class XcodeBuild {
|
|
|
71
69
|
private readonly resultBundleVersion?: string;
|
|
72
70
|
private _didBuildFail: boolean;
|
|
73
71
|
private _didProcessExit: boolean;
|
|
74
|
-
private readonly _buildSettingsPromises = new Map<
|
|
75
|
-
string,
|
|
76
|
-
Promise<XcodeBuildSettings | undefined>
|
|
77
|
-
>();
|
|
72
|
+
private readonly _buildSettingsPromises = new Map<string, Promise<XcodeBuildSettings | undefined>>();
|
|
78
73
|
private noSessionProxy?: NoSessionProxy;
|
|
79
74
|
private xctestrunFilePath?: string;
|
|
80
75
|
|
|
@@ -121,8 +116,7 @@ export class XcodeBuild {
|
|
|
121
116
|
this.mjpegServerPort = args.mjpegServerPort;
|
|
122
117
|
this.maxHttpRequestBodySize = args.maxHttpRequestBodySize;
|
|
123
118
|
|
|
124
|
-
this.prebuildDelay =
|
|
125
|
-
typeof args.prebuildDelay === 'number' ? args.prebuildDelay : PREBUILD_DELAY;
|
|
119
|
+
this.prebuildDelay = typeof args.prebuildDelay === 'number' ? args.prebuildDelay : PREBUILD_DELAY;
|
|
126
120
|
|
|
127
121
|
this.allowProvisioningDeviceRegistration = args.allowProvisioningDeviceRegistration;
|
|
128
122
|
|
|
@@ -165,9 +159,7 @@ export class XcodeBuild {
|
|
|
165
159
|
* @param options - Optional scheme, SDK, configuration, or destination
|
|
166
160
|
* @returns Build settings for the `build` action, or `undefined` if they cannot be determined
|
|
167
161
|
*/
|
|
168
|
-
async retrieveBuildSettings(
|
|
169
|
-
options?: RetrieveBuildSettingsOptions,
|
|
170
|
-
): Promise<XcodeBuildSettings | undefined> {
|
|
162
|
+
async retrieveBuildSettings(options?: RetrieveBuildSettingsOptions): Promise<XcodeBuildSettings | undefined> {
|
|
171
163
|
const cacheKey = buildSettingsCacheKey(options);
|
|
172
164
|
let promise = this._buildSettingsPromises.get(cacheKey);
|
|
173
165
|
if (!promise) {
|
|
@@ -314,9 +306,7 @@ export class XcodeBuild {
|
|
|
314
306
|
if (!(err as Error)?.message?.includes(`Process didn't end after`)) {
|
|
315
307
|
throw err;
|
|
316
308
|
}
|
|
317
|
-
this.log.debug(
|
|
318
|
-
`xcodebuild process did not end in a timely fashion: '${(err as Error)?.message}'.`,
|
|
319
|
-
);
|
|
309
|
+
this.log.debug(`xcodebuild process did not end in a timely fashion: '${(err as Error)?.message}'.`);
|
|
320
310
|
}
|
|
321
311
|
|
|
322
312
|
try {
|
|
@@ -330,9 +320,7 @@ export class XcodeBuild {
|
|
|
330
320
|
}
|
|
331
321
|
}
|
|
332
322
|
|
|
333
|
-
private async fetchBuildSettings(
|
|
334
|
-
options?: RetrieveBuildSettingsOptions,
|
|
335
|
-
): Promise<XcodeBuildSettings | undefined> {
|
|
323
|
+
private async fetchBuildSettings(options?: RetrieveBuildSettingsOptions): Promise<XcodeBuildSettings | undefined> {
|
|
336
324
|
const schemeLabel = options?.scheme ?? 'default';
|
|
337
325
|
let stdout: string;
|
|
338
326
|
try {
|
|
@@ -344,9 +332,7 @@ export class XcodeBuild {
|
|
|
344
332
|
...buildSettingsArgsFromOptions(options),
|
|
345
333
|
]));
|
|
346
334
|
} catch (err: any) {
|
|
347
|
-
this.log.warn(
|
|
348
|
-
`Cannot retrieve WDA build settings for scheme '${schemeLabel}'. Original error: ${err.message}`,
|
|
349
|
-
);
|
|
335
|
+
this.log.warn(`Cannot retrieve WDA build settings for scheme '${schemeLabel}'. Original error: ${err.message}`);
|
|
350
336
|
return;
|
|
351
337
|
}
|
|
352
338
|
|
|
@@ -409,9 +395,7 @@ export class XcodeBuild {
|
|
|
409
395
|
}
|
|
410
396
|
args.push('-destination', `id=${this.device.udid}`);
|
|
411
397
|
|
|
412
|
-
const versionMatch = this.platformVersion
|
|
413
|
-
? new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion)
|
|
414
|
-
: null;
|
|
398
|
+
const versionMatch = this.platformVersion ? new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion) : null;
|
|
415
399
|
if (versionMatch) {
|
|
416
400
|
args.push(
|
|
417
401
|
`${isTvOS(this.platformName || '') ? 'TV' : 'IPHONE'}OS_DEPLOYMENT_TARGET=${versionMatch[1]}.${versionMatch[2]}`,
|
|
@@ -429,10 +413,7 @@ export class XcodeBuild {
|
|
|
429
413
|
args.push('-xcconfig', this.xcodeConfigFile);
|
|
430
414
|
}
|
|
431
415
|
if (this.xcodeOrgId && this.xcodeSigningId) {
|
|
432
|
-
args.push(
|
|
433
|
-
`DEVELOPMENT_TEAM=${this.xcodeOrgId}`,
|
|
434
|
-
`CODE_SIGN_IDENTITY=${this.xcodeSigningId}`,
|
|
435
|
-
);
|
|
416
|
+
args.push(`DEVELOPMENT_TEAM=${this.xcodeOrgId}`, `CODE_SIGN_IDENTITY=${this.xcodeSigningId}`);
|
|
436
417
|
}
|
|
437
418
|
if (this.updatedWDABundleId) {
|
|
438
419
|
args.push(`PRODUCT_BUNDLE_IDENTIFIER=${this.updatedWDABundleId}`);
|
|
@@ -555,9 +536,7 @@ export class XcodeBuild {
|
|
|
555
536
|
return currentStatus;
|
|
556
537
|
}
|
|
557
538
|
|
|
558
|
-
this.log.debug(
|
|
559
|
-
`WebDriverAgent successfully started after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
|
|
560
|
-
);
|
|
539
|
+
this.log.debug(`WebDriverAgent successfully started after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
|
|
561
540
|
} catch (err: any) {
|
|
562
541
|
this.log.debug(err.stack);
|
|
563
542
|
throw new Error(
|