diff --git a/build.gradle b/build.gradle index b0e0637b2..b26c8eec8 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ compileJava { ] } -ext.seleniumVersion = '3.9.1' +ext.seleniumVersion = '3.11.0' dependencies { compile ("org.seleniumhq.selenium:selenium-java:${seleniumVersion}") { diff --git a/src/main/java/io/appium/java_client/AppiumFluentWait.java b/src/main/java/io/appium/java_client/AppiumFluentWait.java index 635835aad..0f832b7f8 100644 --- a/src/main/java/io/appium/java_client/AppiumFluentWait.java +++ b/src/main/java/io/appium/java_client/AppiumFluentWait.java @@ -16,18 +16,19 @@ package io.appium.java_client; +import static java.time.Duration.ofMillis; + import com.google.common.base.Throwables; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.support.ui.Clock; -import org.openqa.selenium.support.ui.Duration; import org.openqa.selenium.support.ui.FluentWait; import org.openqa.selenium.support.ui.Sleeper; import java.lang.reflect.Field; +import java.time.Duration; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; @@ -167,7 +168,7 @@ protected T getInput() { /** * Sets the strategy for polling. The default strategy is null, * which means, that polling interval is always a constant value and is - * set by {@link #pollingEvery(long, TimeUnit)} method. Otherwise the value set by that + * set by {@link #pollingEvery(Duration)} method. Otherwise the value set by that * method might be just a helper to calculate the actual interval. * Although, by setting an alternative polling strategy you may flexibly control * the duration of this interval for each polling round. @@ -228,7 +229,7 @@ public AppiumFluentWait withPollingStrategy(Function @Override public V until(Function isTrue) { final long start = getClock().now(); - final long end = getClock().laterBy(getTimeout().in(TimeUnit.MILLISECONDS)); + final long end = getClock().laterBy(getTimeout().toMillis()); long iterationNumber = 1; Throwable lastException; while (true) { @@ -254,7 +255,7 @@ public V until(Function isTrue) { String timeoutMessage = String.format( "Expected condition failed: %s (tried for %d second(s) with %s interval)", message == null ? "waiting for " + isTrue : message, - getTimeout().in(TimeUnit.SECONDS), getInterval()); + getTimeout().getSeconds(), getInterval()); throw timeoutException(timeoutMessage, lastException); } @@ -262,7 +263,7 @@ public V until(Function isTrue) { Duration interval = getInterval(); if (pollingStrategy != null) { final IterationInfo info = new IterationInfo(iterationNumber, - new Duration(getClock().now() - start, TimeUnit.MILLISECONDS), getTimeout(), + ofMillis(getClock().now() - start), getTimeout(), interval); interval = pollingStrategy.apply(info); } diff --git a/src/main/java/io/appium/java_client/events/DefaultAspect.java b/src/main/java/io/appium/java_client/events/DefaultAspect.java index 0534f5e2e..b6a93fd5e 100644 --- a/src/main/java/io/appium/java_client/events/DefaultAspect.java +++ b/src/main/java/io/appium/java_client/events/DefaultAspect.java @@ -83,6 +83,8 @@ class DefaultAspect { + ".rotate(..))"; private static final String EXECUTION_CONTEXT = "execution(* org.openqa.selenium.ContextAware." + "context(..))"; + private static final String EXECUTION_SWITCH_TO_WINDOW = "execution(* org.openqa.selenium.WebDriver.TargetLocator" + + ".window(..))"; private static final String AROUND = "execution(* org.openqa.selenium.WebDriver.*(..)) || " + "execution(* org.openqa.selenium.WebElement.*(..)) || " + "execution(* org.openqa.selenium.WebDriver.Navigation.*(..)) || " @@ -463,6 +465,24 @@ public void afterMaximization(JoinPoint joinPoint) throws Throwable { } } + @Before(EXECUTION_SWITCH_TO_WINDOW) + public void beforeSwitchToWindow(JoinPoint joinPoint) throws Throwable { + try { + listener.beforeSwitchToWindow(castArgument(joinPoint, 0), driver); + } catch (Throwable t) { + throw getRootCause(t); + } + } + + @After(EXECUTION_SWITCH_TO_WINDOW) + public void afterSwitchToWindow(JoinPoint joinPoint) throws Throwable { + try { + listener.afterSwitchToWindow(castArgument(joinPoint, 0), driver); + } catch (Throwable t) { + throw getRootCause(t); + } + } + @Before(EXECUTION_ROTATE) public void beforeRotation(JoinPoint joinPoint) throws Throwable { try { diff --git a/src/main/java/io/appium/java_client/events/DefaultListener.java b/src/main/java/io/appium/java_client/events/DefaultListener.java index 0ad0050da..72f31b835 100644 --- a/src/main/java/io/appium/java_client/events/DefaultListener.java +++ b/src/main/java/io/appium/java_client/events/DefaultListener.java @@ -209,6 +209,16 @@ public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point ((WindowEventListener) dispatcher).afterWindowIsMaximized(driver, window); } + @Override + public void beforeSwitchToWindow(String windowName, WebDriver driver) { + ((WebDriverEventListener) dispatcher).beforeSwitchToWindow(windowName, driver); + } + + @Override + public void afterSwitchToWindow(String windowName, WebDriver driver) { + ((WebDriverEventListener) dispatcher).afterSwitchToWindow(windowName, driver); + } + @Override public void beforeSwitchingToContext(WebDriver driver, String context) { ((ContextEventListener) dispatcher).beforeSwitchingToContext(driver, context); } diff --git a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java b/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java index 28c4e9160..6d7347944 100644 --- a/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java +++ b/src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java @@ -78,4 +78,20 @@ void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, * @param window is the window which has been maximized */ void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window); + + /** + * This action will be performed each time before + * {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}. + * + * @param driver WebDriver + */ + void beforeSwitchToWindow(String windowName, WebDriver driver); + + /** + * This action will be performed each time after + * {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}. + * + * @param driver WebDriver + */ + void afterSwitchToWindow(String windowName, WebDriver driver); } 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 cef9a3e77..ecbde1b6c 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java @@ -21,6 +21,8 @@ import static io.appium.java_client.pagefactory.ThrowableUtil.isStaleElementReferenceException; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType; import static java.lang.String.format; +import static java.time.Duration.ofMillis; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import io.appium.java_client.pagefactory.bys.ContentMappedBy; import io.appium.java_client.pagefactory.locator.CacheableLocator; @@ -34,6 +36,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.FluentWait; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.function.Function; @@ -45,7 +48,7 @@ class AppiumElementLocator implements CacheableLocator { private final boolean shouldCache; private final By by; - private final TimeOutDuration duration; + private final Duration duration; private final SearchContext searchContext; private WebElement cachedElement; private List cachedElementList; @@ -59,11 +62,31 @@ class AppiumElementLocator implements CacheableLocator { * @param by a By locator strategy * @param shouldCache is the flag that signalizes that elements which * are found once should be cached - * @param duration is a POJO which contains timeout parameters for the element to be searched + * @param duration is a POJO which contains timeout parameters for the element to be found + * @deprecated This constructor is going to be removed. Use {@link #AppiumElementLocator(SearchContext, By, + * boolean, Duration)} instead. */ - + @Deprecated public AppiumElementLocator(SearchContext searchContext, By by, boolean shouldCache, TimeOutDuration duration) { + this(searchContext, by, shouldCache, + ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit()))); + } + + /** + * 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 by a By locator strategy + * @param shouldCache is the flag that signalizes that elements which + * are found once should be cached + * @param duration timeout parameter for the element to be found + */ + + public AppiumElementLocator(SearchContext searchContext, By by, boolean shouldCache, + Duration duration) { this.searchContext = searchContext; this.shouldCache = shouldCache; this.duration = duration; @@ -94,7 +117,7 @@ private T waitFor(Supplier supplier) { try { FluentWait> wait = new FluentWait<>(supplier) .ignoring(NoSuchElementException.class); - wait.withTimeout(duration.getTime(), duration.getTimeUnit()); + wait.withTimeout(duration); return wait.until(function); } catch (TimeoutException e) { if (function.foundStaleElementReferenceException != null) { 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 48c7ecb59..a7b99d841 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java @@ -16,7 +16,10 @@ package io.appium.java_client.pagefactory; +import static io.appium.java_client.pagefactory.WithTimeout.DurationBuilder.build; +import static java.time.Duration.ofMillis; import static java.util.Optional.ofNullable; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder; import io.appium.java_client.pagefactory.locator.CacheableElementLocatorFactory; @@ -26,23 +29,38 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; +import java.time.Duration; import javax.annotation.Nullable; public class AppiumElementLocatorFactory implements CacheableElementLocatorFactory { private final SearchContext searchContext; - private final TimeOutDuration duration; + private final Duration duration; private final AppiumByBuilder builder; /** * Creates a new mobile element locator factory. * * @param searchContext The context to use when finding the element - * @param duration is a POJO which contains timeout parameters for the element to be searched + * @param duration is a POJO which contains timeout parameters for the elements to be found * @param builder is handler of Appium-specific page object annotations + * @deprecated This constructor is going to be + * removed. Use {@link #AppiumElementLocatorFactory(SearchContext, Duration, AppiumByBuilder)} instead. */ - + @Deprecated public AppiumElementLocatorFactory(SearchContext searchContext, TimeOutDuration duration, AppiumByBuilder builder) { + this(searchContext, ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit())), builder); + } + + /** + * Creates a new mobile element locator factory. + * + * @param searchContext The context to use when finding the element + * @param duration timeout parameters for the elements to be found + * @param builder is handler of Appium-specific page object annotations + */ + public AppiumElementLocatorFactory(SearchContext searchContext, Duration duration, + AppiumByBuilder builder) { this.searchContext = searchContext; this.duration = duration; this.builder = builder; @@ -53,10 +71,10 @@ public AppiumElementLocatorFactory(SearchContext searchContext, TimeOutDuration } @Override public @Nullable CacheableLocator createLocator(AnnotatedElement annotatedElement) { - TimeOutDuration customDuration; + Duration customDuration; if (annotatedElement.isAnnotationPresent(WithTimeout.class)) { WithTimeout withTimeout = annotatedElement.getAnnotation(WithTimeout.class); - customDuration = new TimeOutDuration(withTimeout.time(), withTimeout.unit()); + customDuration = build(withTimeout); } else { customDuration = duration; } 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 4e6f40821..9aeeb8f47 100644 --- a/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java +++ b/src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java @@ -19,7 +19,10 @@ import static io.appium.java_client.internal.ElementMap.getElementClass; import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy; import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext; +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; import static java.util.Optional.ofNullable; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import com.google.common.collect.ImmutableList; @@ -42,6 +45,7 @@ import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -62,16 +66,20 @@ public class AppiumFieldDecorator implements FieldDecorator { private static final List> availableElementClasses = ImmutableList.of(WebElement.class, RemoteWebElement.class, MobileElement.class, AndroidElement.class, IOSElement.class, WindowsElement.class); - public static long DEFAULT_TIMEOUT = 1; - public static TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS; + public static final Duration DEFAULT_WAITING_TIMEOUT = ofSeconds(1); + @Deprecated + public static final long DEFAULT_TIMEOUT = 1; + @Deprecated + public static final TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS; private final WebDriver webDriver; private final DefaultFieldDecorator defaultElementFieldDecoracor; private final AppiumElementLocatorFactory widgetLocatorFactory; private final String platform; private final String automation; - private final TimeOutDuration duration; + private final Duration duration; + @Deprecated public AppiumFieldDecorator(SearchContext context, long timeout, TimeUnit timeUnit) { this(context, new TimeOutDuration(timeout, timeUnit)); @@ -84,8 +92,23 @@ public AppiumFieldDecorator(SearchContext context, long timeout, * It may be the instance of {@link WebDriver} or {@link WebElement} or * {@link Widget} or some other user's extension/implementation. * @param duration is a desired duration of the waiting for an element presence. + * @deprecated This constructor is going to be removed. Use {@link #AppiumFieldDecorator(SearchContext, Duration)} + * instead. */ + @Deprecated public AppiumFieldDecorator(SearchContext context, TimeOutDuration duration) { + this(context, ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit()))); + } + + /** + * Creates field decorator based on {@link SearchContext} and timeout {@code duration}. + * + * @param context is an instance of {@link SearchContext} + * It may be the instance of {@link WebDriver} or {@link WebElement} or + * {@link Widget} or some other user's extension/implementation. + * @param duration is a desired duration of the waiting for an element presence. + */ + public AppiumFieldDecorator(SearchContext context, Duration duration) { this.webDriver = unpackWebDriverFromSearchContext(context); HasSessionDetails hasSessionDetails = ofNullable(this.webDriver).map(webDriver -> { if (!HasSessionDetails.class.isAssignableFrom(webDriver.getClass())) { @@ -105,8 +128,8 @@ public AppiumFieldDecorator(SearchContext context, TimeOutDuration duration) { this.duration = duration; defaultElementFieldDecoracor = new DefaultFieldDecorator( - new AppiumElementLocatorFactory(context, duration, - new DefaultElementByBuilder(platform, automation))) { + new AppiumElementLocatorFactory(context, duration, + new DefaultElementByBuilder(platform, automation))) { @Override protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator) { return proxyForAnElement(locator); @@ -115,7 +138,7 @@ protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator @Override @SuppressWarnings("unchecked") protected List proxyForListLocator(ClassLoader ignored, - ElementLocator locator) { + ElementLocator locator) { ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator); return getEnhancedProxy(ArrayList.class, elementInterceptor); } @@ -142,11 +165,11 @@ protected List proxyForListLocator(ClassLoader ignored, }; widgetLocatorFactory = - new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation)); + new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation)); } public AppiumFieldDecorator(SearchContext context) { - this(context, DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT); + this(context, DEFAULT_WAITING_TIMEOUT); } /** diff --git a/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java b/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java index 4ec68861d..0af7aa2ee 100644 --- a/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java +++ b/src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java @@ -23,7 +23,11 @@ /** * Represents an duration of waiting for element rendering. + * + * @deprecated this class is going to be removed in favour of {@link java.time.Duration} + * usage. */ +@Deprecated public class TimeOutDuration { private long time; diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java index 37fb1c21e..747a9eadd 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetInterceptor.java @@ -30,6 +30,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.time.Duration; import java.util.HashMap; import java.util.Map; @@ -37,12 +38,12 @@ class WidgetInterceptor extends InterceptorOfASingleElement { private final Map> instantiationMap; private final Map cachedInstances = new HashMap<>(); - private final TimeOutDuration duration; + private final Duration duration; private WebElement cachedElement; WidgetInterceptor(CacheableLocator locator, WebDriver driver, WebElement cachedElement, Map> instantiationMap, - TimeOutDuration duration) { + Duration duration) { super(locator, driver); this.cachedElement = cachedElement; this.instantiationMap = instantiationMap; diff --git a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java index 9c752322a..580de7fb2 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java +++ b/src/main/java/io/appium/java_client/pagefactory/WidgetListInterceptor.java @@ -29,6 +29,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -38,13 +39,13 @@ class WidgetListInterceptor extends InterceptorOfAListOfElements { private final Map> instantiationMap; private final List cachedWidgets = new ArrayList<>(); private final Class declaredType; - private final TimeOutDuration duration; + private final Duration duration; private final WebDriver driver; private List cachedElements; WidgetListInterceptor(CacheableLocator locator, WebDriver driver, Map> instantiationMap, - Class declaredType, TimeOutDuration duration) { + Class declaredType, Duration duration) { super(locator); this.instantiationMap = instantiationMap; this.declaredType = declaredType; diff --git a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java index f20cd0997..c2d13133f 100644 --- a/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java +++ b/src/main/java/io/appium/java_client/pagefactory/WithTimeout.java @@ -16,10 +16,17 @@ package io.appium.java_client.pagefactory; +import static java.time.temporal.ChronoUnit.FOREVER; +import static java.time.temporal.ChronoUnit.MILLIS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; /** @@ -38,7 +45,28 @@ /** * Desired time unit. * + * @deprecated use {@link #chronoUnit()} instead. This property is going to be removed. * @return time unit */ - TimeUnit unit(); + @Deprecated + TimeUnit unit() default NANOSECONDS; + + /** + * Desired time unit. + * + * @return time unit. Default value {@link java.time.temporal.ChronoUnit#FOREVER} was added + * for backward compatibility temporary. + */ + ChronoUnit chronoUnit() default FOREVER; + + class DurationBuilder { + static Duration build(WithTimeout withTimeout) { + //providing backward compatibility + if (!FOREVER.equals(withTimeout.chronoUnit())) { + return Duration.of(withTimeout.time(), withTimeout.chronoUnit()); + } + + return Duration.of(MILLISECONDS.convert(withTimeout.time(), withTimeout.unit()), MILLIS); + } + } } diff --git a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java index 65d34d32a..f7968db69 100644 --- a/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java +++ b/src/test/java/io/appium/java_client/android/AndroidFunctionTest.java @@ -1,5 +1,7 @@ package io.appium.java_client.android; +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; @@ -20,7 +22,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -80,7 +81,7 @@ public class AndroidFunctionTest extends BaseAndroidTest { searchingFunction.compose(contextFunction); Wait wait = new FluentWait<>(Pattern.compile("WEBVIEW")) - .withTimeout(30, TimeUnit.SECONDS); + .withTimeout(ofSeconds(30)); List elements = wait.until(compositeFunction); assertThat("Element size should be 1", elements.size(), is(1)); @@ -115,7 +116,7 @@ public class AndroidFunctionTest extends BaseAndroidTest { }); Wait wait = new FluentWait<>(Pattern.compile("WEBVIEW")) - .withTimeout(30, TimeUnit.SECONDS); + .withTimeout(ofSeconds(30)); List elements = wait.until(compositeFunction); assertThat("Element size should be 1", elements.size(), is(1)); assertThat("WebView is expected", driver.getContext(), containsString("WEBVIEW")); @@ -124,13 +125,13 @@ public class AndroidFunctionTest extends BaseAndroidTest { @Test(expected = TimeoutException.class) public void nullPointerExceptionSafetyTestWithPrecondition() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) - .withTimeout(30, TimeUnit.SECONDS).pollingEvery(500, TimeUnit.MILLISECONDS); + .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); assertTrue(wait.until(searchingFunction.compose(contextFunction)).size() > 0); } @Test(expected = TimeoutException.class) public void nullPointerExceptionSafetyTestWithPostConditions() { Wait wait = new FluentWait<>(Pattern.compile("Fake_context")) - .withTimeout(30, TimeUnit.SECONDS).pollingEvery(500, TimeUnit.MILLISECONDS); + .withTimeout(ofSeconds(30)).pollingEvery(ofMillis(500)); assertTrue(wait.until(contextFunction.andThen(searchingFunction).andThen(filteringFunction)).size() > 0); } } diff --git a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java b/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java index dffc566e3..9b549183b 100644 --- a/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java +++ b/src/test/java/io/appium/java_client/appium/AppiumFluentWaitTest.java @@ -16,6 +16,7 @@ package io.appium.java_client.appium; +import static java.time.Duration.ofSeconds; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsEqual.equalTo; @@ -25,15 +26,14 @@ import org.junit.Assert; import org.junit.Test; import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.support.ui.Duration; import org.openqa.selenium.support.ui.SystemClock; import org.openqa.selenium.support.ui.Wait; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; public class AppiumFluentWaitTest { + private static class FakeElement { public boolean isDisplayed() { return false; @@ -44,11 +44,11 @@ public boolean isDisplayed() { public void testDefaultStrategy() { final FakeElement el = new FakeElement(); final Wait wait = new AppiumFluentWait<>(el, new SystemClock(), duration -> { - assertThat(duration.in(TimeUnit.SECONDS), is(equalTo(1L))); - Thread.sleep(duration.in(TimeUnit.MILLISECONDS)); + assertThat(duration.getSeconds(), is(equalTo(1L))); + Thread.sleep(duration.toMillis()); }).withPollingStrategy(AppiumFluentWait.IterationInfo::getInterval) - .withTimeout(3, TimeUnit.SECONDS) - .pollingEvery(1, TimeUnit.SECONDS); + .withTimeout(ofSeconds(3)) + .pollingEvery(ofSeconds(1)); wait.until(FakeElement::isDisplayed); Assert.fail("TimeoutException is expected"); } @@ -59,11 +59,11 @@ public void testCustomStrategyOverridesDefaultInterval() { final AtomicInteger callsCounter = new AtomicInteger(0); final Wait wait = new AppiumFluentWait<>(el, new SystemClock(), duration -> { callsCounter.incrementAndGet(); - assertThat(duration.in(TimeUnit.SECONDS), is(equalTo(2L))); - Thread.sleep(duration.in(TimeUnit.MILLISECONDS)); - }).withPollingStrategy(info -> new Duration(2, TimeUnit.SECONDS)) - .withTimeout(3, TimeUnit.SECONDS) - .pollingEvery(1, TimeUnit.SECONDS); + assertThat(duration.getSeconds(), is(equalTo(2L))); + Thread.sleep(duration.toMillis()); + }).withPollingStrategy(info -> ofSeconds(2)) + .withTimeout(ofSeconds(3)) + .pollingEvery(ofSeconds(1)); try { wait.until(FakeElement::isDisplayed); Assert.fail("TimeoutException is expected"); @@ -81,11 +81,11 @@ public void testIntervalCalculationForCustomStrategy() { final Function pollingStrategy = x -> x * 2; final Wait wait = new AppiumFluentWait<>(el, new SystemClock(), duration -> { int callNumber = callsCounter.incrementAndGet(); - assertThat(duration.in(TimeUnit.SECONDS), is(equalTo(pollingStrategy.apply((long) callNumber)))); - Thread.sleep(duration.in(TimeUnit.MILLISECONDS)); - }).withPollingStrategy(info -> new Duration(pollingStrategy.apply(info.getNumber()), TimeUnit.SECONDS)) - .withTimeout(4, TimeUnit.SECONDS) - .pollingEvery(1, TimeUnit.SECONDS); + assertThat(duration.getSeconds(), is(equalTo(pollingStrategy.apply((long) callNumber)))); + Thread.sleep(duration.toMillis()); + }).withPollingStrategy(info -> ofSeconds(pollingStrategy.apply(info.getNumber()))) + .withTimeout(ofSeconds(4)) + .pollingEvery(ofSeconds(1)); try { wait.until(FakeElement::isDisplayed); Assert.fail("TimeoutException is expected"); diff --git a/src/test/java/io/appium/java_client/events/BaseListenerTest.java b/src/test/java/io/appium/java_client/events/BaseListenerTest.java index 8ee18412d..a36b6160e 100644 --- a/src/test/java/io/appium/java_client/events/BaseListenerTest.java +++ b/src/test/java/io/appium/java_client/events/BaseListenerTest.java @@ -270,6 +270,8 @@ protected boolean assertThatWindowListenerWorks(EmptyWebDriver driver, TestListe window.maximize(); + driver.switchTo().window("Test window"); + assertThat(listener.messages, contains(prefix + "Attempt to change size of the window. The height is " + d.getHeight() + " the width is " + d.getWidth(), @@ -280,7 +282,9 @@ protected boolean assertThatWindowListenerWorks(EmptyWebDriver driver, TestListe prefix + "The position the window has been changed. The X is " + p.getX() + " the Y is " + p.getY(), prefix + "Attempt to maximize the window.", - prefix + "The window has been maximized")); + prefix + "The window has been maximized", + prefix + "Attempt to switch to window Test window", + prefix + "driver is switched to window Test window")); return true; } finally { listener.messages.clear(); diff --git a/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java b/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java index 1e952204d..bb295c925 100644 --- a/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/events/WebDriverEventListenerCompatibilityTest.java @@ -71,7 +71,6 @@ public void alertEventTest() { WEBDRIVER_EVENT_LISTENER + "The alert was accepted", WEBDRIVER_EVENT_LISTENER + "Attempt to dismiss alert", WEBDRIVER_EVENT_LISTENER + "The alert was dismissed")); - assertThat(listener.messages.size(), is(4)); } finally { listener.messages.clear(); } @@ -82,4 +81,17 @@ public void exceptionEventTest() { assertThat(super.assertThatExceptionListenerWorks(driver, listener, WEBDRIVER_EVENT_LISTENER), is(true)); } + + @Test + public void windowListenerTest() { + try { + driver.switchTo().window("Test window"); + assertThat(listener.messages, + hasItems(WEBDRIVER_EVENT_LISTENER + "Attempt to switch to window Test window", + WEBDRIVER_EVENT_LISTENER + "driver is switched to window Test window")); + } finally { + listener.messages.clear(); + } + + } } diff --git a/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java b/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java index 89740977b..4365eb200 100644 --- a/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java +++ b/src/test/java/io/appium/java_client/events/listeners/AppiumListener.java @@ -1,5 +1,7 @@ package io.appium.java_client.events.listeners; +import static java.lang.String.format; + import io.appium.java_client.events.api.general.AppiumWebDriverEventListener; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; @@ -112,4 +114,14 @@ public void beforeAlertDismiss(WebDriver driver) { @Override public void onException(Throwable throwable, WebDriver driver) { messages.add("WebDriverEventListener: The exception was thrown: " + throwable.getClass()); } + + @Override + public void beforeSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("WebDriverEventListener: Attempt to switch to window %s", windowName)); + } + + @Override + public void afterSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("WebDriverEventListener: driver is switched to window %s", windowName)); + } } diff --git a/src/test/java/io/appium/java_client/events/listeners/WindowListener.java b/src/test/java/io/appium/java_client/events/listeners/WindowListener.java index 193e5b5fd..cf8c786c0 100644 --- a/src/test/java/io/appium/java_client/events/listeners/WindowListener.java +++ b/src/test/java/io/appium/java_client/events/listeners/WindowListener.java @@ -1,5 +1,7 @@ package io.appium.java_client.events.listeners; +import static java.lang.String.format; + import io.appium.java_client.events.api.general.WindowEventListener; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; @@ -42,4 +44,14 @@ public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point @Override public void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window) { messages.add("The window has been maximized"); } + + @Override + public void beforeSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("Attempt to switch to window %s", windowName)); + } + + @Override + public void afterSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("driver is switched to window %s", windowName)); + } } diff --git a/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java b/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java index 3f0c802fd..60a912364 100644 --- a/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java +++ b/src/test/java/io/appium/java_client/events/listeners/WindowListener2.java @@ -1,5 +1,7 @@ package io.appium.java_client.events.listeners; +import static java.lang.String.format; + import io.appium.java_client.events.api.general.WindowEventListener; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; @@ -46,4 +48,14 @@ public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point @Override public void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window) { messages.add("Externally defined listener: The window has been maximized"); } + + @Override + public void beforeSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("Externally defined listener: Attempt to switch to window %s", windowName)); + } + + @Override + public void afterSwitchToWindow(String windowName, WebDriver driver) { + messages.add(format("Externally defined listener: driver is switched to window %s", windowName)); + } } 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 b975e0b87..6355b71c9 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 @@ -17,6 +17,7 @@ package io.appium.java_client.pagefactory_tests; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; +import static java.time.Duration.ofSeconds; import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -46,7 +47,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.concurrent.TimeUnit; public class AndroidPageObjectTest extends BaseAndroidTest { @@ -242,7 +242,7 @@ public class AndroidPageObjectTest extends BaseAndroidTest { @Before public void setUp() { if (!populated) { //This time out is set because test can be run on slow Android SDK emulator - PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); + PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } populated = true; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java index 680657df4..0f6e178db 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/DesktopBrowserCompatibilityTest.java @@ -19,6 +19,7 @@ import static io.appium.java_client.ChromeDriverPathUtil.getChromeDriver; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; import static java.lang.System.setProperty; +import static java.time.Duration.ofSeconds; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -39,7 +40,6 @@ import java.io.File; import java.util.List; -import java.util.concurrent.TimeUnit; public class DesktopBrowserCompatibilityTest { @@ -64,7 +64,7 @@ public class DesktopBrowserCompatibilityTest { WebDriver driver = new ChromeDriver(); try { PageFactory - .initElements(new AppiumFieldDecorator(driver, 15, TimeUnit.SECONDS), + .initElements(new AppiumFieldDecorator(driver, ofSeconds(15)), this); driver.get(new File("src/test/java/io/appium/java_client/hello appium - saved page.htm") .toURI().toString()); diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/IOSMobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/IOSMobileBrowserCompatibilityTest.java index fb6730f02..6f2615033 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/IOSMobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/IOSMobileBrowserCompatibilityTest.java @@ -16,6 +16,8 @@ package io.appium.java_client.pagefactory_tests; +import static java.time.Duration.ofSeconds; + import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; @@ -36,7 +38,6 @@ import org.openqa.selenium.support.PageFactory; import java.util.List; -import java.util.concurrent.TimeUnit; public class IOSMobileBrowserCompatibilityTest { @@ -65,7 +66,7 @@ public class IOSMobileBrowserCompatibilityTest { //sometimes environment has performance problems capabilities.setCapability(IOSMobileCapabilityType.LAUNCH_TIMEOUT, 500000); driver = new IOSDriver<>(service.getUrl(), capabilities); - PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); + PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } /** diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java index 72e166327..4be99b958 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/MobileBrowserCompatibilityTest.java @@ -16,6 +16,8 @@ package io.appium.java_client.pagefactory_tests; +import static java.time.Duration.ofSeconds; + import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; @@ -35,7 +37,6 @@ import org.openqa.selenium.support.PageFactory; import java.util.List; -import java.util.concurrent.TimeUnit; public class MobileBrowserCompatibilityTest { @@ -67,7 +68,7 @@ public class MobileBrowserCompatibilityTest { capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, MobileBrowserType.BROWSER); driver = new AndroidDriver(service.getUrl(), capabilities); //This time out is set because test can be run on slow Android SDK emulator - PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); + PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } /** diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/SelendroidModeTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/SelendroidModeTest.java index 6f277c782..2c056c2ef 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/SelendroidModeTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/SelendroidModeTest.java @@ -17,6 +17,7 @@ package io.appium.java_client.pagefactory_tests; import static io.appium.java_client.pagefactory.LocatorGroupStrategy.ALL_POSSIBLE; +import static java.time.Duration.ofSeconds; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; @@ -46,7 +47,6 @@ import java.io.File; import java.util.List; -import java.util.concurrent.TimeUnit; public class SelendroidModeTest { private static int SELENDROID_PORT = 9999; @@ -130,7 +130,7 @@ public class SelendroidModeTest { @Before public void setUp() { if (!populated) { //This time out is set because test can be run on slow Android SDK emulator - PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); + PageFactory.initElements(new AppiumFieldDecorator(driver, ofSeconds(5)), this); } populated = true; diff --git a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java index e5b5422fb..701bd648c 100644 --- a/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java +++ b/src/test/java/io/appium/java_client/pagefactory_tests/TimeoutTest.java @@ -17,21 +17,19 @@ package io.appium.java_client.pagefactory_tests; import static io.appium.java_client.ChromeDriverPathUtil.getChromeDriver; -import static io.appium.java_client.pagefactory.AppiumFieldDecorator.DEFAULT_TIMEOUT; -import static io.appium.java_client.pagefactory.AppiumFieldDecorator.DEFAULT_TIMEUNIT; +import static io.appium.java_client.pagefactory.AppiumFieldDecorator.DEFAULT_WAITING_TIMEOUT; import static java.lang.Math.abs; import static java.lang.String.format; import static java.lang.System.currentTimeMillis; import static java.lang.System.setProperty; -import static java.util.concurrent.TimeUnit.MICROSECONDS; -import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.time.Duration.ofSeconds; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.apache.commons.lang3.time.DurationFormatUtils.formatDuration; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertThat; import static org.openqa.selenium.support.PageFactory.initElements; import io.appium.java_client.pagefactory.AppiumFieldDecorator; -import io.appium.java_client.pagefactory.TimeOutDuration; import io.appium.java_client.pagefactory.WithTimeout; import org.junit.After; import org.junit.Before; @@ -43,13 +41,12 @@ import org.openqa.selenium.support.FindAll; import org.openqa.selenium.support.FindBy; +import java.time.Duration; import java.util.List; -import java.util.concurrent.TimeUnit; public class TimeoutTest { private static final long ACCEPTABLE_TIME_DIFF_MS = 1500; - private static final String MESSAGE = "Check difference from the expected waiting duration %s %s"; private WebDriver driver; @@ -63,10 +60,10 @@ public class TimeoutTest { @FindBy(className = "OneAnotherClassWhichDoesNotExist")}) private List stubElements2; - private TimeOutDuration timeOutDuration; + private Duration timeOutDuration; - private static long getExpectedMillis(long value, TimeUnit sourceTimeUnit) { - return MILLISECONDS.convert(value, sourceTimeUnit); + private static long getExpectedMillis(Duration duration) { + return duration.toMillis(); } private static long getPerformanceDiff(long expectedMs, Runnable runnable) { @@ -76,6 +73,11 @@ private static long getPerformanceDiff(long expectedMs, Runnable runnable) { return abs(expectedMs - (endMark - startMark)); } + private static String assertionMessage(Duration expectedDuration) { + return format("Check difference from the expected waiting duration %s", + formatDuration(expectedDuration.toMillis(), "H:mm:ss:SSS", true)); + } + /** * The setting up. */ @@ -83,7 +85,7 @@ private static long getPerformanceDiff(long expectedMs, Runnable runnable) { setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, getChromeDriver().getAbsolutePath()); driver = new ChromeDriver(); - timeOutDuration = new TimeOutDuration(DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT); + timeOutDuration = DEFAULT_WAITING_TIMEOUT; initElements(new AppiumFieldDecorator(driver, timeOutDuration), this); } @@ -94,39 +96,23 @@ private static long getPerformanceDiff(long expectedMs, Runnable runnable) { driver.quit(); } - @Test public void defaultTimeOutTest() { - assertThat(format(MESSAGE, DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT), - getPerformanceDiff(getExpectedMillis(DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT), () -> stubElements.size()), - lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - - timeOutDuration.setTime(15500000, MICROSECONDS); - assertThat(format(MESSAGE, 15500000, MICROSECONDS), - getPerformanceDiff(getExpectedMillis(15500000, MICROSECONDS), () -> stubElements.size()), - lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - - timeOutDuration.setTime(3, SECONDS); - assertThat(format(MESSAGE, 3, SECONDS), - getPerformanceDiff(getExpectedMillis(3, SECONDS), () -> stubElements.size()), - lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - } - @Test public void withCustomizedTimeOutTest() { - assertThat(format(MESSAGE, DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT), - getPerformanceDiff(getExpectedMillis(DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT), () -> stubElements.size()), + assertThat(assertionMessage(DEFAULT_WAITING_TIMEOUT), + getPerformanceDiff(getExpectedMillis(DEFAULT_WAITING_TIMEOUT), () -> stubElements.size()), lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - assertThat(format(MESSAGE, 5, SECONDS), - getPerformanceDiff(getExpectedMillis(5, SECONDS), () -> stubElements2.size()), + assertThat(assertionMessage(ofSeconds(5)), + getPerformanceDiff(getExpectedMillis(ofSeconds(5)), () -> stubElements2.size()), lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - timeOutDuration.setTime(15500000, MICROSECONDS); + timeOutDuration.plus(ofSeconds(10)); - assertThat(format(MESSAGE, 15500000, MICROSECONDS), - getPerformanceDiff(getExpectedMillis(15500000, MICROSECONDS), () -> stubElements.size()), + assertThat(assertionMessage(timeOutDuration), + getPerformanceDiff(getExpectedMillis(timeOutDuration), () -> stubElements.size()), lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); - assertThat(format(MESSAGE, 5, SECONDS), - getPerformanceDiff(getExpectedMillis(5, SECONDS), () -> stubElements2.size()), + assertThat(assertionMessage(ofSeconds(5)), + getPerformanceDiff(getExpectedMillis(ofSeconds(5)), () -> stubElements2.size()), lessThanOrEqualTo(ACCEPTABLE_TIME_DIFF_MS)); } }