Custom ExpectedCondition in Selenium Java - Build an Automation Script
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.TimeoutException; import java.time.Duration; import static org.junit.jupiter.api.Assertions.assertEquals; public class CustomExpectedConditionTest { private WebDriver driver; public CustomExpectedConditionTest(WebDriver driver) { this.driver = driver; } public void waitForTextToBeCompleted() { By statusMessageLocator = By.id("status-message"); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); // Custom ExpectedCondition using lambda ExpectedCondition<Boolean> textIsCompleted = drv -> { WebElement element = drv.findElement(statusMessageLocator); return "Completed".equals(element.getText()); }; try { wait.until(textIsCompleted); WebElement statusElement = driver.findElement(statusMessageLocator); assertEquals("Completed", statusElement.getText(), "Status message text should be 'Completed'"); } catch (TimeoutException e) { throw new AssertionError("Timed out waiting for text to be 'Completed'", e); } } }
The code defines a method waitForTextToBeCompleted that waits up to 10 seconds for the element with id status-message to have the exact text Completed.
We use WebDriverWait with a custom ExpectedCondition implemented as a lambda. This lambda checks the element's text and returns true only when it matches Completed.
If the wait succeeds, we assert the text is exactly Completed. If the wait times out, we throw an assertion error with a clear message.
This approach avoids using Thread.sleep, uses explicit waits, and follows best practices for element locating and exception handling.
Now add data-driven testing with 3 different expected texts: 'Completed', 'Failed', 'Pending'
Practice
Custom ExpectedCondition in Selenium Java?Solution
Step 1: Understand the role of ExpectedCondition
ExpectedCondition defines a condition that WebDriverWait checks repeatedly until it returns a non-null value or true.Step 2: Purpose of Custom ExpectedCondition
Creating a custom one allows you to specify your own logic for waiting, beyond built-in conditions.Final Answer:
To define a specific condition that WebDriverWait will wait for before proceeding -> Option DQuick Check:
Custom ExpectedCondition = Custom wait logic [OK]
- Thinking it replaces WebDriverWait
- Assuming it speeds up tests by skipping waits
- Confusing it with reporting features
Solution
Step 1: Recall ExpectedCondition interface
The ExpectedCondition interface requires implementing theapplymethod that takes a WebDriver and returns a result or null.Step 2: Identify correct method name
Onlyapply(WebDriver driver)is the correct method signature for custom conditions.Final Answer:
apply(WebDriver driver) -> Option AQuick Check:
Custom ExpectedCondition method = apply() [OK]
- Using wrong method names like waitForCondition or execute
- Confusing with WebElement methods
- Missing the WebDriver parameter
ExpectedCondition<Boolean> condition = driver -> {
WebElement el = driver.findElement(By.id("status"));
return el.getText().equals("Ready") ? true : null;
};
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
boolean result = wait.until(condition);Solution
Step 1: Analyze the condition logic
The condition returns true if the element's text equals "Ready", otherwise null.Step 2: Understand WebDriverWait behavior
WebDriverWait waits until the condition returns a non-null, true value. Since text is "Ready", condition returns true immediately.Final Answer:
The wait will pass and result will be true -> Option BQuick Check:
Condition true means wait passes [OK]
- Thinking null return means pass
- Assuming wait throws error on true
- Confusing null with false
ExpectedCondition<Boolean> condition = driver -> {
WebElement el = driver.findElement(By.id("submit"));
if(el.isDisplayed()) {
return true;
} else {
return false;
}
};Solution
Step 1: Understand ExpectedCondition return rules
ExpectedCondition should return null to continue waiting, true to stop waiting successfully.Step 2: Analyze the code's return values
Returning false causes wait.until to stop waiting and throw TimeoutException immediately, which is not desired.Final Answer:
Returning false instead of null causes wait.until to stop waiting prematurely -> Option CQuick Check:
Return null to keep waiting, not false [OK]
- Returning false instead of null to continue wait
- Assuming lambda is invalid
- Ignoring exception handling
Solution
Step 1: Understand the requirement
Wait until at least 3 elements with class 'item' are visible (isDisplayed() true).Step 2: Analyze each option
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); long visibleCount = items.stream().filter(WebElement::isDisplayed).count(); return visibleCount >= 3 ? true : null; }; counts visible elements and returns true if count >= 3, else null to keep waiting. This matches requirement and wait logic.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); int count = 0; for(WebElement item : items) { if(item.isDisplayed()) count++; } return count > 3 ? true : false; }; returns false if count is not > 3, which stops wait prematurely.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); return items.size() >= 3; }; checks total size, ignoring visibility.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); return items.stream().allMatch(WebElement::isDisplayed); }; waits until all are visible, not at least 3.Final Answer:
Option A correctly waits for at least 3 visible elements -> Option AQuick Check:
Return true if condition met, else null to wait [OK]
- Returning false instead of null to continue wait
- Ignoring visibility check
- Checking all elements visible instead of at least 3
Ready to prove it?
Pass the test and this pattern moves unknown
