Skip to content

Commit 2226123

Browse files
authored
feat: install prebuilt WDA as prebuiltWDAPath capability (#1672)
* feat: install wda * docs: add prebuiltWDAPath * revert: desired-caps... * chore: add prebuiltWDAPath * chore: move the ts-expect-error * chore: tweak * chore: tweak * docs: add appium:prebuiltWDAPath in the preinstallation section * docs: add example * docs: update run-preinstalled-wda.md
1 parent cd7bcaa commit 2226123

File tree

4 files changed

+65
-8
lines changed

4 files changed

+65
-8
lines changed

docs/capabilities.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ Capability | Description
5656
|`appium:showXcodeLog`|Whether to display the output of the Xcode command used to run the tests. If this is `true`, there will be **lots** of extra logging at startup. Defaults to `false`|e.g., `true`|
5757
|`appium:iosInstallPause`|Time in milliseconds to pause between installing the application and starting `WebDriverAgent` on the device. Used particularly for larger applications. Defaults to `0`|e.g., `8000`|
5858
|`appium:usePrebuiltWDA`|Skips the build phase of running the WDA app. Building is then the responsibility of the user. Only works for Xcode 8+. Defaults to `false`.|e.g., `true`|
59-
|`appium:usePreinstalledWDA`| Whether to launch a preinstalled WebDriverAgentRunner application using a custom XCTest API client (via `com.apple.instruments` service) instead of running `xcodebuild` for real devices. The preinstalled WebDriverAgent package must have been built by Xcode 12+. The default target bundle identifier is `com.facebook.WebDriverAgentRunner.xctrunner`. If `appium:updatedWDABundleId` is provided, `<appium:updatedWDABundleId>.xctrunner` will be launched. Please read [Run Preinstalled WebDriverAgentRunner](./run-preinstalled-wda.md) for more details. Defaults to `false`. |`true` or `false`|
59+
|`appium:prebuiltWDAPath`| The path to a WebDriverAgentRunner application package to be installed with `appium:usePreinstalledWDA` capability for real devices. The package's bundle id will be used over `appium:updatedWDABundleId`. |e.g., `/path/to/WebDriverAgentRunner-Runner.app`|
60+
|`appium:usePreinstalledWDA`| Whether to launch a preinstalled WebDriverAgentRunner application using a custom XCTest API client (via `com.apple.instruments` service) instead of running `xcodebuild` for real devices. If `appium:prebuiltWDAPath` is provided, XCUITest driver will install it before launching the application. The preinstalled WebDriverAgent package must have been built by Xcode 12+. The default target bundle identifier is `com.facebook.WebDriverAgentRunner.xctrunner`. If `appium:updatedWDABundleId` is provided, `<appium:updatedWDABundleId>.xctrunner` will be launched. Please read [Run Preinstalled WebDriverAgentRunner](./run-preinstalled-wda.md) for more details. Defaults to `false`. |`true` or `false`|
6061
|`appium:shouldUseSingletonTestManager`|Use default proxy for test management within `WebDriverAgent`. Setting this to `false` sometimes helps with socket hangup problems. Defaults to `true`.|e.g., `false`|
6162
|`appium:waitForIdleTimeout`|The amount of time in float seconds to wait until the application under test is idling. XCTest requires the app's main thread to be idling in order to execute any action on it, so WDA might not even start/freeze if the app under test is constantly hogging the main thread. The default value is `10` (seconds). Setting it to zero disables idling checks completely (not recommended) and has the same effect as setting `waitForQuiescence` to `false`. Available since Appium 1.20.0. |
6263
|`appium:useXctestrunFile`|Use Xctestrun file to launch WDA. It will search for such file in `bootstrapPath`. Expected name of file is `WebDriverAgentRunner_iphoneos<sdkVersion>-arm64.xctestrun` for real device and `WebDriverAgentRunner_iphonesimulator<sdkVersion>-x86_64.xctestrun` for simulator. One can do `build-for-testing` for `WebDriverAgent` project for simulator and real device and then you will see [Product Folder like this](useXctestrunFile.png) and you need to copy content of this folder at `bootstrapPath` location. Since this capability expects that you have already built `WDA` project, it neither checks whether you have necessary dependencies to build `WDA` nor will it try to build project. Defaults to `false`. _Tips: `Xcodebuild` builds for the target platform version. We'd recommend you to build with minimal OS version which you'd like to run as the original WDA module. e.g. If you build WDA for 12.2, the module cannot run on iOS 11.4 because of loading some module error on simulator. A module built with 11.4 can work on iOS 12.2. (This is xcodebuild's expected behaviour.)_ |e.g., `true`|

docs/run-preinstalled-wda.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ It lets you to start a XCUITest driver session without the `xcodebuild` command
1313
- [`appium:usePreinstalledWDA`](capabilities.md#webdriveragent)
1414
- Optional
1515
- [`appium:updatedWDABundleId`](capabilities.md#webdriveragent)
16+
- [`appium:prebuiltWDAPath`](capabilities.md#webdriveragent)
1617

1718
### Example steps with Xcode
1819

@@ -80,3 +81,32 @@ Some 3rd party tools such as [ios-deploy](https://github.com/ios-control/ios-dep
8081

8182
`WebDriverAgentRunner-Runner.app` package may exist in a `derivedDataPath` directory as explained in [Real Device Configuration tutorial](./real-device-config.md).
8283
The `WebDriverAgentRunner-Runner.app` can be installed without xcodebuild with the 3rd party tools.
84+
85+
86+
### Set `appium:prebuiltWDAPath`
87+
88+
If `appium:prebuiltWDAPath` is provided with properly signed `WebDriverAgentRunner-Runner.app` test bundle (please check [Real Device Configuration tutorial](real-device-config.md)), XCUITest driver will install the application and launch it every test session.
89+
Test bundles cannot be versioned using `CFBundleVersion` as vanilla applications do. That is why it is necessary to (re)install them for every test session.
90+
91+
Usually you can find the actual WebDriverAgentRunner application bundle at the below location if you use Xcode to build it.
92+
93+
```
94+
~/Library/Developer/Xcode/DerivedData/WebDriverAgent-<random string>/Build/Products/Debug-iphoneos/WebDriverAgentRunner-Runner.app
95+
```
96+
97+
Then, the capabilities will be:
98+
99+
```ruby
100+
# Ruby
101+
capabilities: {
102+
"platformName": "ios",
103+
"appium:automationName": "xcuitest",
104+
"appium:udid": "<udid>",
105+
"appium:usePreinstalledWDA": true,
106+
"appium:prebuiltWDAPath": "/path/to/Library/Developer/Xcode/DerivedData/WebDriverAgent-<random string>/Build/Products/Debug-iphoneos/WebDriverAgentRunner-Runner.app"
107+
}
108+
@core = Appium::Core.for capabilities: capabilities
109+
driver = @core.start_driver
110+
# do something
111+
driver.quit
112+
```

lib/desired-caps.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ const desiredCapConstraints = /** @type {const} */({
135135
usePrebuiltWDA: {
136136
isBoolean: true
137137
},
138+
prebuiltWDAPath: {
139+
isString: true,
140+
},
138141
usePreinstalledWDA: {
139142
isBoolean: true,
140143
},

lib/driver.js

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -748,12 +748,19 @@ class XCUITestDriver extends BaseDriver {
748748
);
749749
}
750750

751-
if (this.opts.usePreinstalledWDA && !this.isRealDevice()) {
752-
throw new Error(
753-
`'usePreinstalledWDA' capability is only supported for real devices. ` +
754-
`'useXctestrunFile' or 'usePrebuiltWDA' may help to get similar errort on Simulators.`
755-
);
751+
if (this.opts.usePreinstalledWDA) {
752+
if (!this.isRealDevice()) {
753+
throw new Error(
754+
`'usePreinstalledWDA' capability is only supported for real devices. ` +
755+
`'useXctestrunFile' or 'usePrebuiltWDA' may help to get similar errort on Simulators.`
756+
);
757+
}
756758
// below will be only for real devices if the caps has "this.opts.usePreinstalledWDA"
759+
760+
if (this.opts.prebuiltWDAPath && !(await fs.exists(this.opts.prebuiltWDAPath))) {
761+
throw new Error(`'${this.opts.prebuiltWDAPath}' provided as 'prebuiltWDAPath' capability did not exist. ` +
762+
`Please make sure if the path exits.`);
763+
}
757764
}
758765

759766
return await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
@@ -817,8 +824,24 @@ class XCUITestDriver extends BaseDriver {
817824
// Stop the existing process before starting a new one to start a fresh WDA process every session.
818825
await this.mobileKillApp(this.wda.bundleIdForXctest);
819826

820-
// TODO: Define `prebuiltWDAPath` or something as a new capability.
821-
// Then, we can start installing the WDA package to start a session without xcodebuild.
827+
if (this.opts.prebuiltWDAPath) {
828+
const candidateBundleId = await extractBundleId.bind(this)(this.opts.prebuiltWDAPath);
829+
this.wda.updatedWDABundleId = candidateBundleId.replace('.xctrunner', '');
830+
this.log.info(`Installing prebuilt WDA ${this.opts.prebuiltWDAPath}`);
831+
// Note: The CFBundleVersion in the test bundle was always 1.
832+
// It may not be able to compare with the installed versio.
833+
await installToRealDevice(
834+
// @ts-expect-error - do not assign arbitrary properties to `this.opts`
835+
this.opts.device,
836+
this.opts.prebuiltWDAPath,
837+
candidateBundleId,
838+
{
839+
skipUninstall: true,
840+
timeout: this.opts.appPushTimeout,
841+
strategy: this.opts.appInstallStrategy,
842+
}
843+
);
844+
}
822845
}
823846

824847
// Over Xcode 10 will often try to access the app from its staging

0 commit comments

Comments
 (0)