如何通过JS事件

时间:2015-05-21 15:19:32

标签: selenium webdriver

我正致力于自动化一个网站,该网站有许多通过JS事件加载新网页的链接。基本上,有些元素是可点击的,点击一个元素会导致一些JavaScript运行,这会导致表单被提交并路由到新页面。

现在,如果这些只是标准的HTML链接,那就没有问题了,因为Selenium非常聪明,可以告诉他们有一个新页面即将来临并等待做事。但是,尽管如此,Selenium无法分辨出这个实例中的点击是否会导致新页面加载,因此它不会等待并且继续前进。因此它不会等待新页面,尝试查找不存在的元素,我的测试都会失败。长号。

作为临时解决方案,我只是将程序暂停三秒钟,如下:

oldPageDriver.clickThatButton();

try {
  Thread.sleep(3000);
} catch(InterruptedException ex) {
  Thread.currentThread().interrupt();
}

newPageDriver = new NewPageDriver(driver);
newPageDriver.doStuffOnNewPage();

这样可行。我不喜欢它,因为它是“hacky”,只是打断程序而不是做一些更聪明的事情。因为延迟是在三秒钟硬编码,所以如果链接工作但是速度慢,我会失败。我已经考虑过类似于隐式等待的东西,但它完成了同样的事情,并且在经过大量研究后,我在Java中找不到一个可靠,可行的答案。

那么,任何人都可以提出解决方法吗?具体来说,如何让Selenium知道一个新的页面,并等到它可用?

3 个答案:

答案 0 :(得分:6)

等待document.ready事件并不是解决此问题的全部方法,因为此代码仍然处于竞争状态:有时在处理click事件之前触发此代码,因此直接返回,因为浏览器没有& #39; t开始加载新页面。

经过一番搜索后,我在Obay the testing goat找到了一个帖子,该帖子有解决此问题的方法。该解决方案的c#代码如下:

 IWebElement page = null;
 ...
 public void WaitForPageLoad()
 {
    if (page != null)
    {
       var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
       waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
    }

    var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));

    page = driver.FindElement(By.TagName("html"));

}

`  我在driver.navigate.gotourl之后直接触发此方法,以便它尽快获得页面的引用。玩得开心!

答案 1 :(得分:3)

显式等待是您所需要的;

http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp

您可以直接将其添加到测试中,或者您可能想要将其干掉,特别是如果存在共同的等待期望,例如旋转图标消失。

您可以将click方法扩展为在单击或后续页面对象后始终等待,将wait_until_loaded方法添加到基页类。还有许多其他有效的方法,但取决于AUT的实现方式

答案 2 :(得分:3)

简单的 ready2use 代码段,非常适合我

static void waitForPageLoad(WebDriver wdriver) {
    WebDriverWait wait = new WebDriverWait(wdriver, 60);

    Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

    };
    wait.until(pageLoaded);
}