Skip to content

Commit ac43e99

Browse files
committed
Merge pull request #26 from bootstraponline/complex
Fix complexFind. Add scrollTo, scrollToExact
2 parents c4561a4 + 37fae29 commit ac43e99

File tree

7 files changed

+149
-7
lines changed

7 files changed

+149
-7
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ out
44
out/*
55
target/classes/*
66
target/test-classes/*
7-
target/surfire-reports/*
7+
target/surefire-reports/*
88
settings.xml

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,9 @@ Locators:
6363
- when no appium server is running, the proper error is thrown, instead of a NullPointerException
6464
*1.0.2*
6565
- recompiled to include some missing methods such as shake() and complexFind()
66+
67+
## Running tests
68+
69+
Run a test using
70+
71+
> mvn -Dtest=io.appium.java_client.MobileDriverAndroidTest clean test

java-client.iml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
<output-test url="file://$MODULE_DIR$/target/test-classes" />
66
<content url="file://$MODULE_DIR$">
77
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="false" />
8+
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
89
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
910
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
10-
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
1111
<excludeFolder url="file://$MODULE_DIR$/target" />
1212
</content>
1313
<orderEntry type="inheritedJdk" />
@@ -25,6 +25,7 @@
2525
<orderEntry type="library" name="org.json-20131017" level="project" />
2626
<orderEntry type="library" name="commons-codec-1.9" level="project" />
2727
<orderEntry type="library" name="Maven: com.google.collections:google-collections:1.0" level="project" />
28+
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.2.4" level="project" />
2829
<orderEntry type="library" name="Maven: org.seleniumhq.selenium:selenium-java:2.41.0" level="project" />
2930
<orderEntry type="library" name="Maven: org.seleniumhq.selenium:selenium-chrome-driver:2.41.0" level="project" />
3031
<orderEntry type="library" name="Maven: org.seleniumhq.selenium:selenium-remote-driver:2.41.0" level="project" />

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
<artifactId>google-collections</artifactId>
1414
<version>1.0</version>
1515
</dependency>
16+
<dependency>
17+
<groupId>com.google.code.gson</groupId>
18+
<artifactId>gson</artifactId>
19+
<version>2.2.4</version>
20+
</dependency>
1621
<dependency>
1722
<groupId>org.seleniumhq.selenium</groupId>
1823
<artifactId>selenium-java</artifactId>

src/main/java/io/appium/java_client/AppiumDriver.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,16 @@ public class AppiumDriver extends RemoteWebDriver implements MobileDriver, Conte
3535
FindsByAndroidUIAutomator, FindsByAccessibilityId {
3636

3737
private final static MobileErrorHandler errorHandler = new MobileErrorHandler();
38+
private URL remoteAddress;
39+
private ComplexFind complexFind;
3840

3941
public AppiumDriver(URL remoteAddress, Capabilities desiredCapabilities){
4042

4143
super(remoteAddress, desiredCapabilities);
4244

45+
this.remoteAddress = remoteAddress;
46+
complexFind = new ComplexFind(this);
47+
4348
ImmutableMap.Builder<String, CommandInfo> builder = ImmutableMap.builder();
4449
builder
4550
.put(RESET, postC("/session/:sessionId/appium/app/reset"))
@@ -461,14 +466,17 @@ public void shake() {
461466
execute(SHAKE);
462467
}
463468

464-
public String complexFind(String[] complex) {
465-
Response response = execute(COMPLEX_FIND, ImmutableMap.of("selector", complex));
466-
467-
return response.toString();
469+
public MobileElement complexFind(String complex) {
470+
return complexFind.execute(complex);
468471
}
469472

473+
public MobileElement scrollTo(String text) {
474+
return complexFind.scrollTo(text);
475+
}
470476

471-
477+
public MobileElement scrollToExact(String text) {
478+
return complexFind.scrollToExact(text);
479+
}
472480

473481
@Override
474482
public WebDriver context(String name) {
@@ -571,4 +579,7 @@ private static CommandInfo deleteC(String url) {
571579
return new CommandInfo(url, HttpVerb.DELETE);
572580
}
573581

582+
public URL getRemoteAddress() {
583+
return remoteAddress;
584+
}
574585
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package io.appium.java_client;
2+
3+
import com.google.gson.JsonParser;
4+
import org.apache.http.HttpEntity;
5+
import org.apache.http.client.HttpClient;
6+
import org.apache.http.client.methods.HttpPost;
7+
import org.apache.http.entity.StringEntity;
8+
import org.apache.http.impl.client.HttpClients;
9+
import org.apache.http.util.EntityUtils;
10+
import org.openqa.selenium.remote.RemoteWebElement;
11+
12+
public class ComplexFind {
13+
14+
private AppiumDriver driver;
15+
private static final HttpClient client = HttpClients.createDefault();
16+
private static final JsonParser parser = new JsonParser();
17+
18+
public ComplexFind(AppiumDriver driver) {
19+
this.driver = driver;
20+
}
21+
22+
/**
23+
* Create a new remote web element.
24+
*/
25+
private MobileElement newElement(final String elementId) {
26+
final MobileElement element = new MobileElement(new RemoteWebElement(), driver);
27+
element.setParent(driver);
28+
element.setId(elementId);
29+
element.setFileDetector(driver.getFileDetector());
30+
return element;
31+
}
32+
33+
/*
34+
This is a port of the following Ruby code from github.com/appium/ruby_lib
35+
The Selenium Java bindings make it impossible to post JSON so we're using
36+
HttpPost directly.
37+
38+
# Scroll to an element containing target text or description.
39+
# @param text [String] the text to search for in the text value and content description
40+
# @return [Element] the element scrolled to
41+
def scroll_to text
42+
args = 'scroll',
43+
# textContains(text)
44+
[ [3, text] ],
45+
# descriptionContains(text)
46+
[ [7, text] ]
47+
48+
mobile :find, args
49+
end
50+
*/
51+
protected MobileElement scrollTo(String text) {
52+
text = text.replaceAll("\"", "\\\""); // quotes must be escaped.
53+
// ["scroll", [[3,"animation"]], [[7,"animation"]]]
54+
final String complex = "[\"scroll\",[[3,\"" + text + "\"]],[[7,\"" + text + "\"]]]";
55+
return execute(complex);
56+
}
57+
58+
protected MobileElement scrollToExact(String text) {
59+
text = text.replaceAll("\"", "\\\""); // quotes must be escaped.
60+
// ["scroll", [[1,"Animation"]], [[5,"Animation"]]]
61+
final String complex = "[\"scroll\",[[1,\"" + text + "\"]],[[5,\"" + text + "\"]]]";
62+
return execute(complex);
63+
}
64+
65+
protected MobileElement execute(String complex) {
66+
MobileElement element = null;
67+
try {
68+
final String id = driver.getSessionId().toString();
69+
final String executeURL = driver.getRemoteAddress() + "/session/" + id + "/appium/app/complex_find";
70+
71+
final HttpPost post = new HttpPost(executeURL);
72+
post.setEntity(new StringEntity(complex, "UTF8"));
73+
post.setHeader("Content-type", "application/json");
74+
75+
final HttpEntity responseEntity = client.execute(post).getEntity();
76+
77+
if (responseEntity != null) {
78+
try {
79+
final String responseString = EntityUtils.toString(responseEntity);
80+
// {"status":0,"value":{"ELEMENT":"1"},"sessionId":"8e982755-980f-4036-b3d1-c0e14e890273"}
81+
final String elementId = parser.parse(responseString)
82+
.getAsJsonObject().get("value").getAsJsonObject().get("ELEMENT")
83+
.getAsString();
84+
85+
element = newElement(elementId);
86+
} catch (final Exception e) {
87+
e.printStackTrace();
88+
} finally {
89+
EntityUtils.consume(responseEntity);
90+
}
91+
}
92+
} catch (final Exception e) {
93+
e.printStackTrace();
94+
}
95+
return element;
96+
}
97+
}

src/test/java/io/appium/java_client/AndroidUIAutomatorTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,28 @@ public void tearDown() throws Exception {
3838
driver.quit();
3939
}
4040

41+
@Test
42+
public void complexFind() {
43+
String animation = String.format("[\"scroll\",[[3,\"%1$s\"]],[[7,\"%1$s\"]]]", "animation");
44+
String cloning = String.format("[\"scroll\",[[3,\"%1$s\"]],[[7,\"%1$s\"]]]", "cloning");
45+
46+
driver.complexFind(animation).click();
47+
driver.complexFind(cloning).click();
48+
}
49+
50+
@Test
51+
public void scrollTo() {
52+
driver.scrollTo("animation").click();
53+
driver.scrollTo("cloning").click();
54+
}
55+
56+
@Test
57+
public void scrollToExact() {
58+
driver.scrollToExact("Animation").click();
59+
driver.scrollToExact("Cloning").click();
60+
}
61+
62+
4163
@Test
4264
public void findElementTest() {
4365
WebElement element = driver.findElementByAndroidUIAutomator("new UiSelector().index(0)");

0 commit comments

Comments
 (0)