org.openqa.selenium.ElementNotVisibleException: Element is not currently visible while clicking a checkbox through SeleniumWebDriver and Java
I have to select a checkbox that is contained in the following HTML snippet. The checkbox is contained in an input tag
<div formarrayname="entityTypes" fxlayout="" fxlayoutgap="10px" class="ng-untouched ng-pristine ng-valid ng-star-inserted" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div class="form-row ng-untouched ng-pristine ng-valid" fxlayout="row" fxlayoutgap="10px" style="flex-direction: row; box-sizing: border-box; display: flex;">
<app-checkbox formcontrolname="isSelected" _nghost-c26="" class="ng-untouched ng-pristine ng-valid"><div _ngcontent-c26="" class="checkbox-wrapper">
<span _ngcontent-c26="" class="tix-checkbox" fxlayout="row" fxlayoutalign="start center" style="flex-direction: row; box-sizing: border-box; display: flex; max-height: 100%; place-content: center flex-start; align-items: center;">
<!---->
<input _ngcontent-c26="" type="checkbox" name="undefined" class="ng-star-inserted" style="" xpath="1">
Funder
<label _ngcontent-c26=""></label>
</span>
<!---->
<!---->
</div>
</app-checkbox>
</div>
</div>
I have tried various things to identify it and select it but it is never visible. I have printed out the text of the label of the checkbox to the console so can't understand why the checkbox itself is not visible. The following java code successfully prints the label but fails to click the checkbox and throws the error element not visible.
//print text of input box
WebElement labelFunder = driver.findElement(By.xpath("//div[@fxflex='50']//div[3]//div[1]//app-checkbox[1]//div[1]//span[1]//input[1]"));
String textFunderLabel2 = labelFunder.getAttribute("innerText").toString();
System.out.println(textFunderLabel);
labelFunder.click();
I have tried different waits but that has not been successful either.
//select the funder checkbox
//driver.findElement(By.xpath("//div[@fxflex='50']//div[3]//div[1]//app-checkbox[1]//div[1]//span[1]//input[@type='checkbox']")).click();
//WebDriverWait wait = new WebDriverWait(driver, 30);
//WebElement checkbox = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html[1]/body[1]/app-root[1]/main[1]/section[1]/div[2]/app-company-detail[1]/div[2]/form[1]/md-tab-group[1]/div[1]/md-tab-body[1]/div[1]/div[1]/div[2]/div[1]/div[2]/div[3]/div[1]/app-checkbox[1]/div[1]/span[1]/input[1]")));
//checkbox.click();
Could anyone point me in the right direction here
Thanks.
Solution 1:
This complete error message is...
Exception in thread "main" org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with Command duration or timeout: 2.05 seconds
...implies that the desired element was not visible within the HTML DOM while the WebDriver instance was trying to find it.
ElementNotVisibleException
ElementNotVisibleException is thrown to indicate that although an element is present on the DOM Tree, it is not visible, and so is not able to be interacted with. It is a runtime exception and have the following hierarchy:
java.lang.RuntimeException
org.openqa.selenium.WebDriverException
org.openqa.selenium.InvalidElementStateException
org.openqa.selenium.ElementNotInteractableException
org.openqa.selenium.ElementNotVisibleException
Field Summary
The fields of this exception are inherited from class org.openqa.selenium.WebDriverException and are as follows:
Modifier and Type Field and Description
--------------------------------- ---------------------
protected static java.lang.String BASE_SUPPORT_URL
static java.lang.String DRIVER_INFO
static java.lang.String SESSION_ID
Reason
One possitive take away from ElementNotVisibleException is the fact that the WebElement is present within the HTML and this exception is commonly encountered when trying to click()
or read
an attribute of an element that is hidden from view.
Solution
As ElementNotVisibleException ensures that the WebElement is present within the HTML so the solution ahead would be two folds as per the next steps as detailed below:
-
If you next step is to read any attribute of the desired element, then you need to induce WebDriverWait in-conjunction with ExpectedConditions clause set to visibilityOfElementLocated as follows:
//using id attribute new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.id("element_id"))).getAttribute("innerHTML"); //using linkText attribute new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.linkText("element_linkText"))).getAttribute("innerHTML"); //using cssSelector new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("element_cssSelector"))).getAttribute("innerHTML"); //using xpath new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath"))).getAttribute("innerHTML");
-
If you next step is to invoke
click()
on the desired element, then you need to induce WebDriverWait in-conjunction with ExpectedConditions clause set to elementToBeClickable as follows://using id attribute new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.id("element_id"))).click(); //using linkText attribute new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.linkText("element_linkText"))).click(); //using cssSelector new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.cssSelector("element_cssSelector"))).click(); //using xpath new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("element_xpath"))).click();
This usecase
The desired element is an Angular element so you need to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
-
cssSelector
:new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("span.tix-checkbox input.ng-star-inserted[name='undefined']"))).click();
-
xpath
:new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//span[@class='tix-checkbox']//input[@class='ng-star-inserted' and @name='undefined']"))).click();
Solution 2:
Try with javascript click:
public void clickElementWithJS(By locator) {
String jsClickCode = "arguments[0].scrollIntoView(true); arguments[0].click();";
try {
WebElement elementToClick = driver.findElement(locator);
((JavascriptExecutor) driver).executeScript(jsClickCode, elementToClick);
} catch(Exception e) {
System.out.println("Element could not be clicked.. " + e.getMessage());
}
}