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

feat: Return web atom response #941

Merged
merged 5 commits into from
Oct 30, 2023
Merged
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ import io.appium.espressoserver.lib.model.EspressoElement
import io.appium.espressoserver.lib.model.web.WebAtomsParams
import io.appium.espressoserver.lib.viewmatcher.withView

class WebAtoms : RequestHandler<WebAtomsParams, Void?> {
class WebAtoms : RequestHandler<WebAtomsParams, Any?> {

@Throws(AppiumException::class)
override fun handleInternal(params: WebAtomsParams): Void? {
var webViewInteraction:WebInteraction<*>
override fun handleInternal(params: WebAtomsParams): Any? {
var webViewInteraction: WebInteraction<*>

// TODO: Add a 'waitForDocument' feature to wait for HTML DOCUMENT to be ready

// Initialize onWebView with web view matcher (if webviewEl provided)
params.webviewElement.let{ webviewElement ->
params.webviewElement.let { webviewElement ->
AndroidLogger.info("Initializing webView interaction on webview with el: '$webviewElement'")
val viewState = EspressoElement.getCachedViewStateById(webviewElement)
val matcher = withView(viewState.view)
Expand All @@ -53,18 +53,22 @@ class WebAtoms : RequestHandler<WebAtomsParams, Void?> {
// Iterate through methodsChain and call the atoms
params.methodChain.forEach { method ->
val atom = invokeStaticMethod(DriverAtoms::class.java, method.atom.name, *method.atom.args) as? Atom<*>
?: throw InvalidArgumentException("'${method.atom.name}' did not return a valid " +
"'${Atom::class.qualifiedName}' object")
?: throw InvalidArgumentException(
"'${method.atom.name}' did not return a valid " +
"'${Atom::class.qualifiedName}' object",
)

AndroidLogger.info("Calling interaction '${method.name}' with the atom '${method.atom}'")

val res = invokeInstanceMethod(webViewInteraction, method.name, atom) as? WebInteraction<*>
?: throw InvalidArgumentException("'${method.name}' does not return a valid " +
"'${WebInteraction::class.qualifiedName}' object")
?: throw InvalidArgumentException(
"'${method.name}' does not return a valid " +
"'${WebInteraction::class.qualifiedName}' object",
)

webViewInteraction = res
}

return null
// param size check is for the case when we want to check element exists but don't have any action to perform
return if (params.methodChain.size == 1) "success" else webViewInteraction.get()
Copy link
Contributor

@mykola-mokhnach mykola-mokhnach Oct 29, 2023

Choose a reason for hiding this comment

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

[debug] [EspressoDriver@7732 (d0303a0b)] Proxying [POST /appium/execute_mobile/web_atoms] to [POST http://127.0.0.1:58945/session/f55230ec-2f73-44dc-a17c-8a12a999146a/appium/execute_mobile/web_atoms] with body: {"webviewElement":"cd114239-cbe6-43c1-bbde-2376269c0336","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@Data-QA='safety-centre-item']"}}}]}

[debug] [EspressoDriver@7732 (d0303a0b)] java.lang.IllegalStateException: Perform or Check never called on this WebInteraction!

I am still not quite convinced on this one. Why it is not possible to call isDisplayed atom to verify existence of the found element?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No such method isDisplayed in DriverAtom

[HTTP] --> POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/element
[HTTP] {"using":"xpath","value":"//*[(./@class = 'android.webkit.WebView')]"}
[EspressoDriver@9c32 (4f5644ec)] Driver proxy active, passing request on via HTTP proxy
[debug] [EspressoDriver@9c32 (4f5644ec)] Matched '/wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/element' to command name 'findElement'
[debug] [EspressoDriver@9c32 (4f5644ec)] Proxying [POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/element] to [POST http://127.0.0.1:62016/session/9d001ba8-192b-4a19-8095-fed953da7fc6/element] with body: {"using":"xpath","value":"//*[(./@class = 'android.webkit.WebView')]"}
[debug] [EspressoDriver@9c32 (4f5644ec)] Got response with status 200: {"id":"f973f813-accd-4cb1-bff1-8851faf333c6","sessionId":"9d001ba8-192b-4a19-8095-fed953da7fc6","value":{"ELEMENT":"a8d32be7-7182-4370-ac89-494e66eab4aa"}}
[EspressoDriver@9c32 (4f5644ec)] Replacing sessionId 9d001ba8-192b-4a19-8095-fed953da7fc6 with 4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7
[HTTP] <-- POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/element 200 44 ms - 232
[HTTP]
[HTTP] --> POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync
[HTTP] {"script":"mobile: webAtoms","args":[{"webviewElement":"a8d32be7-7182-4370-ac89-494e66eab4aa","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"isDisplayed"}]}]}
[debug] [EspressoDriver@9c32 (4f5644ec)] Calling AppiumDriver.execute() with args: ["mobile: webAtoms",[{"webviewElement":"a8d32be7-7182-4370-ac89-494e66eab4aa","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"isDisplayed"}]}],"4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7"]
[EspressoDriver@9c32 (4f5644ec)] Executing native command 'mobile: webAtoms'
[debug] [EspressoDriver@9c32 (4f5644ec)] Proxying [POST /appium/execute_mobile/web_atoms] to [POST http://127.0.0.1:62016/session/9d001ba8-192b-4a19-8095-fed953da7fc6/appium/execute_mobile/web_atoms] with body: {"webviewElement":"a8d32be7-7182-4370-ac89-494e66eab4aa","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"isDisplayed"}]}
[EspressoDriver@9c32 (4f5644ec)] Got response with status 500: {"id":"026636b8-cc3a-44bb-9e47-d2cc9751b057","sessionId":"9d001ba8-192b-4a19-8095-fed953da7fc6","value":{"error":"unknown error","message":"java.lang.NoSuchMethodException: No such method: isDisplayed() on class: androidx.test.espresso.web.webdriver.DriverAtoms","stacktrace":"java.lang.NoSuchMethodException: No such method: isDisplayed() on class: androidx.test.espresso.web.webdriver.DriverAtoms\n\tat io.appium.espressoserver.lib.helpers.reflection.MethodUtils.invokeStaticMethod(MethodUtils.java:57)\n\tat io.appium.espressoserver.lib.helpers.ReflectionUtils.invokeStaticMethod(ReflectionUtils.kt:39)\n\tat io.appium.espressoserver.lib.handlers.WebAtoms.handleInternal(WebAtoms.kt:55)\n\tat io.appium.espressoserver.lib.handlers.WebAtoms.handleInternal(WebAtoms.kt:32)\n\tat io.appium.espressoserver.lib.handlers.RequestHandler$DefaultImpls.handle(RequestHandler.kt:57)\n\tat io.appium.espressoserver.lib.handlers.WebAtoms.handle(WebAtoms.kt:32)\n\tat io.appium.espressoserver.lib.http.Router.route(Router.kt:231)\n\...
[debug] [W3C] Matched W3C error code 'unknown error' to UnknownError
[debug] [EspressoDriver@9c32 (4f5644ec)] Encountered internal error running command: An unknown server-side error occurred while processing the command. Original error: java.lang.NoSuchMethodException: No such method: isDisplayed() on class: androidx.test.espresso.web.webdriver.DriverAtoms
[debug] [EspressoDriver@9c32 (4f5644ec)] java.lang.NoSuchMethodException: No such method: isDisplayed() on class: androidx.test.espresso.web.webdriver.DriverAtoms
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.helpers.reflection.MethodUtils.invokeStaticMethod(MethodUtils.java:57)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.helpers.ReflectionUtils.invokeStaticMethod(ReflectionUtils.kt:39)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.handlers.WebAtoms.handleInternal(WebAtoms.kt:55)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.handlers.WebAtoms.handleInternal(WebAtoms.kt:32)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.handlers.RequestHandler$DefaultImpls.handle(RequestHandler.kt:57)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.handlers.WebAtoms.handle(WebAtoms.kt:32)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.http.Router.route(Router.kt:231)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at io.appium.espressoserver.lib.http.Server.serve(Server.kt:54)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:945)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at fi.iki.elonen.NanoHTTPD$ClientHandler.run(NanoHTTPD.java:192)
[debug] [EspressoDriver@9c32 (4f5644ec)] 	at java.lang.Thread.run(Thread.java:1012)
[debug] [EspressoDriver@9c32 (4f5644ec)]
[HTTP] <-- POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync 500 83 ms - 1262
[HTTP]

One option I see is to call selectActiveElement. Here's the response of that

[HTTP]
[HTTP] --> POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync
[HTTP] {"script":"mobile: webAtoms","args":[{"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}]}
[debug] [EspressoDriver@9c32 (4f5644ec)] Calling AppiumDriver.execute() with args: ["mobile: webAtoms",[{"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}],"4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7"]
[EspressoDriver@9c32 (4f5644ec)] Executing native command 'mobile: webAtoms'
[debug] [EspressoDriver@9c32 (4f5644ec)] Proxying [POST /appium/execute_mobile/web_atoms] to [POST http://127.0.0.1:62016/session/9d001ba8-192b-4a19-8095-fed953da7fc6/appium/execute_mobile/web_atoms] with body: {"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}
[debug] [EspressoDriver@9c32 (4f5644ec)] Got response with status 200: {"id":"908094ab-7ec4-404e-a9e3-b4ea2b54cd6b","sessionId":"9d001ba8-192b-4a19-8095-fed953da7fc6","value":{"opaque":":wdc:1698617571775"}}
[debug] [EspressoDriver@9c32 (4f5644ec)] Responding to client with driver.execute() result: {"opaque":":wdc:1698617571775"}
[HTTP] <-- POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync 200 90 ms - 41[HTTP]
[HTTP] --> POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync
[HTTP] {"script":"mobile: webAtoms","args":[{"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}]}
[debug] [EspressoDriver@9c32 (4f5644ec)] Calling AppiumDriver.execute() with args: ["mobile: webAtoms",[{"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}],"4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7"]
[EspressoDriver@9c32 (4f5644ec)] Executing native command 'mobile: webAtoms'
[debug] [EspressoDriver@9c32 (4f5644ec)] Proxying [POST /appium/execute_mobile/web_atoms] to [POST http://127.0.0.1:62016/session/9d001ba8-192b-4a19-8095-fed953da7fc6/appium/execute_mobile/web_atoms] with body: {"webviewElement":"ab90db14-932b-44d7-aa19-d66a16adc4e1","forceJavascriptEnabled":true,"methodChain":[{"name":"withElement","atom":{"name":"findElement","locator":{"using":"XPATH","value":"//*[@data-qa='safety-centre-item']"}}},{"name":"perform","atom":"selectActiveElement"}]}
[debug] [EspressoDriver@9c32 (4f5644ec)] Got response with status 200: {"id":"908094ab-7ec4-404e-a9e3-b4ea2b54cd6b","sessionId":"9d001ba8-192b-4a19-8095-fed953da7fc6","value":{"opaque":":wdc:1698617571775"}}
[debug] [EspressoDriver@9c32 (4f5644ec)] Responding to client with driver.execute() result: {"opaque":":wdc:1698617571775"}
[HTTP] <-- POST /wd/hub/session/4f5644ec-ffb6-4ab4-83cf-a4b4af3ffbd7/execute/sync 200 90 ms - 41

How about I document the case in the documentation and code and remove the size check?

Copy link
Contributor

Choose a reason for hiding this comment

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

How about I document the case in the documentation and code and remove the size check?

I feel it would be still a workaround. We could probably improve this extension by adding the support of check method on top of the existing perform one.

Would you be interested in that @pr4bh4sh (of course not as part of this particular PR)?

Also more documentation, especially with good usage examples, would always be super useful.

Copy link
Contributor Author

@pr4bh4sh pr4bh4sh Oct 30, 2023

Choose a reason for hiding this comment

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

Sure, I'll work on implementing check in another PR.

}
}
Loading