WebDriver:更改事件未触发

Posted

技术标签:

【中文标题】WebDriver:更改事件未触发【英文标题】:WebDriver: Change event not firing 【发布时间】:2013-05-26 13:38:14 【问题描述】:

我有一个使用 KnockoutJS 的应用程序,我正在尝试编写一些测试表单的测试。如果您不了解 KnockoutJS,简单来说就是它提供了从我的视图到我的数据模型的绑定。这意味着当我在输入字段中键入一个值时,我的基础对象会自动使用该输入字段值进行更新。默认情况下,这是通过更改事件完成的。

我遇到的问题是,当我的 WebDriver 测试在字段中输入时,更改事件没有触发,因此我的基础数据模型没有适当的值。这会导致我的表单验证在不应该失败的情况下失败。

为了完成这项工作,我已尽我所能在互联网上找到。我已经:

    发送tab键 点击离开表单域 发送 javascript 代码以触发焦点和模糊事件(在模糊时进行验证) 在输入前点击了表单域 设置等待以防是时间问题 更改了 KnockoutJS 以在 afterkeydown 上更新输入字段

这些都不适合我。

此外,我已验证这不是事件冒泡问题,因为我明确删除了所有其他事件,只留下了 KnockoutJS 更改事件。

我正在寻找的解决方案适用于所有浏览器驱动程序(...至少是主要驱动程序,例如 IE、FF、Chrome、Safari)并且不需要使用 jQuery。

我该如何解决这个问题?

这是我用来在字段中输入值的相关代码:

// find element
WebElement input = this.element.findElement(By.className("controls"))
                               .findElement(By.tagName("input"));

// to set focus?
input.click();

// erase any existing value (because clear does not send any events
for (int i = 0; i < input.getAttribute("value").length(); i++) 
    input.sendKeys(Keys.BACK_SPACE);


// type in value
input.sendKeys(text);

// to fire change & blur? (doesnt fire change)
//input.sendKeys(Keys.TAB);

// to fire change & blur? (doesnt fire change)
driver.findElement(By.tagName("body")).click();

【问题讨论】:

所以,如果我理解的话,它会在每次击键时更新 input 字段? 请原谅我提出了一个可能很愚蠢的问题,但是当您在浏览器中手动与之交互时,该页面是否正常工作?即,如果您在浏览器中查看页面,在文本字段中输入并从文本字段中跳出标签,模型是否正在更新? @Brian 输入字段由用户更新。当 onchange 事件触发时(至少应该如此),底层数据模型会更新为输入字段中的值。如果我更改数据模型中的基础值,输入字段将自动更新为新值。这都是由 KnockoutJS 提供的。 @RodneyTrotter 是的,它在所有浏览器中都按预期工作。只是在通过 WebDriver 使用浏览器时不行。从那以后,我已经用我将发布的一个 kludge 解决了这个问题,但我现在不打算将它标记为答案,因为我觉得应该有更好的方法。 @loesak:你能发布你的网络应用程序的 html 吗?如果是 onblur 触发了更新,那么当您使用 javascript 显式触发 onblur 事件时什么都没有发生似乎很奇怪。 【参考方案1】:

所以我现在找到了解决此问题的方法,但到目前为止,我相信这是正确的解决方案。这确实违反了我不使用 jQuery 的规则,但是我觉得这对我来说没问题,因为 KnockoutJS 需要加载 jQuery。可能有一种简单的 JavaScript 方式来执行此操作。我已经用 FireFox、Safari 和 PhantomJS 对此进行了测试。我认为它在 Chrome 中也能正常工作。我对 Internet Explorer 不做任何承诺。

不会将此答案标记为正确答案。正确的解决方案应该是通过 WebDriver 浏览器触发正确的事件。只有当我认为通过 WebDriver 无法做到这一点时,我才会将此标记为正确答案。

// find element in question
WebElement input = this.element.findElement(By.className("controls"))
                               .findElement(By.tagName("input"));

// click it to fire focus event
input.click();

// erase any existing value
for (int i = 0; i < input.getAttribute("value").length(); i++) 
    input.sendKeys(Keys.BACK_SPACE);


// enter in desired text
input.sendKeys(text);

// fire on change event (WebDriver SHOULD DO THIS)
((JavascriptExecutor) driver).executeScript(
        "$(arguments[0]).change(); return true;"
    , input);

// click away to fire blur event
driver.findElement(By.tagName("body")).click();

【讨论】:

如果您可以提供可重现的场景并证明这是 WebDriver 的问题,然后提交错误。 所以我创建了一个项目来重现这个,这样做我发现了问题。简而言之,这是一个新手错误。我会链接到演示项目,但我的 git noobness 阻止我签入项目。【参考方案2】:

所以我相信我已经发现了我的问题。我完全承认这是 PEBKAC。我忘记了如果浏览器窗口没有主动关注机器(这对我来说仍然很奇怪),WebDriver 会出现问题。当我调试问题时,我正在使用我的编辑器来单步调试代码。通过正常运行代码且不从浏览器移除焦点,事件会使用所有三种解决方案(选项卡、点击离开和 javascript)按预期触发。

我有一个显示所有三种方法的示例项目,但是我是 git 和 github 的主要菜鸟,并且在交付项目时遇到问题。一旦我弄清楚了,我将与大家分享这个项目。

编辑:在 GitHub (https://github.com/loesak/knockout.webdriver.change.event.test) 上获取示例代码。您可以将项目作为服务器中的 web 应用程序启动并手动运行测试,也可以通过 maven (mvn clean install) 运行测试。我并没有付出太多努力来让它正常工作,所以假设你已经安装了 Firefox 并且端口 0808 8080 是开放的。

编辑:固定端口号

【讨论】:

恭喜解决问题,+1。

以上是关于WebDriver:更改事件未触发的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 selenium-webdriver 错误 - $ 未定义?

关于Webdriver自动化测试时,页面数据与数据库id不一致的处理方式,需要使用鼠标事件

如何使用 JavaScript 在 Firefox 中触发鼠标滚轮事件?

Selenium Webdriver如何触发HTTP请求

Python - selenium_WebDriver 鼠标键盘事件

WebDriver中的api总结--关于鼠标键盘事件