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

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

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

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

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

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

Вы можете проверить страницу URL, чтобы узнать, загружена ли страница или нет?

Sneha Shinde 14.05.2018 11:58
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
1
4 811
7

Ответы 7

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

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

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

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

Вы делаете предположение, что веб-сайт, управляемый Selenium, использует JQuery ...

Ardesco 13.03.2019 15:24

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

Щелкните здесь для получения ссылки

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

Он преодолевает использование потоков или явного ожидания.

Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из обзора

Zabuzard 14.05.2018 14:57

@Zabuza: Код добавлен. Спасибо.

Ishita Shah 14.05.2018 15:18

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

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

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

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

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


Теперь, когда ваш вариант использования относится к полной загрузке страницы, вы можете использовать pageLoadStrategy (), установленный на normal [поддерживаемые значения: никто, жаждущий или обычный], используя либо экземпляр класса Желаемые возможности, либо класс ChromeOptions следующим образом:

  • Использование класса Желаемые возможности:

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

Вы можете найти подробное обсуждение в Стратегия загрузки страницы для драйвера Chrome (обновлено до Selenium v3.12.0)


Теперь установка PageLoadStrategy на ОБЫЧНЫЙ и ваша пробная версия кода гарантируют, что Клиент браузера (то есть Веб-браузер) достиг 'document.readyState', равного "complete". Как только это условие выполнено, Selenium выполняет следующую строку кода.

Вы можете найти подробное обсуждение в Selenium IE WebDriver работает только во время отладки

Но достижение Клиент браузера'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);
    }
}

Вы можете найти подробное обсуждение в Дождитесь завершения запроса ajax - selenium webdriver


Теперь два вышеуказанных подхода через PageLoadStrategy и "return jQuery.active == 0", похоже, ожидают неопределенных событий. Таким образом, для определенного ожидания вы можете вызвать WebDriverWait в сочетании с Ожидаемые условия, установленным на метод 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 в соединении с Ожидаемые условия, установленным на метод 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");
    }
}

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

Что-то вроде этого должно сработать (прошу прощения за питон в java-ответе):

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

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

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

  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, который в большинстве одностраничных приложений дал бы другой результат, вытащите externalhtml первого тега html.

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

Есть простой способ сделать это. Когда вы впервые запрашиваете состояние через 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);

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

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