Skip to content

Commit ed4476d

Browse files
authored
Extracted IConditionalWait (#25)
* extracted ISettingsFile and added tests * added documentation for ISettingsFile * extracted ILoggerConfiguration * extracted ITimeoutConfiguration * extracted IRetryConfiguration * renamed one test * added empty end line and updated com.fasterxml.jackson.core to 2.10.2 * renamed constants to upper case * removed redundant method from ISettingsFile * fixed naming and added empty line at the end of files * fixed naming and added empty line at the end of files * fixed naming and added empty line at the end of files * merged with master and added test for CustomSettingsFile * fix for the tests * merge and small refactoring of tests * merge from master * merge from master * extracted IElementCacheConfiguration * extracted IConditionalWait * merge and test fix * application to applications added tests for conditionalWait * removed SupportedLanguaged and added default language if configuration is absent * support multiple threads in ConditionalWaitTests added friendly messages to the tests * register configuration as singleton * fixed comments * moved SettingsFileUtil to ISettingsFile * added IWaitingsModule * small fix in summary * merge * update doc * rename applications to application in docs * #6 removed using of DI in tests * Merge branch 'master' into Feature/6-ConditionalWait # Conflicts: # src/main/java/aquality/selenium/core/applications/AqualityModule.java # src/main/java/aquality/selenium/core/localization/ILocalizationManager.java # src/main/java/aquality/selenium/core/localization/LocalizationManager.java # src/test/resources/TestSuite.xml updated IConditionalWait * Merge branch 'master' into Feature/6-ConditionalWait # Conflicts: # src/main/java/aquality/selenium/core/applications/AqualityModule.java # src/main/java/aquality/selenium/core/localization/ILocalizationManager.java # src/main/java/aquality/selenium/core/localization/LocalizationManager.java # src/test/resources/TestSuite.xml updated IConditionalWait refactored tests for ConditionalWait * small fix * merge with master * optimized import * fixed tests
1 parent 42af04b commit ed4476d

27 files changed

+979
-20
lines changed

src/main/java/aquality/selenium/core/application/AqualityModule.java renamed to src/main/java/aquality/selenium/core/applications/AqualityModule.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
package aquality.selenium.core.application;
1+
package aquality.selenium.core.applications;
22

33
import aquality.selenium.core.configurations.*;
4-
import aquality.selenium.core.localization.*;
4+
import aquality.selenium.core.localization.ILocalizationManager;
5+
import aquality.selenium.core.localization.ILocalizationModule;
6+
import aquality.selenium.core.localization.ILocalizedLogger;
57
import aquality.selenium.core.logging.Logger;
68
import aquality.selenium.core.utilities.IElementActionRetrier;
79
import aquality.selenium.core.utilities.ISettingsFile;
810
import aquality.selenium.core.utilities.IUtilitiesModule;
11+
import aquality.selenium.core.waitings.IConditionalWait;
12+
import aquality.selenium.core.waitings.IWaitingsModule;
913
import com.google.inject.AbstractModule;
1014
import com.google.inject.Provider;
1115
import com.google.inject.Singleton;
@@ -14,7 +18,7 @@
1418
* Describes all dependencies which is registered for the project.
1519
*/
1620
public class AqualityModule<T extends IApplication> extends AbstractModule
17-
implements ILocalizationModule, IUtilitiesModule {
21+
implements ILocalizationModule, IUtilitiesModule, IWaitingsModule {
1822

1923
private final Provider<T> applicationProvider;
2024

@@ -37,5 +41,6 @@ protected void configure() {
3741
bind(IElementActionRetrier.class).to(getElementActionRetrierImplementation()).in(Singleton.class);
3842
bind(ILocalizationManager.class).to(getLocalizationManagerImplementation()).in(Singleton.class);
3943
bind(ILocalizedLogger.class).to(getLocalizedLoggerImplementation()).in(Singleton.class);
44+
bind(IConditionalWait.class).to(getConditionalWaitImplementation());
4045
}
4146
}

src/main/java/aquality/selenium/core/application/AqualityServices.java renamed to src/main/java/aquality/selenium/core/applications/AqualityServices.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package aquality.selenium.core.application;
1+
package aquality.selenium.core.applications;
22

33
import com.google.inject.Guice;
44
import com.google.inject.Injector;

src/main/java/aquality/selenium/core/application/IApplication.java renamed to src/main/java/aquality/selenium/core/applications/IApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package aquality.selenium.core.application;
1+
package aquality.selenium.core.applications;
22

33
import org.openqa.selenium.remote.RemoteWebDriver;
44

src/main/java/aquality/selenium/core/localization/ILocalizationManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
public interface ILocalizationManager {
77
/**
88
* Gets localized message from resources by its key.
9+
*
910
* @param messageKey Key in resource file.
1011
* @param args Arguments, which will be provided to template of localized message.
1112
* @return Localized message.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package aquality.selenium.core.waitings;
2+
3+
import aquality.selenium.core.applications.IApplication;
4+
import aquality.selenium.core.configurations.ITimeoutConfiguration;
5+
import com.google.common.base.Strings;
6+
import com.google.inject.Inject;
7+
import com.google.inject.Provider;
8+
import org.openqa.selenium.StaleElementReferenceException;
9+
import org.openqa.selenium.support.ui.ExpectedCondition;
10+
import org.openqa.selenium.support.ui.WebDriverWait;
11+
12+
import java.time.Duration;
13+
import java.util.Collection;
14+
import java.util.Collections;
15+
import java.util.Optional;
16+
import java.util.concurrent.TimeUnit;
17+
import java.util.concurrent.TimeoutException;
18+
import java.util.function.BooleanSupplier;
19+
20+
public class ConditionalWait implements IConditionalWait {
21+
22+
private final Provider<IApplication> applicationProvider;
23+
private final ITimeoutConfiguration timeoutConfiguration;
24+
25+
@Inject
26+
public ConditionalWait(Provider<IApplication> applicationProvider, ITimeoutConfiguration timeoutConfiguration) {
27+
this.applicationProvider = applicationProvider;
28+
this.timeoutConfiguration = timeoutConfiguration;
29+
}
30+
31+
@Override
32+
public boolean waitFor(BooleanSupplier condition, Long timeoutInSeconds, Long pollingIntervalInMilliseconds, String message, Collection<Class<? extends Throwable>> exceptionsToIgnore) {
33+
try {
34+
waitForTrue(condition, timeoutInSeconds, pollingIntervalInMilliseconds, message, exceptionsToIgnore);
35+
return true;
36+
} catch (TimeoutException e) {
37+
return false;
38+
}
39+
}
40+
41+
@Override
42+
public void waitForTrue(BooleanSupplier condition, Long timeoutInSeconds, Long pollingIntervalInMilliseconds, String message, Collection<Class<? extends Throwable>> exceptionsToIgnore) throws TimeoutException {
43+
BooleanSupplier supplier = Optional.ofNullable(condition).orElseThrow(() -> new IllegalArgumentException("Condition cannot be null"));
44+
Long timeout = resolveConditionTimeout(timeoutInSeconds);
45+
Long pollingInterval = resolvePollingInterval(pollingIntervalInMilliseconds);
46+
String exMessage = resolveMessage(message);
47+
double startTime = getCurrentTime();
48+
while (true) {
49+
if (isConditionSatisfied(supplier, exceptionsToIgnore)) {
50+
return;
51+
}
52+
53+
double currentTime = getCurrentTime();
54+
if ((currentTime - startTime) > timeout) {
55+
String exceptionMessage = String.format("Timed out after %1$s seconds during wait for condition '%2$s'", timeout, exMessage);
56+
throw new TimeoutException(exceptionMessage);
57+
}
58+
59+
try {
60+
Thread.sleep(pollingInterval);
61+
} catch (InterruptedException e) {
62+
Thread.currentThread().interrupt();
63+
}
64+
}
65+
}
66+
67+
@Override
68+
public <T> T waitFor(ExpectedCondition<T> condition, Long timeoutInSeconds, Long pollingIntervalInMilliseconds, String message, Collection<Class<? extends Throwable>> exceptionsToIgnore) {
69+
IApplication app = applicationProvider.get();
70+
app.setImplicitWaitTimeout(0, TimeUnit.SECONDS);
71+
Long timeout = resolveConditionTimeout(timeoutInSeconds);
72+
Long pollingInterval = resolvePollingInterval(pollingIntervalInMilliseconds);
73+
String exMessage = resolveMessage(message);
74+
WebDriverWait wait = new WebDriverWait(app.getDriver(), timeout);
75+
wait.pollingEvery(Duration.ofMillis(pollingInterval));
76+
wait.withMessage(exMessage);
77+
wait.ignoreAll(exceptionsToIgnore == null ? Collections.singleton(StaleElementReferenceException.class) : exceptionsToIgnore);
78+
try {
79+
return wait.until(condition);
80+
} finally {
81+
app.setImplicitWaitTimeout(timeoutConfiguration.getImplicit(), TimeUnit.SECONDS);
82+
}
83+
}
84+
85+
private double getCurrentTime() {
86+
return System.nanoTime() / Math.pow(10, 9);
87+
}
88+
89+
private boolean isConditionSatisfied(BooleanSupplier condition, Collection<Class<? extends Throwable>> exceptionsToIgnore) {
90+
try {
91+
return condition.getAsBoolean();
92+
} catch (Exception e) {
93+
if (exceptionsToIgnore == null || !exceptionsToIgnore.contains(e.getClass())) {
94+
throw e;
95+
}
96+
97+
return false;
98+
}
99+
}
100+
101+
private Long resolveConditionTimeout(Long timeout) {
102+
return Optional.ofNullable(timeout).orElse(timeoutConfiguration.getCommand());
103+
}
104+
105+
private Long resolvePollingInterval(Long timeout) {
106+
return Optional.ofNullable(timeout).orElse(timeoutConfiguration.getPollingInterval());
107+
}
108+
109+
private String resolveMessage(String message) {
110+
return Strings.isNullOrEmpty(message) ? "" : message;
111+
}
112+
}

0 commit comments

Comments
 (0)