Есть ли у нас какие-либо общие функции, чтобы проверить, полностью ли загружена страница в Selenium?

Я пытаюсь проверить, загружена ли веб-страница завершена или нет (т.е. проверяется, что загружен весь элемент управления) в селене.

Я попробовал ниже код:

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

но даже если страница загружается выше, код не ждет.

Я знаю, что могу проверить конкретный элемент, чтобы убедиться, что он видимый / кликабельный и т. Д., Но я ищу какое-то общее решение

7 ответов

Как вы упомянули, есть ли какая- либо общая функция, чтобы проверить, полностью ли загружена страница в Selenium, ответ - Нет.

Сначала давайте посмотрим на пробную версию кода, которая выглядит следующим образом:

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

Параметр pageLoadTimeout в приведенной выше строке кода на самом деле не похож на фактический pageLoadTimeout(),

Здесь вы можете найти подробное обсуждение pageLoadTimeout в Selenium не работает


Теперь, когда ваш сценарий использования связан с полной загрузкой страницы, вы можете использовать pageLoadStrategy() установлен в normal [поддерживаемые значения: none, нетерпеливые или нормальные ] с использованием экземпляра класса 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 myDemo2 
     {
        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 myDemo1 
    {
        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 и ваша пробная версия кода гарантирует, что клиент браузера (т.е. веб-браузер) достиг 'document.readyState' равно "complete", Как только это условие выполнено, Selenium выполняет следующую строку кода.

Вы можете найти подробное обсуждение в Selenium IE WebDriver only works while debugging

Но клиент браузера достигает 'document.readyState' равно "complete" до сих пор не гарантирует, что все вызовы JavaScript и Ajax завершены.


Чтобы дождаться завершения всех вызовов JavaScript и Ajax, вы можете написать функцию следующим образом:

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" выглядят как ожидающие неопределенных событий. Таким образом, для определенного ожидания вы можете вызвать несоответствие WebDriverWait с ExpectedConditions установлен в 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();

Теперь время от времени это возможно, хотя заголовок страницы будет соответствовать заголовку вашего приложения, но желаемый элемент, с которым вы хотите взаимодействовать, еще не загружен. Таким образом, более детальный подход заключается в том, чтобы вызвать несоответствие WebDriverWait с ExpectedConditions установлен в 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();
    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");
    }
}

Попробуйте этот метод

Я тоже использую селен, и у меня была та же проблема, чтобы исправить это, я просто жду и загрузки jQuery.

Так что, если у вас есть та же проблема, попробуйте это также

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

Вы можете заключить обе функции в метод и проверять, пока не загрузятся и страница, и jQuery.

Это хорошо работает для меня с динамически отображаемыми веб-сайтами:

  1. Дождитесь полной загрузки страницы

Реализуйте это, это работает для многих из нас, включая меня. Он включает ожидание веб-страницы на 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);
            }
          }

Нажмите здесь для ссылки Ссылка

Дайте мне знать, если вы застряли где-нибудь путем реализации.

Он преодолевает использование Thread или Explicit Wait.

Есть простой способ сделать это. Когда вы сначала запрашиваете состояние через javascript, он сообщает вам, что страница есть, но после этого переходит в состояние. Первое состояние было начальной страницей!

Поэтому мое предложение состоит в том, чтобы проверить 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);

Проверка присутствия элемента также работает хорошо, но вам нужно убедиться, что этот элемент присутствует только на целевой странице.

Что-то вроде этого должно работать (пожалуйста, извините питона в ответе Java):

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

Это должно блокировать, пока цикл событий не будет свободен, что означает, что все активы должны быть загружены.

Другие вопросы по тегам