Javascript WebDriver:更改事件未触发

Javascript WebDriver:更改事件未触发,javascript,testing,knockout.js,webdriver,Javascript,Testing,Knockout.js,Webdriver,我有一个使用KnockoutJS的应用程序,我正在尝试编写一些测试表单的测试。如果您不知道KnockoutJS,那么简单的说就是它提供了从我的视图到我的数据模型的绑定。这意味着,当我在输入字段中键入一个值时,我的基础对象将自动使用该输入字段值进行更新。默认情况下,这是通过更改事件完成的 我遇到的问题是,当我的WebDriver测试在字段中键入时,更改事件没有触发,因此我的基础数据模型没有适当的值。这会导致我的表单验证在不应该的情况下失败 我已经尽了我所能在互联网上找到使这项工作。我已经: 发送t

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

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

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

  • 发送tab键
  • 从表单字段中单击
  • 将JavaScript代码发送到fire focus和blur事件(在blur上进行验证)
  • 键入前单击表单字段
  • 设置等待,以防出现时间问题
  • 更改了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();
    
    //查找元素
    WebElement输入=this.element.findElement(按.className(“控件”))
    .findElement(按.tagName(“输入”));
    //设定焦点?
    输入。单击();
    //删除任何现有值(因为clear不发送任何事件
    对于(int i=0;i
    所以我现在已经找到了解决这个问题的方法,但到目前为止,我相信这是正确的解决方案。这确实打破了我不使用jQuery的规定,但是我觉得这对我来说没问题,因为KnockoutJS要求加载jQuery。可能有一种简单的ol'JavaScript方法可以做到这一点。我已经用FireFox、Safari和PhantomJS。我想它在Chrome中也能正常工作。我对IE浏览器没有承诺

    我不打算将此答案标记为正确答案。正确的解决方案应该是通过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();
    
    //查找有问题的元素
    WebElement输入=this.element.findElement(按.className(“控件”))
    .findElement(按.tagName(“输入”));
    //单击它以触发焦点事件
    输入。单击();
    //删除任何现有值
    对于(int i=0;i
    所以我相信我已经发现了我的问题。我完全承认这是PEBKAC的问题。我忘记了如果浏览器窗口未在机器上处于活动焦点,WebDriver会出现问题(这对我来说仍然很奇怪)。当我调试问题时,我正在使用编辑器逐步完成代码。通过正常运行代码并且不从浏览器中移除焦点,使用所有三种解决方案(tab、click away和javascript)按预期触发事件

    我有一个展示所有三种方法的示例项目,但是我是git和github的主要noob,在交付项目时遇到了问题。一旦我弄明白了这一点,我将与大家分享这个项目

    编辑:在GitHub()上获得示例代码。您可以在服务器中以webapp的形式启动项目并手动运行测试,也可以通过maven(
    mvn clean install
    )运行测试.我并没有花太多的精力让它正常工作,所以假设您已经安装了Firefox,并且端口080808080是打开的


    编辑:固定了指定的端口号

    ,因此,如果我理解的话,它会用每个按键来更新
    输入
    字段?请原谅我问了一个潜在的愚蠢问题,但是当您在浏览器中手动与该页面交互时,该页面是否正常工作?即,如果您在浏览器中查看该页面,请键入文本文本字段外的字段和选项卡,模型是否正在更新?@Brian输入字段由用户更新。当onchange事件触发时,基础数据模型将更新为输入字段中的值(至少应该是这样)。如果我更改数据模型中的基础值,输入字段将自动更新为新值。这都是由KnockoutJS提供的。@RodneyRotter是的,它在所有浏览器中都按预期工作。只是在通过WebDriver使用浏览器时没有。我已经用我将发布的一篇文章解决了这个问题,但我我现在不打算把它作为答案,因为我觉得应该有更好的方法。@loesak:你能发布你的web应用程序的html吗?如果触发更新的是onblur,那么当你使用javascript显式触发onblur事件时,似乎什么都没有发生,这很奇怪。如果你能提供一个可复制的场景,并证明这是一个问题em和WebDriver一起,然后提交一个bug。所以我创建了一个项目来重现这个问题,在这样做的过程中,我发现了这个问题。简言之,这是一个新手犯的错误。我会的