提问者:小点点

WebDriver等待JQuery完成


我在Java使用WebDriver,我有一个自定义的方法来等待DOM事件(通过JQuery):

 public void waitForJQuery(WebDriver driver) {
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
    public Boolean apply(WebDriver d) {
    JavascriptExecutor js = (JavascriptExecutor) d;
    return (Boolean) js.executeScript("return jQuery.active == 0");
    }
});
}

当测试命中此方法并抛出错误时:

org.openqa.selenium.WebDriverException: jQuery is not defined
Build info: version: '2.37.0', revision: 'a7c61cb', time: '2013-10-18 17:14:00'
System info: host: 'WMWIN70089', ip: '10.68.44.231', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0'
Driver info: driver.version: unknown
Command duration or timeout: 190 milliseconds
Build info: version: '2.37.0', revision: 'a7c61cb', time: '2013-10-18 17:15:02'
System info: host: 'LMWIN70038', ip: '10.86.44.35', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_17'
Session ID: 2cf19cb9-edcd-463e-b77e-0121eb05e246
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities [{platform=XP, acceptSslCerts=true, javascriptEnabled=true, browserName=firefox, rotatable=false, locationContextEnabled=true, webdriver.remote.sessionid=2cf19cb9-edcd-463e-b77e-0121eb05e246, version=25.0.1, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=true, webStorageEnabled=true, applicationCacheEnabled=true, takesScreenshot=true}]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:193)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:554)
    at org.openqa.selenium.remote.RemoteWebDriver.executeScript(RemoteWebDriver.java:463)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.openqa.selenium.remote.Augmenter$CompoundHandler.intercept(Augmenter.java:280)
    at org.openqa.selenium.remote.RemoteWebDriver$$EnhancerByCGLIB$$13369d6d.executeScript(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.openqa.selenium.support.events.EventFiringWebDriver$2.invoke(EventFiringWebDriver.java:101)
    at com.sun.proxy.$Proxy10.executeScript(Unknown Source)
    at org.openqa.selenium.support.events.EventFiringWebDriver.executeScript(EventFiringWebDriver.java:209)
    at driver.core.web.core.WebDriverMaster$2.apply(WebDriverMaster.java:186)
    at driver.core.web.core.WebDriverMaster$2.apply(WebDriverMaster.java:1)
    at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:208)
    at driver.core.web.core.WebDriverMaster.waitForJQuery(WebDriverMaster.java:183)
    at driver.services.web.ib4b.template.CreateTemplateDetails.searchItemBy(CreateTemplateDetails.java:364)
    at driver.services.web.csu.regression.testSearchAndSort.testSearchByAllFields(testSearchAndSort.java:59)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

你能帮我解决这个问题吗?

谢谢。


共2个答案

匿名用户

您可以添加一个检查以查看jQuery是否首先定义,这样它就不会抛出异常:

public void waitForJQuery(WebDriver driver) {
    (new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver d) {
            JavascriptExecutor js = (JavascriptExecutor) d;
            return (Boolean) js.executeScript("return !!window.jQuery && window.jQuery.active == 0");
        }
    });
}

匿名用户

这就是我最终让它工作的方式(带有一些用于调试的打印输出)。

从这里改编:

http://pastebin.com/3uMWQ5L0

    private static void waitForPageLoad(WebDriver driver) {
    System.out.println("Wating for ready state complete");
    (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver d) {
            JavascriptExecutor js = (JavascriptExecutor) d;
            String readyState = js.executeScript("return document.readyState").toString();
            System.out.println("Ready State: " + readyState);
            return (Boolean) readyState.equals("complete");
        }
    });
}

调试输出:

Wating for ready state complete
Ready State: interactive
Ready State: interactive
Ready State: complete

对于JQuery,只需将"返回文档. readyState"替换为"返回!!window.jQuery

这里是没有调试信息的JQuery代码(我希望不那么混乱)。

    private static void waitForJQuery(PhantomJSDriver driver) {
    (new WebDriverWait(driver, 5)).until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver d) {
            JavascriptExecutor js = (JavascriptExecutor) d;
            return (Boolean) js.executeScript("return !!window.jQuery && window.jQuery.active == 0");
        }
    });
}