Selenium 2.0b3的IE WebDriver,点击无反应

41

使用IE9驱动程序时,偶尔单击方法仅选择按钮,而不执行单击()的操作。请注意,这种情况只会偶尔发生,因此我认为问题不在代码上。使用Firefox4与Firefox驱动程序没有问题。我还遇到一个问题,即元素有时无法找到,但仅限于IE,而不是Firefox。

if (Driver.FindElement(By.Name("username")) == null) {
    //sometimes gets here in IE, never gets here in Firefox
}
Driver.FindElement(By.Name("username")).SendKeys(username);
Driver.FindElement(By.Name("surname")).SendKeys(surname);
Driver.FindElement(By.Name("firstname")).SendKeys(firstname);
string url = Driver.Url;
Driver.FindElement(By.Name("cmd")).Click();
if (Driver.Url == url) {
    //if the page didnt change, click the link again
    Driver.FindElement(By.Name("cmd")).Click();
}

我看到了类似的问题(https://dev59.com/OVPTa4cB1Zd3GeqPkIg5

18个回答

28

在使用 .Click() 点击链接时,我发现在Internet Explorer 8上也会遇到同样的问题 - 尽管我可以看到Selenium点击了该链接。从我的经验来看,如果浏览器没有焦点,则初始单击不起作用。

解决此问题的方法是在尝试单击链接之前,向页面中的另一个元素发送 .Click(),以使浏览器获得焦点,例如它的父级:

Driver.FindElement(By.Id("Logout")).FindElement(By.XPath("..")).Click();
Driver.FindElement(By.Id("Logout")).Click();

我很感激这个简单的解决方案,也感谢它的原因。这有助于我找到最佳的问题解决方案。 - Tony
8
我遇到了一个问题,就是我无法点击所选择元素的父元素。虽然连续两次点击相同的元素可以解决问题,但我担心如果窗口已经有焦点,这可能会导致不必要的行为。对所选解决方案进行微小更改后,我的问题得到了解决:(使用C#)driver.FindElement(By.TagName("body")).Click(); - Tony
还要检查您的IE的缩放比例。重要的是,缩放比例始终设置为100%! - Ralph
@Naishy:你使用什么语言来使用WebDriver进行点击操作?是Java吗?还是其他的? - Ripon Al Wasim
@evanmcdonnal 第一次点击是针对你实际想要点击的元素的父级,以获得焦点。第二次点击是在你实际想要点击的元素上。如果浏览器已经有了焦点,那么第一次点击将没有任何影响。这是一个hack吗?是的,因为这几乎肯定是IE webdriver组件的问题,现在可能已经修复了。 - Naishy
显示剩余3条评论

16

我发现IE驱动程序存在缺陷,而且在使用相同版本的IE时,我的代码在不同的机器上表现不同。

为了在每次执行操作之前保持一致,我会按照以下步骤进行。

   driver.SwitchTo().Window(driver.CurrentWindowHandle);//Force Focus

对我来说,这样可以使IE驱动程序的行为更符合预期。


知道这点很好,但我认为每次想要焦点时调用SwitchTo()有点贵。我认为有更“便宜”的方法来强制聚焦。 - Tony
2
昂贵与否,这远比被接受的廉价方法要优越得多。 - evanmcdonnal
这对我来说不成功。 - he_the_great
Java版本:driver.switchTo().window(driver.getWindowHandle());// 强制聚焦 - Dave

8

我遇到了同样的问题,我的IE浏览器无法使用点击功能。我找到了一个解决方法,通过执行Driver.FindElement(By.Name("...")).sendKeys("\n")来模拟点击(实际上是在按钮上按下回车键)。虽然不太优雅,但在问题得到解决之前它是有效的!


7
我已经根据在项目中引用Selenium WebDriver 2.15.0并使用Selenium WebDriver Server 2.16.0进行了重构,并得出以下结论:
  • 使用FirefoxDriver时,单击事件会正确触发。
  • 对于某些控件,使用RemoteWebDriverDesiredCapabilities.Firefox时,单击事件不会正确触发。
  • 使用RemoteWebDriverDesiredCapabilities.HtmlUnit以及DesiredCapabilities.HtmlUnitWithJavaScript时,单击事件会正确触发。
  • InternetExplorerDriver和使用DesiredCapabilities.InternetExplorerRemoteWebDriver(实际上是同一件事)仍然给我带来了不一致的结果,我很难解决这个问题。
对于前三点,我的解决方案是创建自己的类来扩展RemoteWebDriverRemoteWebElement,以便我可以将自定义行为隐藏在继续引用IRemoteWebDriverIWebElement的测试代码之后。
以下是我的当前“调整”,但如果您使用这些自定义类,您将能够根据自己的需要调整驱动程序和Web元素的行为,而无需更改测试代码。
public class MyRemoteWebDriver : RemoteWebDriver
{
    //Constructors...

    protected override RemoteWebElement CreateElement(string elementId)
    {
        return new MyWebElement(this, elementId);
    }
}

public class MyWebElement : RemoteWebElement, IWebElement
{
    //Constructor...

    void IWebElement.Click()
    {
        if (Settings.Default.WebDriver.StartsWith("HtmlUnit"))
        {
            Click();
            return;
        }

        if (TagName == "a")
        {
            SendKeys("\n");
            Thread.Sleep(100);
            return;
        }

        if (TagName == "input")
        {
            switch (GetAttribute("type"))
            {
                case "submit":
                case "image":
                    Submit();
                    return;
                case "checkbox":
                case "radio":
                    //Send the 'spacebar' keystroke
                    SendKeys(" ");
                    return;
            }
        }

        //If no special conditions are detected, just run the normal click
        Click();
    }
}

(TagName == "input") 不是万能的 - 还有 <button> 标签。你可能也需要检查 case "button",因为 <input>/<button> 可能有自定义脚本逻辑。 - Joel Purra
此外,如果(...HtmlUnit...),该函数会为每个元素发送“Click()”,而在其他情况下不会回退到“Click()”。 - Joel Purra

7

以上解决方案都对我无效。但是这个方法行得通:

Java

element.sendKeys(org.openqa.selenium.Keys.CONTROL);
element.click();

格鲁维

element << org.openqa.selenium.Keys.CONTROL
element.click()

Geb

如果您正在使用 Geb,那么有一个更好的解决方案,完全不会影响原有代码:

(已测试在IE7和Geb 0.7.0上)

abstract class BaseSpec extends geb.spock.GebSpec
{
    static
    {
        def oldClick = geb.navigator.NonEmptyNavigator.metaClass.getMetaMethod("click")
        def metaclass = new geb.navigator.AttributeAccessingMetaClass(new ExpandoMetaClass(geb.navigator.NonEmptyNavigator))

        // Wrap the original click method
        metaclass.click = {->
            delegate << org.openqa.selenium.Keys.CONTROL
            oldClick.invoke(delegate)
        }

        metaclass.initialize()

        geb.navigator.NonEmptyNavigator.metaClass = metaclass
    }
}

class ClickSpec extends BaseSpec
{
    def "verify click"()
    {
        given:
        to HomePage

        expect:
        waitFor { at HomePage }

        when:
        dialog.dismiss()
        // Call the wrapped .click() method normally
        $('#someLink').click()

        then:
        waitFor { at SomePage }
    }
}

class HomePage extends geb.Page
{
    static url = "index.html"
    static at = { title == "Home - Example.com" }
    static content = {
        dialog { module DialogModule }
    }
}

class SomePage extends geb.Page { ... }
class DialogModule extends geb.Module { def dismiss() { ... } }

在我的情况下,在关闭动画模态覆盖层(我们使用jQuery Tools Overlay Modal Dialog)之后,单击IE7似乎会失败。上面的Geb方法解决了这个问题。

在C#中,这对于IE驱动程序(但不适用于其他浏览器如Chrome)对我有效:Element.SendKeys(Keys.CONTROL); Element.Click(); - mojjj
你能详细说明一下为什么要发送控制信号吗?这样做不会在新窗口中打开每个点击的链接吗? - Mark Mayo
以上代码模拟在目标元素上按下并释放按键(按下后松开)的操作。在调用 oldClick 时,模拟的 <kbd>Ctrl</kbd> 键已经被释放,因此链接不会在新标签页/窗口中打开。 - Andy Dvorak
请注意,我的答案基于Emmanuel的解决方案:向目标元素发送按键事件似乎足以使其获得焦点。我选择了Ctrl键,因为它不会触发任何默认浏览器行为,并且很少有JavaScript事件处理程序只会寻找该键。 - Andy Dvorak
对我来说,使用Java和IE可以正常工作。您能否解释一下指令element.sendKeys(org.openqa.selenium.Keys.CONTROL)的作用是什么? - Enrico Giurin
Enrico,发送CONTROL键按下事件到元素只是一种hack方法,用于强制IE将焦点设置到该元素上,以便随后的click()调用能够按预期工作。 - Andy Dvorak

2

你可以通过功能来实现这一点,但它仍然不能保证始终正常工作。 - bogdan.mustiata

1

PHPUnit + facebook/php-webdriver

有时候click()函数不能选中复选框元素。

我的解决方案是:

$Element = $WebDriver->findElement(
    WebDriverBy::id('checkbox_id')
);

if(false === $Element->isSelected())
{
    $Element->sendKeys(WebDriverKeys::SPACE);
}

1

我正在使用IE版本:9 遇到了同样的问题。以下方法在我的情况下有效

element.sendKeys(Keys.ENTER);
element.click();

1
简短回答:
如果您正在使用触摸屏幕监视器(例如Windows 8触摸笔记本电脑)上打开的IE11浏览器窗口中运行自动化Selenium测试,请尝试在非触摸屏幕上打开浏览器窗口运行测试。原始的.click()方法应该可以正常工作,无需所有代码解决方案。
回答背景:
我与我们QA团队的一名测试人员合作调查了类似的问题。在尝试了这里和selenium webdriver IE button issue大部分的代码解决方案后,我们最终发现问题只会在测试人员的Windows 8笔记本电脑触摸屏上运行的IE(对我们来说是版本11)中出现。
在外部Dell监视器上运行IE窗口的Selenium测试允许测试每次都能正常运行,即使只使用标准的.click()调用。
我们还在Magnific Popup(http://dimsemenov.com/plugins/magnific-popup/)对话框中的按钮单击事件上失败。
我的假设是:IE11(不确定其他版本)在触摸屏上将触摸事件转换为/从鼠标单击事件的处理存在问题。

1

Another one:

v2.29.0

WebDriver: * 支持Firefox 18。 * IEDriver支持“requireWindowFocus”期望能力。使用此功能和本地事件时,IE驱动程序将要求焦点,并且用户交互将使用SendInput()模拟用户交互。请注意,这意味着在运行测试时,您不能在运行IE的计算机上执行其他任何操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接