Sriram Sridharan
Sriram Sridharan

Reputation: 740

Selenium WebDriver - Strange behavior in simulating mouseover

I have a drop down menu, whose mark-up is like below:

<li>
  <a href="#">Services</a>
  <div class="menu-drop">
    <a href="#">Service 1</a>
    <a href="#">Service 2</a>
  </div>
</li>
<li>
  <a href="#">Operations</a>
  <div class="menu-drop">
    <a href="#">Operation 1</a>
    <a href="#">Operation 2</a>
  </div>
</li>

The links "Services" and "Operations" are the menu items, hovering upon which brings up a dropdown div with the two sub menu items.

Now, If I have to use WebDriver to click "Services 1" link, I'll have to hover on the "Services" menu option and then click "Service 1".

I am doing this by using the following code:

WebElement menu = driver.findElement(By.linkText("Services"));
Actions builder = new Actions(driver);
builder.moveToElement(menu).build().perform();
WebElement li = menu.findElement(By.xpath("ancestor::li"));
WebElement menuDrop = li.findElement(By.className("menu-drop"));
WebElement subMenuLink = menuDrop.findElement(By.linkText("Service 1"));
subLink.click();

By the way, I use Eclipse to develop my framework.

Now, the above code works perfectly fine, ONLY when I debug it in eclipse. Meaning, I have a breakpoint next to the first line of the code-snippet I've given here, and then press F6 and keep doing that, it works perfectly fine.

But when I don't, that is, when I run the code without breakpoints, it just doesn't work. What happens is, the hover is performed, but only for a fraction of a second, and the following line

WebElement subMenuLink = menuDrop.findElement(By.linkText("Service 1"));

returns a no such element exception.

What could be the problem?

Upvotes: 1

Views: 1360

Answers (5)

schattenjager
schattenjager

Reputation: 105

I had the same issue and the reason was that elements were not available yet, the DOM was not updated in time, so I made it work inserting a thread.sleep() before some driver.findelements(), something like this:

try {
     Thread.sleep(1500);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
     driver.findElement(By.xpath("<xpath_here>").click();

I know is not the most beautiful way, but when it fails even with using WebdriverWait, it saves me some pain.

Upvotes: 0

Amol Thakurdware
Amol Thakurdware

Reputation: 1

I have also faced the same problem. Use javascript as a workaround.

public static void mouseHoverJScript(WebElement HoverElement) {
        try {
            if (isElementPresent(HoverElement)) {

                String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover',true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
                ((JavascriptExecutor) Selenium.webDriver).executeScript(mouseOverScript,HoverElement);

        } else {
            System.out.println("Element was not visible to hover " + "\n");

        }
    } catch (StaleElementReferenceException e) {
        System.out.println("Element with " + HoverElement
                + "is not attached to the page document"
                + e.getStackTrace());
    } catch (NoSuchElementException e) {
        System.out.println("Element " + HoverElement + " was not found in DOM"
                + e.getStackTrace());
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Error occurred while hovering"
                + e.getStackTrace());
    }
}

public static boolean isElementPresent(WebElement element) {
    boolean flag = false;
    try {
        if (element.isDisplayed()
                || element.isEnabled())
            flag = true;
    } catch (NoSuchElementException e) {
        flag = false;
    } catch (StaleElementReferenceException e) {
        flag = false;
    }
    return flag;
}

Upvotes: 0

nilesh
nilesh

Reputation: 14287

If this works in debug mode, that means it could be probably a synchronization issue. You are probably trying to click on the element before the DOM is even updated. The work around you found could just be a false alarm. By the time you move your mouse to the active window, the DOM could perhaps be loaded and thats why probably you are able to click on the element.

Did you try something like this?

WebDriverWait wait = new WebDriverWait(driver,30);
WebElement menu = driver.findElement(By.linkText("Services"));
Actions builder = new Actions(driver);
builder.moveToElement(menu).build().perform();
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Service 1"))).click();

Edit #1 Try this,

 builder.moveToElement(menu).click(driver.findElement(By.linkText("Service 1"))).perform();

If you get NoSuchElementException for linkText then you must use WebDriverWait because you are trying to find the element before it actually appears in the DOM. In that case try below.

builder.moveToElement(menu).click(wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Service 1")))).perform();

Upvotes: 1

Sriram Sridharan
Sriram Sridharan

Reputation: 740

Ok. I figured it out. But I cannot say if it is a solution or a workaround. The latter seems to be more appealing.

I stumbled upon this link

Issue with losing focus of “hover” command when the mouse is outside of the active window

According to what was discussed there, I just moved my real mouse cursor to a point (any point) in the active window where the test is running, and it worked.

It's funny for sure, but I would appreceate if someone can throw light on the exact cause of the problem and help me find the solution.

Upvotes: 0

Alpha
Alpha

Reputation: 14046

Please give a try with following:

action.moveToElement(menu).moveToElement(subMenuLink).click().build().perform();

Upvotes: 0

Related Questions