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 searching elements inside WebViews for iOS 13.3 #273

Merged
merged 1 commit into from
Jan 13, 2020

Conversation

fr0l
Copy link

@fr0l fr0l commented Jan 10, 2020

Fixes issue with searching and interacting with elements inside WebViews for iOS 13.3

Swizzle defaultParameters of XCAXClient_iOS to set maxDepth to a meaningful level of recursion.

Original implementation of defaultParams returns this values

{
  maxArrayCount = 2147483647;
  maxChildren = 2147483647;
  maxDepth = 2147483647;
  traverseFromParentsToChildren = 1;
}

It is quite possible, that it is enough to change only the maxDepth parameter. I'm still experimenting.

Please do not merge yet, Just for verification if it does not break stuff.

@fr0l
Copy link
Author

fr0l commented Jan 10, 2020

Possibly fixes appium/appium#13776

@imurchie
Copy link

Thanks for this!

I'm not sure it will fix the actual going into webviews (as in appium/appium#13776) but it will hopefully fix the accessing of webview contents within the native context (as in appium/appium#13821). This latter has always been a crapshoot, changing from version to version of both iOS and Xcode.

@fr0l
Copy link
Author

fr0l commented Jan 10, 2020

@imurchie i didn't quite get about

actual going into webviews

Basically what happens with the fix — is now XCTest can traverse views and subviews (including WebViews) of an XCUIApplication and then return XCUIElementQuery (s) and XCUIElement (s) in a meaningful time.

If someone would have very deep element hierarchy, then probably increasing maxDepth would help (but it also will increase chance of a timed out operation.

Most probably we could make the maxDepth parameter configurable (i.e. add it to FBConfiguration) to make it easy to do experiment.

What was happening before — a WebView process would start to consume 100% CPU and method _XCT_requestSnapshotForElement: attributes: parameters: reply: (which is highly likely used under the hood of XCUIElementQuery while getting snapshots XCElementSnapshot) would just timeout somewhere on the way, but a WebView would still consume 100% CPU.

Currently I've tested this fix with several applications using XCTest (the lowest level framework from Appium's point of view)

Hopefully it would not require any changes in Appium tools at all (apart from recompiling WebDriverAgent)

@imurchie
Copy link

imurchie commented Jan 10, 2020

I mean that the way webview contents are generally better handled is to switch to the webview context and interact with the HTML there, rather than interacting through the native layer. The SafariViewController issue is attempting to do that, and it is unlikely that any changes in WebDriverAgent will affect that.

See https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/hybrid.md

@rakurati7
Copy link

I tried your new change with new WebDriverAgent and it's working great, thanks. However I still find that few websites like yahoo.com, msn.com, m.weibo.cn webview content is not accessible.

For reference here is the actual issue that I posted

@mykola-mokhnach
Copy link

I agree it would be nice to have the depth value configurable. We also had exactly the same issue in Android and workarounded it by setting the maximum recursion depth to 70.

@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

@mykola-mokhnach i will update the PR in 10-15 min with configurable value

@fr0l fr0l force-pushed the xcode_11_3_web_view branch 5 times, most recently from 2b54cbb to 024f047 Compare January 11, 2020 13:16
@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

@mykola-mokhnach @imurchie I've modified the PR with allowing to change configuration.

@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

@rakurati7
I've tested the default value of maxDepth to 50 to cover case of web resources like 'yahoo.com' to still be able to find elements.

If you need bigger level of maxDepth, then you need to modify the snapshotTimeout parameter to somewhat like 40 seconds.

@mykola-mokhnach
Copy link

If you need bigger level of maxDepth, then you need to modify the snapshotTimeout parameter to somewhat like 40 seconds.

It would be nice to describe this somewhere in the troubleshooting documentation at https://github.com/appium/appium/tree/master/docs/en/writing-running-appium/ios

@fr0l fr0l force-pushed the xcode_11_3_web_view branch 2 times, most recently from 622aae8 to e9f253c Compare January 11, 2020 15:35
@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

If you need bigger level of maxDepth, then you need to modify the snapshotTimeout parameter to somewhat like 40 seconds.

