WebDriver 执行 javascript 奇怪的行为

发布于 2024-11-24 22:33:59 字数 1401 浏览 1 评论 0原文

我正在通过 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);       
}

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

I'm using Webdriver through JBehave-Web distribution (3.3.4) to test an application and I'm facing something quite strange:

I'm trying to interact with a modalPanel from Richfaces, which gave me a lot of problems because it throws ElementNotVisibleException. I solved it by using javascript:

This is the code in my page object which extends from 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);
}

The strange behaviour is that if I execute the test normally, it does nothing, but if I put a breakpoint in the last line (in Eclipse), select the line and execute from Eclipse (Ctrl + U), I can see the changes in the browser.

I checked the JavascriptExecutor and the WebDriver classes to see if there was any kind of buffering, but I couldn't find anything. Any ideas?

EDIT
I found out that putting the thread to sleep for 1 second it makes it work, so it looks some kind of race condition, but cannot find out why...

This is the way it "works", but I'm not very happy about it:

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

Putting the wait in any other position doesn't work either...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江湖正好 2024-12-01 22:33:59

第一个想法:

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

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

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

第二个想法:

在变异之前显式等待元素可用:

/**
 * 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);
}

First idea:

Ensure that target element is initialized and enumerable. See if this returns null:

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

Since you're using makeNonLazy(), probably just add the target as a WebElement member of your Page Object (assuming Page Factory type of initialization in JBehave).

Second idea:

Explicitly wait for the element to be available before mutating:

/**
 * 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文