diff --git a/README.md b/README.md index a67b56fd3..9adc60380 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Depends upon the Selenium Java client library, available [here](http://docs.sele io.appium java-client - 1.3.0 + 1.5.0 ``` diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java new file mode 100644 index 000000000..29f6da8de --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBy.java @@ -0,0 +1,26 @@ +package io.appium.java_client.pagefactory; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Used to mark a field on a Page Object to indicate an alternative mechanism for locating the + * element or a list of elements. Used in conjunction with + * {@link org.openqa.selenium.support.PageFactory} + * this allows users to quickly and easily create PageObjects. + * using Android UI selectors, accessibility, id, name, class name, tag and xpath + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface AndroidFindBy { + String uiAutomator() default ""; + String accessibility() default ""; + String id() default ""; + String name() default ""; + String className() default ""; + String tagName() default ""; + String xpath() default ""; +} diff --git a/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java new file mode 100644 index 000000000..ddcb77633 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AndroidFindBys.java @@ -0,0 +1,15 @@ +package io.appium.java_client.pagefactory; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to mark a field on a Page Object to indicate that lookup should use a series of @AndroidFindBy tags + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface AndroidFindBys { + AndroidFindBy[] value(); +} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumAnnotations.java b/src/main/java/io/appium/java_client/pagefactory/AppiumAnnotations.java new file mode 100644 index 000000000..6c8d48b67 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumAnnotations.java @@ -0,0 +1,261 @@ +package io.appium.java_client.pagefactory; + +import io.appium.java_client.MobileBy; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.support.pagefactory.Annotations; +import org.openqa.selenium.support.pagefactory.ByChained; + +class AppiumAnnotations extends Annotations{ + + private final static List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = new ArrayList() { + private static final long serialVersionUID = 1L; + { + List objectClassMethodNames = getMethodNames(Object.class + .getDeclaredMethods()); + addAll(objectClassMethodNames); + List annotationClassMethodNames = getMethodNames(Annotation.class + .getDeclaredMethods()); + annotationClassMethodNames.removeAll(objectClassMethodNames); + addAll(annotationClassMethodNames); + } + }; + private final static Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[] {}; + private final static String ANDROID_PLATFORM = "Android"; + private final static String IOS_PLATFORM = "iOS"; + + private static List getMethodNames(Method[] methods) { + List names = new ArrayList(); + for (Method m : methods) { + names.add(m.getName()); + } + return names; + } + + private static enum Strategies { + BYUIAUTOMATOR("uiAutomator") { + @Override + By getBy(Annotation annotation) { + String value = getValue(annotation, this); + if (annotation.annotationType().equals(AndroidFindBy.class)) { + return MobileBy.AndroidUIAutomator(value); + } + if (annotation.annotationType().equals(iOSFindBy.class)) { + return MobileBy.IosUIAutomation(value); + } + return super.getBy(annotation); + } + }, + BYACCESSABILITY("accessibility") { + @Override + By getBy(Annotation annotation) { + return MobileBy.AccessibilityId(getValue(annotation, this)); + } + }, + BYCLASSNAME("className") { + @Override + By getBy(Annotation annotation) { + return By.className(getValue(annotation, this)); + } + }, + BYID("id") { + @Override + By getBy(Annotation annotation) { + return By.id(getValue(annotation, this)); + } + }, + BYTAG("tagName") { + @Override + By getBy(Annotation annotation) { + return By.tagName(getValue(annotation, this)); + } + }, + BYNAME("name") { + @Override + By getBy(Annotation annotation) { + return By.name(getValue(annotation, this)); + } + }, + BYXPATH("xpath") { + @Override + By getBy(Annotation annotation) { + return By.xpath(getValue(annotation, this)); + } + }; + + private final String valueName; + + private String returnValueName() { + return valueName; + } + + private Strategies(String valueName) { + this.valueName = valueName; + } + + private static String[] strategiesNames() { + Strategies[] strategies = values(); + String[] result = new String[strategies.length]; + int i = 0; + for (Strategies strategy : values()) { + result[i] = strategy.valueName; + i++; + } + return result; + } + + private static String getValue(Annotation annotation, + Strategies strategy) { + try { + Method m = annotation.getClass().getMethod(strategy.valueName, + DEFAULT_ANNOTATION_METHOD_ARGUMENTS); + return m.invoke(annotation, new Object[] {}).toString(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + By getBy(Annotation annotation) { + return null; + } + } + + private final Field mobileField; + private final String platform; + + AppiumAnnotations(Field field, String platform) { + super(field); + mobileField = field; + this.platform = String.valueOf(platform). + toUpperCase().trim(); + } + + private void assertValidAnnotations() { + AndroidFindBy androidBy = mobileField + .getAnnotation(AndroidFindBy.class); + AndroidFindBys androidBys = mobileField + .getAnnotation(AndroidFindBys.class); + + iOSFindBy iOSBy = mobileField.getAnnotation(iOSFindBy.class); + iOSFindBys iOSBys = mobileField.getAnnotation(iOSFindBys.class); + + if (androidBy != null && androidBys != null) { + throw new IllegalArgumentException( + "If you use a '@AndroidFindBy' annotation, " + + "you must not also use a '@AndroidFindBys' annotation"); + } + + if (iOSBy != null && iOSBys != null) { + throw new IllegalArgumentException( + "If you use a '@iOSFindBy' annotation, " + + "you must not also use a '@iOSFindBys' annotation"); + } + } + + private static Method[] prepareAnnotationMethods( + Class annotation) { + List targeAnnotationMethodNamesList = getMethodNames(annotation.getDeclaredMethods()); + targeAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); + Method[] result = new Method[targeAnnotationMethodNamesList.size()]; + for (String methodName: targeAnnotationMethodNamesList){ + try { + result[targeAnnotationMethodNamesList.indexOf(methodName)] = annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } + } + return result; + } + + // I suppose that only @AndroidFindBy and @iOSFindBy will be here + private static String getFilledValue(Annotation mobileBy) { + Method[] values = prepareAnnotationMethods(mobileBy.getClass()); + for (Method value : values) { + try { + String strategyParameter = value.invoke(mobileBy, + new Object[] {}).toString(); + if (!"".equals(strategyParameter)) { + return value.getName(); + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + throw new IllegalArgumentException("@" + + mobileBy.getClass().getSimpleName() + ": one of " + + Strategies.strategiesNames().toString() + " should be filled"); + } + + private By getMobileBy(Annotation annotation, String valueName) { + Strategies strategies[] = Strategies.values(); + for (Strategies strategy : strategies) { + if (strategy.returnValueName().equals(valueName)) { + return strategy.getBy(annotation); + } + } + throw new IllegalArgumentException("@" + + annotation.getClass().getSimpleName() + + ": There is an unknown strategy " + valueName); + } + + private By getChainedMobileBy(Annotation[] annotations) { + ; + By[] byArray = new By[annotations.length]; + for (int i = 0; i < annotations.length; i++) { + byArray[i] = getMobileBy(annotations[i], + getFilledValue(annotations[i])); + } + return new ByChained(byArray); + } + + @Override + public By buildBy() { + assertValidAnnotations(); + + AndroidFindBy androidBy = mobileField + .getAnnotation(AndroidFindBy.class); + if (androidBy != null && ANDROID_PLATFORM.toUpperCase().equals(platform)) { + return getMobileBy(androidBy, getFilledValue(androidBy)); + } + + AndroidFindBys androidBys = mobileField + .getAnnotation(AndroidFindBys.class); + if (androidBys != null && ANDROID_PLATFORM.toUpperCase().equals(platform)) { + return getChainedMobileBy(androidBys.value()); + } + + iOSFindBy iOSBy = mobileField.getAnnotation(iOSFindBy.class); + if (iOSBy != null && IOS_PLATFORM.toUpperCase().equals(platform)) { + return getMobileBy(iOSBy, getFilledValue(iOSBy)); + } + + iOSFindBys iOSBys = mobileField.getAnnotation(iOSFindBys.class); + if (iOSBys != null && IOS_PLATFORM.toUpperCase().equals(platform)) { + return getChainedMobileBy(iOSBys.value()); + } + + return super.buildBy(); + } + +} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java new file mode 100644 index 000000000..7216d1916 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -0,0 +1,154 @@ +package io.appium.java_client.pagefactory; + +import io.appium.java_client.remote.MobileCapabilityType; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.By; +import org.openqa.selenium.HasCapabilities; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.internal.WrapsDriver; +import org.openqa.selenium.internal.WrapsElement; +import org.openqa.selenium.support.pagefactory.ElementLocator; +import org.openqa.selenium.support.ui.FluentWait; + +import com.google.common.base.Function; + +class AppiumElementLocator implements ElementLocator { + + // This function waits for not empty element list using all defined by + private static class WaitingFunction implements + Function> { + private final SearchContext searchContext; + + private WaitingFunction(SearchContext searchContext) { + this.searchContext = searchContext; + } + + public List apply(By by) { + List result = new ArrayList(); + try { + result.addAll(searchContext.findElements(by)); + } catch (StaleElementReferenceException ignored) {} + if (result.size() > 0) { + return result; + } else { + return null; + } + } + } + + private final SearchContext searchContext; + private final boolean shouldCache; + private final By by; + private WebElement cachedElement; + private List cachedElementList; + + private final long implicitlyWaitTimeOut; + private final TimeUnit timeUnit ; + + /** + * Creates a new mobile element locator. It instantiates {@link WebElement} + * using @AndroidFindBy (-s), @iOSFindBy (-s) and @FindBy (-s) annotation sets + * + * @param searchContext + * The context to use when finding the element + * @param field + * The field on the Page Object that will hold the located value + */ + public AppiumElementLocator(SearchContext searchContext, Field field, + long implicitlyWaitTimeOut, TimeUnit timeUnit) { + this.searchContext = searchContext; + // All known webdrivers implement HasCapabilities + String platform = String + .valueOf(((HasCapabilities) unpackWebDriverFromSearchContext()) + .getCapabilities().getCapability( + MobileCapabilityType.PLATFORM_NAME)); + AppiumAnnotations annotations = new AppiumAnnotations(field, platform); + this.implicitlyWaitTimeOut = implicitlyWaitTimeOut; + this.timeUnit = timeUnit; + shouldCache = annotations.isLookupCached(); + by = annotations.buildBy(); + } + + private WebDriver unpackWebDriverFromSearchContext(){ + WebDriver driver = null; + if (searchContext instanceof WebDriver){ + driver = (WebDriver) searchContext; + } + //Search context it is not only Webdriver. Webelement is search context too. + //RemoteWebElement and MobileElement implement WrapsDriver + if (searchContext instanceof WebElement){ + WebElement element = (WebElement) searchContext; //there can be something that + //implements WebElement interface and wraps original + while (element instanceof WrapsElement){ + element = ((WrapsElement) element).getWrappedElement(); + } + driver = ((WrapsDriver) searchContext).getWrappedDriver(); + } + return driver; + } + + private void changeImplicitlyWaitTimeOut(long newTimeOut, TimeUnit newTimeUnit){ + unpackWebDriverFromSearchContext().manage().timeouts().implicitlyWait(newTimeOut, newTimeUnit); + } + + //This method waits for not empty element list using all defined by + private List waitFor(){ + //When we use complex By strategies (like ChainedBy or ByAll) + //there are some problems (StaleElementReferenceException, implicitly wait time out + //for each chain By section, etc) + try{ + changeImplicitlyWaitTimeOut(0, TimeUnit.SECONDS); + FluentWait wait = new FluentWait(by); + wait.withTimeout(implicitlyWaitTimeOut, timeUnit); + return wait.until(new WaitingFunction(searchContext)); + } + catch (TimeoutException e){ + return new ArrayList(); + } + finally{ + changeImplicitlyWaitTimeOut(implicitlyWaitTimeOut, timeUnit); + } + } + + /** + * Find the element. + */ + public WebElement findElement() { + if (cachedElement != null && shouldCache) { + return cachedElement; + } + List result = waitFor(); + if (result.size() == 0){ + String message = "Cann't locate an element by this strategy: " + by.toString(); + throw new NoSuchElementException(message); + } + if (shouldCache) { + cachedElement = result.get(0); + } + return result.get(0); + } + + /** + * Find the element list. + */ + public List findElements() { + if (cachedElementList != null && shouldCache) { + return cachedElementList; + } + List result = waitFor(); + if (shouldCache) { + cachedElementList = result; + } + return result; + } +} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java new file mode 100644 index 000000000..8bcbeb62f --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -0,0 +1,38 @@ +package io.appium.java_client.pagefactory; + +import java.lang.reflect.Field; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.support.pagefactory.ElementLocator; +import org.openqa.selenium.support.pagefactory.ElementLocatorFactory; + +class AppiumElementLocatorFactory implements ElementLocatorFactory, ResetsImplicitlyWaitTimeOut { + private static long DEFAULT_IMPLICITLY_WAIT_TIMEOUT = 1; + private static TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS; + + private final SearchContext searchContext; + private long implicitlyWaitTimeOut; + private TimeUnit timeUnit; + + public AppiumElementLocatorFactory(SearchContext searchContext, + long implicitlyWaitTimeOut, TimeUnit timeUnit) { + this.searchContext = searchContext; + this.implicitlyWaitTimeOut = implicitlyWaitTimeOut; + this.timeUnit = timeUnit; + } + + public AppiumElementLocatorFactory(SearchContext searchContext) { + this(searchContext, DEFAULT_IMPLICITLY_WAIT_TIMEOUT, DEFAULT_TIMEUNIT); + } + + public ElementLocator createLocator(Field field) { + return new AppiumElementLocator(searchContext, field, implicitlyWaitTimeOut, timeUnit); + } + + @Override + public void resetImplicitlyWaitTimeOut(long timeOut, TimeUnit timeUnit) { + implicitlyWaitTimeOut = timeOut; + this.timeUnit = timeUnit; + } +} diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java new file mode 100644 index 000000000..e37ddb5ed --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -0,0 +1,112 @@ +package io.appium.java_client.pagefactory; + +import io.appium.java_client.MobileElement; + +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.concurrent.TimeUnit; + +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; +import org.openqa.selenium.support.FindAll; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.FindBys; +import org.openqa.selenium.support.pagefactory.ElementLocator; +import org.openqa.selenium.support.pagefactory.FieldDecorator; + +/** + * Default decorator for use with PageFactory. Will decorate 1) all of the + * WebElement fields and 2) List fields that have + * {@literal @AndroidFindBy}, {@literal @AndroidFindBys}, or + * {@literal @iOSFindBy/@iOSFindBys} annotation with a proxy that locates the + * elements using the passed in ElementLocatorFactory. + * + * Please pay attention: fields of {@link WebElement}, {@link RemoteWebElement} and + * {@link MobileElement} are allowed to use with this decorator + */ +public class AppiumFieldDecorator implements FieldDecorator, ResetsImplicitlyWaitTimeOut { + private final AppiumElementLocatorFactory factory; + + public AppiumFieldDecorator(SearchContext context, long implicitlyWaitTimeOut, TimeUnit timeUnit) { + factory = new AppiumElementLocatorFactory(context, implicitlyWaitTimeOut, timeUnit); + } + + public AppiumFieldDecorator(SearchContext context) { + factory = new AppiumElementLocatorFactory(context); + } + + public Object decorate(ClassLoader ignored, Field field) { + if (!(WebElement.class.isAssignableFrom(field.getType()) || isDecoratableList(field))) { + return null; + } + + ElementLocator locator = factory.createLocator(field); + if (locator == null) { + return null; + } + + if (WebElement.class.isAssignableFrom(field.getType())) { + return proxyForLocator(field, locator); + } else if (List.class.isAssignableFrom(field.getType())) { + return proxyForListLocator(locator); + } else { + return null; + } + } + + private boolean isDecoratableList(Field field) { + if (!List.class.isAssignableFrom(field.getType())) { + return false; + } + + // Type erasure in Java isn't complete. Attempt to discover the generic + // type of the list. + Type genericType = field.getGenericType(); + if (!(genericType instanceof ParameterizedType)) { + return false; + } + + Type listType = ((ParameterizedType) genericType).getActualTypeArguments()[0]; + + if (!WebElement.class.equals(listType) && RemoteWebElement.class.equals(listType) + && MobileElement.class.equals(listType)) { + return false; + } + + + if (field.getAnnotation(AndroidFindBy.class) == null + && field.getAnnotation(iOSFindBy.class) == null + && field.getAnnotation(AndroidFindBys.class) == null + && field.getAnnotation(iOSFindBys.class) == null + && field.getAnnotation(FindBy.class) == null + && field.getAnnotation(FindBys.class) == null + && field.getAnnotation(FindAll.class) == null){ + return false; + } + + return true; + } + + private Object proxyForLocator(Field field, ElementLocator locator) { + ElementInterceptor elementInterceptor = new ElementInterceptor(locator); + return ProxyFactory.getEnhancedProxy(field.getType(), + elementInterceptor); + } + + @SuppressWarnings("unchecked") + private List proxyForListLocator( + ElementLocator locator) { + ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator); + return ProxyFactory.getEnhancedProxy(ArrayList.class, + elementInterceptor); + } + + @Override + public void resetImplicitlyWaitTimeOut(long timeOut, TimeUnit timeUnit) { + factory.resetImplicitlyWaitTimeOut(timeOut, timeUnit); + } +} diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java new file mode 100644 index 000000000..b028aa7a4 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/ElementInterceptor.java @@ -0,0 +1,30 @@ +package io.appium.java_client.pagefactory; + +import io.appium.java_client.MobileElement; + +import java.lang.reflect.Method; + +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.pagefactory.ElementLocator; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * Intercepts requests to {@link MobileElement} + * + */ +class ElementInterceptor implements MethodInterceptor { + private final ElementLocator locator; + + ElementInterceptor(ElementLocator locator) { + this.locator = locator; + } + + public Object intercept(Object obj, Method method, Object[] args, + MethodProxy proxy) throws Throwable { + WebElement realElement = locator.findElement(); + return method.invoke(realElement, args); + } + +} diff --git a/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java new file mode 100644 index 000000000..111ab5a49 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/ElementListInterceptor.java @@ -0,0 +1,32 @@ +package io.appium.java_client.pagefactory; + +import io.appium.java_client.MobileElement; + +import java.lang.reflect.Method; +import java.util.ArrayList; + +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.pagefactory.ElementLocator; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * Intercepts requests to the list of {@link MobileElement} + * + */ +class ElementListInterceptor implements MethodInterceptor{ + private final ElementLocator locator; + + ElementListInterceptor(ElementLocator locator){ + this.locator = locator; + } + + public Object intercept(Object obj, Method method, Object[] args, + MethodProxy proxy) throws Throwable { + ArrayList realElements = new ArrayList(); + realElements.addAll(locator.findElements()); + return method.invoke(realElements, args); + } + +} diff --git a/src/main/java/io/appium/java_client/pagefactory/ProxyFactory.java b/src/main/java/io/appium/java_client/pagefactory/ProxyFactory.java new file mode 100644 index 000000000..fc49f039a --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/ProxyFactory.java @@ -0,0 +1,25 @@ +package io.appium.java_client.pagefactory; + + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; + +/** + * Original class is a super class of a + * proxy object here + */ +abstract class ProxyFactory { + + private ProxyFactory() { + super(); + } + + @SuppressWarnings("unchecked") + static T getEnhancedProxy(Class requiredClazz, MethodInterceptor interceptor){ + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(requiredClazz); + enhancer.setCallback(interceptor); + return (T) enhancer.create(new Class[] {}, new Object[] {}); + } + +} diff --git a/src/main/java/io/appium/java_client/pagefactory/ResetsImplicitlyWaitTimeOut.java b/src/main/java/io/appium/java_client/pagefactory/ResetsImplicitlyWaitTimeOut.java new file mode 100644 index 000000000..8b676f231 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/ResetsImplicitlyWaitTimeOut.java @@ -0,0 +1,7 @@ +package io.appium.java_client.pagefactory; + +import java.util.concurrent.TimeUnit; + +interface ResetsImplicitlyWaitTimeOut { + void resetImplicitlyWaitTimeOut(long timeOut, TimeUnit timeUnit); +} diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSFindBy.java b/src/main/java/io/appium/java_client/pagefactory/iOSFindBy.java new file mode 100644 index 000000000..b9076ed9e --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/iOSFindBy.java @@ -0,0 +1,26 @@ +package io.appium.java_client.pagefactory; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Used to mark a field on a Page Object to indicate an alternative mechanism for locating the + * element or a list of elements. Used in conjunction with + * {@link org.openqa.selenium.support.PageFactory} + * this allows users to quickly and easily create PageObjects. + * using iOS UI selectors, accessibility, id, name, class name, tag and xpath + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface iOSFindBy { + String uiAutomator() default ""; + String accessibility() default ""; + String id() default ""; + String name() default ""; + String className() default ""; + String tagName() default ""; + String xpath() default ""; +} diff --git a/src/main/java/io/appium/java_client/pagefactory/iOSFindBys.java b/src/main/java/io/appium/java_client/pagefactory/iOSFindBys.java new file mode 100644 index 000000000..ae4ef5212 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/iOSFindBys.java @@ -0,0 +1,15 @@ +package io.appium.java_client.pagefactory; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to mark a field on a Page Object to indicate that lookup should use a series of @iOSFindBy tags + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface iOSFindBys { + iOSFindBy[] value(); +} 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 new file mode 100644 index 000000000..7ca5a57a2 --- /dev/null +++ b/src/test/java/io/appium/java_client/pagefactory_tests/AndroidPageObjectTest.java @@ -0,0 +1,259 @@ +package io.appium.java_client.pagefactory_tests; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.MobileElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AndroidFindBys; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; +import io.appium.java_client.pagefactory.iOSFindBy; +import io.appium.java_client.pagefactory.iOSFindBys; +import io.appium.java_client.remote.MobileCapabilityType; + +import java.io.File; +import java.net.URL; +import java.util.List; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +public class AndroidPageObjectTest { + + private AppiumDriver driver; + @FindBy(className = "android.widget.TextView") + private List textVieWs; + + @AndroidFindBy(className = "android.widget.TextView") + private List androidTextViews; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private List iosTextViews; + + @iOSFindBy(uiAutomator = ".elements()[0]") + @AndroidFindBy(className = "android.widget.TextView") + private List androidOriOsTextViews; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private List androidUIAutomatorViews; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private List mobileElementViews; + + @FindBy(className = "android.widget.TextView") + private List mobiletextVieWs; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private List remoteElementViews; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(className = "android.widget.TextView") + }) + private List chainElementViews; + + @iOSFindBys({@iOSFindBy(uiAutomator = ".elements()[0]"), + @iOSFindBy(xpath = "//someElement")}) + private List iosChainTextViews; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(id = "android:id/text1") + }) + @iOSFindBys({@iOSFindBy(uiAutomator = ".elements()[0]"), + @iOSFindBy(xpath = "//someElement")}) + private List chainAndroidOrIOSUIAutomatorViews; + + + @FindBy(id = "android:id/text1") + private WebElement textView; + + @AndroidFindBy(className = "android.widget.TextView") + private WebElement androidTextView; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private WebElement iosTextView; + + @AndroidFindBy(className = "android.widget.TextView") + @iOSFindBy(uiAutomator = ".elements()[0]") + private WebElement androidOriOsTextView; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private WebElement androidUIAutomatorView; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private MobileElement mobileElementView; + + @FindBy(className = "android.widget.TextView") + private MobileElement mobiletextVieW; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private RemoteWebElement remotetextVieW; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(className = "android.widget.TextView") + }) + private WebElement chainElementView; + + @iOSFindBys({@iOSFindBy(uiAutomator = ".elements()[0]"), + @iOSFindBy(xpath = "//someElement")}) + private WebElement iosChainTextView; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(id = "android:id/text1") + }) + @iOSFindBys({@iOSFindBy(uiAutomator = ".elements()[0]"), + @iOSFindBy(xpath = "//someElement")}) + private WebElement chainAndroidOrIOSUIAutomatorView; + + @Before + public void setUp() throws Exception { + File appDir = new File("src/test/java/io/appium/java_client"); + File app = new File(appDir, "ApiDemos-debug.apk"); + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, ""); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android"); + capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); + driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); + + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + @After + public void tearDown() throws Exception { + driver.quit(); + } + + @Test + public void findByElementsTest() { + Assert.assertNotEquals(0, textVieWs.size()); + } + + @Test + public void findByElementTest() { + Assert.assertNotEquals(null, textView.getAttribute("text")); + } + + + @Test + public void androidFindByElementsTest(){ + Assert.assertNotEquals(0, androidTextViews.size()); + } + + @Test + public void androidFindByElementTest(){ + Assert.assertNotEquals(null, androidTextView.getAttribute("text")); + } + + @Test + public void checkThatElementsWereNotFoundByIOSUIAutomator(){ + Assert.assertEquals(0, iosTextViews.size()); + } + + @Test + public void checkThatElementWasNotFoundByIOSUIAutomator(){ + NoSuchElementException nsee = null; + try{ + iosTextView.getAttribute("text"); + } + catch (Exception e){ + nsee = (NoSuchElementException) e; + } + Assert.assertNotNull(nsee); + } + + @Test + public void androidOrIOSFindByElementsTest(){ + Assert.assertNotEquals(0, androidOriOsTextViews.size()); + } + + @Test + public void androidOrIOSFindByElementTest(){ + Assert.assertNotEquals(null, androidOriOsTextView.getAttribute("text")); + } + + @Test + public void androidFindByUIAutomatorElementsTest(){ + Assert.assertNotEquals(0, androidUIAutomatorViews.size()); + } + + @Test + public void androidFindByUIAutomatorElementTest(){ + Assert.assertNotEquals(null, androidUIAutomatorView.getAttribute("text")); + } + + @Test + public void areMobileElementsTest(){ + Assert.assertNotEquals(0, mobileElementViews.size()); + } + + @Test + public void isMobileElementTest(){ + Assert.assertNotEquals(null, mobileElementView.getAttribute("text")); + } + + @Test + public void areMobileElements_FindByTest(){ + Assert.assertNotEquals(0, mobiletextVieWs.size()); + } + + @Test + public void isMobileElement_FindByTest(){ + Assert.assertNotEquals(null, mobiletextVieW.getAttribute("text")); + } + + @Test + public void areRemoteElementsTest(){ + Assert.assertNotEquals(0, remoteElementViews.size()); + } + + @Test + public void isRemoteElementTest(){ + Assert.assertNotEquals(null, remotetextVieW.getAttribute("text")); + } + + @Test + public void androidChainSearchElementsTest(){ + Assert.assertNotEquals(0, chainElementViews.size()); + } + + @Test + public void androidChainSearchElementTest(){ + Assert.assertNotEquals(null, chainElementView.getAttribute("text")); + } + + @Test + public void checkThatElementsWereNotFoundByIOSUIAutomator_Chain(){ + Assert.assertEquals(0, iosChainTextViews.size()); + } + + @Test + public void checkThatElementWasNotFoundByIOSUIAutomator_Chain(){ + NoSuchElementException nsee = null; + try{ + iosChainTextView.getAttribute("text"); + } + catch (Exception e){ + nsee = (NoSuchElementException) e; + } + Assert.assertNotNull(nsee); + } + + @Test + public void androidOrIOSFindByElementsTest_ChainSearches(){ + Assert.assertNotEquals(0, chainAndroidOrIOSUIAutomatorViews.size()); + } + + @Test + public void androidOrIOSFindByElementTest_ChainSearches(){ + Assert.assertNotEquals(null, chainAndroidOrIOSUIAutomatorView.getAttribute("text")); + } +} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/BrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/BrowserCompatibilityTest.java new file mode 100644 index 000000000..10ab92c76 --- /dev/null +++ b/src/test/java/io/appium/java_client/pagefactory_tests/BrowserCompatibilityTest.java @@ -0,0 +1,216 @@ +package io.appium.java_client.pagefactory_tests; + +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AndroidFindBys; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; +import io.appium.java_client.pagefactory.iOSFindBy; +import io.appium.java_client.pagefactory.iOSFindBys; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.Platform; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeDriverService; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.ie.InternetExplorerDriver; +import org.openqa.selenium.ie.InternetExplorerDriverService; +import org.openqa.selenium.safari.SafariDriver; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.FindBys; +import org.openqa.selenium.support.PageFactory; +import org.openqa.selenium.remote.RemoteWebElement; + +public class BrowserCompatibilityTest { + + private static enum AvailableDrivers { + FIREFOX(FirefoxDriver.class, new ArrayList() { + private static final long serialVersionUID = 1L; + { + add(Platform.WINDOWS); + add(Platform.MAC); + } + + }, new HashMap(), null), CHROME(ChromeDriver.class, + new ArrayList() { + private static final long serialVersionUID = 1L; + { + add(Platform.WINDOWS); + add(Platform.MAC); + } + + }, new HashMap() { + private static final long serialVersionUID = 1L; + + { + put(Platform.WINDOWS, + new File( + "src/test/java/io/appium/java_client/pagefactory_tests/chromedriver.exe")); + put(Platform.MAC, + new File( + "src/test/java/io/appium/java_client/pagefactory_tests/chromedriver")); + } + }, ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY), + INTERNET_EXPLORER( + InternetExplorerDriver.class, new ArrayList() { + private static final long serialVersionUID = 1L; + { + add(Platform.WINDOWS); + } + }, new HashMap() { + private static final long serialVersionUID = 1L; + + { + put(Platform.WINDOWS, + new File( + "src/test/java/io/appium/java_client/pagefactory_tests/IEDriverServer.exe")); + } + }, InternetExplorerDriverService.IE_DRIVER_EXE_PROPERTY), SAFARI( + SafariDriver.class, new ArrayList() { + private static final long serialVersionUID = 1L; + { + add(Platform.MAC); + } + + }, new HashMap(), null); + // TODO Linux can be added if is necessary + + private final Class driverClazz; + private final List platformCompatible; + private final Map serviceBinaries; + private final String propertyName; + + private AvailableDrivers(Class driverClazz, + List platformCompatible, + Map serviceBinaries, String property) { + this.driverClazz = driverClazz; + this.platformCompatible = platformCompatible; + this.serviceBinaries = serviceBinaries; + this.propertyName = property; + } + + private static AvailableDrivers getAvailableDriver( + Class driverClass, Platform p) { + AvailableDrivers[] availableDrivers = AvailableDrivers.values(); + for (AvailableDrivers availableDriver : availableDrivers) { + if (!availableDriver.driverClazz.equals(driverClass)){ + continue; + } + + for (Platform compatible: availableDriver.platformCompatible){ + if (p.is(compatible)){ + return availableDriver; + } + } + } + return null; + } + + private void setSystemProperty(Platform p) { + Platform platform = null; + for (Platform compatible: platformCompatible){ + if (p.is(compatible)){ + platform = compatible; + break; + } + } + + if ((platform != null) && (propertyName != null) + && (serviceBinaries.get(platform) != null)) { + System.setProperty(propertyName, serviceBinaries.get(platform) + .getAbsolutePath()); + } + } + } + + + public void setUp(Class driverClass) { + AvailableDrivers availableDriver = AvailableDrivers.getAvailableDriver(driverClass, current); + if (availableDriver != null){ + availableDriver.setSystemProperty(current); + } + } + + private final Platform current = Platform.getCurrent(); + private final long IMPLICITLY_WAIT = 15; + + @FindBy(name = "q") + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/someId\")") + @iOSFindBy(uiAutomator = ".elements()[0]") + private WebElement searchTextField; + + @AndroidFindBys({ + @AndroidFindBy(className = "someClass"), + @AndroidFindBy(xpath = "//someTag")}) + @iOSFindBys({ + @iOSFindBy(xpath = "//selector[1]"), + @iOSFindBy(xpath = "//someTag")}) + @FindBy(id="gbqfb") + private RemoteWebElement searchButton; + + @AndroidFindBy(className = "someClass") + @iOSFindBys({ + @iOSFindBy(xpath = "//selector[1]"), + @iOSFindBy(xpath = "//someTag")}) + @FindBys({@FindBy(className = "r"), @FindBy(tagName = "a")}) + private List foundLinks; + + private void test(WebDriver driver){ + try { + PageFactory.initElements(new AppiumFieldDecorator(driver, IMPLICITLY_WAIT, TimeUnit.SECONDS), this); + driver.get("https://www.google.com"); + + searchTextField.sendKeys("Hello"); + searchButton.click(); + Assert.assertNotEquals(0, foundLinks.size()); + searchTextField.clear(); + searchTextField.sendKeys("Hello, Appium!"); + searchButton.click(); + Assert.assertNotEquals(0, foundLinks.size()); + } finally { + driver.quit(); + } + } + + @Test + public void fireFoxTest() { + if (AvailableDrivers.getAvailableDriver(FirefoxDriver.class, current)!=null){ + setUp(FirefoxDriver.class); + test(new FirefoxDriver()); + } + } + + @Test + public void chromeTest() { + System.getProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY); + if (AvailableDrivers.getAvailableDriver(ChromeDriver.class, current)!=null){ + setUp(ChromeDriver.class); + test(new ChromeDriver()); + } + } + + @Test + public void ieTest() { + if (AvailableDrivers.getAvailableDriver(InternetExplorerDriver.class, current)!=null){ + setUp(InternetExplorerDriver.class); + test(new InternetExplorerDriver()); + } + } + + @Test + public void safariTest() { + if (AvailableDrivers.getAvailableDriver(SafariDriver.class, current)!=null){ + setUp(SafariDriver.class); + test(new SafariDriver()); + } + } + +} diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/IEDriverServer.exe b/src/test/java/io/appium/java_client/pagefactory_tests/IEDriverServer.exe new file mode 100644 index 000000000..415561f9b Binary files /dev/null and b/src/test/java/io/appium/java_client/pagefactory_tests/IEDriverServer.exe differ diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver b/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver new file mode 100755 index 000000000..d5eeb48ba Binary files /dev/null and b/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver differ diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver.exe b/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver.exe new file mode 100644 index 000000000..c295cc8ae Binary files /dev/null and b/src/test/java/io/appium/java_client/pagefactory_tests/chromedriver.exe differ 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 new file mode 100644 index 000000000..e9d228f2c --- /dev/null +++ b/src/test/java/io/appium/java_client/pagefactory_tests/iOSPageObjectTest.java @@ -0,0 +1,216 @@ +package io.appium.java_client.pagefactory_tests; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.MobileElement; +import io.appium.java_client.pagefactory.AndroidFindBy; +import io.appium.java_client.pagefactory.AndroidFindBys; +import io.appium.java_client.pagefactory.AppiumFieldDecorator; +import io.appium.java_client.pagefactory.iOSFindBy; +import io.appium.java_client.remote.MobileCapabilityType; + +import java.io.File; +import java.net.URL; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebElement; +import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.PageFactory; + +public class iOSPageObjectTest { + + private AppiumDriver driver; + @FindBy(className = "UIAButton") + private List uiButtons; + + @FindBy(className = "UIAButton") + private List iosUIButtons; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private List iosUIAutomatorButtons; + + @iOSFindBy(uiAutomator = ".elements()[0]") + @AndroidFindBy(className = "android.widget.TextView") + private List androidOriOsTextViews; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private List androidUIAutomatorViews; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private List mobileButtons; + + @FindBy(className = "UIAButton") + private List mobiletFindBy_Buttons; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private List remoteElementViews; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(className = "android.widget.TextView") + }) + private List chainElementViews; + + + @FindBy(className = "UIAButton") + private WebElement uiButton; + + @FindBy(className = "UIAButton") + private WebElement iosUIButton; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private WebElement iosUIAutomatorButton; + + @AndroidFindBy(className = "android.widget.TextView") + @iOSFindBy(uiAutomator = ".elements()[0]") + private WebElement androidOriOsTextView; + + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/text1\")") + private WebElement androidUIAutomatorView; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private MobileElement mobileButton; + + @FindBy(className = "UIAButton") + private MobileElement mobiletFindBy_Button; + + @iOSFindBy(uiAutomator = ".elements()[0]") + private RemoteWebElement remotetextVieW; + + @AndroidFindBys({ + @AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"android:id/list\")"), + @AndroidFindBy(className = "android.widget.TextView") + }) + private WebElement chainElementView; + + @Before + public void setUp() throws Exception { + File appDir = new File("src/test/java/io/appium/java_client"); + File app = new File(appDir, "TestApp.app.zip"); + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, ""); + capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.1"); + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS"); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator"); + capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); + driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); + + PageFactory.initElements(new AppiumFieldDecorator(driver), this); + } + + @After + public void tearDown() throws Exception { + driver.quit(); + } + + @Test + public void findByElementsTest() { + Assert.assertNotEquals(0, uiButtons.size()); + } + + @Test + public void findByElementTest() { + Assert.assertNotEquals(null, uiButton.getText()); + } + + + @Test + public void iOSFindByElementsTest(){ + Assert.assertNotEquals(0, iosUIButtons.size()); + } + + @Test + public void iosFindByElementTest(){ + Assert.assertNotEquals(null, iosUIButton.getText()); + } + + @Test + public void checkThatElementsWereNotFoundByAndroidUIAutomator(){ + Assert.assertEquals(0, androidUIAutomatorViews.size()); + } + + @Test + public void checkThatElementWasNotFoundByAndroidUIAutomator(){ + NoSuchElementException nsee = null; + try{ + androidUIAutomatorView.getText(); + } + catch (Exception e){ + nsee = (NoSuchElementException) e; + } + Assert.assertNotNull(nsee); + } + + @Test + public void androidOrIOSFindByElementsTest(){ + Assert.assertNotEquals(0, androidOriOsTextViews.size()); + } + + @Test + public void androidOrIOSFindByElementTest(){ + Assert.assertNotEquals(null, androidOriOsTextView.getText()); + } + + @Test + public void iOSFindByUIAutomatorElementsTest(){ + Assert.assertNotEquals(0, iosUIAutomatorButtons.size()); + } + + @Test + public void iOSFindByUIAutomatorElementTest(){ + Assert.assertNotEquals(null, iosUIAutomatorButton.getText()); + } + + @Test + public void areMobileElementsTest(){ + Assert.assertNotEquals(0, mobileButtons.size()); + } + + @Test + public void isMobileElementTest(){ + Assert.assertNotEquals(null, mobileButton.getText()); + } + + @Test + public void areMobileElements_FindByTest(){ + Assert.assertNotEquals(0, mobiletFindBy_Buttons.size()); + } + + @Test + public void isMobileElement_FindByTest(){ + Assert.assertNotEquals(null, mobiletFindBy_Button.getText()); + } + + @Test + public void areRemoteElementsTest(){ + Assert.assertNotEquals(0, remoteElementViews.size()); + } + + @Test + public void isRemoteElementTest(){ + Assert.assertNotEquals(null, remotetextVieW.getText()); + } + + @Test + public void checkThatElementsWereNotFoundByAndroidUIAutomator_Chain(){ + Assert.assertEquals(0, chainElementViews.size()); + } + + @Test + public void checkThatElementWasNotFoundByAndroidUIAutomator_Chain(){ + NoSuchElementException nsee = null; + try{ + chainElementView.getText(); + } + catch (Exception e){ + nsee = (NoSuchElementException) e; + } + Assert.assertNotNull(nsee); + } +}