How can I use WebDriverWait.until without a locator?
I am using Selenium WebDriver implemented with framework (Cucumber) and before doing action on it I ran into problem while waiting for item to load.
At first I wanted to use implicit waits, but if the item is not loaded immediately, it will wait for a timeout. As is often the case, this makes my tests take longer than I would like.
Then I want to use Explicit Wait to make the wait as short as possible for each case. The problem is that most of the ExpectedConditions in WebDriverWait.until look for elements located by the By locator (which are ClassName, CssSelector, Id, LinkText, Name, PartialLinkText, Tagname, or XPath). I am using WebDriverWait.until in a generic function used to click on a web element. The web elements on the website I am testing are generated by dojo and do not have a static id. They don't always have a different type of locator, or they are not static. The developers then added an additional attribute called data-automation-id to the web element. I would like to use this attribute in an explicit expectation, but could not find a way to do it.
I tried xpath using the following code:
public void clickOnDataAutomationId(String dataautomationid) {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//" + findDataAutomationId(dataautomationid).getAttribute("tagName") + "[contains(@data-automation-id, '" + dataautomationid + "')]")));
findDataAutomationId(dataautomationid).click();
}
findDataAutomationId () is a function that returns the first web element containing a data automation identifier as a FluentWebElement.
The problem is that findDataAutomationId fails if the web element is not loaded immediately, making WebDriverWait.until meaningless. Do you see another way to bypass Locators without refactoring the website?
source to share
Instead of retrieving the web element using the findDataAutomationId method , you can directly find the web element and then click on it like below:
public void clickOnDataAutomationId(String dataautomationid) {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(@data-automation-id, '" + dataautomationid + "')]")));
element.click();
}
OR if data-automation-id is full text and not part, then you can use the below code:
public void clickOnDataAutomationId(String dataautomationid) {
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@data-automation-id, '" + dataautomationid + "')]")));
element.click();
}
source to share
You are below the solution. It will not return until apply () is true or until the timeout has expired
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(new Function<WebDriver, Object>() {
@Nullable
public Object apply(@Nullable WebDriver input) {
//add any condition or check your data-automation-id is visible/clickable
return true;
}
});
}
source to share