Селен ждать, пока документ не будет готов


133

Может кто-нибудь разрешить мне, как заставить селен ждать, пока страница полностью не загрузится? Я хочу что-то общее, я знаю, что могу настроить WebDriverWait и вызвать что-то вроде 'find', чтобы заставить его ждать, но я не захожу так далеко. Мне просто нужно проверить, что страница загружается успешно, и перейти к следующей странице для проверки.

Я нашел что-то в .net, но не смог заставить его работать в Java ...

IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));

Есть какие-нибудь мысли?


Почему вы не хотите использовать wait?
Эми

7
Вы имеете в виду явное ожидание? Это отнимает много времени, я тестирую около 10 тыс. Страниц.
Гириш

2
Я имею в виду, что добавление ожидания исправления может быть плохой идеей, если я тестирую большое количество ссылок, верно?
Гириш

10
Ожидание определенного количества секунд бесполезно. Это гадание.
Андерс Линден

Учитывая, что javascript страницы может запускать любой общий код, написание программы для ожидания ее завершения невозможно. Это форма проблемы остановки ( en.wikipedia.org/wiki/Halting_problem ). Любое решение здесь должно идти на компромиссы или основываться на предположениях базовой веб-страницы.
скоростной самолет

Ответы:


83

Попробуйте этот код:

  driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);

Приведенный выше код будет ждать до 10 секунд для загрузки страницы. Если загрузка страницы превышает время, она выдаст TimeoutException. Вы ловите исключение и выполняете свои потребности. Я не уверен, завершает ли он загрузку страницы после сгенерированного исключения. я еще не пробовал этот код Хочешь просто попробовать.

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

Смотрите документацию дляWebDriver.Timeouts получения дополнительной информации.


3
Спасибо, так что же произойдет, если страница будет загружена до 10 секунд, будет ли она еще 10 секунд для выполнения следующей строки после загрузки?
Гириш

Нет, если ваша страница загружается раньше, чем через 10 секунд, это означает, что она прервет условие ожидания и выполнит предыдущую строку.
Манигандан

3
Это используется для случаев, когда вы ожидаете загрузки страниц, которые занимают слишком много времени для тайм-аута и генерируют исключения, это не сразу ожидает загрузки страницы или устанавливает лучшую политику загрузки. По умолчанию это бесконечное время, поэтому загрузка вашей страницы никогда не вызывает исключений, а Selenium всегда пытается дождаться их полной загрузки.
Петр Янечек

19
Проблема этого метода заключается в том, что DOM может быть не полностью доступен, даже если неявное ожидание ранее успешно вернуло объект WebElement. Затем, если вы попытаетесь щелкнуть элемент, вы получите исключение устаревшего элемента. Таким образом, этот ответ не совсем безопасен.
Джангофан

3
Как этот тайм-аут связан с ожиданием загрузки документа?
Андерс Линден

90

Ваше предлагаемое решение только ожидает сигнала DOMreadyStatecomplete . Но Селен по умолчанию пытается ждать тех , кто (и немного больше) на загрузке страницы с помощью driver.get()и element.click()методов. Они уже блокируются, они ждут полной загрузки страницы, и они должны работать нормально.

Проблема, очевидно, заключается в переадресации с помощью запросов AJAX и запуска скриптов - Selenium не может их перехватить, он не ждет их завершения. Кроме того, вы не можете надежно их перехватить readyState- он немного ждет, что может быть полезно, но он будет сигнализировать completeзадолго до того, как будет загружен весь контент AJAX.

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

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

См. Мои два ответа по этому поводу для получения дополнительной информации:


20
Это неточно, Selenium не ждет и не блокирует element.click()звонки.
hwjp 03

3
@hwjp Хотите подробнее рассказать? В JavaDocs говорится иначе : «Если это вызывает загрузку новой страницы, этот метод будет пытаться заблокировать, пока страница не загрузится».
Петр Янечек

5
cf некоторые разговоры, которые у меня были в списке рассылки, кажутся неточными. selenium может блокировать вызовы .get, в которых вы явно запрашиваете URL-адрес, но он не делает ничего особенного для вызовов click, поскольку не может определить, щелкнули ли вы по «настоящей» гиперссылке или по той, которая будет перехвачена javascript. ..
hwjp 03

4
Я ссылаюсь на ошибку в начале обсуждения в списке рассылки. Даже документация двусмысленно: «Если click () [...] выполняется путем отправки собственного события, то метод * не * будет ждать»
hwjp

