【问题标题】:How to make Selenium WebDriver wait for page to load when new page is loaded via JS event通过JS事件加载新页面时如何使Selenium WebDriver等待页面加载
【发布时间】:2017-03-05 21:51:39
【问题描述】:

我正在致力于自动化一个站点,该站点具有许多通过 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 知道需要一个新页面并等待它可用?

【问题讨论】:

标签: selenium webdriver


【解决方案1】:

等待 document.ready 事件并不是解决这个问题的全部,因为这段代码仍然处于竞争状态:有时这段代码在点击事件被处理之前被触发,所以它直接返回,因为浏览器没有'还没有开始加载新页面。

经过一番搜索,我在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 之后触发此方法,以便它尽快获得页面的引用。玩得开心!

【讨论】:

  • 完美,忍不住说声谢谢!
【解决方案2】:

显式等待是您所需要的;

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

您可以直接将其添加到您的测试中,或者您可能希望将其干燥,尤其是在存在常见的等待预期(例如旋转图标消失)时。

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

【讨论】:

    【解决方案3】:

    简单的ready2use sn-p,非常适合我

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

    【讨论】:

    • 完美的 Java 示例。在 Java 8+ 时代,需要注意的是,这里使用的是 com.google.common.base.Predicate,而不是 Java8 原生的 Predicates,但这是一个细节。
    猜你喜欢
    • 2012-07-07
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    相关资源
    最近更新 更多