Skip to content

Commit 470c27e

Browse files
Merge pull request #863 from TikhomirovSergey/master
#846 and #742 FIX
2 parents 2f60e64 + 3dd8fce commit 470c27e

25 files changed

+284
-98
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ compileJava {
5050
]
5151
}
5252

53-
ext.seleniumVersion = '3.9.1'
53+
ext.seleniumVersion = '3.11.0'
5454

5555
dependencies {
5656
compile ("org.seleniumhq.selenium:selenium-java:${seleniumVersion}") {

src/main/java/io/appium/java_client/AppiumFluentWait.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,19 @@
1616

1717
package io.appium.java_client;
1818

19+
import static java.time.Duration.ofMillis;
20+
1921
import com.google.common.base.Throwables;
2022

2123
import org.openqa.selenium.TimeoutException;
2224
import org.openqa.selenium.WebDriverException;
2325
import org.openqa.selenium.support.ui.Clock;
24-
import org.openqa.selenium.support.ui.Duration;
2526
import org.openqa.selenium.support.ui.FluentWait;
2627
import org.openqa.selenium.support.ui.Sleeper;
2728

2829
import java.lang.reflect.Field;
30+
import java.time.Duration;
2931
import java.util.List;
30-
import java.util.concurrent.TimeUnit;
3132
import java.util.function.Function;
3233
import java.util.function.Supplier;
3334

@@ -167,7 +168,7 @@ protected T getInput() {
167168
/**
168169
* Sets the strategy for polling. The default strategy is null,
169170
* which means, that polling interval is always a constant value and is
170-
* set by {@link #pollingEvery(long, TimeUnit)} method. Otherwise the value set by that
171+
* set by {@link #pollingEvery(Duration)} method. Otherwise the value set by that
171172
* method might be just a helper to calculate the actual interval.
172173
* Although, by setting an alternative polling strategy you may flexibly control
173174
* the duration of this interval for each polling round.
@@ -228,7 +229,7 @@ public AppiumFluentWait<T> withPollingStrategy(Function<IterationInfo, Duration>
228229
@Override
229230
public <V> V until(Function<? super T, V> isTrue) {
230231
final long start = getClock().now();
231-
final long end = getClock().laterBy(getTimeout().in(TimeUnit.MILLISECONDS));
232+
final long end = getClock().laterBy(getTimeout().toMillis());
232233
long iterationNumber = 1;
233234
Throwable lastException;
234235
while (true) {
@@ -254,15 +255,15 @@ public <V> V until(Function<? super T, V> isTrue) {
254255
String timeoutMessage = String.format(
255256
"Expected condition failed: %s (tried for %d second(s) with %s interval)",
256257
message == null ? "waiting for " + isTrue : message,
257-
getTimeout().in(TimeUnit.SECONDS), getInterval());
258+
getTimeout().getSeconds(), getInterval());
258259
throw timeoutException(timeoutMessage, lastException);
259260
}
260261

261262
try {
262263
Duration interval = getInterval();
263264
if (pollingStrategy != null) {
264265
final IterationInfo info = new IterationInfo(iterationNumber,
265-
new Duration(getClock().now() - start, TimeUnit.MILLISECONDS), getTimeout(),
266+
ofMillis(getClock().now() - start), getTimeout(),
266267
interval);
267268
interval = pollingStrategy.apply(info);
268269
}

src/main/java/io/appium/java_client/events/DefaultAspect.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class DefaultAspect {
8383
+ ".rotate(..))";
8484
private static final String EXECUTION_CONTEXT = "execution(* org.openqa.selenium.ContextAware."
8585
+ "context(..))";
86+
private static final String EXECUTION_SWITCH_TO_WINDOW = "execution(* org.openqa.selenium.WebDriver.TargetLocator"
87+
+ ".window(..))";
8688
private static final String AROUND = "execution(* org.openqa.selenium.WebDriver.*(..)) || "
8789
+ "execution(* org.openqa.selenium.WebElement.*(..)) || "
8890
+ "execution(* org.openqa.selenium.WebDriver.Navigation.*(..)) || "
@@ -463,6 +465,24 @@ public void afterMaximization(JoinPoint joinPoint) throws Throwable {
463465
}
464466
}
465467

468+
@Before(EXECUTION_SWITCH_TO_WINDOW)
469+
public void beforeSwitchToWindow(JoinPoint joinPoint) throws Throwable {
470+
try {
471+
listener.beforeSwitchToWindow(castArgument(joinPoint, 0), driver);
472+
} catch (Throwable t) {
473+
throw getRootCause(t);
474+
}
475+
}
476+
477+
@After(EXECUTION_SWITCH_TO_WINDOW)
478+
public void afterSwitchToWindow(JoinPoint joinPoint) throws Throwable {
479+
try {
480+
listener.afterSwitchToWindow(castArgument(joinPoint, 0), driver);
481+
} catch (Throwable t) {
482+
throw getRootCause(t);
483+
}
484+
}
485+
466486
@Before(EXECUTION_ROTATE)
467487
public void beforeRotation(JoinPoint joinPoint) throws Throwable {
468488
try {

src/main/java/io/appium/java_client/events/DefaultListener.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,16 @@ public void afterWindowIsMoved(WebDriver driver, WebDriver.Window window, Point
209209
((WindowEventListener) dispatcher).afterWindowIsMaximized(driver, window);
210210
}
211211

212+
@Override
213+
public void beforeSwitchToWindow(String windowName, WebDriver driver) {
214+
((WebDriverEventListener) dispatcher).beforeSwitchToWindow(windowName, driver);
215+
}
216+
217+
@Override
218+
public void afterSwitchToWindow(String windowName, WebDriver driver) {
219+
((WebDriverEventListener) dispatcher).afterSwitchToWindow(windowName, driver);
220+
}
221+
212222
@Override public void beforeSwitchingToContext(WebDriver driver, String context) {
213223
((ContextEventListener) dispatcher).beforeSwitchingToContext(driver, context);
214224
}

src/main/java/io/appium/java_client/events/api/general/WindowEventListener.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,20 @@ void afterWindowIsMoved(WebDriver driver, WebDriver.Window window,
7878
* @param window is the window which has been maximized
7979
*/
8080
void afterWindowIsMaximized(WebDriver driver, WebDriver.Window window);
81+
82+
/**
83+
* This action will be performed each time before
84+
* {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}.
85+
*
86+
* @param driver WebDriver
87+
*/
88+
void beforeSwitchToWindow(String windowName, WebDriver driver);
89+
90+
/**
91+
* This action will be performed each time after
92+
* {@link org.openqa.selenium.WebDriver.TargetLocator#window(java.lang.String)}.
93+
*
94+
* @param driver WebDriver
95+
*/
96+
void afterSwitchToWindow(String windowName, WebDriver driver);
8197
}

src/main/java/io/appium/java_client/pagefactory/AppiumElementLocator.java

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import static io.appium.java_client.pagefactory.ThrowableUtil.isStaleElementReferenceException;
2222
import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.getCurrentContentType;
2323
import static java.lang.String.format;
24+
import static java.time.Duration.ofMillis;
25+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
2426

2527
import io.appium.java_client.pagefactory.bys.ContentMappedBy;
2628
import io.appium.java_client.pagefactory.locator.CacheableLocator;
@@ -34,6 +36,7 @@
3436
import org.openqa.selenium.WebElement;
3537
import org.openqa.selenium.support.ui.FluentWait;
3638

39+
import java.time.Duration;
3740
import java.util.ArrayList;
3841
import java.util.List;
3942
import java.util.function.Function;
@@ -45,7 +48,7 @@ class AppiumElementLocator implements CacheableLocator {
4548

4649
private final boolean shouldCache;
4750
private final By by;
48-
private final TimeOutDuration duration;
51+
private final Duration duration;
4952
private final SearchContext searchContext;
5053
private WebElement cachedElement;
5154
private List<WebElement> cachedElementList;
@@ -59,11 +62,31 @@ class AppiumElementLocator implements CacheableLocator {
5962
* @param by a By locator strategy
6063
* @param shouldCache is the flag that signalizes that elements which
6164
* are found once should be cached
62-
* @param duration is a POJO which contains timeout parameters for the element to be searched
65+
* @param duration is a POJO which contains timeout parameters for the element to be found
66+
* @deprecated This constructor is going to be removed. Use {@link #AppiumElementLocator(SearchContext, By,
67+
* boolean, Duration)} instead.
6368
*/
64-
69+
@Deprecated
6570
public AppiumElementLocator(SearchContext searchContext, By by, boolean shouldCache,
6671
TimeOutDuration duration) {
72+
this(searchContext, by, shouldCache,
73+
ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit())));
74+
}
75+
76+
/**
77+
* Creates a new mobile element locator. It instantiates {@link WebElement}
78+
* using @AndroidFindBy (-s), @iOSFindBy (-s) and @FindBy (-s) annotation
79+
* sets
80+
*
81+
* @param searchContext The context to use when finding the element
82+
* @param by a By locator strategy
83+
* @param shouldCache is the flag that signalizes that elements which
84+
* are found once should be cached
85+
* @param duration timeout parameter for the element to be found
86+
*/
87+
88+
public AppiumElementLocator(SearchContext searchContext, By by, boolean shouldCache,
89+
Duration duration) {
6790
this.searchContext = searchContext;
6891
this.shouldCache = shouldCache;
6992
this.duration = duration;
@@ -94,7 +117,7 @@ private <T> T waitFor(Supplier<T> supplier) {
94117
try {
95118
FluentWait<Supplier<T>> wait = new FluentWait<>(supplier)
96119
.ignoring(NoSuchElementException.class);
97-
wait.withTimeout(duration.getTime(), duration.getTimeUnit());
120+
wait.withTimeout(duration);
98121
return wait.until(function);
99122
} catch (TimeoutException e) {
100123
if (function.foundStaleElementReferenceException != null) {

src/main/java/io/appium/java_client/pagefactory/AppiumElementLocatorFactory.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package io.appium.java_client.pagefactory;
1818

19+
import static io.appium.java_client.pagefactory.WithTimeout.DurationBuilder.build;
20+
import static java.time.Duration.ofMillis;
1921
import static java.util.Optional.ofNullable;
22+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
2023

2124
import io.appium.java_client.pagefactory.bys.builder.AppiumByBuilder;
2225
import io.appium.java_client.pagefactory.locator.CacheableElementLocatorFactory;
@@ -26,23 +29,38 @@
2629

2730
import java.lang.reflect.AnnotatedElement;
2831
import java.lang.reflect.Field;
32+
import java.time.Duration;
2933
import javax.annotation.Nullable;
3034

3135
public class AppiumElementLocatorFactory implements CacheableElementLocatorFactory {
3236
private final SearchContext searchContext;
33-
private final TimeOutDuration duration;
37+
private final Duration duration;
3438
private final AppiumByBuilder builder;
3539

3640
/**
3741
* Creates a new mobile element locator factory.
3842
*
3943
* @param searchContext The context to use when finding the element
40-
* @param duration is a POJO which contains timeout parameters for the element to be searched
44+
* @param duration is a POJO which contains timeout parameters for the elements to be found
4145
* @param builder is handler of Appium-specific page object annotations
46+
* @deprecated This constructor is going to be
47+
* removed. Use {@link #AppiumElementLocatorFactory(SearchContext, Duration, AppiumByBuilder)} instead.
4248
*/
43-
49+
@Deprecated
4450
public AppiumElementLocatorFactory(SearchContext searchContext, TimeOutDuration duration,
4551
AppiumByBuilder builder) {
52+
this(searchContext, ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit())), builder);
53+
}
54+
55+
/**
56+
* Creates a new mobile element locator factory.
57+
*
58+
* @param searchContext The context to use when finding the element
59+
* @param duration timeout parameters for the elements to be found
60+
* @param builder is handler of Appium-specific page object annotations
61+
*/
62+
public AppiumElementLocatorFactory(SearchContext searchContext, Duration duration,
63+
AppiumByBuilder builder) {
4664
this.searchContext = searchContext;
4765
this.duration = duration;
4866
this.builder = builder;
@@ -53,10 +71,10 @@ public AppiumElementLocatorFactory(SearchContext searchContext, TimeOutDuration
5371
}
5472

5573
@Override public @Nullable CacheableLocator createLocator(AnnotatedElement annotatedElement) {
56-
TimeOutDuration customDuration;
74+
Duration customDuration;
5775
if (annotatedElement.isAnnotationPresent(WithTimeout.class)) {
5876
WithTimeout withTimeout = annotatedElement.getAnnotation(WithTimeout.class);
59-
customDuration = new TimeOutDuration(withTimeout.time(), withTimeout.unit());
77+
customDuration = build(withTimeout);
6078
} else {
6179
customDuration = duration;
6280
}

src/main/java/io/appium/java_client/pagefactory/AppiumFieldDecorator.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
import static io.appium.java_client.internal.ElementMap.getElementClass;
2020
import static io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy;
2121
import static io.appium.java_client.pagefactory.utils.WebDriverUnpackUtility.unpackWebDriverFromSearchContext;
22+
import static java.time.Duration.ofMillis;
23+
import static java.time.Duration.ofSeconds;
2224
import static java.util.Optional.ofNullable;
25+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
2326

2427
import com.google.common.collect.ImmutableList;
2528

@@ -42,6 +45,7 @@
4245
import java.lang.reflect.Field;
4346
import java.lang.reflect.ParameterizedType;
4447
import java.lang.reflect.Type;
48+
import java.time.Duration;
4549
import java.util.ArrayList;
4650
import java.util.List;
4751
import java.util.Map;
@@ -62,16 +66,20 @@ public class AppiumFieldDecorator implements FieldDecorator {
6266
private static final List<Class<? extends WebElement>> availableElementClasses = ImmutableList.of(WebElement.class,
6367
RemoteWebElement.class, MobileElement.class, AndroidElement.class,
6468
IOSElement.class, WindowsElement.class);
65-
public static long DEFAULT_TIMEOUT = 1;
66-
public static TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS;
69+
public static final Duration DEFAULT_WAITING_TIMEOUT = ofSeconds(1);
70+
@Deprecated
71+
public static final long DEFAULT_TIMEOUT = 1;
72+
@Deprecated
73+
public static final TimeUnit DEFAULT_TIMEUNIT = TimeUnit.SECONDS;
6774
private final WebDriver webDriver;
6875
private final DefaultFieldDecorator defaultElementFieldDecoracor;
6976
private final AppiumElementLocatorFactory widgetLocatorFactory;
7077
private final String platform;
7178
private final String automation;
72-
private final TimeOutDuration duration;
79+
private final Duration duration;
7380

7481

82+
@Deprecated
7583
public AppiumFieldDecorator(SearchContext context, long timeout,
7684
TimeUnit timeUnit) {
7785
this(context, new TimeOutDuration(timeout, timeUnit));
@@ -84,8 +92,23 @@ public AppiumFieldDecorator(SearchContext context, long timeout,
8492
* It may be the instance of {@link WebDriver} or {@link WebElement} or
8593
* {@link Widget} or some other user's extension/implementation.
8694
* @param duration is a desired duration of the waiting for an element presence.
95+
* @deprecated This constructor is going to be removed. Use {@link #AppiumFieldDecorator(SearchContext, Duration)}
96+
* instead.
8797
*/
98+
@Deprecated
8899
public AppiumFieldDecorator(SearchContext context, TimeOutDuration duration) {
100+
this(context, ofMillis(MILLISECONDS.convert(duration.getTime(), duration.getTimeUnit())));
101+
}
102+
103+
/**
104+
* Creates field decorator based on {@link SearchContext} and timeout {@code duration}.
105+
*
106+
* @param context is an instance of {@link SearchContext}
107+
* It may be the instance of {@link WebDriver} or {@link WebElement} or
108+
* {@link Widget} or some other user's extension/implementation.
109+
* @param duration is a desired duration of the waiting for an element presence.
110+
*/
111+
public AppiumFieldDecorator(SearchContext context, Duration duration) {
89112
this.webDriver = unpackWebDriverFromSearchContext(context);
90113
HasSessionDetails hasSessionDetails = ofNullable(this.webDriver).map(webDriver -> {
91114
if (!HasSessionDetails.class.isAssignableFrom(webDriver.getClass())) {
@@ -105,8 +128,8 @@ public AppiumFieldDecorator(SearchContext context, TimeOutDuration duration) {
105128
this.duration = duration;
106129

107130
defaultElementFieldDecoracor = new DefaultFieldDecorator(
108-
new AppiumElementLocatorFactory(context, duration,
109-
new DefaultElementByBuilder(platform, automation))) {
131+
new AppiumElementLocatorFactory(context, duration,
132+
new DefaultElementByBuilder(platform, automation))) {
110133
@Override
111134
protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator) {
112135
return proxyForAnElement(locator);
@@ -115,7 +138,7 @@ protected WebElement proxyForLocator(ClassLoader ignored, ElementLocator locator
115138
@Override
116139
@SuppressWarnings("unchecked")
117140
protected List<WebElement> proxyForListLocator(ClassLoader ignored,
118-
ElementLocator locator) {
141+
ElementLocator locator) {
119142
ElementListInterceptor elementInterceptor = new ElementListInterceptor(locator);
120143
return getEnhancedProxy(ArrayList.class, elementInterceptor);
121144
}
@@ -142,11 +165,11 @@ protected List<WebElement> proxyForListLocator(ClassLoader ignored,
142165
};
143166

144167
widgetLocatorFactory =
145-
new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation));
168+
new AppiumElementLocatorFactory(context, duration, new WidgetByBuilder(platform, automation));
146169
}
147170

148171
public AppiumFieldDecorator(SearchContext context) {
149-
this(context, DEFAULT_TIMEOUT, DEFAULT_TIMEUNIT);
172+
this(context, DEFAULT_WAITING_TIMEOUT);
150173
}
151174

152175
/**

src/main/java/io/appium/java_client/pagefactory/TimeOutDuration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323

2424
/**
2525
* Represents an duration of waiting for element rendering.
26+
*
27+
* @deprecated this class is going to be removed in favour of {@link java.time.Duration}
28+
* usage.
2629
*/
30+
@Deprecated
2731
public class TimeOutDuration {
2832

2933
private long time;

0 commit comments

Comments
 (0)