Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit e58985a

Browse files
committed
Refactored the Wait API's internal class structure and overall design
The API (Wait.java) didn't actually change but a lot of the internal classes did: - Sleeper abstraction to allow for better testability - Reduced visibility of most classes to the package - Added additional wait operation for waiting until a given boolean supplier returns true - Replaced WaitOperations with a much more streamlined and less complex class Waiter
1 parent b397ed0 commit e58985a

18 files changed

+1195
-297
lines changed

webtester-core/src/main/java/info/novatec/testit/webtester/WebTesterException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ protected WebTesterException(String message, Throwable cause) {
1616
super(message, cause);
1717
}
1818

19+
protected WebTesterException(Throwable cause) {
20+
super(cause);
21+
}
22+
1923
}
Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,75 @@
11
package info.novatec.testit.webtester.waiting;
22

3-
import java.util.concurrent.TimeUnit;
3+
import java.util.function.Supplier;
44

5-
import info.novatec.testit.webtester.pagefragments.PageFragment;
5+
import lombok.AccessLevel;
6+
import lombok.Getter;
67

78

89
/**
9-
* This class is used to configure {@link Wait} operations with custom settings like the {@code timeout}.
10+
* This class is used to configure {@link Wait} operations with custom settings like a {@code timeout}.
1011
*
1112
* @see Wait
1213
* @see WaitUntil
14+
* @see Waiter
15+
* @see WaitConfig
1316
* @since 2.0
1417
*/
18+
@Getter(AccessLevel.PACKAGE)
1519
public class ConfiguredWait {
1620

17-
private final long timeout;
18-
private final TimeUnit timeUnit;
21+
/**
22+
* The {@link Waiter} to use when executing wait operations.
23+
*/
24+
private final Waiter waiter;
25+
/**
26+
* The {@link WaitConfig} to use when deciding how long to wait.
27+
*/
28+
private final WaitConfig config;
1929

2030
/**
21-
* Creates a new {@link ConfiguredWait} instance with the given timeout in seconds.
31+
* Creates a new {@link ConfiguredWait} instance with the given {@link Waiter} and {@link WaitConfig}.
2232
*
23-
* @param timeout the timeout to use
33+
* @param waiter the waiter to use
34+
* @param config the configuration to use
35+
* @see Waiter
36+
* @see WaitConfig
2437
* @since 2.0
2538
*/
26-
public ConfiguredWait(long timeout) {
27-
this(timeout, TimeUnit.SECONDS);
39+
ConfiguredWait(Waiter waiter, WaitConfig config) {
40+
this.waiter = waiter;
41+
this.config = config;
2842
}
2943

3044
/**
31-
* Creates a new {@link ConfiguredWait} instance with the given timeout in the given {@link TimeUnit}.
45+
* Creates a {@link WaitUntil} with this {@link ConfiguredWait}'s {@link ConfiguredWait} for the given object.
3246
*
33-
* @param timeout the timeout to use
34-
* @param timeUnit the unit of time to use
47+
* @param object the object for the wait until operation
48+
* @param <T> the type of object
49+
* @return the fluent wait instance
50+
* @see Wait
51+
* @see WaitUntil
52+
* @see Waiter
53+
* @see WaitConfig
3554
* @since 2.0
3655
*/
37-
public ConfiguredWait(long timeout, TimeUnit timeUnit) {
38-
this.timeout = timeout;
39-
this.timeUnit = timeUnit;
56+
public <T> WaitUntil<T> until(T object) {
57+
return new WaitUntil<>(waiter, config, object);
4058
}
4159

4260
/**
43-
* Creates a {@link WaitUntil fluent wait until} with the timeout settings of this {@link ConfiguredWait} for the given
44-
* {@link PageFragment}.
61+
* Executes a wait operation based on this {@link ConfiguredWait}'s {@link ConfiguredWait} and the given boolean
62+
* supplier. The wait is executed until either the supplier returns <code>true</code> or the timeout is reached.
4563
*
46-
* @param fragment the fragment for the wait until operation
47-
* @param <T> the type of the page fragment subclass
48-
* @return the fluent wait instance
64+
* @param condition the supplier for the wait until operation
4965
* @see Wait
5066
* @see WaitUntil
67+
* @see Waiter
68+
* @see WaitConfig
5169
* @since 2.0
5270
*/
53-
public <T extends PageFragment> WaitUntil<T> until(T fragment) {
54-
return new WaitUntil<>(fragment, timeout, timeUnit);
71+
public void until(Supplier<Boolean> condition) {
72+
waiter.waitUntil(config, condition);
5573
}
5674

5775
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package info.novatec.testit.webtester.waiting;
2+
3+
/**
4+
* This implementation of {@link Sleeper} will execute the sleep on the current {@link Thread}.
5+
*
6+
* @see Sleeper
7+
* @since 2.0
8+
*/
9+
class CurrentThreadSleeper implements Sleeper {
10+
11+
@Override
12+
public void sleep(long milliseconds) throws InterruptionException {
13+
try {
14+
Thread.sleep(milliseconds);
15+
} catch (java.lang.InterruptedException e) {
16+
throw new InterruptionException(e);
17+
}
18+
}
19+
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package info.novatec.testit.webtester.waiting;
2+
3+
import info.novatec.testit.webtester.WebTesterException;
4+
5+
6+
/**
7+
* This {@link WebTesterException} is thrown in case a wait operation is interrupted.
8+
*
9+
* @see Wait
10+
* @see WaitUntil
11+
* @since 2.0
12+
*/
13+
public class InterruptionException extends WebTesterException {
14+
15+
public InterruptionException(Throwable cause) {
16+
super(cause);
17+
}
18+
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package info.novatec.testit.webtester.waiting;
2+
3+
/**
4+
* Implementations of this interface can be used to trigger a 'sleep' state for a certain amount of time.
5+
*
6+
* @since 2.0
7+
*/
8+
interface Sleeper {
9+
/**
10+
* Sleep for the given amount of milliseconds.
11+
*
12+
* @param milliseconds the milliseconds to sleep
13+
* @throws InterruptionException in case the sleep operation is interrupted
14+
* @since 2.0
15+
*/
16+
void sleep(long milliseconds) throws InterruptionException;
17+
}

webtester-core/src/main/java/info/novatec/testit/webtester/waiting/TimeoutException.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
import info.novatec.testit.webtester.WebTesterException;
44

5+
6+
/**
7+
* This {@link WebTesterException} is thrown in case a wait operation timed out.
8+
*
9+
* @see Wait
10+
* @see WaitUntil
11+
* @since 2.0
12+
*/
513
public class TimeoutException extends WebTesterException {
614

715
public TimeoutException(String message) {

webtester-core/src/main/java/info/novatec/testit/webtester/waiting/Wait.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77

88
/**
9-
* This class aims to provide a fluent API for wait operations.
10-
* It is currently considered 'beta' and is subject to (possibly breaking) changes.
9+
* This class provides a fluent API for wait operations.
1110
* <p>
1211
* <b>Example:</b>
1312
* <pre>
@@ -18,60 +17,87 @@
1817
* Wait.until(fragment).is(visible()).but().not(editable());
1918
* </pre>
2019
*
21-
* @see WaitOperations
20+
* @see Waiter
2221
* @since 2.0
2322
*/
2423
public final class Wait {
2524

25+
/**
26+
* The {@link Waiter} to use when executing wait operations.
27+
* This field is package-private in order to allow for it to be tests.
28+
*/
29+
private static Waiter waiter = new Waiter();
30+
2631
private Wait() {
2732
// utility class constructor
2833
}
2934

3035
/**
3136
* Creates a {@link ConfiguredWait configured fluent wait} with a custom timeout.
37+
* <p>
38+
* <b>Note:</b> see {@link WaitConfig} for defaults besides the timeout!
3239
*
3340
* @param timeout the timeout in seconds
3441
* @return the fluent wait instance
3542
* @see Wait
3643
* @see ConfiguredWait
44+
* @see WaitConfig
3745
* @since 2.0
3846
*/
39-
public static ConfiguredWait withTimeoutOf(long timeout) {
40-
return withTimeoutOf(timeout, TimeUnit.SECONDS);
47+
public static ConfiguredWait withTimeoutOf(int timeout) {
48+
return new ConfiguredWait(waiter, new WaitConfig().setTimeout(timeout));
4149
}
4250

4351
/**
4452
* Creates a {@link ConfiguredWait configured fluent wait} with a custom timeout and time unit.
53+
* <p>
54+
* <b>Note:</b> see {@link WaitConfig} for defaults besides the timeout!
4555
*
4656
* @param timeout the timeout value
4757
* @param timeUnit the time unit the value is specified as
4858
* @return the fluent wait instance
4959
* @see Wait
5060
* @see ConfiguredWait
61+
* @see WaitConfig
5162
* @since 2.0
5263
*/
53-
public static ConfiguredWait withTimeoutOf(long timeout, TimeUnit timeUnit) {
54-
return new ConfiguredWait(timeout, timeUnit);
64+
public static ConfiguredWait withTimeoutOf(int timeout, TimeUnit timeUnit) {
65+
return new ConfiguredWait(waiter, new WaitConfig().setTimeout(timeout).setTimeUnit(timeUnit));
5566
}
5667

5768
/**
58-
* Creates a {@link WaitUntil fluent wait until} with the default timeout of the browser the given
59-
* {@link PageFragment fragment} was created in.
69+
* Creates a {@link WaitUntil} with the default timeout configuration of {@link WaitConfig} for the given object.
70+
*
71+
* @param object the object for the wait until operation
72+
* @param <T> the type of the object
73+
* @return the fluent wait instance
74+
* @see Wait
75+
* @see WaitUntil
76+
* @see WaitConfig
77+
* @since 2.0
78+
*/
79+
public static <T> WaitUntil<T> until(T object) {
80+
return new WaitUntil<>(waiter, new WaitConfig(), object);
81+
}
82+
83+
/**
84+
* Creates a {@link WaitUntil} with the default timeout from the given {@link PageFragment}'s configuration.
6085
*
6186
* @param fragment the fragment for the wait until operation
6287
* @param <T> the type of the page fragment subclass
6388
* @return the fluent wait instance
6489
* @see Wait
6590
* @see WaitUntil
91+
* @see WaitConfig
6692
* @since 2.0
6793
*/
6894
public static <T extends PageFragment> WaitUntil<T> until(T fragment) {
69-
return new WaitUntil<>(fragment);
95+
return new WaitUntil<>(waiter, WaitConfig.from(fragment), fragment);
7096
}
7197

7298
/**
7399
* Waits the given amount of time with the given unit.
74-
*
100+
* <p>
75101
* <b>Example:</b>
76102
* <pre>
77103
* Wait.exactly(10, TimeUnit.SECONDS);
@@ -83,7 +109,7 @@ public static <T extends PageFragment> WaitUntil<T> until(T fragment) {
83109
* @since 2.0
84110
*/
85111
public static void exactly(long duration, TimeUnit timeUnit) {
86-
WaitOperations.wait(duration, timeUnit);
112+
waiter.waitExactly(duration, timeUnit);
87113
}
88114

89115
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package info.novatec.testit.webtester.waiting;
2+
3+
import java.util.concurrent.TimeUnit;
4+
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
import lombok.experimental.Accessors;
8+
9+
import info.novatec.testit.webtester.browser.Browser;
10+
import info.novatec.testit.webtester.config.Configuration;
11+
import info.novatec.testit.webtester.pagefragments.PageFragment;
12+
13+
14+
/**
15+
* This class is used to store configuration parameters for wait operations. This includes a timeout, the unit of the
16+
* timeout
17+
* as well as an invervall which should be used by periodical check waits like a 'wait until X'.
18+
*
19+
* @see Wait
20+
* @see WaitUntil
21+
* @since 2.0
22+
*/
23+
@Getter
24+
@Setter
25+
@Accessors(chain = true)
26+
@SuppressWarnings("PMD")
27+
public class WaitConfig {
28+
29+
public static final int DEFAULT_TIMEOUT = 2;
30+
public static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;
31+
public static final long DEFAULT_INTERVAL = 100L;
32+
33+
/**
34+
* The timeout to use. It's actual value is relative to it's {@link #timeUnit}.
35+
*/
36+
private int timeout = DEFAULT_TIMEOUT;
37+
/**
38+
* The time unit to use when evaluating the {@link #timeout}.
39+
*/
40+
private TimeUnit timeUnit = DEFAULT_TIME_UNIT;
41+
/**
42+
* The interval in which to check conditions of 'wait until X' style wait operations.
43+
*/
44+
private long interval = DEFAULT_INTERVAL;
45+
46+
/**
47+
* Converts the set {@link #timeout} into milliseconds.
48+
*
49+
* @return the timeout in milliseconds
50+
* @since 2.0
51+
*/
52+
public long getTimeoutInMillis() {
53+
return timeUnit.toMillis(timeout);
54+
}
55+
56+
/**
57+
* Creates a new {@link WaitConfig} from the given {@link PageFragment}'s {@link Configuration}.
58+
*
59+
* @param fragment the fragment who's configuration should be used
60+
* @return the new wait config instance
61+
* @since 2.0
62+
*/
63+
static WaitConfig from(PageFragment fragment) {
64+
return from(fragment.getBrowser());
65+
}
66+
67+
/**
68+
* Creates a new {@link WaitConfig} from the given {@link Browser}'s {@link Configuration}.
69+
*
70+
* @param browser the browser who's configuration should be used
71+
* @return the new wait config instance
72+
* @since 2.0
73+
*/
74+
static WaitConfig from(Browser browser) {
75+
return from(browser.configuration());
76+
}
77+
78+
/**
79+
* Creates a new {@link WaitConfig} from the given {@link Configuration}.
80+
*
81+
* @param configuration the configuration to used
82+
* @return the new wait config instance
83+
* @since 2.0
84+
*/
85+
static WaitConfig from(Configuration configuration) {
86+
return new WaitConfig().setTimeout(configuration.getWaitTimeout())
87+
.setTimeUnit(TimeUnit.SECONDS)
88+
.setInterval(configuration.getWaitInterval());
89+
}
90+
91+
}

0 commit comments

Comments
 (0)