我们是否有任何通用功能来检查页面是否已在Selenium中完全加载

时间:2018-05-14 09:31:06

标签: java selenium selenium-webdriver pageload dom-events

我正试图在selenium中检查网页是否已加载完成(即检查是否已加载所有控件)。

我尝试了以下代码:

new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
          webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

但即使页面加载上面的代码也不会等待。

我知道我可以检查特定元素以检查其是否可见/可点击等,但我正在寻找一些通用解决方案

7 个答案:

答案 0 :(得分:3)

正如您所提到的,如果有任何通用功能来检查页面是否已在Selenium中完全加载,答案是

首先让我们看一下您的代码试用,如下所示:

new WebDriverWait(firefoxDriver, pageLoadTimeout).until(webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

上述代码行中的参数pageLoadTimeout并非真正与实际pageLoadTimeout()相似。

您可以在此处找到pageLoadTimeout in Selenium not working

的详细讨论

现在,当您的用例与完全加载的网页相关时,您可以使用pageLoadStrategy()设置为 normal [支持的值 DesiredCapabilities 类或 ChromeOptions 类的实例使用渴望正常]如下:

  • 使用 DesiredCapabilities 类:

     import org.openqa.selenium.WebDriver;
     import org.openqa.selenium.firefox.FirefoxDriver;
     import org.openqa.selenium.firefox.FirefoxOptions;
     import org.openqa.selenium.remote.DesiredCapabilities;
    
     public class myDemo 
     {
        public static void main(String[] args) throws Exception 
        {
            System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
            DesiredCapabilities dcap = new DesiredCapabilities();
            dcap.setCapability("pageLoadStrategy", "normal");
            FirefoxOptions opt = new FirefoxOptions();
            opt.merge(dcap);
            WebDriver driver = new FirefoxDriver(opt);
            driver.get("https://www.google.com/");
            System.out.println(driver.getTitle());
            driver.quit();
        }
    }
    
  • 使用 ChromeOptions 类:

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.firefox.FirefoxOptions;
    import org.openqa.selenium.PageLoadStrategy;
    
    public class myDemo 
    {
        public static void main(String[] args) throws Exception 
        {
            System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
            FirefoxOptions opt = new FirefoxOptions();
            opt.setPageLoadStrategy(PageLoadStrategy.NORMAL);
            WebDriver driver = new FirefoxDriver(opt);
            driver.get("https://www.google.com/");
            System.out.println(driver.getTitle());
            driver.quit();
        }
    }
    

您可以在Page load strategy for Chrome driver (Updated till Selenium v3.12.0)

中找到详细的讨论

现在将 PageLoadStrategy 设置为 NORMAL ,您的代码试用版确保浏览器客户端具有(即 Web浏览器)已达到'document.readyState'等于"complete"。一旦满足这个条件,Selenium就会执行下一行代码。

您可以在Selenium IE WebDriver only works while debugging

中找到详细的讨论

浏览器客户端获得'document.readyState'等于"complete"仍然不能保证所有 JavaScript Ajax电话已完成。

要等待所有 JavaScript Ajax Calls 完成,您可以编写如下函数:

public void WaitForAjax2Complete() throws InterruptedException
{
    while (true)
    {
        if ((Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")){
            break;
        }
        Thread.sleep(100);
    }
}

您可以在Wait for ajax request to complete - selenium webdriver

中找到详细的讨论

现在,通过 PageLoadStrategy "return jQuery.active == 0"的上述两种方法看起来都在等待无限期事件。因此,对于明确的等待,您可以WebDriverWaitExpectedConditions设置为titleContains()方法,以确保页面标题(即网页) )是可见的,并假设所有元素也可见如下:

driver.get("https://www.google.com/");
new WebDriverWait(driver, 10).until(ExpectedConditions.titleContains("partial_title_of_application_under_test"));
System.out.println(driver.getTitle());
driver.quit();

现在,有时虽然页面标题可以匹配您的应用程序标题,但您想要交互的所需元素仍然无法完成加载。因此,更细粒度的方法是将WebDriverWaitExpectedConditions设置为visibilityOfElementLocated()方法联系起来,这将使您的程序等待所需的元素可见如下:

driver.get("https://www.google.com/");
WebElement ele = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xpath_of_the_desired_element")));
System.out.println(ele.getText());
driver.quit();

答案 1 :(得分:0)

我也使用selenium而且我遇到了同样的问题,要解决这个问题我还要等待jQuery加载。

因此,如果您遇到同样的问题,请尝试此操作

((Long) ((JavascriptExecutor) browser).executeScript("return jQuery.active") == 0);

您可以将两个函数包装在一个方法中并检查,直到加载了页面和jQuery

答案 2 :(得分:0)

实现这一点,它为包括我在内的许多人工作。它包括JavaScript页面等待,Angular,JQuery,如果它在那里。

如果您的应用包含Javascript& JQuery你只能为那些编写代码,

通过单一方法定义它,您可以在任何地方调用它:

          // Wait for jQuery to load
          {             
            ExpectedCondition<Boolean> jQueryLoad = driver -> ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active") == 0);

            boolean jqueryReady = (Boolean) js.executeScript("return jQuery.active==0");

            if (!jqueryReady) {
                // System.out.println("JQuery is NOT Ready!");
                wait.until(jQueryLoad);
            }
            wait.until(jQueryLoad);
          }

          // Wait for ANGULAR to load
          {               
            String angularReadyScript = "return angular.element(document).injector().get('$http').pendingRequests.length === 0";

            ExpectedCondition<Boolean> angularLoad = driver -> Boolean.valueOf(((JavascriptExecutor) driver).executeScript(angularReadyScript).toString());

            boolean angularReady = Boolean.valueOf(js.executeScript(angularReadyScript).toString());

            if (!angularReady) {
                // System.out.println("ANGULAR is NOT Ready!");
                wait.until(angularLoad);
            }
          }

          // Wait for Javascript to load    
          {             
            ExpectedCondition<Boolean> jsLoad = driver -> ((JavascriptExecutor) driver).executeScript("return document.readyState").toString()
                    .equals("complete");

            boolean jsReady = (Boolean) js.executeScript("return document.readyState").toString().equals("complete");

            // Wait Javascript until it is Ready!
            if (!jsReady) {
                // System.out.println("JS in NOT Ready!");
                wait.until(jsLoad);
            }
          }

Click here for Reference Link

让我知道你是否坚持实施。

它克服了线程或显式等待的使用。

答案 3 :(得分:0)

    public static void waitForPageToLoad(long timeOutInSeconds) {
    ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver driver) {
            return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
        }
    };
    try {
        System.out.println("Waiting for page to load...");
        WebDriverWait wait = new WebDriverWait(Driver.getDriver(), timeOutInSeconds);
        wait.until(expectation);
    } catch (Throwable error) {
        System.out.println(
                "Timeout waiting for Page Load Request to complete after " + timeOutInSeconds + " seconds");
    }
}

