Java-等待使用Selenium

时间:2018-11-07 22:56:32

标签: javascript java selenium events onchange

一组与逻辑相关的input字段具有一个 onchange 事件。遍历字段并修改其值后,某些字段会正确更新,而某些字段由于onchange事件所做的事情而不会更新。

onchange事件在某个字段上触发时,它会开始进行一些处理(涉及其他相关字段),将值存储在某个位置,并清除其他相关字段(如果先前未由自己的{{1 }}事件。

我可以使线程休眠任意时间,但这看起来并不好。只是猜测要花多少时间,然后在浪费大量时间浪费大量时间或选择可以中止超时的脚本之间进行选择。

是否有办法知道JavaScript代码(由onchange事件调用)何时完成工作?

原始代码

onchange

输出

有睡眠:Wait<WebDriver> wait = new WebDriverWait(driver, 25, 500); for(int i = 1; i <= fieldCount; i++) { elementId = "field$" + i; wait.until(ExpectedConditions.elementToBeClickable(By.id(elementId))); driver.findElementById(elementId).sendKeys(data); //The mess happens if I don't sleep Thread.sleep(3000); } Field1 ... _w_Field2 ... _x_Field3 ... {{ 1}}:_y_

不睡觉:FieldN_z_ ... Field1_w_ ... Field2___ ... {{ 1}}:Field3

注释:

我在这方面遇到了一些问题,所以我认为值得一提的是简短的经验教训:

  

WARNING:请勿混合使用隐式和显式等待。

     

使用WebDriverWait_y_的专业化)而不是FieldN,除非您有非常具体的要求。例如,___默认忽略FluentWaitFluentWait的超类)。参见recomendation

4 个答案:

答案 0 :(得分:1)

经过认真的重构和一些研究,我终于做到了。当onchange字段的值更改并且元素失去焦点时,将触发input事件。不能选择使用WebElement(例如sendKeys())来处理字段,因为您无法控制后台处理,因此选择使用JavascriptExecutor。首先,我使用JavaScript更新了字段的值(不会触发事件),然后,我也使用JavaScript触发了onchange事件:

//Setting implicit wait to 0 to avoid mess with explicit waits
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
//Use WebDriverWait instead of FluentWait (it's superclass)
Wait<WebDriver> wait = new WebDriverWait(driver, 25, 500);
for(int i = 1; i <= fieldCount; i++) {
    String elementId = "field$" + i;
    String javaScript = String.format("document.getElementById('%s').value='%s';", elementId , myValue);
    Object jsResult = wait.until(ExpectedConditions.javaScriptThrowsNoExceptions(javaScript));
    javaScript = String.format("return document.getElementById('%s').dispatchEvent(new Event('change'));", elementId);
    jsResult = wait.until(ExpectedConditions.jsReturnsValue(javaScript));
}

这里有一些关键方面。

  • 请勿混合使用隐式和显式等待(我很难学到),否则会导致意外结果。
  • 使用WebDriverWaitFluentWait的专业化)代替其超类,除非您有非常特殊的要求。如果您使用FluentWait,请确保忽略适当的例外;否则,您将开始获得NoSuchElementException
  • onchange字段的值更改并且元素失去焦点时,将触发input事件。
  • dispatchEvent()在指定的EventTarget( synchronously )上调度事件,并以适当的顺序调用受影响的EventListener。这也适用于custom events。这是事件的very nice post

我使用以下代码更好地掌握了ExpectedConditions.javaScriptThrowsNoExceptionsExpectedConditions.jsReturnsValue。这是一个JavaScript函数调用,仅会使引擎忙几秒钟。这样,您可以看到显式等待与JavaScript的交互,并检查返回值。请注意,每个ExpectedCondition的JS代码略有不同:

//ExpectedConditions.jsReturnsValue
String javaScript = "(function watcher(ms){var start=new Date().getTime();var end = start;while(end<start+ms){end=new Date().getTime();};return 'complete';})(5000);return 'success';";
log.trace("javaScript={}", javaScript);
Object jsResult = wait.until(ExpectedConditions.jsReturnsValue(javaScript));
log.trace("jsResult={}", jsResult);

//ExpectedConditions.javaScriptThrowsNoExceptions
javaScript = "(function watcher(ms){var start=new Date().getTime();var end = start;while(end<start+ms){end=new Date().getTime();};return 'complete';})(5000);";
log.trace("javaScript={}", javaScript);
jsResult = wait.until(ExpectedConditions.javaScriptThrowsNoExceptions(javaScript));
log.trace("jsResult={}", jsResult);

答案 1 :(得分:0)

据我所知,您不能等待使用Selenium Web驱动程序的异步事件。但是,您可以使用WebDriverWait类来等待该事件的影响。如果您提到了事件,请在DOM中进行一些更改,然后可以使用选定的ExpectedConditions来检测这些更改。

   Wait<WebDriver> wait = new WebDriverWait(driver, 15, 500);

   // here you make some change to the input

   wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input")));

这个简单的示例将等到按钮处于活动状态。 如果在接下来的15秒内没有满足预期的条件,则会引发异常。

如果提供的ExpectedConditions集合不足,则可以始终通过实施ExpectedCondition接口来创建自己的。 有关更多信息,请访问文档。

https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/package-summary.html https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/package-summary.html

答案 2 :(得分:0)

您可以尝试使用此方法,直到JQuery设置为非活动状态为止。

/**
 * Wait until JQuery is inactive
 * @author Bill Hileman
 */
public void waitForJQueryToBeInactive() {

    Boolean isJqueryUsed = (Boolean) ((JavascriptExecutor) driver)
            .executeScript("return (typeof(jQuery) != 'undefined')");

    if (isJqueryUsed) {
        while (true) {
            // JavaScript test to verify jQuery is active or not
            Boolean ajaxIsComplete = (Boolean) (((JavascriptExecutor) driver)
                    .executeScript("return jQuery.active == 0"));
            if (ajaxIsComplete)
                break;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }

}

答案 3 :(得分:0)

以下例程检查文档准备状态是否为“完成”,并在页面加载/更改完成后返回。

/**
 * Wait for the web page to finish loading
 * @author Bill Hileman
 */
public void waitForPageToLoad() {

    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(new ExpectedCondition<Boolean>() {

        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
        }
    });
}