The following search method executes a keyword search by
clearing an existing value from the search box
typing a keyword in the search box
pressing ENTER
public ResultsPage search(String keyword) {
driver.findElement(SEARCH_BOX_ID).clear();
driver.findElement(SEARCH_BOX_ID).sendKeys(keyword);
driver.findElement(SEARCH_BOX_ID).sendKeys(Keys.ENTER);
return new ResultsPage(driver);
}
On the first look, it seems to be correct.
Looking more carefully, though,
one can see that driver.findElement(SEARCH_BOX_ID) is used in all 3 lines of the method. This means that the element is found once for clearing the search box, then found again for typing the keyword and found one more time for pressing ENTER.
The element is found 3 times.
This is very inefficient and also done through code duplication.
It is incorrect to find the element each time it is used. Unless the element changes all the time (it changes after it is cleared and then it changes again after the keyword is typed).
Instead of finding the element multiple times, we should find it once:
public ResultsPage search(String keyword) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
wait.until(ExpectedConditions.elementToBeClickable(SEARCH_BOX_ID));
WebElement searchBox = driver.findElement(SEARCH_BOX_ID);
searchBox.clear();
searchBox.sendKeys(keyword);
searchBox.sendKeys(Keys.ENTER);
return new ResultsPage(driver);
}
This method waits until the element is in the page and the element’s status is clickable before finding the element.
We can simplify this method a bit as follows:
public ResultsPage search(String keyword) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
WebElement searchBox = wait.until(
ExpectedConditions.elementToBeClickable(SEARCH_BOX_ID));
searchBox.clear();
searchBox.sendKeys(keyword);
searchBox.sendKeys(Keys.ENTER);
return new ResultsPage(driver);
}
The wait.until() method returns the element that it waited for, if the element is found.
This method is shorter than the previous one but less clear. It is not obvious that the wait.until() does both the waiting for the element and also the element’s finding.
But, what if the element changes every time it is used?
What do we do in this case?
In this situation, move the element finding to a separate private method and use the private method in search(). The element will still be found 3 times but at least there is no code duplication:
public ResultsPage search(String keyword) {
searchBox().clear();
searchBox().sendKeys(keyword);
searchBox().sendKeys(Keys.ENTER);
return new ResultsPage(driver);
}
private WebElement searchBox() {
return driver.findElement(SEARCH_BOX_ID);
}