Skip to content

Commit 9d1a1b5

Browse files
1 parent ddac8ff commit 9d1a1b5

7 files changed

Lines changed: 133 additions & 21 deletions

File tree

src/main/java/io/appium/java_client/pagefactory/AppiumAnnotations.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.appium.java_client.pagefactory;
22

33
import static io.appium.java_client.remote.MobilePlatform.*;
4+
import static io.appium.java_client.remote.AutomationName.*;
45
import io.appium.java_client.MobileBy;
56

67
import java.lang.annotation.Annotation;
@@ -300,7 +301,7 @@ public By buildBy() {
300301
SelendroidFindBy selendroidBy = mobileField
301302
.getAnnotation(SelendroidFindBy.class);
302303
if (selendroidBy != null && ANDROID.toUpperCase().equals(platform)
303-
&& "Selendroid".toUpperCase().equals(automation)) {
304+
&& SELENDROID.toUpperCase().equals(automation)) {
304305
return setByForTheNativeContentAndReturn(
305306
getMobileBy(selendroidBy, getFilledValue(selendroidBy)),
306307
contentMap);
@@ -309,7 +310,7 @@ public By buildBy() {
309310
SelendroidFindBys selendroidBys = mobileField
310311
.getAnnotation(SelendroidFindBys.class);
311312
if (selendroidBys != null && ANDROID.toUpperCase().equals(platform)
312-
&& "Selendroid".toUpperCase().equals(automation)) {
313+
&& SELENDROID.toUpperCase().equals(automation)) {
313314
return setByForTheNativeContentAndReturn(
314315
getComplexMobileBy(selendroidBys.value(), ByChained.class),
315316
contentMap);
@@ -318,7 +319,7 @@ public By buildBy() {
318319
SelendroidFindAll selendroidAll = mobileField
319320
.getAnnotation(SelendroidFindAll.class);
320321
if (selendroidAll != null && ANDROID.toUpperCase().equals(platform)
321-
&& "Selendroid".toUpperCase().equals(automation)) {
322+
&& SELENDROID.toUpperCase().equals(automation)) {
322323
return setByForTheNativeContentAndReturn(
323324
getComplexMobileBy(selendroidAll.value(), ByAll.class),
324325
contentMap);

src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
package io.appium.java_client.pagefactory;
22

3+
import io.appium.java_client.android.AndroidDriver;
4+
import io.appium.java_client.ios.IOSDriver;
35
import io.appium.java_client.remote.MobileCapabilityType;
46

57
import java.lang.reflect.Field;
68
import java.util.ArrayList;
79
import java.util.List;
810
import java.util.concurrent.TimeUnit;
911

10-
import org.openqa.selenium.By;
11-
import org.openqa.selenium.Capabilities;
12-
import org.openqa.selenium.HasCapabilities;
13-
import org.openqa.selenium.NoSuchElementException;
14-
import org.openqa.selenium.SearchContext;
15-
import org.openqa.selenium.StaleElementReferenceException;
16-
import org.openqa.selenium.TimeoutException;
17-
import org.openqa.selenium.WebElement;
12+
import io.appium.java_client.remote.MobilePlatform;
13+
import org.openqa.selenium.*;
1814
import org.openqa.selenium.support.pagefactory.ElementLocator;
1915
import org.openqa.selenium.support.ui.FluentWait;
2016

@@ -26,6 +22,7 @@ class AppiumElementLocator implements ElementLocator {
2622
private static class WaitingFunction implements
2723
Function<By, List<WebElement>> {
2824
private final SearchContext searchContext;
25+
private final static String INVALID_SELECTOR_PATTERN = "Invalid locator strategy:";
2926

3027
private WaitingFunction(SearchContext searchContext) {
3128
this.searchContext = searchContext;
@@ -37,12 +34,26 @@ public List<WebElement> apply(By by) {
3734
result.addAll(searchContext.findElements(by));
3835
} catch (StaleElementReferenceException ignored) {
3936
}
37+
catch (RuntimeException e){
38+
if (!isInvalidSelectorRootCause(e))
39+
throw e;
40+
}
4041
if (result.size() > 0) {
4142
return result;
4243
} else {
4344
return null;
4445
}
4546
}
47+
48+
private static boolean isInvalidSelectorRootCause(Throwable e){
49+
if (e == null)
50+
return false;
51+
52+
if (String.valueOf(e.getMessage()).contains(INVALID_SELECTOR_PATTERN))
53+
return true;
54+
55+
return isInvalidSelectorRootCause(e.getCause());
56+
}
4657
}
4758

4859
private final SearchContext searchContext;
@@ -66,15 +77,9 @@ public List<WebElement> apply(By by) {
6677
AppiumElementLocator(SearchContext searchContext, Field field,
6778
TimeOutDuration timeOutDuration) {
6879
this.searchContext = searchContext;
69-
// All known webdrivers implement HasCapabilities
70-
Capabilities capabilities = ((HasCapabilities) WebDriverUnpackUtility.
71-
unpackWebDriverFromSearchContext(this.searchContext))
72-
.getCapabilities();
7380

74-
String platform = String.valueOf(capabilities
75-
.getCapability(MobileCapabilityType.PLATFORM_NAME));
76-
String automation = String.valueOf(capabilities
77-
.getCapability(MobileCapabilityType.AUTOMATION_NAME));
81+
String platform = getPlatform();
82+
String automation = getAutomation();
7883

7984
AppiumAnnotations annotations = new AppiumAnnotations(field, platform,
8085
automation);
@@ -88,6 +93,41 @@ public List<WebElement> apply(By by) {
8893
by = annotations.buildBy();
8994
}
9095

96+
private String getPlatform(){
97+
WebDriver d = WebDriverUnpackUtility.
98+
unpackWebDriverFromSearchContext(this.searchContext);
99+
if (d == null)
100+
return null;
101+
102+
Class<?> driverClass = d.getClass();
103+
if (AndroidDriver.class.isAssignableFrom(driverClass))
104+
return MobilePlatform.ANDROID;
105+
106+
if (IOSDriver.class.isAssignableFrom(driverClass))
107+
return MobilePlatform.IOS;
108+
109+
//it is possible that here customers implementation of WebDriver
110+
//At this case it has to implement HasCapabilities
111+
if (HasCapabilities.class.isAssignableFrom(driverClass))
112+
return String.valueOf(((HasCapabilities) d).getCapabilities().
113+
getCapability(MobileCapabilityType.PLATFORM_NAME));
114+
115+
return null;
116+
}
117+
118+
private String getAutomation(){
119+
WebDriver d = WebDriverUnpackUtility.
120+
unpackWebDriverFromSearchContext(this.searchContext);
121+
if (d == null)
122+
return null;
123+
124+
if (HasCapabilities.class.isAssignableFrom(d.getClass()))
125+
return String.valueOf(((HasCapabilities) d).getCapabilities().
126+
getCapability(MobileCapabilityType.AUTOMATION_NAME));
127+
128+
return null;
129+
}
130+
91131
private void changeImplicitlyWaitTimeOut(long newTimeOut,
92132
TimeUnit newTimeUnit) {
93133
WebDriverUnpackUtility.unpackWebDriverFromSearchContext(searchContext)

src/main/java/io/appium/java_client/pagefactory/ContentMappedBy.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ private By returnRelevantBy(SearchContext context){
2222
if (!ContextAware.class.isAssignableFrom(driver.getClass())){ //it is desktop browser
2323
return map.get(ContentType.HTML);
2424
}
25-
25+
26+
By result = null;
27+
2628
ContextAware contextAware = ContextAware.class.cast(driver);
2729
String currentContext = contextAware.getContext();
2830
if (currentContext.contains(NATIVE_APP_PATTERN))
@@ -35,4 +37,17 @@ public List<WebElement> findElements(SearchContext context) {
3537
return context.findElements(returnRelevantBy(context));
3638
}
3739

40+
@Override
41+
public String toString(){
42+
By defaultBy = map.get(ContentType.HTML);
43+
By nativeBy = map.get(ContentType.NATIVE);
44+
45+
if (defaultBy.equals(nativeBy))
46+
return defaultBy.toString();
47+
48+
return "Locator map: " + "\n" +
49+
"- native content: \"" + nativeBy.toString() + "\" \n" +
50+
"- html content: \"" + defaultBy.toString() + "\"";
51+
}
52+
3853
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.appium.java_client.remote;
2+
3+
4+
public interface AutomationName {
5+
String APPIUM = "Appium";
6+
String SELENDROID = "Selendroid";
7+
}

src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ public class AndroidPageObjectTest {
160160

161161
@AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")")
162162
private TouchableElement touchabletextVieW;
163+
164+
@iOSFindBy(uiAutomator = ".elements()[0]")
165+
@FindBy(css = "e.e1.e2")
166+
private List<WebElement> elementsWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy;
167+
168+
@iOSFindBy(uiAutomator = ".elements()[0]")
169+
@FindBy(css = "e.e1.e2")
170+
private WebElement elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy;
163171

164172
@SuppressWarnings("rawtypes")
165173
@Before
@@ -348,4 +356,20 @@ public void isTheFieldAndroidElement(){
348356
androidElement = (AndroidElement) remotetextVieW; //declared as RemoteWedElement
349357
androidElement = (AndroidElement) touchabletextVieW; //declared as TouchABLEElement
350358
}
359+
360+
@Test
361+
public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy(){
362+
try {
363+
Assert.assertNotEquals(null, elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text"));
364+
}
365+
catch (NoSuchElementException ignored){
366+
return;
367+
}
368+
throw new RuntimeException(NoSuchElementException.class.getName() + " has been expected.");
369+
}
370+
371+
@Test
372+
public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy_List(){
373+
Assert.assertEquals(0, elementsWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.size());
374+
}
351375
}

src/test/java/io/appium/java_client/pagefactory_tests/SelendroidModeTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.appium.java_client.pagefactory.SelendroidFindAll;
77
import io.appium.java_client.pagefactory.SelendroidFindBy;
88
import io.appium.java_client.pagefactory.SelendroidFindBys;
9+
import io.appium.java_client.remote.AutomationName;
910
import io.appium.java_client.remote.MobileCapabilityType;
1011

1112
import org.openqa.selenium.WebElement;
@@ -79,7 +80,7 @@ public void setUp() throws Exception {
7980
DesiredCapabilities capabilities = new DesiredCapabilities();
8081
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
8182
capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
82-
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Selendroid");
83+
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.SELENDROID);
8384
capabilities.setCapability(MobileCapabilityType.SELENDROID_PORT, SELENDROID_PORT);
8485
driver = new AndroidDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
8586

src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ public class iOSPageObjectTest {
117117
})
118118
private List<WebElement> findAllElements;
119119

120+
@AndroidFindBy(className = "android.widget.TextView")
121+
@FindBy(css = "e.e1.e2")
122+
private List<WebElement> elementsWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy;
123+
124+
@AndroidFindBy(className = "android.widget.TextView")
125+
@FindBy(css = "e.e1.e2")
126+
private WebElement elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy;
127+
120128
@SuppressWarnings("rawtypes")
121129
@Before
122130
public void setUp() throws Exception {
@@ -280,4 +288,20 @@ public void isTheFieldIOSElement(){
280288
iOSElement = (IOSElement) remotetextVieW; //declared as RemoteWebElement
281289
iOSElement = (IOSElement) touchableButton; //declared as TouchABLEElement
282290
}
291+
292+
@Test
293+
public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy(){
294+
try {
295+
Assert.assertNotEquals(null, elementWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.getAttribute("text"));
296+
}
297+
catch (NoSuchElementException ignored){
298+
return;
299+
}
300+
throw new RuntimeException(NoSuchElementException.class.getName() + " has been expected.");
301+
}
302+
303+
@Test
304+
public void checkThatTestWillNotBeFailedBecauseOfInvalidFindBy_List(){
305+
Assert.assertEquals(0, elementsWhenAndroidLocatorIsNotDefinedAndThereIsInvalidFindBy.size());
306+
}
283307
}

0 commit comments

Comments
 (0)