diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java index 026ea3005..3371718f6 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -1,14 +1,17 @@ package io.appium.java_client.pagefactory; +import io.appium.java_client.AppiumDriver; import io.appium.java_client.MobileElement; +import io.appium.java_client.TouchableElement; +import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.IOSElement; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.concurrent.TimeUnit; import org.openqa.selenium.SearchContext; @@ -37,24 +40,38 @@ public class AppiumFieldDecorator implements FieldDecorator, ResetsImplicitlyWai add(WebElement.class); add(RemoteWebElement.class); add(MobileElement.class); + add(TouchableElement.class); add(AndroidElement.class); add(IOSElement.class); } }; + + private final static Map, Class> elementRuleMap = + new HashMap, Class>(){ + private static final long serialVersionUID = 1L; + { + put(AndroidDriver.class, AndroidElement.class); + put(AndroidElement.class, AndroidElement.class); + put(IOSDriver.class, IOSElement.class); + put(IOSElement.class, IOSElement.class); + } + }; private final AppiumElementLocatorFactory factory; - + private final SearchContext context; public static long DEFAULT_IMPLICITLY_WAIT_TIMEOUT = 1; public static TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS; public AppiumFieldDecorator(SearchContext context, long implicitlyWaitTimeOut, TimeUnit timeUnit) { - factory = new AppiumElementLocatorFactory(context, implicitlyWaitTimeOut, timeUnit); + this.context = context; + factory = new AppiumElementLocatorFactory(this.context, implicitlyWaitTimeOut, timeUnit); } public AppiumFieldDecorator(SearchContext context) { - factory = new AppiumElementLocatorFactory(context); + this.context = context; + factory = new AppiumElementLocatorFactory(this.context); } public Object decorate(ClassLoader ignored, Field field) { @@ -68,7 +85,7 @@ public Object decorate(ClassLoader ignored, Field field) { } if (WebElement.class.isAssignableFrom(field.getType())) { - return proxyForLocator(field, locator); + return proxyForLocator(locator); } else if (List.class.isAssignableFrom(field.getType())) { return proxyForListLocator(locator); } else { @@ -107,13 +124,22 @@ private boolean isDecoratableList(Field field) { //DefaultElementLocator has an issue :) } - private Object proxyForLocator(Field field, ElementLocator locator) { - Class type = field.getType(); - if (type.equals(WebElement.class)){ - type = RemoteWebElement.class; - } + private Class getTypeForProxy(){ + Class contextClass = context.getClass(); + Iterable, Class>> rules = elementRuleMap.entrySet(); + Iterator, Class>> iterator = rules.iterator(); + while (iterator.hasNext()){ //it will return MobileElement subclass when here is something + //that extends AppiumDriver or MobileElement + Map.Entry, Class> e = iterator.next(); + if (e.getKey().isAssignableFrom(contextClass)) + return e.getValue(); + } //it is compatible with desktop browser. So at this case it returns RemoteWebElement.class + return RemoteWebElement.class; + } + + private Object proxyForLocator(ElementLocator locator) { ElementInterceptor elementInterceptor = new ElementInterceptor(locator); - return ProxyFactory.getEnhancedProxy(type, + return ProxyFactory.getEnhancedProxy(getTypeForProxy(), elementInterceptor); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java index e5a8fc9ef..a8019c1bd 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -1,6 +1,7 @@ package io.appium.java_client.pagefactory_tests; import io.appium.java_client.MobileElement; +import io.appium.java_client.TouchableElement; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import io.appium.java_client.pagefactory.AndroidFindAll; @@ -17,6 +18,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import org.apache.xpath.operations.And; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -76,6 +78,9 @@ public class AndroidPageObjectTest { @iOSFindBy(xpath = "//someElement")}) private List chainAndroidOrIOSUIAutomatorViews; + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private List touchabletextVieWs; + @FindBy(id = "android:id/text1") private WebElement textView; @@ -153,6 +158,9 @@ public class AndroidPageObjectTest { @AndroidFindBy(id = "android:id/text1") @SelendroidFindBy(id = "Invalid Identifier") private WebElement textAndroidId; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private TouchableElement touchabletextVieW; @Before public void setUp() throws Exception { @@ -320,5 +328,23 @@ public void findAllElementsTest(){ @Test public void findByAndroidAnnotationOnlyTest(){ Assert.assertNotEquals(null, textAndroidId.getAttribute("text")); - } + } + + @Test + public void isTouchableElement(){ + Assert.assertNotEquals(null, touchabletextVieW.getAttribute("text")); + } + + @Test + public void areTouchableElements(){ + Assert.assertNotEquals(0, touchabletextVieWs.size()); + } + + @Test + public void isTheFieldAndroidElement(){ + AndroidElement androidElement = (AndroidElement) mobiletextVieW; //declared as MobileElement + androidElement = (AndroidElement) androidTextView; //declared as WedElement + androidElement = (AndroidElement) remotetextVieW; //declared as RemoteWedElement + androidElement = (AndroidElement) touchabletextVieW; //declared as TouchABLEElement + } } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java index 5236a1a22..73b361f96 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java @@ -1,6 +1,8 @@ package io.appium.java_client.pagefactory_tests; import io.appium.java_client.MobileElement; +import io.appium.java_client.TouchableElement; +import io.appium.java_client.android.AndroidElement; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.ios.IOSElement; import io.appium.java_client.pagefactory.AndroidFindBy; @@ -80,6 +82,12 @@ public class iOSPageObjectTest { @iOSFindBy(uiAutomator = ".elements()[0]") private MobileElement mobileButton; + @iOSFindBy(uiAutomator = ".elements()[0]") + private TouchableElement touchableButton; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private List touchableButtons; + @FindBy(className = "UIAButton") private MobileElement mobiletFindBy_Button; @@ -253,4 +261,22 @@ public void findAllElementsTest(){ public void findAllElementTest(){ Assert.assertNotEquals(null, findAllElement.getText()); } + + @Test + public void isTouchAbleElement(){ + Assert.assertNotEquals(null, touchableButton.getText()); + } + + @Test + public void areTouchAbleElements(){ + Assert.assertNotEquals(0, touchableButtons.size()); + } + + @Test + public void isTheFieldIOSElement(){ + IOSElement iOSElement = (IOSElement) mobileButton; //declared as MobileElement + iOSElement = (IOSElement) iosUIAutomatorButton; //declared as WedElement + iOSElement = (IOSElement) remotetextVieW; //declared as RemoteWedElement + iOSElement = (IOSElement) touchableButton; //declared as TouchABLEElement + } }