Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: uninstall wda with '.xctrunner' suffix for real device #1052

Merged
merged 20 commits into from
Sep 1, 2019

Conversation

KazuCocoa
Copy link
Member

closes appium/appium#13086

Will take a look again tomorrow.
(Draft for now)


  • Built by over Xcode 11:
    • On simulator => 'com.facebook.WebDriverAgentRunner.xctrunner'
    • On real device => 'xxxxx.xctrunner'. xxxx is this.opts.updatedWDABundleId
  • Buiild by Xcode 10-
    • Only 'com.apple.test.WebDriverAgentRunner-Runner' (both real device and simulator)

*
* @param {string} updatedWDABundleId The bundle id which will be uninstalled
*/
async uninstall (updatedWDABundleId = WDA_RUNNER_BUNDLE_ID) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't updatedWDABundleId already sent in as an argument to the constructor? Why not just save that as an instance variable and use it?

} else {
// On simulator, the bundle id should be 'com.facebook.WebDriverAgentRunner.xctrunner'
// even if 'updatedWDABundleId' was given
const bundle_id = `${this.realDevice ? updatedWDABundleId : WDA_RUNNER_BUNDLE_ID}${WDA_XCTRUNNER_SUFFIX}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should probably keep with camel case for variable names. I personally would also prefer the conditional to figure out the bundle id, then a single call to removeApp.

Copy link
Contributor

Choose a reason for hiding this comment

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

bundleId

Copy link
Member Author

Choose a reason for hiding this comment

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

true

try {
await this.device.removeApp(WDA_BUNDLE_ID);
if (this.xcodeVersion.major < 11) {
Copy link
Contributor

Choose a reason for hiding this comment

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

it might be that xcode version is unknown for real devices

Copy link
Member Author

Choose a reason for hiding this comment

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

ah...
Let me check again...

Copy link
Member Author

Choose a reason for hiding this comment

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

this.xcodeVersion had Xcode version on a real device.
The value might be undefined if this.opts.webDriverAgentUrl was also provided in createSession

Copy link
Contributor

Choose a reason for hiding this comment

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

The value might be undefined if this.opts.webDriverAgentUrl was also provided in createSession

exactly

* @param {string} updatedWDABundleId The bundle id which will be uninstalled
*/
async quitAndUninstall (updatedWDABundleId = WDA_RUNNER_BUNDLE_ID) {
const status = await this.getStatus();
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Aug 26, 2019

Choose a reason for hiding this comment

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

Can we fallback to read the id from the actual plist bundle since status might not be available at this stage?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds good.
Here is only called by 'useNewWDA' is true

@KazuCocoa KazuCocoa marked this pull request as ready for review August 27, 2019 16:04
@umutuzgur
Copy link
Member

@KazuCocoa I have a simpler solution. We can look or add a certain identifier to the Info.plist of the webdriveragent project. This would help us to find what we want to uninstall and we can avoid bundleid based search

@KazuCocoa
Copy link
Member Author

Do you mean like https://github.com/appium/appium-xcuitest-driver/pull/1052/files#diff-a0e3f2ac971dfbd2354c4efa8121165aR222-R234 ? It gets CFBundleIdentifier in Info.plist. The value is exactly follow #1052 (comment) rule.

Yeah, it should work.

Below are cases I considered.
I concerned the 4, so considered to refer productBundleIdentifier. But I thought yesterday we could ignore the potential case since the case was maybe very rare. Not so common environment.

  1. With useXctestrunFile
    • We can get Info.Plist with current implementation this
  2. With usePrebuiltWDA
    • Should work with this. It refers derivedDataPath.
  3. With webDriverAgentUrl
    • We do not uninstall WDA since handing WDA is out of scope by Appium
  4. Our built-in cache (re-use running WDA) feature and useNewWDA
    • It means Appium re-use running WDA on the device.
      • Potentially, failed to uninstall the running WDA happen if running WDA has different bundleid from bundleId which Appium has.

Will work to simplify today. (maybe, a couple of hours later)

@umutuzgur
Copy link
Member

Something like that. We can get a list of the applications from the phone and check for an entry like IsAppiumWDA=true. This would help us remove the code for checking if wda is removable without caring about any other configurations. On top of this, I really don't wanna deal with xcode changing the bundle id format of xctrunners

@umutuzgur
Copy link
Member

We can modify this method https://github.com/appium/appium-ios-simulator/blob/master/lib/simulator-xcode-6.js#L182 and list all apps with their Info.plist parsed. This would do the same thing for real devices https://github.com/appium/appium-ios-device/blob/master/lib/installation-proxy/index.js#L39

@KazuCocoa
Copy link
Member Author

That's cool!
I've added custom key as Info.Plist, but it did not appear as the returned value.
I think filtered by value.CFBundleName === 'WebDriverAgentRunner-Runner' or value. CFBundleDisplayName === 'WebDriverAgentRunner-Runner' are enough for real devices.
https://gist.github.com/KazuCocoa/ed4963fe5807e5f33e8944b8e54df92a is the result of Xcode 10.3 and 11 beta

@umutuzgur
Copy link
Member

XCode might be building it weirdly and stripping stuff from the Info.plist but CFBundleName also sounds cool

*/
async getInstalledWDBundleId () {
if (this.isRealDevice) {
return await getIBundleIdsByCFBundleName(this.device, WDA_CF_BUNDLE_NAME);
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Aug 29, 2019

Choose a reason for hiding this comment

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

I assume this function and the next one should be methods of this.device object

@@ -216,11 +217,11 @@ async function shutdownOtherSimulators (currentDevice) {

async function getInstalledBundleIds (device, candidateBundleIds) {
const bundleIds = [];
for (const bundleId of candidateBundleIds) {
await B.filter(candidateBundleIds, async (bundleId) => {
if (await device.isAppInstalled(bundleId)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

not really - the filter condition should be async (bundleId) => await device.isAppInstalled(bundleId)

Copy link
Contributor

Choose a reason for hiding this comment

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

and the result could be returned immediately. There is no need for the intermediate accumulator

@@ -422,7 +423,7 @@ class WebDriverAgent {
*/
async getInstalledWDBundleId () {
return this.isRealDevice
? await getIBundleIdsByCFBundleName(this.device, WDA_CF_BUNDLE_NAME)
Copy link
Contributor

Choose a reason for hiding this comment

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

so how about moving these methods into corresponding classes and make it polymorphic?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes. I also thought we can get CFBundleNam in simulator case (ios-simulator does not have such a method for now tho) as future work

@@ -214,5 +215,15 @@ async function shutdownOtherSimulators (currentDevice) {
}
}

async function getInstalledBundleIds (device, candidateBundleIds) {
Copy link
Member

Choose a reason for hiding this comment

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

Should we actually change this in appium-ios-simulator that we get a similar api like what the real devices have? This would help us get rid of having a list of potential bundle ids

Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Aug 30, 2019

Choose a reason for hiding this comment

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

we can either add this call to ios simulator or we can attach it to the object dynamically right in this module:

this.device.getInstalledBundleIds = getInstalledBundleIds.bind(this.device);

Then this context in this method will be pointing to device instance if called from this.device.getInstalledBundleIds(...)

Copy link
Member

Choose a reason for hiding this comment

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

I'm talking about something else. I'm talking about making this method similar as the getBundleIdsByBundleName (device, bundleName)

Copy link
Contributor

Choose a reason for hiding this comment

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

^
This one as well. Otherwise how can it be polymorphic?

}

log.debug(`Uninstalling WDAs: '${bundleIds}'`);
await B.each(bundleIds, async (bundleId) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

and here I would revert back to for of. each call does not provide any preferences over a normal loop

* @returns {Array<string>} A list of User level apps' bundle ids which has
* 'CFBundleName' attribute as 'bundleName'.
*/
async function getBundleIdsByBundleName (device, bundleName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

yep, lets move this method into IOSDeploy class

@@ -214,5 +215,15 @@ async function shutdownOtherSimulators (currentDevice) {
}
}

async function getInstalledBundleIds (device, candidateBundleIds) {
Copy link
Contributor

Choose a reason for hiding this comment

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

since this is an oneliner then we could simply move it to getInstalledWDBundleId

Copy link
Contributor

@mykola-mokhnach mykola-mokhnach left a comment

Choose a reason for hiding this comment

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

I like it

Copy link
Member

@umutuzgur umutuzgur left a comment

Choose a reason for hiding this comment

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

Nice work!

@KazuCocoa KazuCocoa merged commit 291da78 into appium:master Sep 1, 2019
@KazuCocoa KazuCocoa deleted the km/fix-differnet-bundleid branch September 1, 2019 23:44
khanayan123 pushed a commit to khanayan123/appium-xcuitest-driver that referenced this pull request May 10, 2021
)

* fix: Follow the new bundleid if running env on Xcode 11

* get bundleid via ios-device, revert some implementations

* move getBundleIdsByBundleName to iosdeploy

* call getUserInstalledBundleIdsByBundleName from device

* add unittests for uninstall
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

xcode 11 changes the bundle id of WDA
4 participants