Reputation: 2224
I am trying to automate functional testing of a web application using Selenium and Java. In my application there are several menus. When clicked on a particular menu, a drop down of sub menus appear click to view screenshot of menu
I use below code to click sub menu
driver.findElement(By.xpath("id=menu")).click();
driver.findElement(By.xpath("id=sub_menu_a")).click();
but the issue is that it throws a 'ElementNotVisibleException' at the second line. The same happens even if I use implicit wait
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
explicit wait
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
and fluent wait.
Wait<WebDriver> fluentWait=new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(2, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class,ElementNotVisibleException.class);
WebElement element=fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver){
driver.findElement(By.xpath("id=menu"));
return driver.findElement(By.xpath("id=sub_menu_a"));
}
});
element.click();
but no luck. But the code works fine if add sleep time using
Thread.sleep(sleeptime);
before and after the first line of code. But it is not a permanent solution since the page load time may vary depend on the network speed and the data in the page. Is there any other solution?
Upvotes: 2
Views: 2232
Reputation:
Try this
WebElement menu=driver.findElement(By.xpath("id=menu"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", menu);
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
executor.executeScript("arguments[0].click();", subMenu);
Hope this work
Upvotes: 1
Reputation: 86
Try to use Actions class and see if it works or not ...
driver.findElement(By.xpath("id=menu")).click();
WebElement subMenu=driver.findElement(By.xpath("id=sub_menu_a"));
Actions myaction = new Actions(driver);
myaction.moveToElement(subMenu);
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(subMenu));
myaction.click().perform();
Upvotes: 1
Reputation: 1932
Long time ago I have the similar issue (don't remember the exact case so indeed your HTML page snipped would be helpful) so I was forced to use Thread.sleep() To avoid long waits will propose something like this method:
static void waitAndClick(WebDriver driver, By by, int attempts, int sleep) throws InterruptedException {
for (int i = 0; i < attempts; i++) {
WebElement element = null;
try {
element = driver.findElement(by);
} catch (NoSuchElementException e) {
// Do nothing
}
if (element == null) {
int time = sleep * (i + 1);
Thread.sleep(time);
} else {
element.click();
break;
}
}
throw new NoSuchElementException("Error");
}
It's not a 100% complete solution but just an idea.
Upvotes: 0
Reputation: 357
Could you try
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("id=sub_menu_a")));
Also it would be better if you can give html to find the right xpath as I think better XPATH will yield the result of click on the submenu.
Upvotes: 0
Reputation: 1510
Fluent waits should work fine. Try using something like this:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("id=sub_menu_a")));
but I would go for css Selectors they are perfect for html pages.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#sub_menu_a")));
Or if your sub_menu_a is a child of menu I would go for
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).ignoring(NoSuchElementException.class);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#menu #sub_menu_a")));
Upvotes: 0