试试这个方法

答案 4 :(得分:0)

类似这样的方法应该起作用(请原谅java回答中的python):

idle = driver.execute_async_script("""
  window.requestIdleCallback(() => {
    arguments[0](true)
  })
""")

这应该阻塞,直到事件循环空闲为止,这意味着应该加载所有资产。

答案 5 :(得分:0)

这对我来说很适合动态呈现的网站:

  1. 等待完整页面加载

WebDriverWait wait = new WebDriverWait(driver, 50); 
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));

  1. 使用总是失败的虚拟条件进行另一个隐式等待

  try {          
 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + "This text will always fail :)" + "')]"))); // condition you are certain won't be true 
  } 
  catch (TimeoutException te) {
  }

  1. 最后,不是获取 html 源代码——这在大多数页面应用程序中会给你不同的结果,而是拉取第一个 html 标签的外层 html

String script = "return document.getElementsByTagName(\"html\")[0].outerHTML;"; 
content = ((JavascriptExecutor) driver).executeScript(script).toString();

答案 6 :(得分:0)

有一种简单的方法可以做到。当您第一次通过 javascript 请求状态时,它告诉您页面是 complete,但之后它进入状态 loading。第一个 complete 状态是初始页面!

所以我的建议是在 complete 状态之后检查 loading 状态。在 PHP 中检查这段代码,很容易翻译成另一种语言。

        $prevStatus  = '';
        $checkStatus = function ($driver) use (&$prevStatus){

          $status = $driver->executeScript("return document.readyState"); 

          if ($prevStatus=='' && $status=='loading'){
            //save the previous status and continue waiting
            $prevStatus = $status; 
            return false;
          }

          if ($prevStatus=='loading' && $status=='complete'){
            //loading -> complete, stop waiting, it is finish!
            return true;
          }
          //continue waiting 
          return false;

        };
        $this->driver->wait(20, 150)->until($checkStatus);

检查元素是否存在也很有效,但您需要确保该元素仅存在于目标页面中。