My html code is:
<div class="v-datefield v-datefield-popupcalendar v-widget webdp-ui-datefield v-datefield-webdp-ui-datefield v-required v-datefield-required v-has-width v-datefield-year" id="buildingYear" style="width: 255px;">
<input type="text" class="v-textfield v-datefield-textfield" autocomplete="off" aria-describedby="gwt-uid-357" aria-controls="gwt-uid-358" id="gwt-uid-386" aria-labelledby="gwt-uid-385" aria-required="true" tabindex="0">
<button type="button" class="v-datefield-button" tabindex="-1" role="button" aria-hidden="true" aria-controls="gwt-uid-358" aria-disabled="false"></button></div>
I tried to acces input text (By.cssSelector) to write the value in this field but not working. Version of my code is:
WebElement buildingYear = wait.until(ExpectedConditions.
presenceOfElementLocated(By.cssSelector("#buildingYear input")));
buildingYear.sendKeys("2024");
Error: Exception in thread "main" org.openqa.selenium.ElementNotInteractableException: element not interactable
I tried next code and it works:
WebElement buildingYear = wait.until(ExpectedConditions.
presenceOfElementLocated(By.xpath("//input[@id='gwt-uid-386']"))); //works
buildingYear.sendKeys("2024");
But here I have a problem with @id (this is dynamic value) and I can't get it.
How do I select a input value from that div? Can you help me, please?
I have a couple suggestions:
Check the CSS selector in the browser devtools to make sure it's unique on that page.
Open that page in the browser, open the devtools (usually F12), and try $$("#buildingYear input")
to run your CSS selector. NOTE: You can use $x(locator)
to test XPaths. Does it return more than 1 element? I'm guessing that it's going to return more than one and maybe the first one it returns is in the mobile version of the page, etc. so that it's not visible, i.e. not interactable. If this is the case, try to find a parent element that you can use to separate the two (or more) versions of the page, e.g. some pages have a high level DIV, etc. with id='mobile' vs id='desktop' or similar. Then you can change your locator to "#desktop #buildingYear input".
Use ExpectedConditions.visibilityOfElementLocated()
instead of ExpectedConditions.presenceOfElementLocated()
.
Presence means that the element exists in the DOM but not that it is visible and can be interacted with. If the page is a little slow to finish loading, this may solve the problem assuming your CSS selector locator is unique on the page (issue #1).
Use presence if you need to find an element but it doesn't need to be visible. Use visible if you plan to interact with it (get text from, etc.). Use clickable if you are going to click it.
Another option would be to write a method that takes a locator, finds all elements, and then filters down to only those elements that are visible, e.g.
public List<WebElement> findVisibleElements(By locator) {
return driver.findElements(locator).stream().filter(e -> e.isDisplayed()).collect(Collectors.toList());
}
You can use it like
List<WebElement> inputs = SeleniumSandbox.findVisibleElements(By.cssSelector("#buildingYear input"));
System.out.println(inputs.size()); // this should be 1
inputs.get(0).sendKeys("2024");
I would only use this if you can't find a way to make the locator unique as in suggestion #1, above.