WebDriver执行javascript奇怪的行为

时间:2011-07-19 15:48:34

标签: javascript testing selenium webdriver

我正在通过JBehave-Web发行版(3.3.4)使用Webdriver来测试应用程序,我面临着一些非常奇怪的事情:

我正在尝试与Richfaces的modalPanel进行交互,这给了我很多问题,因为它会抛出ElementNotVisibleException。我用javascript解决了它:

这是我的页面对象中的代码,它来自org.jbehave.web.selenium.WebDriverPage

protected void changeModalPanelInputText(String elementId, String textToEnter){
    makeNonLazy();
    JavascriptExecutor je = (JavascriptExecutor) webDriver();
    String script ="document.getElementById('" + elementId + "').value = '" + textToEnter + "';";
    je.executeScript(script);
}

奇怪的行为是,如果我正常执行测试,它什么都不做,但如果我在最后一行(在Eclipse中)放置断点,选择行并从Eclipse执行(Ctrl + U),我可以看到浏览器中的更改。

我检查了JavascriptExecutor和WebDriver类,看看是否有任何缓冲,但我找不到任何东西。有什么想法吗?

修改 我发现让线程睡了1秒就可以了,所以它看起来有种竞争条件,但是找不到原因......

这就是“工作”的方式,但我对此并不高兴:

protected void changeModalPanelInputText(String elementId, String textToEnter){
    String script ="document.getElementById('" + elementId + "').value = '" + textToEnter + "';";
    executeJavascript(script);
}

    private void executeJavascript(String script){
    makeNonLazy();
    JavascriptExecutor je = (JavascriptExecutor) webDriver();
    try {
        Thread.sleep(1500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    je.executeScript(script);       
}

将等待放在任何其他位置也不起作用......

1 个答案:

答案 0 :(得分:1)

第一个想法:

确保目标元素已初始化且可枚举。看看是否会返回null

Object objValue = je.executeScript(
    "return document.getElementById('"+elementId+"');");

由于你正在使用makeNonLazy(),可能只需将目标添加为页面对象的WebElement成员(在JBehave中假设Page Factory类型的初始化)。

第二个想法:

在变异之前明确等待元素可用:

/**
 * re-usable utility class
 */
public static class ElementAvailable implements Predicate<WebDriver> {

    private static String IS_NOT_UNDEFINED = 
        "return (typeof document.getElementById('%s') != 'undefined');";
    private final String elementId;

    private ElementAvailable(String elementId) {
        this.elementId = elementId;
    }

    @Override
    public boolean apply(WebDriver driver) {
        Object objValue = ((JavascriptExecutor)driver).executeScript(
                String.format(IS_NOT_UNDEFINED, elementId));
        return (objValue instanceof Boolean && ((Boolean)objValue));
    }
}

...

protected void changeModalPanelInputText(String elementId, String textToEnter){
    makeNonLazy();

    // wait at most 3 seconds before throwing an unchecked Exception
    long timeout = 3;
    (new WebDriverWait(webDriver(), timeout))
            .until(new ElementAvailable(elementId));

    // element definitely available now
    String script = String.format(
            "document.getElementById('%s').value = '%s';",
            elementId,
            textToEnter);
    ((JavascriptExecutor) webDriver()).executeScript(script);
}