Skip to content

Commit 5aadcb8

Browse files
chore: Improve type declarations (#1065)
1 parent 9b2875c commit 5aadcb8

File tree

6 files changed

+120
-41
lines changed

6 files changed

+120
-41
lines changed

lib/check-dependencies.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { fs } from '@appium/support';
2-
import _ from 'lodash';
32
import { exec } from 'teen_process';
4-
import path from 'path';
5-
import {XcodeBuild} from './xcodebuild';
6-
import * as xcode from 'appium-xcode';
3+
import path from 'node:path';
74
import {
85
WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP
96
} from './constants';
@@ -29,14 +26,10 @@ export async function checkForDependencies () {
2926

3027
/**
3128
*
32-
* @param {XcodeBuild} xcodebuild
29+
* @param {import('./xcodebuild').XcodeBuild} xcodebuild
3330
* @returns {Promise<string>}
3431
*/
3532
export async function bundleWDASim (xcodebuild) {
36-
if (xcodebuild && !_.isFunction(xcodebuild.retrieveDerivedDataPath)) {
37-
xcodebuild = new XcodeBuild(/** @type {import('appium-xcode').XcodeVersion} */ (await xcode.getVersion(true)), {});
38-
}
39-
4033
const derivedDataPath = await xcodebuild.retrieveDerivedDataPath();
4134
if (!derivedDataPath) {
4235
throw new Error('Cannot retrieve the path to the Xcode derived data folder');

lib/types.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,77 @@ export interface WDACapabilities {
5050
defaultAlertAction?: 'accept' | 'dismiss';
5151
appLaunchStateTimeoutSec?: number;
5252
}
53+
54+
export interface WebDriverAgentArgs {
55+
device: AppleDevice; // Required
56+
platformVersion?: string;
57+
platformName?: string;
58+
iosSdkVersion?: string;
59+
host?: string;
60+
realDevice?: boolean;
61+
wdaBundlePath?: string;
62+
bootstrapPath?: string;
63+
agentPath?: string;
64+
wdaLocalPort?: number;
65+
wdaRemotePort?: number;
66+
wdaBaseUrl?: string;
67+
prebuildWDA?: boolean;
68+
webDriverAgentUrl?: string;
69+
wdaConnectionTimeout?: number;
70+
useXctestrunFile?: boolean;
71+
usePrebuiltWDA?: boolean;
72+
derivedDataPath?: string;
73+
mjpegServerPort?: number;
74+
updatedWDABundleId?: string;
75+
wdaLaunchTimeout?: number;
76+
usePreinstalledWDA?: boolean;
77+
updatedWDABundleIdSuffix?: string;
78+
showXcodeLog?: boolean;
79+
xcodeConfigFile?: string;
80+
xcodeOrgId?: string;
81+
xcodeSigningId?: string;
82+
keychainPath?: string;
83+
keychainPassword?: string;
84+
useSimpleBuildTest?: boolean;
85+
allowProvisioningDeviceRegistration?: boolean;
86+
resultBundlePath?: string;
87+
resultBundleVersion?: string;
88+
reqBasePath?: string;
89+
launchTimeout?: number;
90+
}
91+
92+
export interface AppleDevice {
93+
udid: string;
94+
simctl?: any;
95+
devicectl?: any;
96+
idb?: any;
97+
[key: string]: any;
98+
}
99+
100+
export interface XcodeBuildArgs {
101+
realDevice: boolean; // Required
102+
agentPath: string; // Required
103+
bootstrapPath: string; // Required
104+
platformVersion?: string;
105+
platformName?: string;
106+
iosSdkVersion?: string;
107+
showXcodeLog?: boolean;
108+
xcodeConfigFile?: string;
109+
xcodeOrgId?: string;
110+
xcodeSigningId?: string;
111+
keychainPath?: string;
112+
keychainPassword?: string;
113+
prebuildWDA?: boolean;
114+
usePrebuiltWDA?: boolean;
115+
useSimpleBuildTest?: boolean;
116+
useXctestrunFile?: boolean;
117+
launchTimeout?: number;
118+
wdaRemotePort?: number;
119+
updatedWDABundleId?: string;
120+
derivedDataPath?: string;
121+
mjpegServerPort?: number;
122+
prebuildDelay?: number;
123+
allowProvisioningDeviceRegistration?: boolean;
124+
resultBundlePath?: string;
125+
resultBundleVersion?: string;
126+
}

lib/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ async function setRealDeviceSecurity (keychainPath, keychainPassword) {
161161
/**
162162
* Information of the device under test
163163
* @typedef {Object} DeviceInfo
164-
* @property {string} isRealDevice - Equals to true if the current device is a real device
164+
* @property {boolean} isRealDevice - Equals to true if the current device is a real device
165165
* @property {string} udid - The device UDID.
166166
* @property {string} platformVersion - The platform version of OS.
167167
* @property {string} platformName - The platform name of iOS, tvOS

lib/webdriveragent.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,10 @@ export class WebDriverAgent {
3636

3737
/**
3838
* @param {import('appium-xcode').XcodeVersion} xcodeVersion
39-
* // TODO: make args typed
40-
* @param {import('@appium/types').StringRecord} [args={}]
39+
* @param {import('./types').WebDriverAgentArgs} args
4140
* @param {import('@appium/types').AppiumLogger?} [log=null]
4241
*/
43-
constructor (xcodeVersion, args = {}, log = null) {
42+
constructor (xcodeVersion, args, log = null) {
4443
this.xcodeVersion = xcodeVersion;
4544

4645
this.args = _.clone(args);
@@ -52,7 +51,7 @@ export class WebDriverAgent {
5251
this.iosSdkVersion = args.iosSdkVersion;
5352
this.host = args.host;
5453
this.isRealDevice = !!args.realDevice;
55-
this.idb = (args.device || {}).idb;
54+
this.idb = args.device.idb;
5655
this.wdaBundlePath = args.wdaBundlePath;
5756

5857
this.setWDAPaths(args.bootstrapPath, args.agentPath);
@@ -121,7 +120,7 @@ export class WebDriverAgent {
121120
get canSkipXcodebuild () {
122121
// Use this.args.webDriverAgentUrl to guarantee
123122
// the capabilities set gave the `appium:webDriverAgentUrl`.
124-
return this.usePreinstalledWDA || this.args.webDriverAgentUrl;
123+
return this.usePreinstalledWDA || !!this.args.webDriverAgentUrl;
125124
}
126125

127126
/**
@@ -396,7 +395,7 @@ export class WebDriverAgent {
396395
// Current method to launch WDA process can be done via 'xcrun devicectl',
397396
// but it has limitation about the WDA preinstalled package.
398397
// https://github.com/appium/appium/issues/19206#issuecomment-2014182674
399-
if (util.compareVersions(this.platformVersion, '>=', '17.0')) {
398+
if (this.platformVersion && util.compareVersions(this.platformVersion, '>=', '17.0')) {
400399
await this._launchViaDevicectl({env: xctestEnv});
401400
} else {
402401
this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv});
@@ -631,7 +630,7 @@ export class WebDriverAgent {
631630
if (!this.args.webDriverAgentUrl) {
632631
// if we populated the url ourselves (during `setupCaching` call, for instance)
633632
// then clean that up. If the url was supplied, we want to keep it
634-
this.webDriverAgentUrl = null;
633+
this.webDriverAgentUrl = undefined;
635634
}
636635
}
637636

lib/xcodebuild.js

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,11 @@ export class XcodeBuild {
4747

4848
/**
4949
* @param {import('appium-xcode').XcodeVersion} xcodeVersion
50-
* @param {any} device
51-
* // TODO: make args typed
52-
* @param {import('@appium/types').StringRecord} [args={}]
53-
* @param {import('@appium/types').AppiumLogger?} [log=null]
50+
* @param {import('./types').AppleDevice} device
51+
* @param {import('./types').XcodeBuildArgs} args
52+
* @param {import('@appium/types').AppiumLogger | null} [log=null]
5453
*/
55-
constructor (xcodeVersion, device, args = {}, log = null) {
54+
constructor (xcodeVersion, device, args, log = null) {
5655
this.xcodeVersion = xcodeVersion;
5756

5857
this.device = device;
@@ -110,13 +109,19 @@ export class XcodeBuild {
110109
this.noSessionProxy = noSessionProxy;
111110

112111
if (this.useXctestrunFile) {
113-
const deviveInfo = {
114-
isRealDevice: this.realDevice,
112+
/** @type {import('./utils').DeviceInfo} */
113+
const deviceInfo = {
114+
isRealDevice: !!this.realDevice,
115115
udid: this.device.udid,
116-
platformVersion: this.platformVersion,
117-
platformName: this.platformName
116+
platformVersion: this.platformVersion || '',
117+
platformName: this.platformName || ''
118118
};
119-
this.xctestrunFilePath = await setXctestrunFile(deviveInfo, this.iosSdkVersion, this.bootstrapPath, this.wdaRemotePort);
119+
this.xctestrunFilePath = await setXctestrunFile(
120+
deviceInfo,
121+
this.iosSdkVersion || '',
122+
this.bootstrapPath,
123+
this.wdaRemotePort || 8100
124+
);
120125
return;
121126
}
122127

@@ -200,8 +205,8 @@ export class XcodeBuild {
200205
* @returns {Promise<void>}
201206
*/
202207
async cleanProject () {
203-
const libScheme = isTvOS(this.platformName) ? LIB_SCHEME_TV : LIB_SCHEME_IOS;
204-
const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
208+
const libScheme = isTvOS(this.platformName || '') ? LIB_SCHEME_TV : LIB_SCHEME_IOS;
209+
const runnerScheme = isTvOS(this.platformName || '') ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
205210

206211
for (const scheme of [libScheme, runnerScheme]) {
207212
this.log.debug(`Cleaning the project scheme '${scheme}' to make sure there are no leftovers from previous installs`);
@@ -249,22 +254,24 @@ export class XcodeBuild {
249254
if (this.useXctestrunFile && this.xctestrunFilePath) {
250255
args.push('-xctestrun', this.xctestrunFilePath);
251256
} else {
252-
const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
257+
const runnerScheme = isTvOS(this.platformName || '') ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
253258
args.push('-project', this.agentPath, '-scheme', runnerScheme);
254259
if (this.derivedDataPath) {
255260
args.push('-derivedDataPath', this.derivedDataPath);
256261
}
257262
}
258263
args.push('-destination', `id=${this.device.udid}`);
259264

260-
const versionMatch = new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion);
261-
if (versionMatch) {
265+
let versionMatch;
266+
if (this.platformVersion && (versionMatch = new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion))) {
262267
args.push(
263-
`${isTvOS(this.platformName) ? 'TV' : 'IPHONE'}OS_DEPLOYMENT_TARGET=${versionMatch[1]}.${versionMatch[2]}`
268+
`${isTvOS(this.platformName || '') ? 'TV' : 'IPHONE'}OS_DEPLOYMENT_TARGET=${versionMatch[1]}.${versionMatch[2]}`
264269
);
265270
} else {
266-
this.log.warn(`Cannot parse major and minor version numbers from platformVersion "${this.platformVersion}". ` +
267-
'Will build for the default platform instead');
271+
this.log.warn(
272+
`Cannot parse major and minor version numbers from platformVersion "${this.platformVersion}". ` +
273+
'Will build for the default platform instead'
274+
);
268275
}
269276

270277
if (this.realDevice) {
@@ -413,10 +420,11 @@ export class XcodeBuild {
413420
*/
414421
async waitForStart (timer) {
415422
// try to connect once every 0.5 seconds, until `launchTimeout` is up
416-
this.log.debug(`Waiting up to ${this.launchTimeout}ms for WebDriverAgent to start`);
423+
const timeout = this.launchTimeout || 60000; // Default to 60 seconds if not set
424+
this.log.debug(`Waiting up to ${timeout}ms for WebDriverAgent to start`);
417425
let currentStatus = null;
418426
try {
419-
const retries = Math.trunc(this.launchTimeout / 500);
427+
const retries = Math.trunc(timeout / 500);
420428
await retryInterval(retries, 1000, async () => {
421429
if (this._didProcessExit) {
422430
// there has been an error elsewhere and we need to short-circuit
@@ -448,7 +456,7 @@ export class XcodeBuild {
448456
} catch (err) {
449457
this.log.debug(err.stack);
450458
throw new Error(
451-
`We were not able to retrieve the /status response from the WebDriverAgent server after ${this.launchTimeout}ms timeout.` +
459+
`We were not able to retrieve the /status response from the WebDriverAgent server after ${timeout}ms timeout.` +
452460
`Try to increase the value of 'appium:wdaLaunchTimeout' capability as a possible workaround.`
453461
);
454462
}

test/unit/webdriveragent-specs.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import _ from 'lodash';
66
import sinon from 'sinon';
77

88
const fakeConstructorArgs = {
9-
device: 'some sim',
9+
device: {
10+
udid: 'some-sim-udid',
11+
simctl: {},
12+
devicectl: {},
13+
idb: null
14+
},
1015
platformVersion: '9',
1116
host: 'me',
1217
port: '5000',
@@ -186,7 +191,7 @@ describe('setupCaching()', function () {
186191
const getTimestampStub = sinon.stub(utils, 'getWDAUpgradeTimestamp');
187192

188193
beforeEach(function () {
189-
wda = new WebDriverAgent('1');
194+
wda = new WebDriverAgent('1', fakeConstructorArgs);
190195
wdaStub = sinon.stub(wda, 'getStatus');
191196
wdaStubUninstall = sinon.stub(wda, 'uninstall');
192197
});
@@ -249,7 +254,7 @@ describe('setupCaching()', function () {
249254
});
250255

251256
it('should not call uninstall since bundle id is equal to updatedWDABundleId capability', async function () {
252-
wda = new WebDriverAgent('1', { updatedWDABundleId: 'com.example.WebDriverAgent' });
257+
wda = new WebDriverAgent('1', { ...fakeConstructorArgs, updatedWDABundleId: 'com.example.WebDriverAgent' });
253258
wdaStub = sinon.stub(wda, 'getStatus');
254259
wdaStubUninstall = sinon.stub(wda, 'uninstall');
255260

0 commit comments

Comments
 (0)