Skip to content

Commit

Permalink
Merge pull request #863 from TikhomirovSergey/master
Browse files Browse the repository at this point in the history
 #846 and #742 FIX
  • Loading branch information
TikhomirovSergey authored Apr 10, 2018
2 parents 2f60e64 + 3dd8fce commit 470c27e
Show file tree
Hide file tree
Showing 25 changed files with 284 additions and 98 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ compileJava {
]
}

ext.seleniumVersion = '3.9.1'
ext.seleniumVersion = '3.11.0'

dependencies {
compile ("org.seleniumhq.selenium:selenium-java:${seleniumVersion}") {
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/io/appium/java_client/AppiumFluentWait.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -228,7 +229,7 @@ public AppiumFluentWait<T> withPollingStrategy(Function<IterationInfo, Duration>
@Override
public <V> V until(Function<? super T, V> 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) {
Expand All @@ -254,15 +255,15 @@ public <V> V until(Function<? super T, V> 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);
}

try {
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);
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/io/appium/java_client/events/DefaultAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.*(..)) || "
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/io/appium/java_client/events/DefaultListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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<WebElement> cachedElementList;
Expand All @@ -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;
Expand Down Expand Up @@ -94,7 +117,7 @@ private <T> T waitFor(Supplier<T> supplier) {
try {
FluentWait<Supplier<T>> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -62,16 +66,20 @@ public class AppiumFieldDecorator implements FieldDecorator {
private static final List<Class<? extends WebElement>> 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));
Expand All @@ -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())) {
Expand All @@ -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);
Expand All @@ -115,7 +138,7 @@ protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator
@Override
@SuppressWarnings("unchecked")
protected List<WebElement> proxyForListLocator(ClassLoader ignored,
ElementLocator locator) {
ElementLocator locator) {
ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator);
return getEnhancedProxy(ArrayList.class, elementInterceptor);
}
Expand All @@ -142,11 +165,11 @@ protected List<WebElement> 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);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 470c27e

Please sign in to comment.