From 37fae29abbd9b3c267efc0219cba7b447b53717e Mon Sep 17 00:00:00 2001 From: bootstraponline Date: Sun, 18 May 2014 17:38:40 -0400 Subject: [PATCH] Fix complexFind. Add scrollTo, scrollToExact --- .gitignore | 2 +- README.md | 6 ++ java-client.iml | 3 +- pom.xml | 5 + .../io/appium/java_client/AppiumDriver.java | 21 +++- .../io/appium/java_client/ComplexFind.java | 97 +++++++++++++++++++ .../java_client/AndroidUIAutomatorTest.java | 22 +++++ 7 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 src/main/java/io/appium/java_client/ComplexFind.java diff --git a/.gitignore b/.gitignore index 514e95f89..b12b66ee1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ out out/* target/classes/* target/test-classes/* -target/surfire-reports/* +target/surefire-reports/* settings.xml diff --git a/README.md b/README.md index 430aec1c5..dfbf27c53 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,9 @@ Locators: - when no appium server is running, the proper error is thrown, instead of a NullPointerException *1.0.2* - recompiled to include some missing methods such as shake() and complexFind() + +## Running tests + +Run a test using + +> mvn -Dtest=io.appium.java_client.MobileDriverAndroidTest clean test \ No newline at end of file diff --git a/java-client.iml b/java-client.iml index 96f806544..3ff4d8e2e 100644 --- a/java-client.iml +++ b/java-client.iml @@ -5,9 +5,9 @@ + - @@ -25,6 +25,7 @@ + diff --git a/pom.xml b/pom.xml index e258813da..9e074205f 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,11 @@ google-collections 1.0 + + com.google.code.gson + gson + 2.2.4 + org.seleniumhq.selenium selenium-java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 1c8ccce13..b1ec52ec8 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -35,11 +35,16 @@ public class AppiumDriver extends RemoteWebDriver implements MobileDriver, Conte FindsByAndroidUIAutomator, FindsByAccessibilityId { private final static MobileErrorHandler errorHandler = new MobileErrorHandler(); + private URL remoteAddress; + private ComplexFind complexFind; public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities){ super(remoteAddress, desiredCapabilities); + this.remoteAddress = remoteAddress; + complexFind = new ComplexFind(this); + ImmutableMap.Builder builder = ImmutableMap.builder(); builder .put(RESET, postC("/session/:sessionId/appium/app/reset")) @@ -461,14 +466,17 @@ public void shake() { execute(SHAKE); } - public String complexFind(String[] complex) { - Response response = execute(COMPLEX_FIND, ImmutableMap.of("selector", complex)); - - return response.toString(); + public MobileElement complexFind(String complex) { + return complexFind.execute(complex); } + public MobileElement scrollTo(String text) { + return complexFind.scrollTo(text); + } - + public MobileElement scrollToExact(String text) { + return complexFind.scrollToExact(text); + } @Override public WebDriver context(String name) { @@ -571,4 +579,7 @@ private static CommandInfo deleteC(String url) { return new CommandInfo(url, HttpVerb.DELETE); } + public URL getRemoteAddress() { + return remoteAddress; + } } \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/ComplexFind.java b/src/main/java/io/appium/java_client/ComplexFind.java new file mode 100644 index 000000000..3821a9bf3 --- /dev/null +++ b/src/main/java/io/appium/java_client/ComplexFind.java @@ -0,0 +1,97 @@ +package io.appium.java_client; + +import com.google.gson.JsonParser; +import org.apache.http.HttpEntity; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.openqa.selenium.remote.RemoteWebElement; + +public class ComplexFind { + + private AppiumDriver driver; + private static final HttpClient client = HttpClients.createDefault(); + private static final JsonParser parser = new JsonParser(); + + public ComplexFind(AppiumDriver driver) { + this.driver = driver; + } + + /** + * Create a new remote web element. + */ + private MobileElement newElement(final String elementId) { + final MobileElement element = new MobileElement(new RemoteWebElement(), driver); + element.setParent(driver); + element.setId(elementId); + element.setFileDetector(driver.getFileDetector()); + return element; + } + + /* + This is a port of the following Ruby code from github.com/appium/ruby_lib + The Selenium Java bindings make it impossible to post JSON so we're using + HttpPost directly. + + # Scroll to an element containing target text or description. + # @param text [String] the text to search for in the text value and content description + # @return [Element] the element scrolled to + def scroll_to text + args = 'scroll', + # textContains(text) + [ [3, text] ], + # descriptionContains(text) + [ [7, text] ] + + mobile :find, args + end + */ + protected MobileElement scrollTo(String text) { + text = text.replaceAll("\"", "\\\""); // quotes must be escaped. + // ["scroll", [[3,"animation"]], [[7,"animation"]]] + final String complex = "[\"scroll\",[[3,\"" + text + "\"]],[[7,\"" + text + "\"]]]"; + return execute(complex); + } + + protected MobileElement scrollToExact(String text) { + text = text.replaceAll("\"", "\\\""); // quotes must be escaped. + // ["scroll", [[1,"Animation"]], [[5,"Animation"]]] + final String complex = "[\"scroll\",[[1,\"" + text + "\"]],[[5,\"" + text + "\"]]]"; + return execute(complex); + } + + protected MobileElement execute(String complex) { + MobileElement element = null; + try { + final String id = driver.getSessionId().toString(); + final String executeURL = driver.getRemoteAddress() + "/session/" + id + "/appium/app/complex_find"; + + final HttpPost post = new HttpPost(executeURL); + post.setEntity(new StringEntity(complex, "UTF8")); + post.setHeader("Content-type", "application/json"); + + final HttpEntity responseEntity = client.execute(post).getEntity(); + + if (responseEntity != null) { + try { + final String responseString = EntityUtils.toString(responseEntity); + // {"status":0,"value":{"ELEMENT":"1"},"sessionId":"8e982755-980f-4036-b3d1-c0e14e890273"} + final String elementId = parser.parse(responseString) + .getAsJsonObject().get("value").getAsJsonObject().get("ELEMENT") + .getAsString(); + + element = newElement(elementId); + } catch (final Exception e) { + e.printStackTrace(); + } finally { + EntityUtils.consume(responseEntity); + } + } + } catch (final Exception e) { + e.printStackTrace(); + } + return element; + } +} \ No newline at end of file diff --git a/src/test/java/io/appium/java_client/AndroidUIAutomatorTest.java b/src/test/java/io/appium/java_client/AndroidUIAutomatorTest.java index 9dfc21e79..2a9865b65 100644 --- a/src/test/java/io/appium/java_client/AndroidUIAutomatorTest.java +++ b/src/test/java/io/appium/java_client/AndroidUIAutomatorTest.java @@ -38,6 +38,28 @@ public void tearDown() throws Exception { driver.quit(); } + @Test + public void complexFind() { + String animation = String.format("[\"scroll\",[[3,\"%1$s\"]],[[7,\"%1$s\"]]]", "animation"); + String cloning = String.format("[\"scroll\",[[3,\"%1$s\"]],[[7,\"%1$s\"]]]", "cloning"); + + driver.complexFind(animation).click(); + driver.complexFind(cloning).click(); + } + + @Test + public void scrollTo() { + driver.scrollTo("animation").click(); + driver.scrollTo("cloning").click(); + } + + @Test + public void scrollToExact() { + driver.scrollToExact("Animation").click(); + driver.scrollToExact("Cloning").click(); + } + + @Test public void findElementTest() { WebElement element = driver.findElementByAndroidUIAutomator("new UiSelector().index(0)");