It would be nice to describe this somewhere in the troubleshooting documentation at https://github.com/appium/appium/tree/master/docs/en/writing-running-appium/ios

I'll try to do that

@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

@mykola-mokhnach please could you take a look if it is ok now

@@ -411,4 +434,20 @@ + (BOOL)reduceMotionEnabled
}
return NO;
}

/**
Returns defaul parameters for traversing elements tree from parents to children while requesting XCElementSnapshot.

Choose a reason for hiding this comment

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

default

@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

fixed docs

@rakurati7
Copy link

@rakurati7
I've tested the default value of maxDepth to 50 to cover case of web resources like 'yahoo.com' to still be able to find elements.

If you need bigger level of maxDepth, then you need to modify the snapshotTimeout parameter to somewhat like 40 seconds.

QQ, So with your new commit I have to build a new WDA, right? and the parameters maxDepth and snapshotTimeout should be passed as a Webdriver capabilities?. Please clarify, thanks.

@fr0l
Copy link
Author

fr0l commented Jan 11, 2020

@rakurati7 yes, you will need to build WDA. But the parameters snapshotTimeout and maxDepth can be set using /appium/settings API.

For example something like this:

This will get session id:

DEFAULT_SESSION_ID=$(curl -s http://localhost:8100/status | awk -F'[:]' '/sessionId/ { gsub(/[" ,]/, ""); print $2 }')

This will get current settings:

curl -s http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This will change settings:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 100, "snapshotTimeout" : 60 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search'

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

This is example response for found element:

{
  "value" : {
    "ELEMENT" : "0F000000-0000-0000-65DE-000000000000",
    "element-6066-11e4-a52e-4f735466cecf" : "0F000000-0000-0000-65DE-000000000000"
  },
  "sessionId" : "5CB69058-971C-4A2C-B270-C667AA2439B9"
}%

This is changing settings to lower values:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 10, "snapshotTimeout" : 15 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search' again

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

But this time, no element is found:

{
  "value" : {
    "error" : "no such element",
    "message" : "unable to find an element using 'name', value 'Search'",
.....

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

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

🎉
It would be nice to add the snapshotMaxDepth in https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/settings.md latere

@jlipps
Copy link
Member

jlipps commented Jan 12, 2020

thanks for this valuable contribution @fr0l!

@rakurati7
Copy link

@rakurati7 yes, you will need to build WDA. But the parameters snapshotTimeout and maxDepth can be set using /appium/settings API.

For example something like this:

This will get session id:

DEFAULT_SESSION_ID=$(curl -s http://localhost:8100/status | awk -F'[:]' '/sessionId/ { gsub(/[" ,]/, ""); print $2 }')

This will get current settings:

curl -s http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This will change settings:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 100, "snapshotTimeout" : 60 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search'

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

This is example response for found element:

{
  "value" : {
    "ELEMENT" : "0F000000-0000-0000-65DE-000000000000",
    "element-6066-11e4-a52e-4f735466cecf" : "0F000000-0000-0000-65DE-000000000000"
  },
  "sessionId" : "5CB69058-971C-4A2C-B270-C667AA2439B9"
}%

This is changing settings to lower values:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 10, "snapshotTimeout" : 15 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search' again

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

But this time, no element is found:

{
  "value" : {
    "error" : "no such element",
    "message" : "unable to find an element using 'name', value 'Search'",
.....

Thank you, I am referring to this document and I found Appium settings can be set using 'settings[settingsKey]'. So with this commit can I set the following capabilities in Appium inspector.
'settings[snapshotTimeout]' : 40
'settings[maxDepth]' : 60

@fr0l
Copy link
Author

fr0l commented Jan 12, 2020

@mykola-mokhnach thanks for awesome code review!

@mykola-mokhnach
Copy link

you're welcome. Thanks for your contributions

@rakurati7
Copy link

@rakurati7 yes, you will need to build WDA. But the parameters snapshotTimeout and maxDepth can be set using /appium/settings API.
For example something like this:
This will get session id:

DEFAULT_SESSION_ID=$(curl -s http://localhost:8100/status | awk -F'[:]' '/sessionId/ { gsub(/[" ,]/, ""); print $2 }')

This will get current settings:

curl -s http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This will change settings:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 100, "snapshotTimeout" : 60 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search'

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

This is example response for found element:

{
  "value" : {
    "ELEMENT" : "0F000000-0000-0000-65DE-000000000000",
    "element-6066-11e4-a52e-4f735466cecf" : "0F000000-0000-0000-65DE-000000000000"
  },
  "sessionId" : "5CB69058-971C-4A2C-B270-C667AA2439B9"
}%

This is changing settings to lower values:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 10, "snapshotTimeout" : 15 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search' again

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

But this time, no element is found:

{
  "value" : {
    "error" : "no such element",
    "message" : "unable to find an element using 'name', value 'Search'",
.....

Thank you, I am referring to this document and I found Appium settings can be set using 'settings[settingsKey]'. So with this commit can I set the following capabilities in Appium inspector.
'settings[snapshotTimeout]' : 40
'settings[maxDepth]' : 60

@fr0l Could you please clear me this?

@rakurati7
Copy link

@rakurati7 yes, you will need to build WDA. But the parameters snapshotTimeout and maxDepth can be set using /appium/settings API.
For example something like this:
This will get session id:

DEFAULT_SESSION_ID=$(curl -s http://localhost:8100/status | awk -F'[:]' '/sessionId/ { gsub(/[" ,]/, ""); print $2 }')

This will get current settings:

curl -s http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This will change settings:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 100, "snapshotTimeout" : 60 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search'

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

This is example response for found element:

{
  "value" : {
    "ELEMENT" : "0F000000-0000-0000-65DE-000000000000",
    "element-6066-11e4-a52e-4f735466cecf" : "0F000000-0000-0000-65DE-000000000000"
  },
  "sessionId" : "5CB69058-971C-4A2C-B270-C667AA2439B9"
}%

This is changing settings to lower values:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 10, "snapshotTimeout" : 15 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search' again

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

But this time, no element is found:

{
  "value" : {
    "error" : "no such element",
    "message" : "unable to find an element using 'name', value 'Search'",
.....

Thank you, I am referring to this document and I found Appium settings can be set using 'settings[settingsKey]'. So with this commit can I set the following capabilities in Appium inspector.
'settings[snapshotTimeout]' : 40
'settings[maxDepth]' : 60

@rakurati7 yes, you will need to build WDA. But the parameters snapshotTimeout and maxDepth can be set using /appium/settings API.

For example something like this:

This will get session id:

DEFAULT_SESSION_ID=$(curl -s http://localhost:8100/status | awk -F'[:]' '/sessionId/ { gsub(/[" ,]/, ""); print $2 }')

This will get current settings:

curl -s http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This will change settings:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 100, "snapshotTimeout" : 60 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search'

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

This is example response for found element:

{
  "value" : {
    "ELEMENT" : "0F000000-0000-0000-65DE-000000000000",
    "element-6066-11e4-a52e-4f735466cecf" : "0F000000-0000-0000-65DE-000000000000"
  },
  "sessionId" : "5CB69058-971C-4A2C-B270-C667AA2439B9"
}%

This is changing settings to lower values:

curl -s -X POST -d '{ "settings" : { "snapshotMaxDepth" : 10, "snapshotTimeout" : 15 } }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/appium/settings | grep snapshot

This is example search of an element with a name 'Search' again

curl -s -X POST -d '{ "using" : "name", "value" : "Search"  }' http://localhost:8100/session/${DEFAULT_SESSION_ID}/element

But this time, no element is found:

{
  "value" : {
    "error" : "no such element",
    "message" : "unable to find an element using 'name', value 'Search'",
.....

@fr0l I tried the new appium@beta with new WDA. I still not able to find elements inside webview for few websites like yahoo.com, nytimes.com. I am passing the following settings as capabilities in appium inspector
"settings[snapshotTimeout]": 60,
"settings[snapshotMaxDepth]": 100

Original issue here

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.

6 participants