4
Итак, все зависит от того, использует ли браузер «собственные события». И похоже, что большинство из них по умолчанию: code.google.com/p/selenium/wiki/… (так что я бы сказал, что эти документы в лучшем случае вводят в заблуждение. Пингуют список рассылки).
hwjp

61

Это рабочая Java-версия приведенного вами примера:

void waitForLoad(WebDriver driver) {
    new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
            ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}

Пример для C #:

public static void WaitForLoad(IWebDriver driver, int timeoutSec = 15)
{
  IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
  WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
  wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}

1
Чувак, я копирую / вставляю это. Этот фрагмент просто великолепен. Почему я не подумал об этом? Правда в том, что более чем одна пара глазных яблок всегда приводит к хорошему решению. Спасибо.
luis.espinal 08

2
Можете ли вы поместить это в совместимую версию java 1.7, поскольку лямбда-выражения не поддерживают
vkrams

3
Версия Java 1.7: wait.until (new Predicate <WebDriver> () {public boolean apply (драйвер WebDriver) {return (драйвер ((JavascriptExecutor)) .executeScript ("return document.readyState"). Equals ("complete");} });
luQ

1
Если кто-то хочет использовать решение от @IuQ, тогда у Predicate есть импортimport com.google.common.base.Predicate
Knu8,

Я попробовал эту идею в тестовом приложении VB. Работает большую часть времени. Иногда я получаю эту ошибку: System.InvalidOperationException: ошибка JavaScript (UnexpectedJavaScriptError) в OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError (Response errorResponse) Тестовое приложение щелкает ссылку меню уровня 2, затем вызывает WaitObj.Until (Function (D D, InternetExplorerDriver) .ExecuteScript ("return document.readyState") = "complete"). Я думаю, что ошибка вызвана тем, что браузер выгружает текущую страницу и не является объектом документа. Может быть, подождите 1/2 секунды, прежде чем делать «return document.readystate? Ideas?»
CoolBreeze

12

Вот моя попытка полностью универсального решения на Python:

Во-первых, общая функция ожидания (используйте WebDriverWait, если хотите, я считаю их уродливыми):

def wait_for(condition_function):
    start_time = time.time()
    while time.time() < start_time + 3:
        if condition_function():
            return True
        else:
            time.sleep(0.1)
    raise Exception('Timeout waiting for {}'.format(condition_function.__name__))

Далее, решение основывается на том факте, что селен записывает (внутренний) id-номер для всех элементов на странице, включая <html>элемент верхнего уровня . Когда страница обновляется или загружается, она получает новый элемент html с новым идентификатором.

Итак, предположим, что вы хотите щелкнуть ссылку с текстом «моя ссылка», например:

old_page = browser.find_element_by_tag_name('html')

browser.find_element_by_link_text('my link').click()

def page_has_loaded():
    new_page = browser.find_element_by_tag_name('html')
    return new_page.id != old_page.id

wait_for(page_has_loaded)

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

from contextlib import contextmanager

@contextmanager
def wait_for_page_load(browser):
    old_page = browser.find_element_by_tag_name('html')

    yield

    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id

    wait_for(page_has_loaded)

И затем вы можете использовать его практически для любого взаимодействия с селеном:

with wait_for_page_load(browser):
    browser.find_element_by_link_text('my link').click()

Я считаю, что это пуленепробиваемое! Что вы думаете?

Больше информации в блоге об этом здесь


Очень интересный подход. Одна из проблем заключается в том, может ли это работать при начальной загрузке страницы после первого запуска браузера. Нет гарантии, что в исходном состоянии браузера загружена какая-либо страница. Кроме того, в Java я не вижу, что у нас есть идентификатор объекта - я предполагаю, что вы не имеете в виду, что селен вставляет атрибут html id. Я добавлю больше к этому ответу, когда изучу этот вариант подробнее. Спасибо за пост!
Lukus

@hwjp Я использую это решение много раз с отличными результатами, но похоже, что в одном случае оно не работает. Полное объяснение проблемы stackoverflow.com/q/31985739/4249707
Эль Русо,

7

У меня была похожая проблема. Мне нужно было подождать, пока мой документ не будет готов, но также и до завершения всех вызовов Ajax. Второе условие оказалось трудно обнаружить. В конце концов я проверил активные вызовы Ajax, и это сработало.

Javascript:

return (document.readyState == 'complete' && jQuery.active == 0)

Полный метод C #:

private void WaitUntilDocumentIsReady(TimeSpan timeout)
{
    var javaScriptExecutor = WebDriver as IJavaScriptExecutor;
    var wait = new WebDriverWait(WebDriver, timeout);            

    // Check if document is ready
    Func<IWebDriver, bool> readyCondition = webDriver => javaScriptExecutor
        .ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
    wait.Until(readyCondition);
}

Есть ли что-нибудь вроде document.readyState == 'complete' && jQuery.active == 0React?
Rain9333 06


4

Для C # NUnit вам необходимо преобразовать WebDriver в JSExecuter, а затем выполнить сценарий, чтобы проверить, завершено ли состояние document.ready или нет. Проверьте код ниже для справки:

 public static void WaitForLoad(IWebDriver driver)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
        int timeoutSec = 15;
        WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
        wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
    }

