stackoverflow
stackoverflow

Reputation: 2224

Element not visible exception - even if different Selenium waits are used

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

Answers (5)

user6006374
user6006374

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

Radhika Kanle
Radhika Kanle

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

Akceptor
Akceptor

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

nikhil udgirkar
nikhil udgirkar

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

VolkerK
VolkerK

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

Related Questions