Я пытаюсь проверить, загружена ли веб-страница завершена или нет (т.е. проверяется, что все элементы управления загружены) в селене.
Я пробовал код ниже:
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
но даже если страница загружается, вышеуказанный код не ждет.
Я знаю, что могу проверить конкретный элемент, чтобы проверить, виден ли он / доступен для щелчка и т. д., Но я ищу какое-то общее решение.




Я тоже использую селен, и у меня была та же проблема, чтобы исправить это, я просто жду загрузки jQuery.
Так что, если у вас такая же проблема, попробуйте также
((Long) ((JavascriptExecutor) browser).executeScript("return jQuery.active") == 0);
Вы можете обернуть обе функции в метод и проверять, пока не будут загружены и страница, и jQuery.
Вы делаете предположение, что веб-сайт, управляемый Selenium, использует JQuery ...
Реализуйте это, это работает для многих из нас, включая меня. Он включает ожидание веб-страницы на 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);
}
}
Щелкните здесь для получения ссылки
Дайте мне знать, если вы где-то застряли, реализовав.
Он преодолевает использование потоков или явного ожидания.
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из обзора
@Zabuza: Код добавлен. Спасибо.
Как вы упомянули, если есть какая-либо общая функция для проверки, полностью ли загружена страница через Селен, ответ будет Нет.
Сначала позвольте нам взглянуть на вашу пробную версию кода, которая выглядит следующим образом:
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)
})
""")
Это должно блокироваться до тех пор, пока цикл событий не будет простаивать, что означает, что все активы должны быть загружены.
У меня это хорошо работает с динамически отображаемыми веб-сайтами:
WebDriverWait wait = new WebDriverWait(driver, 50);
wait.until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete")); 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) {
}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);
Проверка наличия элемента также работает хорошо, но вы должны убедиться, что этот элемент присутствует только на целевой странице.
Вы можете проверить страницу URL, чтобы узнать, загружена ли страница или нет?