Это будет ждать, пока условие не будет выполнено или не истечет время ожидания.


3

При начальной загрузке страницы я заметил, что «разворачивание» окна браузера практически ожидает завершения загрузки страницы (включая источники).

Заменить:

AppDriver.Navigate().GoToUrl(url);

С участием:

public void OpenURL(IWebDriver AppDriver, string Url)
            {
                try
                {
                    AppDriver.Navigate().GoToUrl(Url);
                    AppDriver.Manage().Window.Maximize();
                    AppDriver.SwitchTo().ActiveElement();
                }
                catch (Exception e)
                {
                    Console.WriteLine("ERR: {0}; {1}", e.TargetSite, e.Message);
                    throw;
                }
            }

чем использовать:

OpenURL(myDriver, myUrl);

Это загрузит страницу, дождется завершения, развернется и сфокусируется на ней. Я не знаю, почему это так, но это работает.

Если вы хотите дождаться загрузки страницы после щелчка по следующей или любому другому триггеру навигации по странице, кроме «Navigate ()», ответ Бена Дайера (в этой ветке) выполнит свою работу.


1

Взгляните на веб-фреймворк для гобеленов . Вы можете скачать исходный код здесь.

Идея состоит в том, чтобы сигнализировать о том, что страница готова, с помощью атрибута html тела. Вы можете использовать эту идею, игнорируя сложные судебные дела.

<html>
<head>
</head>
<body data-page-initialized="false">
    <p>Write you page here</p>

    <script>
    $(document).ready(function () {
        $(document.body).attr('data-page-initialized', 'true');
    });
    </script>  
</body>
</html>

А затем создайте расширение Selenium webdriver (согласно структуре гобелена)

public static void WaitForPageToLoad(this IWebDriver driver, int timeout = 15000)
{
    //wait a bit for the page to start loading
    Thread.Sleep(100);

    //// In a limited number of cases, a "page" is an container error page or raw HTML content
    // that does not include the body element and data-page-initialized element. In those cases,
    // there will never be page initialization in the Tapestry sense and we return immediately.
    if (!driver.ElementIsDisplayed("/html/body[@data-page-initialized]"))
    {                
        return;
    }

    Stopwatch stopwatch = Stopwatch.StartNew();

    int sleepTime = 20;

    while(true)
    {
        if (driver.ElementIsDisplayed("/html/body[@data-page-initialized='true']"))
        {
            return;
        }

        if (stopwatch.ElapsedMilliseconds > 30000)
        {
            throw new Exception("Page did not finish initializing after 30 seconds.");
        }

        Thread.Sleep(sleepTime);
        sleepTime *= 2; // geometric row of sleep time
    }          
}

Используйте расширение ElementIsDisplayed, написанное Алистером Скоттом .

public static bool ElementIsDisplayed(this IWebDriver driver, string xpath)
{
    try
    {
        return driver.FindElement(By.XPath(xpath)).Displayed;
    }
    catch(NoSuchElementException)
    {
        return false;
    }
}

И наконец создайте тест:

driver.Url = this.GetAbsoluteUrl("/Account/Login");            
driver.WaitForPageToLoad();

1

Ответ Бена Драйера не компилировался на моей машине ( "The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").

Рабочая версия Java 8:

Predicate<WebDriver> pageLoaded = wd -> ((JavascriptExecutor) wd).executeScript(
        "return document.readyState").equals("complete");
new FluentWait<WebDriver>(driver).until(pageLoaded);

