0
# Waits and Conditions
1
2
Selenium provides sophisticated waiting mechanisms for handling dynamic content, including explicit waits with pre-built conditions and custom wait logic support.
3
4
## Capabilities
5
6
### WebDriverWait Class
7
8
Explicit wait implementation extending FluentWait for WebDriver-specific operations.
9
10
```java { .api }
11
/**
12
* WebDriverWait class for explicit waiting with WebDriver
13
* Extends FluentWait<WebDriver> with WebDriver-specific functionality
14
*/
15
class WebDriverWait extends FluentWait<WebDriver> {
16
/**
17
* Create WebDriverWait with specified timeout
18
* @param driver - WebDriver instance
19
* @param timeout - Duration to wait before timeout
20
*/
21
WebDriverWait(WebDriver driver, Duration timeout);
22
23
/**
24
* Create WebDriverWait with timeout and polling interval
25
* @param driver - WebDriver instance
26
* @param timeout - Duration to wait before timeout
27
* @param sleep - Polling interval duration
28
*/
29
WebDriverWait(WebDriver driver, Duration timeout, Duration sleep);
30
31
/**
32
* Wait until condition returns non-null/true value
33
* @param isTrue - Function that returns result when condition met
34
* @return Result of the condition function
35
* @throws TimeoutException if timeout reached
36
*/
37
<V> V until(Function<WebDriver, V> isTrue);
38
39
/**
40
* Wait until expected condition is met
41
* @param condition - ExpectedCondition to wait for
42
* @return Result of the expected condition
43
* @throws TimeoutException if timeout reached
44
*/
45
<V> V until(ExpectedCondition<V> condition);
46
}
47
```
48
49
### FluentWait Class
50
51
Generic fluent wait implementation with configurable timeout, polling, and exception handling.
52
53
```java { .api }
54
/**
55
* FluentWait class providing fluent interface for configurable waiting
56
* @param <T> - Type of object to wait on (typically WebDriver)
57
*/
58
class FluentWait<T> {
59
/**
60
* Create FluentWait for specified object
61
* @param input - Object to wait on
62
*/
63
FluentWait(T input);
64
65
/**
66
* Set maximum timeout duration
67
* @param timeout - Maximum time to wait
68
* @return FluentWait instance for chaining
69
*/
70
FluentWait<T> withTimeout(Duration timeout);
71
72
/**
73
* Set polling interval
74
* @param interval - Time between condition checks
75
* @return FluentWait instance for chaining
76
*/
77
FluentWait<T> pollingEvery(Duration interval);
78
79
/**
80
* Add exception type to ignore during waiting
81
* @param exceptionType - Exception class to ignore
82
* @return FluentWait instance for chaining
83
*/
84
FluentWait<T> ignoring(Class<? extends Throwable> exceptionType);
85
86
/**
87
* Add multiple exception types to ignore
88
* @param firstType - First exception type
89
* @param secondType - Second exception type
90
* @return FluentWait instance for chaining
91
*/
92
FluentWait<T> ignoring(Class<? extends Throwable> firstType, Class<? extends Throwable> secondType);
93
94
/**
95
* Set custom timeout message
96
* @param message - Message to include in TimeoutException
97
* @return FluentWait instance for chaining
98
*/
99
FluentWait<T> withMessage(String message);
100
101
/**
102
* Set custom timeout message with supplier
103
* @param messageSupplier - Function to generate timeout message
104
* @return FluentWait instance for chaining
105
*/
106
FluentWait<T> withMessage(Supplier<String> messageSupplier);
107
108
/**
109
* Wait until condition returns non-null/true value
110
* @param isTrue - Function that returns result when condition met
111
* @return Result of the condition function
112
* @throws TimeoutException if timeout reached
113
*/
114
<V> V until(Function<T, V> isTrue);
115
}
116
```
117
118
### ExpectedConditions Class
119
120
Utility class providing pre-built expected conditions for common wait scenarios.
121
122
```java { .api }
123
/**
124
* ExpectedConditions utility class with pre-built wait conditions
125
* All methods return ExpectedCondition instances for use with WebDriverWait
126
*/
127
class ExpectedConditions {
128
/**
129
* Wait for element to be present in DOM (not necessarily visible)
130
* @param locator - By locator for element
131
* @return ExpectedCondition for element presence
132
*/
133
static ExpectedCondition<WebElement> presenceOfElementLocated(By locator);
134
135
/**
136
* Wait for all elements to be present in DOM
137
* @param locator - By locator for elements
138
* @return ExpectedCondition for elements presence
139
*/
140
static ExpectedCondition<List<WebElement>> presenceOfAllElementsLocatedBy(By locator);
141
142
/**
143
* Wait for element to be visible (present in DOM and displayed)
144
* @param locator - By locator for element
145
* @return ExpectedCondition for element visibility
146
*/
147
static ExpectedCondition<WebElement> visibilityOfElementLocated(By locator);
148
149
/**
150
* Wait for existing element to become visible
151
* @param element - WebElement to wait for
152
* @return ExpectedCondition for element visibility
153
*/
154
static ExpectedCondition<WebElement> visibilityOf(WebElement element);
155
156
/**
157
* Wait for all elements to become visible
158
* @param elements - List of WebElements to wait for
159
* @return ExpectedCondition for all elements visibility
160
*/
161
static ExpectedCondition<List<WebElement>> visibilityOfAllElements(List<WebElement> elements);
162
163
/**
164
* Wait for all elements located by locator to become visible
165
* @param locator - By locator for elements
166
* @return ExpectedCondition for all elements visibility
167
*/
168
static ExpectedCondition<List<WebElement>> visibilityOfAllElementsLocatedBy(By locator);
169
170
/**
171
* Wait for element to be clickable (visible and enabled)
172
* @param locator - By locator for element
173
* @return ExpectedCondition for element clickability
174
*/
175
static ExpectedCondition<WebElement> elementToBeClickable(By locator);
176
177
/**
178
* Wait for existing element to be clickable
179
* @param element - WebElement to wait for
180
* @return ExpectedCondition for element clickability
181
*/
182
static ExpectedCondition<WebElement> elementToBeClickable(WebElement element);
183
184
/**
185
* Wait for element to be selected
186
* @param element - WebElement to check
187
* @return ExpectedCondition for element selection
188
*/
189
static ExpectedCondition<Boolean> elementToBeSelected(WebElement element);
190
191
/**
192
* Wait for element located by locator to be selected
193
* @param locator - By locator for element
194
* @return ExpectedCondition for element selection
195
*/
196
static ExpectedCondition<Boolean> elementSelectionStateToBe(By locator, boolean selected);
197
198
/**
199
* Wait for text to be present in element
200
* @param element - WebElement to check
201
* @param text - Text to wait for
202
* @return ExpectedCondition for text presence
203
*/
204
static ExpectedCondition<Boolean> textToBePresentInElement(WebElement element, String text);
205
206
/**
207
* Wait for text to be present in element located by locator
208
* @param locator - By locator for element
209
* @param text - Text to wait for
210
* @return ExpectedCondition for text presence
211
*/
212
static ExpectedCondition<Boolean> textToBePresentInElementLocated(By locator, String text);
213
214
/**
215
* Wait for specific text in element's value attribute
216
* @param locator - By locator for element
217
* @param text - Text to wait for in value
218
* @return ExpectedCondition for value text
219
*/
220
static ExpectedCondition<Boolean> textToBePresentInElementValue(By locator, String text);
221
222
/**
223
* Wait for page title to be exact match
224
* @param title - Expected page title
225
* @return ExpectedCondition for title match
226
*/
227
static ExpectedCondition<Boolean> titleIs(String title);
228
229
/**
230
* Wait for page title to contain text
231
* @param title - Text that title should contain
232
* @return ExpectedCondition for title containing text
233
*/
234
static ExpectedCondition<Boolean> titleContains(String title);
235
236
/**
237
* Wait for URL to be exact match
238
* @param url - Expected URL
239
* @return ExpectedCondition for URL match
240
*/
241
static ExpectedCondition<Boolean> urlToBe(String url);
242
243
/**
244
* Wait for URL to contain text
245
* @param fraction - Text that URL should contain
246
* @return ExpectedCondition for URL containing text
247
*/
248
static ExpectedCondition<Boolean> urlContains(String fraction);
249
250
/**
251
* Wait for URL to match regex pattern
252
* @param regex - Regular expression pattern
253
* @return ExpectedCondition for URL pattern match
254
*/
255
static ExpectedCondition<Boolean> urlMatches(String regex);
256
257
/**
258
* Wait for alert to be present
259
* @return ExpectedCondition for alert presence
260
*/
261
static ExpectedCondition<Alert> alertIsPresent();
262
263
/**
264
* Wait for element to become invisible or not present
265
* @param locator - By locator for element
266
* @return ExpectedCondition for element invisibility
267
*/
268
static ExpectedCondition<Boolean> invisibilityOfElementLocated(By locator);
269
270
/**
271
* Wait for element with text to become invisible
272
* @param locator - By locator for element
273
* @param text - Text that element should not contain
274
* @return ExpectedCondition for element invisibility
275
*/
276
static ExpectedCondition<Boolean> invisibilityOfElementWithText(By locator, String text);
277
278
/**
279
* Wait for attribute to contain specific value
280
* @param locator - By locator for element
281
* @param attribute - Attribute name
282
* @param value - Expected attribute value
283
* @return ExpectedCondition for attribute value
284
*/
285
static ExpectedCondition<Boolean> attributeContains(By locator, String attribute, String value);
286
287
/**
288
* Wait for attribute to be specific value
289
* @param locator - By locator for element
290
* @param attribute - Attribute name
291
* @param value - Expected attribute value
292
* @return ExpectedCondition for attribute value
293
*/
294
static ExpectedCondition<Boolean> attributeToBe(By locator, String attribute, String value);
295
296
/**
297
* Wait for frame to be available and switch to it
298
* @param frameLocator - Frame locator (string name/id or By locator)
299
* @return ExpectedCondition for frame availability
300
*/
301
static ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(String frameLocator);
302
static ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(By frameLocator);
303
304
/**
305
* Wait for number of windows to be specific count
306
* @param expectedNumberOfWindows - Expected window count
307
* @return ExpectedCondition for window count
308
*/
309
static ExpectedCondition<Boolean> numberOfWindowsToBe(int expectedNumberOfWindows);
310
311
/**
312
* Combine multiple conditions with AND logic
313
* @param conditions - ExpectedConditions to combine
314
* @return ExpectedCondition that passes when all conditions pass
315
*/
316
static ExpectedCondition<Boolean> and(ExpectedCondition<?>... conditions);
317
318
/**
319
* Combine multiple conditions with OR logic
320
* @param conditions - ExpectedConditions to combine
321
* @return ExpectedCondition that passes when any condition passes
322
*/
323
static ExpectedCondition<Boolean> or(ExpectedCondition<?>... conditions);
324
325
/**
326
* Negate an expected condition
327
* @param condition - ExpectedCondition to negate
328
* @return ExpectedCondition that passes when original condition fails
329
*/
330
static ExpectedCondition<Boolean> not(ExpectedCondition<?> condition);
331
}
332
```
333
334
## Usage Examples
335
336
### Basic WebDriverWait Usage
337
338
```java
339
import org.openqa.selenium.WebDriver;
340
import org.openqa.selenium.WebElement;
341
import org.openqa.selenium.By;
342
import org.openqa.selenium.chrome.ChromeDriver;
343
import org.openqa.selenium.support.ui.WebDriverWait;
344
import org.openqa.selenium.support.ui.ExpectedConditions;
345
import java.time.Duration;
346
347
WebDriver driver = new ChromeDriver();
348
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
349
350
try {
351
driver.get("https://example.com");
352
353
// Wait for element to be present and visible
354
WebElement submitButton = wait.until(
355
ExpectedConditions.visibilityOfElementLocated(By.id("submit"))
356
);
357
358
// Wait for element to be clickable before interaction
359
WebElement loginButton = wait.until(
360
ExpectedConditions.elementToBeClickable(By.id("login"))
361
);
362
loginButton.click();
363
364
// Wait for text to appear in element
365
WebElement statusMessage = driver.findElement(By.id("status"));
366
wait.until(ExpectedConditions.textToBePresentInElement(statusMessage, "Login successful"));
367
368
// Wait for page title change
369
wait.until(ExpectedConditions.titleIs("Dashboard - MyApp"));
370
371
// Wait for URL change
372
wait.until(ExpectedConditions.urlContains("/dashboard"));
373
374
} finally {
375
driver.quit();
376
}
377
```
378
379
### Advanced FluentWait Configuration
380
381
```java
382
import org.openqa.selenium.support.ui.FluentWait;
383
import org.openqa.selenium.NoSuchElementException;
384
import org.openqa.selenium.StaleElementReferenceException;
385
386
// Configure FluentWait with custom settings
387
FluentWait<WebDriver> fluentWait = new FluentWait<>(driver)
388
.withTimeout(Duration.ofSeconds(30))
389
.pollingEvery(Duration.ofMilliseconds(500))
390
.ignoring(NoSuchElementException.class)
391
.ignoring(StaleElementReferenceException.class)
392
.withMessage("Element was not found within 30 seconds");
393
394
// Use fluent wait with custom condition
395
WebElement dynamicElement = fluentWait.until(driver -> {
396
WebElement element = driver.findElement(By.id("dynamic-content"));
397
return element.isDisplayed() && !element.getText().isEmpty() ? element : null;
398
});
399
400
// Wait for complex condition
401
Boolean complexCondition = fluentWait.until(driver -> {
402
List<WebElement> items = driver.findElements(By.className("item"));
403
return items.size() >= 5 && items.stream().allMatch(WebElement::isDisplayed);
404
});
405
```
406
407
### Custom Expected Conditions
408
409
```java
410
import org.openqa.selenium.support.ui.ExpectedCondition;
411
412
// Custom condition: Wait for element to have specific CSS class
413
public static ExpectedCondition<Boolean> elementToHaveClass(By locator, String className) {
414
return driver -> {
415
WebElement element = driver.findElement(locator);
416
String classes = element.getAttribute("class");
417
return classes != null && classes.contains(className);
418
};
419
}
420
421
// Custom condition: Wait for element count to be specific number
422
public static ExpectedCondition<Boolean> numberOfElementsToBe(By locator, int expectedCount) {
423
return driver -> driver.findElements(locator).size() == expectedCount;
424
}
425
426
// Custom condition: Wait for element to be stale (removed from DOM)
427
public static ExpectedCondition<Boolean> stalenessOf(WebElement element) {
428
return driver -> {
429
try {
430
element.isEnabled(); // Any method call will throw if stale
431
return false;
432
} catch (StaleElementReferenceException e) {
433
return true;
434
}
435
};
436
}
437
438
// Usage of custom conditions
439
wait.until(elementToHaveClass(By.id("loading"), "complete"));
440
wait.until(numberOfElementsToBe(By.className("result-item"), 10));
441
wait.until(stalenessOf(oldElement));
442
```
443
444
### Combining Multiple Conditions
445
446
```java
447
// Wait for multiple conditions using AND
448
ExpectedCondition<Boolean> loginComplete = ExpectedConditions.and(
449
ExpectedConditions.titleIs("Dashboard"),
450
ExpectedConditions.presenceOfElementLocated(By.id("user-menu")),
451
ExpectedConditions.invisibilityOfElementLocated(By.id("loading-spinner"))
452
);
453
wait.until(loginComplete);
454
455
// Wait for any of multiple conditions using OR
456
ExpectedCondition<Boolean> pageReady = ExpectedConditions.or(
457
ExpectedConditions.presenceOfElementLocated(By.id("content")),
458
ExpectedConditions.presenceOfElementLocated(By.id("error-message"))
459
);
460
wait.until(pageReady);
461
462
// Use NOT to wait for condition to become false
463
wait.until(ExpectedConditions.not(
464
ExpectedConditions.attributeContains(By.id("status"), "class", "loading")
465
));
466
```
467
468
### Wait for AJAX and Dynamic Content
469
470
```java
471
// Wait for AJAX request to complete (jQuery example)
472
public static ExpectedCondition<Boolean> jQueryAjaxCompleted() {
473
return driver -> {
474
JavascriptExecutor js = (JavascriptExecutor) driver;
475
return (Boolean) js.executeScript("return jQuery.active === 0");
476
};
477
}
478
479
// Wait for element to stop moving (animations complete)
480
public static ExpectedCondition<Boolean> elementToStopMoving(By locator) {
481
return driver -> {
482
WebElement element = driver.findElement(locator);
483
Point location1 = element.getLocation();
484
try {
485
Thread.sleep(100);
486
} catch (InterruptedException e) {
487
Thread.currentThread().interrupt();
488
}
489
Point location2 = element.getLocation();
490
return location1.equals(location2);
491
};
492
}
493
494
// Wait for page to be fully loaded
495
public static ExpectedCondition<Boolean> pageToBeFullyLoaded() {
496
return driver -> {
497
JavascriptExecutor js = (JavascriptExecutor) driver;
498
return js.executeScript("return document.readyState").equals("complete");
499
};
500
}
501
502
// Usage
503
wait.until(jQueryAjaxCompleted());
504
wait.until(elementToStopMoving(By.id("animated-element")));
505
wait.until(pageToBeFullyLoaded());
506
```
507
508
### Error Handling and Retry Patterns
509
510
```java
511
// Retry pattern with multiple attempts
512
public WebElement findElementWithRetry(By locator, int maxAttempts) {
513
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
514
try {
515
return wait.until(ExpectedConditions.presenceOfElementLocated(locator));
516
} catch (TimeoutException e) {
517
if (attempt == maxAttempts) {
518
throw new NoSuchElementException(
519
"Element not found after " + maxAttempts + " attempts: " + locator
520
);
521
}
522
// Refresh page or perform other recovery action
523
driver.navigate().refresh();
524
}
525
}
526
throw new IllegalStateException("Should not reach here");
527
}
528
529
// Wait with graceful degradation
530
public boolean waitForElementOptional(By locator, Duration timeout) {
531
try {
532
WebDriverWait shortWait = new WebDriverWait(driver, timeout);
533
shortWait.until(ExpectedConditions.presenceOfElementLocated(locator));
534
return true;
535
} catch (TimeoutException e) {
536
return false;
537
}
538
}
539
540
// Usage
541
WebElement element = findElementWithRetry(By.id("flaky-element"), 3);
542
boolean isPresent = waitForElementOptional(By.id("optional-element"), Duration.ofSeconds(5));
543
```
544
545
### Performance Considerations
546
547
```java
548
// Use shorter timeouts for fast-failing conditions
549
WebDriverWait shortWait = new WebDriverWait(driver, Duration.ofSeconds(2));
550
boolean isElementPresent = false;
551
try {
552
shortWait.until(ExpectedConditions.presenceOfElementLocated(By.id("fast-element")));
553
isElementPresent = true;
554
} catch (TimeoutException e) {
555
isElementPresent = false;
556
}
557
558
// Use longer timeouts for slow operations
559
WebDriverWait longWait = new WebDriverWait(driver, Duration.ofSeconds(30));
560
longWait.until(ExpectedConditions.textToBePresentInElementLocated(
561
By.id("slow-loading-content"), "Data loaded successfully"
562
));
563
564
// Optimize polling frequency based on expected timing
565
FluentWait<WebDriver> fastPolling = new FluentWait<>(driver)
566
.withTimeout(Duration.ofSeconds(10))
567
.pollingEvery(Duration.ofMilliseconds(100)); // Fast polling for quick changes
568
569
FluentWait<WebDriver> slowPolling = new FluentWait<>(driver)
570
.withTimeout(Duration.ofMinutes(2))
571
.pollingEvery(Duration.ofSeconds(2)); // Slow polling for long operations
572
```