Skip to content

Commit

Permalink
feat: Support prebuiltWDAPath for iOS 17 (#868)
Browse files Browse the repository at this point in the history
* feat: add a method to launch wda via devicectl

* reflect review and updates

* update type, use waitForCondition

* adjust

* fix lint

* update review
  • Loading branch information
KazuCocoa authored Mar 23, 2024
1 parent f42fb70 commit 39194d4
Showing 1 changed file with 79 additions and 4 deletions.
83 changes: 79 additions & 4 deletions lib/webdriveragent.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { waitForCondition } from 'asyncbox';
import _ from 'lodash';
import path from 'path';
import url from 'url';
Expand Down Expand Up @@ -66,6 +67,7 @@ class WebDriverAgent {

this.updatedWDABundleId = args.updatedWDABundleId;

this.wdaLaunchTimeout = args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT;
this.usePreinstalledWDA = args.usePreinstalledWDA;
this.xctestApiClient = null;

Expand All @@ -87,7 +89,7 @@ class WebDriverAgent {
useSimpleBuildTest: args.useSimpleBuildTest,
usePrebuiltWDA: args.usePrebuiltWDA,
updatedWDABundleId: this.updatedWDABundleId,
launchTimeout: args.wdaLaunchTimeout || WDA_LAUNCH_TIMEOUT,
launchTimeout: this.wdaLaunchTimeout,
wdaRemotePort: this.wdaRemotePort,
useXctestrunFile: this.useXctestrunFile,
derivedDataPath: args.derivedDataPath,
Expand Down Expand Up @@ -184,7 +186,6 @@ class WebDriverAgent {
* }
*
* @return {Promise<any?>} State Object
* @throws {Error} If there was invalid response code or body
*/
async getStatus () {
const noSessionProxy = new NoSessionProxy({
Expand Down Expand Up @@ -287,6 +288,73 @@ class WebDriverAgent {
}
}


/**
* @typedef {Object} LaunchWdaViaDeviceCtlOptions
* @property {Record<string, string|number>} [env] environment variables for the launching WDA process
*/

/**
* Launch WDA with preinstalled package with 'xcrun devicectl device process launch'.
* The WDA package must be prepared properly like published via
* https://github.com/appium/WebDriverAgent/releases
* with proper sign for this case.
*
* When we implement launching XCTest service via appium-ios-device,
* this implementation can be replaced with it.
*
* @param {LaunchWdaViaDeviceCtlOptions} [opts={}] launching WDA with devicectl command options.
* @return {Promise<void>}
*/
async _launchViaDevicectl(opts = {}) {
// FIXME: use appium-xcuitest-driver's Devicectl. Maybe it needs to be included in the `this.device`?
//

const {env} = opts;

let xcrunBinnaryPath;
try {
xcrunBinnaryPath = await fs.which('xcrun');
} catch (e) {
throw new Error(
`xcrun has not been found in PATH. ` +
`Please make sure XCode development tools are installed`,
);
}

const cmd = [
'devicectl',
'device',
'process',
'launch',
`--device`, this.device.udid,
'--terminate-existing'
];
if (!_.isEmpty(env)) {
cmd.push('--environment-variables', JSON.stringify(_.mapValues(env, (v) => _.toString(v))));
};
cmd.push(this.bundleIdForXctest);

const {stdout} = await exec(xcrunBinnaryPath, cmd);
this.log.debug(`The output of devicectl command: ${stdout}`);

// Launching app via decictl does not wait for the app start.
// We should wait for the app start by ourselves.
try {
await waitForCondition(async () => !_.isNull(await this.getStatus()), {
waitMs: this.wdaLaunchTimeout,
intervalMs: 300,
});

} catch (err) {
throw new Error(
`Failed to start the preinstalled WebDriverAgent in ${this.wdaLaunchTimeout} ms. ` +
`The WebDriverAgent might not be properly built or the device might be locked. ` +
'appium:wdaLaunchTimeout capability modifies the timeout.'
);
}
}

/**
* Launch WDA with preinstalled package without xcodebuild.
* @param {string} sessionId Launch WDA and establish the session with this sessionId
Expand All @@ -302,8 +370,15 @@ class WebDriverAgent {
}
this.log.info('Launching WebDriverAgent on the device without xcodebuild');
if (this.isRealDevice) {
this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv});
await this.xctestApiClient.start();
// 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')) {
await this._launchViaDevicectl({env: xctestEnv});
} else {
this.xctestApiClient = new Xctest(this.device.udid, this.bundleIdForXctest, null, {env: xctestEnv});
await this.xctestApiClient.start();
}
} else {
await this.device.simctl.exec('launch', {
args: [
Expand Down

0 comments on commit 39194d4

Please sign in to comment.