Версия Java 7:

Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver input) {
            return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
        }

};
new FluentWait<WebDriver>(driver).until(pageLoaded);

1

Я попробовал этот код, и он у меня работает. Я вызываю эту функцию каждый раз, когда перехожу на другую страницу

public static void waitForPageToBeReady() 
{
    JavascriptExecutor js = (JavascriptExecutor)driver;

    //This loop will rotate for 100 times to check If page Is ready after every 1 second.
    //You can replace your if you wants to Increase or decrease wait time.
    for (int i=0; i<400; i++)
    { 
        try 
        {
            Thread.sleep(1000);
        }catch (InterruptedException e) {} 
        //To check page ready state.

        if (js.executeScript("return document.readyState").toString().equals("complete"))
        { 
            break; 
        }   
      }
 }

1

В Nodejs вы можете получить это через обещания ...

Если вы напишете этот код, вы можете быть уверены, что страница будет полностью загружена, когда вы перейдете к then ...

driver.get('www.sidanmor.com').then(()=> {
    // here the page is fully loaded!!!
    // do your stuff...
}).catch(console.log.bind(console));

Если вы напишете этот код, вы будете перемещаться, а селен будет ждать 3 секунды ...

driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...

Из документации Selenium:

this.get (url) → Thenable

Планирует команду для перехода по заданному URL-адресу.

Возвращает обещание, которое будет разрешено после завершения загрузки документа .

Документация по Selenium (Nodejs)


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, чтобы он как можно скорее получил ссылку на страницу. Веселитесь с этим!


1

нормально, когда селен открывает новую страницу с помощью методов click или submit или get, он будет ждать, пока страница не загружена, но проблема в том, что когда на странице есть вызов xhr (ajax), он никогда не будет ждать загрузки xhr, поэтому создание нового метода для мониторинга xhr и ожидания их будет хорошо.

public boolean waitForJSandJQueryToLoad() {
    WebDriverWait wait = new WebDriverWait(webDriver, 30);
    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
            Long r = (Long)((JavascriptExecutor)driver).executeScript("return $.active");
            return r == 0;
        } catch (Exception e) {
            LOG.info("no jquery present");
            return true;
        }
      }
    };

    // wait for Javascript to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return ((JavascriptExecutor)driver).executeScript("return document.readyState")
        .toString().equals("complete");
      }
    };

  return wait.until(jQueryLoad) && wait.until(jsLoad);
}

if $.active == 0поэтому нет активного вызова xhrs (который работает только с jQuery). для вызова javascript ajax вам необходимо создать переменную в своем проекте и смоделировать ее.


0

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

public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.get("https://www.crowdanalytix.com/#home");
        WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
        int i = 1;
        while (webElement == null && i < 4) {
            webElement = getWebElement(driver, "homessssssssssss");
            System.out.println("calling");
            i++;
        }
        System.out.println(webElement.getTagName());
        System.out.println("End");
        driver.close();
    }

    public static WebElement getWebElement(WebDriver driver, String id) {
        WebElement myDynamicElement = null;
        try {
            myDynamicElement = (new WebDriverWait(driver, 10))
                    .until(ExpectedConditions.presenceOfElementLocated(By
                            .id(id)));
            return myDynamicElement;
        } catch (TimeoutException ex) {
            return null;
        }
    }

0

Я выполнил код javascript, чтобы проверить, готов ли документ. Сэкономила мне много времени на отладку тестов на селен для сайтов с рендерингом на стороне клиента.

public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
    Thread.sleep(100)
    def ready = isDOMReady(driver);
    if (ready) {
        break;
    }
}

}

public static boolean isDOMReady(WebDriver driver){
    return driver.executeScript("return document.readyState");
}

0
public boolean waitForElement(String zoneName, String element, int index, int timeout) {
        WebDriverWait wait = new WebDriverWait(appiumDriver, timeout/1000);
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element)));
        return true;
    }

0

Как Рубанов писал для C #, я пишу для Java, и это:

    public void waitForPageLoaded() {
    ExpectedCondition<Boolean> expectation = new
            ExpectedCondition<Boolean>() {
                public Boolean apply(WebDriver driver) {
                    return (((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete")&&((Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")));
                }
            };
    try {
        Thread.sleep(100);
        WebDriverWait waitForLoad = new WebDriverWait(driver, 30);
        waitForLoad.until(expectation);
    } catch (Throwable error) {
        Assert.fail("Timeout waiting for Page Load Request to complete.");
    }
}

