Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions lib/check-dependencies.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { fs } from '@appium/support';
import _ from 'lodash';
import { exec } from 'teen_process';
import path from 'path';
import {XcodeBuild} from './xcodebuild';
import * as xcode from 'appium-xcode';
import path from 'node:path';
import {
WDA_SCHEME, SDK_SIMULATOR, WDA_RUNNER_APP
} from './constants';
Expand All @@ -29,14 +26,10 @@ export async function checkForDependencies () {

/**
*
* @param {XcodeBuild} xcodebuild
* @param {import('./xcodebuild').XcodeBuild} xcodebuild
* @returns {Promise<string>}
*/
export async function bundleWDASim (xcodebuild) {
if (xcodebuild && !_.isFunction(xcodebuild.retrieveDerivedDataPath)) {
xcodebuild = new XcodeBuild(/** @type {import('appium-xcode').XcodeVersion} */ (await xcode.getVersion(true)), {});
}

const derivedDataPath = await xcodebuild.retrieveDerivedDataPath();
if (!derivedDataPath) {
throw new Error('Cannot retrieve the path to the Xcode derived data folder');
Expand Down
74 changes: 74 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,77 @@ export interface WDACapabilities {
defaultAlertAction?: 'accept' | 'dismiss';
appLaunchStateTimeoutSec?: number;
}

export interface WebDriverAgentArgs {
device: AppleDevice; // Required
platformVersion?: string;
platformName?: string;
iosSdkVersion?: string;
host?: string;
realDevice?: boolean;
wdaBundlePath?: string;
bootstrapPath?: string;
agentPath?: string;
wdaLocalPort?: number;
wdaRemotePort?: number;
wdaBaseUrl?: string;
prebuildWDA?: boolean;
webDriverAgentUrl?: string;
wdaConnectionTimeout?: number;
useXctestrunFile?: boolean;
usePrebuiltWDA?: boolean;
derivedDataPath?: string;
mjpegServerPort?: number;
updatedWDABundleId?: string;
wdaLaunchTimeout?: number;
usePreinstalledWDA?: boolean;
updatedWDABundleIdSuffix?: string;
showXcodeLog?: boolean;
xcodeConfigFile?: string;
xcodeOrgId?: string;
xcodeSigningId?: string;
keychainPath?: string;
keychainPassword?: string;
useSimpleBuildTest?: boolean;
allowProvisioningDeviceRegistration?: boolean;
resultBundlePath?: string;
resultBundleVersion?: string;
reqBasePath?: string;
launchTimeout?: number;
}

export interface AppleDevice {
udid: string;
simctl?: any;
devicectl?: any;
idb?: any;
[key: string]: any;
}

export interface XcodeBuildArgs {
realDevice: boolean; // Required
agentPath: string; // Required
bootstrapPath: string; // Required
platformVersion?: string;
platformName?: string;
iosSdkVersion?: string;
showXcodeLog?: boolean;
xcodeConfigFile?: string;
xcodeOrgId?: string;
xcodeSigningId?: string;
keychainPath?: string;
keychainPassword?: string;
prebuildWDA?: boolean;
usePrebuiltWDA?: boolean;
useSimpleBuildTest?: boolean;
useXctestrunFile?: boolean;
launchTimeout?: number;
wdaRemotePort?: number;
updatedWDABundleId?: string;
derivedDataPath?: string;
mjpegServerPort?: number;
prebuildDelay?: number;
allowProvisioningDeviceRegistration?: boolean;
resultBundlePath?: string;
resultBundleVersion?: string;
}
2 changes: 1 addition & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ async function setRealDeviceSecurity (keychainPath, keychainPassword) {
/**
* Information of the device under test
* @typedef {Object} DeviceInfo
* @property {string} isRealDevice - Equals to true if the current device is a real device
* @property {boolean} isRealDevice - Equals to true if the current device is a real device
* @property {string} udid - The device UDID.
* @property {string} platformVersion - The platform version of OS.
* @property {string} platformName - The platform name of iOS, tvOS
Expand Down
13 changes: 6 additions & 7 deletions lib/webdriveragent.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ export class WebDriverAgent {

/**
* @param {import('appium-xcode').XcodeVersion} xcodeVersion
* // TODO: make args typed
* @param {import('@appium/types').StringRecord} [args={}]
* @param {import('./types').WebDriverAgentArgs} args
* @param {import('@appium/types').AppiumLogger?} [log=null]
*/
constructor (xcodeVersion, args = {}, log = null) {
constructor (xcodeVersion, args, log = null) {
this.xcodeVersion = xcodeVersion;

this.args = _.clone(args);
Expand All @@ -52,7 +51,7 @@ export class WebDriverAgent {
this.iosSdkVersion = args.iosSdkVersion;
this.host = args.host;
this.isRealDevice = !!args.realDevice;
this.idb = (args.device || {}).idb;
this.idb = args.device.idb;
this.wdaBundlePath = args.wdaBundlePath;

this.setWDAPaths(args.bootstrapPath, args.agentPath);
Expand Down Expand Up @@ -121,7 +120,7 @@ export class WebDriverAgent {
get canSkipXcodebuild () {
// Use this.args.webDriverAgentUrl to guarantee
// the capabilities set gave the `appium:webDriverAgentUrl`.
return this.usePreinstalledWDA || this.args.webDriverAgentUrl;
return this.usePreinstalledWDA || !!this.args.webDriverAgentUrl;
}

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

Expand Down
56 changes: 33 additions & 23 deletions lib/xcodebuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ export class XcodeBuild {

/**
* @param {import('appium-xcode').XcodeVersion} xcodeVersion
* @param {any} device
* // TODO: make args typed
* @param {import('@appium/types').StringRecord} [args={}]
* @param {import('@appium/types').AppiumLogger?} [log=null]
* @param {import('./types').AppleDevice} device
* @param {import('./types').XcodeBuildArgs} args
* @param {import('@appium/types').AppiumLogger | null} [log=null]
*/
constructor (xcodeVersion, device, args = {}, log = null) {
constructor (xcodeVersion, device, args, log = null) {
this.xcodeVersion = xcodeVersion;

this.device = device;
Expand Down Expand Up @@ -110,13 +109,19 @@ export class XcodeBuild {
this.noSessionProxy = noSessionProxy;

if (this.useXctestrunFile) {
const deviveInfo = {
isRealDevice: this.realDevice,
/** @type {import('./utils').DeviceInfo} */
const deviceInfo = {
isRealDevice: !!this.realDevice,
udid: this.device.udid,
platformVersion: this.platformVersion,
platformName: this.platformName
platformVersion: this.platformVersion || '',
platformName: this.platformName || ''
};
this.xctestrunFilePath = await setXctestrunFile(deviveInfo, this.iosSdkVersion, this.bootstrapPath, this.wdaRemotePort);
this.xctestrunFilePath = await setXctestrunFile(
deviceInfo,
this.iosSdkVersion || '',
this.bootstrapPath,
this.wdaRemotePort || 8100
);
return;
}

Expand Down Expand Up @@ -200,8 +205,8 @@ export class XcodeBuild {
* @returns {Promise<void>}
*/
async cleanProject () {
const libScheme = isTvOS(this.platformName) ? LIB_SCHEME_TV : LIB_SCHEME_IOS;
const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
const libScheme = isTvOS(this.platformName || '') ? LIB_SCHEME_TV : LIB_SCHEME_IOS;
const runnerScheme = isTvOS(this.platformName || '') ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;

for (const scheme of [libScheme, runnerScheme]) {
this.log.debug(`Cleaning the project scheme '${scheme}' to make sure there are no leftovers from previous installs`);
Expand Down Expand Up @@ -249,22 +254,26 @@ export class XcodeBuild {
if (this.useXctestrunFile && this.xctestrunFilePath) {
args.push('-xctestrun', this.xctestrunFilePath);
} else {
const runnerScheme = isTvOS(this.platformName) ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
const runnerScheme = isTvOS(this.platformName || '') ? RUNNER_SCHEME_TV : RUNNER_SCHEME_IOS;
args.push('-project', this.agentPath, '-scheme', runnerScheme);
if (this.derivedDataPath) {
args.push('-derivedDataPath', this.derivedDataPath);
}
}
args.push('-destination', `id=${this.device.udid}`);

const versionMatch = new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion);
if (versionMatch) {
args.push(
`${isTvOS(this.platformName) ? 'TV' : 'IPHONE'}OS_DEPLOYMENT_TARGET=${versionMatch[1]}.${versionMatch[2]}`
);
if (this.platformVersion) {
const versionMatch = new RegExp(/^(\d+)\.(\d+)/).exec(this.platformVersion);
if (versionMatch) {
args.push(
`${isTvOS(this.platformName || '') ? 'TV' : 'IPHONE'}OS_DEPLOYMENT_TARGET=${versionMatch[1]}.${versionMatch[2]}`
);
}
} else {
this.log.warn(`Cannot parse major and minor version numbers from platformVersion "${this.platformVersion}". ` +
'Will build for the default platform instead');
this.log.warn(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the code wants to print the log for else for if (versionMatch) { case as well..?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

`Cannot parse major and minor version numbers from platformVersion "${this.platformVersion}". ` +
'Will build for the default platform instead'
);
}

if (this.realDevice) {
Expand Down Expand Up @@ -413,10 +422,11 @@ export class XcodeBuild {
*/
async waitForStart (timer) {
// try to connect once every 0.5 seconds, until `launchTimeout` is up
this.log.debug(`Waiting up to ${this.launchTimeout}ms for WebDriverAgent to start`);
const timeout = this.launchTimeout || 60000; // Default to 60 seconds if not set
this.log.debug(`Waiting up to ${timeout}ms for WebDriverAgent to start`);
let currentStatus = null;
try {
const retries = Math.trunc(this.launchTimeout / 500);
const retries = Math.trunc(timeout / 500);
await retryInterval(retries, 1000, async () => {
if (this._didProcessExit) {
// there has been an error elsewhere and we need to short-circuit
Expand Down Expand Up @@ -448,7 +458,7 @@ export class XcodeBuild {
} catch (err) {
this.log.debug(err.stack);
throw new Error(
`We were not able to retrieve the /status response from the WebDriverAgent server after ${this.launchTimeout}ms timeout.` +
`We were not able to retrieve the /status response from the WebDriverAgent server after ${timeout}ms timeout.` +
`Try to increase the value of 'appium:wdaLaunchTimeout' capability as a possible workaround.`
);
}
Expand Down
11 changes: 8 additions & 3 deletions test/unit/webdriveragent-specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import _ from 'lodash';
import sinon from 'sinon';

const fakeConstructorArgs = {
device: 'some sim',
device: {
udid: 'some-sim-udid',
simctl: {},
devicectl: {},
idb: null
},
platformVersion: '9',
host: 'me',
port: '5000',
Expand Down Expand Up @@ -186,7 +191,7 @@ describe('setupCaching()', function () {
const getTimestampStub = sinon.stub(utils, 'getWDAUpgradeTimestamp');

beforeEach(function () {
wda = new WebDriverAgent('1');
wda = new WebDriverAgent('1', fakeConstructorArgs);
wdaStub = sinon.stub(wda, 'getStatus');
wdaStubUninstall = sinon.stub(wda, 'uninstall');
});
Expand Down Expand Up @@ -249,7 +254,7 @@ describe('setupCaching()', function () {
});

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

Expand Down
Loading