Selenium WebDriver - 模拟鼠标悬停时的奇怪行为

时间:2014-05-07 19:26:12

标签: java selenium-webdriver webdriver mouseover

我有一个下拉菜单,其标记如下:

<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>

链接&#34;服务&#34;和&#34;运营&#34;是菜单项,悬停在其上会显示带有两个子菜单项的下拉列表。

现在,如果我必须使用WebDriver点击&#34;服务1&#34;链接,我将不得不徘徊在&#34;服务&#34;菜单选项,然后单击&#34;服务1&#34;。

我使用以下代码执行此操作:

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();

顺便说一句,我使用Eclipse来开发我的框架。

现在,只有当我在eclipse中调试它时,上面的代码才能正常工作。这意味着,我在这里给出的代码片段的第一行旁边有一个断点,然后按F6并继续这样做,它完全正常。

但是当我没有,也就是说,当我运行没有断点的代码时,它就不起作用了。发生的是,执行悬停,但只执行了几分之一秒,以及后续行

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

返回没有这样的元素异常。

可能是什么问题?

5 个答案:

答案 0 :(得分:1)

如果这在调试模式下有效,则意味着它可能是同步问题。您甚至可能在DOM更新之前尝试单击该元素。你发现的工作可能只是一个误报。当您将鼠标移动到活动窗口时,可能会加载DOM,这就是为什么您可以单击该元素。

你尝试过这样的事吗?

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();

编辑#1   试试这个,

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

如果你获得了NoSuchElementException的linkText,那么你必须使用WebDriverWait,因为你试图在它实际出现在DOM之前找到该元素。在这种情况下,请尝试以下。

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

答案 1 :(得分:0)

请试试以下内容:

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

答案 2 :(得分:0)

确定。我想到了。但我不能说它是解决方案还是解决方法。后者似乎更具吸引力。

我偶然发现了这个链接

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

根据那里讨论的内容,我只是将我的真实鼠标光标移动到运行测试的活动窗口中的一个点(任意点),并且它有效。

这肯定很有趣,但如果有人可以说明问题的确切原因并帮助我找到解决方案,我会感激不尽。

答案 3 :(得分:0)

我也面临同样的问题。使用javascript作为解决方法。

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;
}

答案 4 :(得分:0)

我遇到了同样的问题,原因是元素还没有,DOM没有及时更新,所以我让它在一些driver.findelements()之前插入一个thread.sleep(),就像这样:

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

我知道这不是最美丽的方式,但即使使用WebdriverWait也失败了,它给我带来了一些痛苦。