0

В Java это будет примерно так: -

  private static boolean isloadComplete(WebDriver driver)
    {
        return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
                || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
    }

1
Было бы лучше объединить команды JS в одну, чтобы вам не приходилось дважды return document.readyState == 'loaded' || return document.readyState == 'complete'
нажимать

0

Следующий код, вероятно, должен работать:

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));

0

Если у вас медленная страница или сетевое соединение, скорее всего, ничего из вышеперечисленного не сработает. Я перепробовал их все, и единственное, что у меня сработало, - это дождаться последнего видимого элемента на этой странице. Возьмем, к примеру, веб-страницу Bing. Они поместили значок КАМЕРА (кнопка поиска по изображению) рядом с основной кнопкой поиска, которая видна только после загрузки всей страницы. Если все сделали это, то все, что нам нужно сделать, это использовать явное ожидание, как в примерах выше.


-1
public void waitForPageToLoad()
  {
(new WebDriverWait(driver, DEFAULT_WAIT_TIME)).until(new ExpectedCondition<Boolean>() {
      public Boolean apply(WebDriver d) {
        return (((org.openqa.selenium.JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"));
      }
    });//Here DEFAULT_WAIT_TIME is a integer correspond to wait time in seconds

-1

Вот нечто подобное в Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }

Ваш код не работает для меня. Как переключиться на iframe и дождаться onload = "javascript: pageload (); functionPageLoad ();" перезагрузить страницу в Ruby? Я обнаружил, что открываю iframe внутри страницы, у меня есть доступ к нему, затем страница перезагружается, и я больше не могу получить доступ к кадру. Я прочитал много ответов о ожидании, сне, времени, переключении на кадр, затем на родительский, но я не могу достичь своей цели.
Аманда Кавалларо,

1
Похоже, ваш вопрос в первую очередь о том, как переключиться на iFrame, а не об ожидании загрузки документа. Возможно, будет лучше начать новый вопрос, если вы не можете найти решение в вопросе о работе с iFrames.
emery

-1

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

driver.get(homeUrl); 
Thread.sleep(5000);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(userName);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(passWord);
driver.findElement(By.xpath("Your_Xpath_here")).click();

Я считаю, что Thread.sleep (5000) часто является единственным методом, с помощью которого тест работает, несмотря на все рекомендации против его использования. Никакая комбинация ожидания элемента для меня не работает, тем более что многие элементы невозможно идентифицировать, пока они не будут действительно найдены.
Steve Staple

-1

Я проверил, что загрузка страницы завершена, работает в Selenium 3.14.0

    public static void UntilPageLoadComplete(IWebDriver driver, long timeoutInSeconds)
    {
        Until(driver, (d) =>
        {
            Boolean isPageLoaded = (Boolean)((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete");
            if (!isPageLoaded) Console.WriteLine("Document is loading");
            return isPageLoaded;
        }, timeoutInSeconds);
    }

    public static void Until(IWebDriver driver, Func<IWebDriver, Boolean> waitCondition, long timeoutInSeconds)
    {
        WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
        webDriverWait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
        try
        {
            webDriverWait.Until(waitCondition);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

-1

Для людей, которым нужно дождаться появления определенного элемента. (используется C #)

public static void WaitForElement(IWebDriver driver, By element)
{
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
    wait.Until(ExpectedConditions.ElementIsVisible(element));
}

Затем, если вы хотите подождать, например, если в DOM существует class = "error-message", вы просто выполните:

WaitForElement(driver, By.ClassName("error-message"));

Тогда для id это будет

WaitForElement(driver, By.Id("yourid"));


-3

Вы используете Angular? Если это так, возможно, веб-драйвер не распознает, что асинхронные вызовы завершены.

Рекомендую посмотреть на Paul Hammants ngWebDriver . Может пригодиться метод waitForAngularRequestsToFinish ().


Он очень не использовал Angular. Этот ответ был отклонен, потому что, похоже, вы не внимательно прочитали исходный вопрос.
zelusp

Но не позволяйте голосам выводить вас из формы. Люди здесь имеют в виду хорошо. А критика - это на самом деле форма любви (потому что, если кто-то находит время, чтобы поправить кого-то, это потому, что ему не все равно). Checkout Как правильно задавать вопросы - эти идеи также применимы к умным ответам на вопросы.
zelusp
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.