diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java index ae31ff484..c272bd51a 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -51,7 +51,7 @@ public List apply(By by) { private WebElement cachedElement; private List cachedElementList; - private final TimeOutContainer timeOutContainer; + private final TimeOutDuration timeOutDuration; /** * Creates a new mobile element locator. It instantiates {@link WebElement} @@ -64,7 +64,7 @@ public List apply(By by) { * The field on the Page Object that will hold the located value */ AppiumElementLocator(SearchContext searchContext, Field field, - TimeOutContainer timeOutContainer) { + TimeOutDuration timeOutDuration) { this.searchContext = searchContext; // All known webdrivers implement HasCapabilities Capabilities capabilities = ((HasCapabilities) WebDriverUnpackUtility. @@ -78,7 +78,12 @@ public List apply(By by) { AppiumAnnotations annotations = new AppiumAnnotations(field, platform, automation); - this.timeOutContainer = timeOutContainer; + if (field.isAnnotationPresent(WithTimeout.class)){ + WithTimeout withTimeout = field.getAnnotation(WithTimeout.class); + this.timeOutDuration = new TimeOutDuration(withTimeout.time(), withTimeout.unit()); + } + else + this.timeOutDuration = timeOutDuration; shouldCache = annotations.isLookupCached(); by = annotations.buildBy(); } @@ -98,14 +103,14 @@ private List waitFor() { try { changeImplicitlyWaitTimeOut(0, TimeUnit.SECONDS); FluentWait wait = new FluentWait(by); - wait.withTimeout(timeOutContainer.getTimeValue(), - timeOutContainer.getTimeUnitValue()); + wait.withTimeout(timeOutDuration.getTime(), + timeOutDuration.getTimeUnit()); return wait.until(new WaitingFunction(searchContext)); } catch (TimeoutException e) { return new ArrayList(); } finally { - changeImplicitlyWaitTimeOut(timeOutContainer.getTimeValue(), - timeOutContainer.getTimeUnitValue()); + changeImplicitlyWaitTimeOut(timeOutDuration.getTime(), + timeOutDuration.getTimeUnit()); } } diff --git a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java index b46e484c6..7de6bea08 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -1,33 +1,27 @@ 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 { +class AppiumElementLocatorFactory implements ElementLocatorFactory { private final SearchContext searchContext; - private final TimeOutContainer timeOutContainer; + private final TimeOutDuration timeOutDuration; public AppiumElementLocatorFactory(SearchContext searchContext, - long implicitlyWaitTimeOut, TimeUnit timeUnit) { + TimeOutDuration timeOutDuration) { this.searchContext = searchContext; - this.timeOutContainer = new TimeOutContainer(implicitlyWaitTimeOut, timeUnit); + this.timeOutDuration = timeOutDuration; } public AppiumElementLocatorFactory(SearchContext searchContext) { - this(searchContext, AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT, - AppiumFieldDecorator.DEFAULT_TIMEUNIT); + this(searchContext, new TimeOutDuration(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT, + AppiumFieldDecorator.DEFAULT_TIMEUNIT)); } public ElementLocator createLocator(Field field) { - return new AppiumElementLocator(searchContext, field, timeOutContainer); - } - - @Override - public void resetImplicitlyWaitTimeOut(long timeOut, TimeUnit timeUnit) { - timeOutContainer.resetImplicitlyWaitTimeOut(timeOut, timeUnit); + return new AppiumElementLocator(searchContext, field, timeOutDuration); } } 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 3371718f6..ac86d3763 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -1,6 +1,5 @@ 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; @@ -31,7 +30,7 @@ * {@link MobileElement}, {@link AndroidElement} and {@link IOSElement} are allowed * to use with this decorator */ -public class AppiumFieldDecorator implements FieldDecorator, ResetsImplicitlyWaitTimeOut { +public class AppiumFieldDecorator implements FieldDecorator { private static final List> availableElementClasses = new ArrayList>(){ @@ -66,8 +65,13 @@ public class AppiumFieldDecorator implements FieldDecorator, ResetsImplicitlyWai public AppiumFieldDecorator(SearchContext context, long implicitlyWaitTimeOut, TimeUnit timeUnit) { this.context = context; - factory = new AppiumElementLocatorFactory(this.context, implicitlyWaitTimeOut, timeUnit); + factory = new AppiumElementLocatorFactory(this.context, new TimeOutDuration(implicitlyWaitTimeOut, timeUnit)); } + + public AppiumFieldDecorator(SearchContext context, TimeOutDuration timeOutDuration) { + this.context = context; + factory = new AppiumElementLocatorFactory(this.context, timeOutDuration); + } public AppiumFieldDecorator(SearchContext context) { this.context = context; @@ -150,9 +154,4 @@ private List proxyForListLocator( 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/ResetsImplicitlyWaitTimeOut.java b/src/main/java/io/appium/java_client/pagefactory/ResetsImplicitlyWaitTimeOut.java deleted file mode 100644 index 8b676f231..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/ResetsImplicitlyWaitTimeOut.java +++ /dev/null @@ -1,7 +0,0 @@ -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/TimeOutContainer.java b/src/main/java/io/appium/java_client/pagefactory/TimeOutContainer.java deleted file mode 100644 index 3697c792f..000000000 --- a/src/main/java/io/appium/java_client/pagefactory/TimeOutContainer.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.appium.java_client.pagefactory; - -import java.util.concurrent.TimeUnit; - -/** - * Instances of this class contain - * implicit time outs which are used by {@link AppiumElementLocator} - */ -class TimeOutContainer implements ResetsImplicitlyWaitTimeOut{ - private long timeOutValue; - private TimeUnit timeUnit; - - TimeOutContainer(long initialTimeOutValue, TimeUnit initialTimeUnit){ - this.timeOutValue = initialTimeOutValue; - this.timeUnit = initialTimeUnit; - } - - @Override - public void resetImplicitlyWaitTimeOut(long timeOut, TimeUnit timeUnit) { - this.timeOutValue = timeOut; - this.timeUnit = timeUnit; - } - - long getTimeValue(){ - return timeOutValue; - } - - TimeUnit getTimeUnitValue(){ - return timeUnit; - } - -} diff --git a/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java b/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java new file mode 100644 index 000000000..c2f432b75 --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java @@ -0,0 +1,46 @@ +package io.appium.java_client.pagefactory; + +import java.util.concurrent.TimeUnit; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Represents an duration of waiting for element rendering. + */ +public class TimeOutDuration { + + private long time; + private TimeUnit unit; + + /** + * @param time The amount of time. + * @param unit The unit of time. + */ + public TimeOutDuration(long time, TimeUnit unit) { + setTime(time, unit); + } + + public long getTime(){ + return time; + } + + public TimeUnit getTimeUnit(){ + return unit; + } + + public void setTime(long newTime){ + checkArgument(newTime >= 0, "Duration < 0: %d", newTime); + time = newTime; + } + + public void setTime(TimeUnit newTimeUnit){ + checkNotNull(newTimeUnit); + unit = newTimeUnit; + } + + public void setTime(long newTime, TimeUnit newTimeUnit){ + setTime(newTime); + setTime(newTimeUnit); + } +} diff --git a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java new file mode 100644 index 000000000..a7ce797bd --- /dev/null +++ b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java @@ -0,0 +1,19 @@ +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; +import java.util.concurrent.TimeUnit; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +/** + This annotation is used when some element waits for time + that differs from defined by default + */ +public @interface WithTimeout { + long time(); + TimeUnit unit(); +} 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 61028ff68..dd0cc7253 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 @@ -18,7 +18,6 @@ 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; @@ -343,7 +342,8 @@ public void areTouchableElements(){ @Test public void isTheFieldAndroidElement(){ - AndroidElement androidElement = (AndroidElement) mobiletextVieW; //declared as MobileElement + @SuppressWarnings("unused") + 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/IOSfMobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/IOSfMobileBrowserCompatibilityTest.java index 1aa1938d7..59025ac94 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/IOSfMobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/IOSfMobileBrowserCompatibilityTest.java @@ -51,7 +51,7 @@ public void setUp() throws Exception { capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.SAFARI); capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "7.1"); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone Simulator"); - driver = new IOSDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); + driver = new IOSDriver<>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); } diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeOutResetTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeOutResetTest.java index 0b35df625..47b6f647c 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeOutResetTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeOutResetTest.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import io.appium.java_client.pagefactory.TimeOutDuration; +import io.appium.java_client.pagefactory.WithTimeout; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -25,14 +27,20 @@ public class TimeOutResetTest { @FindAll({@FindBy(className = "ClassWhichDoesNotExist"), @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) private List stubElements; - private AppiumFieldDecorator afd; + + @WithTimeout(time = 5, unit = TimeUnit.SECONDS) + @FindAll({@FindBy(className = "ClassWhichDoesNotExist"), + @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) + private List stubElements2; + + private TimeOutDuration timeOutDuration; @Before public void setUp() throws Exception { driver = new FirefoxDriver(); - afd = new AppiumFieldDecorator(driver); - - PageFactory.initElements(afd, this); + timeOutDuration = new TimeOutDuration(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT, + AppiumFieldDecorator.DEFAULT_TIMEUNIT); + PageFactory.initElements(new AppiumFieldDecorator(driver, timeOutDuration), this); } @After @@ -56,7 +64,7 @@ private static void checkTimeDifference(long etalonTime, } } - private long getBenchMark() { + private long getBenchMark(List stubElements) { long startMark = Calendar.getInstance().getTimeInMillis(); stubElements.size(); long endMark = Calendar.getInstance().getTimeInMillis(); @@ -66,20 +74,45 @@ private long getBenchMark() { @Test public void test() { checkTimeDifference(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT, AppiumFieldDecorator.DEFAULT_TIMEUNIT, - getBenchMark()); + getBenchMark(stubElements)); System.out.println(String.valueOf(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT) + " " + AppiumFieldDecorator.DEFAULT_TIMEUNIT.toString() + ": Fine"); - afd.resetImplicitlyWaitTimeOut(15500000, TimeUnit.MICROSECONDS); - checkTimeDifference(15500000, TimeUnit.MICROSECONDS, getBenchMark()); + timeOutDuration.setTime(15500000, TimeUnit.MICROSECONDS); + checkTimeDifference(15500000, TimeUnit.MICROSECONDS, getBenchMark(stubElements)); System.out.println("Change time: " + String.valueOf(15500000) + " " + TimeUnit.MICROSECONDS.toString() + ": Fine"); - afd.resetImplicitlyWaitTimeOut(3, TimeUnit.SECONDS); - checkTimeDifference(3, TimeUnit.SECONDS, getBenchMark()); + timeOutDuration.setTime(3, TimeUnit.SECONDS); + checkTimeDifference(3, TimeUnit.SECONDS, getBenchMark(stubElements)); System.out.println("Change time: " + String.valueOf(3) + " " + TimeUnit.SECONDS.toString() + ": Fine"); } + @Test + public void test2() { + checkTimeDifference(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT, AppiumFieldDecorator.DEFAULT_TIMEUNIT, + getBenchMark(stubElements)); + System.out.println(String.valueOf(AppiumFieldDecorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT) + + " " + AppiumFieldDecorator.DEFAULT_TIMEUNIT.toString() + ": Fine"); + + checkTimeDifference(5, TimeUnit.SECONDS, + getBenchMark(stubElements2)); + System.out.println(String.valueOf(5) + + " " + TimeUnit.SECONDS.toString() + ": Fine"); + + + timeOutDuration.setTime(15500000, TimeUnit.MICROSECONDS); + checkTimeDifference(15500000, TimeUnit.MICROSECONDS, getBenchMark(stubElements)); + System.out.println("Change time: " + String.valueOf(15500000) + " " + + TimeUnit.MICROSECONDS.toString() + ": Fine"); + + checkTimeDifference(5, TimeUnit.SECONDS, + getBenchMark(stubElements2)); + System.out.println(String.valueOf(5) + + " " + TimeUnit.SECONDS.toString() + ": Fine"); + + } + } 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 a03d204ee..2417bbc6f 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 @@ -2,7 +2,6 @@ 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; @@ -275,7 +274,8 @@ public void areTouchAbleElements(){ @Test public void isTheFieldIOSElement(){ - IOSElement iOSElement = (IOSElement) mobileButton; //declared as MobileElement + @SuppressWarnings("unused") + IOSElement iOSElement = (IOSElement) mobileButton; //declared as MobileElement iOSElement = (IOSElement) iosUIAutomatorButton; //declared as WebElement iOSElement = (IOSElement) remotetextVieW; //declared as RemoteWebElement iOSElement = (IOSElement) touchableButton; //declared as TouchABLEElement