Selen poczekaj, aż dokument będzie gotowy

137

Czy ktoś może mi pozwolić, jak mogę sprawić, by selen zaczekał do całkowitego załadowania strony? Chcę czegoś ogólnego, wiem, że mogę skonfigurować WebDriverWait i wywołać coś w rodzaju „find”, aby poczekać, ale nie posuwam się tak daleko. Muszę tylko sprawdzić, czy strona ładuje się pomyślnie i przejść do następnej strony, aby przetestować.

Znalazłem coś w .net, ale nie mogłem sprawić, by działało w Javie ...

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"));

Czy ktoś myśli?

Girish
źródło
Dlaczego nie chcesz używać czekania?
Amey,
7
Masz na myśli wyraźne czekanie? Jest to czasochłonne, testuję około 10 tys. Stron.
Girish
2
Chodzi mi o to, że dodanie poprawki oczekiwania może nie być dobrym pomysłem, jeśli testuję dużą liczbę linków, prawda?
Girish
11
Czekanie przez określoną liczbę sekund nie ma sensu. To zgadywanie.
Anders Lindén
Biorąc pod uwagę, że javascript strony może uruchomić dowolny kod ogólny, napisanie programu czekającego na jego zakończenie jest niemożliwe. Jest to forma problemu zatrzymania ( en.wikipedia.org/wiki/Halting_problem ). Każde rozwiązanie będzie musiało iść na kompromisy lub opierać się na założeniach podstawowej strony internetowej.
speedplane

Odpowiedzi:

84

Wypróbuj ten kod:

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

Powyższy kod będzie czekał do 10 sekund na załadowanie strony. Jeśli ładowanie strony przekroczy czas, wyrzuci plik TimeoutException. Łapiesz wyjątek i spełniasz swoje potrzeby. Nie jestem pewien, czy kończy ładowanie strony po zgłoszeniu wyjątku. nie próbowałem jeszcze tego kodu. Chcę po prostu spróbować.

To jest ukryte oczekiwanie. Jeśli ustawisz to raz, zakres będzie obowiązywał do momentu zniszczenia instancji sterownika sieciowego.

Więcej informacji można znaleźć w dokumentacjiWebDriver.Timeouts .

Manigandan
źródło
3
Dzięki, więc co się stanie, jeśli strona zostanie załadowana przed 10 sekundami, czy nadal będzie czekać 10 sekund na wykonanie następnej linii po załadowaniu?
Girish
Nie, jeśli Twoja strona ładuje się przed upływem 10 sekund, oznacza to, że zakończy warunek oczekiwania i wykona poprzednią linię.
Manigandan
3
Jest to używane, gdy spodziewasz się, że ładowanie strony trwa zbyt długo i generuje wyjątki, nie czeka od razu na załadowanie strony ani nie ustawia lepszej zasady ładowania. Domyślnie jest to nieskończony czas, więc ładowanie strony nigdy nie generuje wyjątków, a Selenium zawsze próbuje czekać, aż załadują się całkowicie.
Petr Janeček
19
Problem z tą metodą polega na tym, że jest możliwe, że DOM nie jest całkowicie dostępny, nawet jeśli niejawne oczekiwanie poprzednio pomyślnie zwróciło obiekt WebElement. Następnie, jeśli spróbujesz kliknąć element, otrzymasz nieaktualny wyjątek elementu. Tak więc ta odpowiedź nie jest całkowicie bezpieczna.
djangofan
3
W jaki sposób ten limit czasu jest powiązany z oczekiwaniem na załadowanie dokumentu?
Anders Lindén
93

Twoje sugerowane rozwiązanie czeka tylko na sygnał DOMreadyStatecomplete . Ale Selenium domyślnie próbuje czekać na te (i trochę więcej) ładunków strony za pomocą metod driver.get()i element.click(). Już się blokują, czekają na pełne załadowanie strony i te powinny działać poprawnie.

Problemem są oczywiście przekierowania za pośrednictwem żądań AJAX i uruchomionych skryptów - Selenium nie może ich przechwycić, nie czeka na ich zakończenie. Ponadto nie można ich niezawodnie złapać readyState- czeka chwilę, co może być przydatne, ale będzie sygnalizować na completedługo przed pobraniem całej zawartości AJAX.

Nie ma ogólnego rozwiązania, które sprawdziłoby się wszędzie i dla każdego, dlatego jest to trudne i każdy używa czegoś innego.

Ogólna zasada polega na tym, że WebDriver wykona swoją część, następnie użyj niejawnego oczekiwania, a następnie użyj jawnego oczekiwania dla elementów, które chcesz potwierdzić na stronie, ale jest o wiele więcej technik, które można zrobić. Na testowanej stronie powinieneś wybrać ten (lub kombinację kilku z nich), który działa najlepiej w Twoim przypadku.

Zobacz moje dwie odpowiedzi dotyczące tego, aby uzyskać więcej informacji:

Petr Janeček
źródło
21
To niedokładne, Selenium nie czeka ani nie blokuje element.click()połączeń.
hwjp
3
@hwjp Chcesz rozwinąć więcej? Dokument JavaDocs mówi inaczej : „Jeśli spowoduje to załadowanie nowej strony, ta metoda będzie próbować blokować do czasu załadowania strony”.
Petr Janeček,
5
cf kilka rozmów, które miałem na liście mailingowej , wydaje się, że to niedokładne. selen może blokować wywołania .get, w przypadku których wyraźnie żądasz adresu URL, ale nie robi nic specjalnego w przypadku wywołań kliknięć, ponieważ nie jest w stanie stwierdzić, czy kliknąłeś „prawdziwy” hiperłącze, czy takie, które zostanie przechwycone przez javascript. ..
hwjp
4
Podaję link do błędu na początku dyskusji na liście mailingowej. Nawet dokumenty nie są jednoznaczne: „Jeśli kliknięcie () [...] zostanie wykonane przez wysłanie natywnego zdarzenia, metoda * nie * zaczeka”
hwjp
4
Wszystko się więc włącza, niezależnie od tego, czy przeglądarka używa „natywnych zdarzeń”. Wygląda na to, że większość z nich będzie domyślnie: code.google.com/p/selenium/wiki/… (więc powiedziałbym, że te dokumenty są w najlepszym razie mylące. Spingują listę mailingową).
hwjp
62

Oto działająca wersja Java przykładu, który podałeś:

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

Przykład dla 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");
}
Ben Dyer
źródło
1
Koleś, kopiuję / wklejam to. Ten fragment jest po prostu genialny. Dlaczego o tym nie pomyślałem? Prawda, że ​​więcej niż jedna para gałek ocznych zawsze prowadzi do dobrego rozwiązania. Dzięki.
luis.espinal
2
Czy możesz umieścić to w wersji
kompatybilnej z Javą
3
Wersja Java 1.7: wait.until (new Predicate <WebDriver> () {public boolean apply (sterownik WebDriver) {return ((JavascriptExecutor) sterownik) .executeScript ("return document.readyState"). Equals ("complete");} });
luQ,
1
Jeśli ktoś chce skorzystać z rozwiązania @IuQ to Predicate ma importimport com.google.common.base.Predicate
Knu8
Wypróbowałem ten pomysł w aplikacji testowej VB. Działa przez większość czasu. Czasami dostaję ten błąd: System.InvalidOperationException: Błąd JavaScript (NieoczekiwanyJavaScriptError) w OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError (Response errorResponse) Testuj aplikację, klikając łącze menu poziomu 2, a następnie wywołuje WaitObj.Until (Function (D) DirectCast D, InternetExplorerDriver) .ExecuteScript ("return document.readyState") = "Complete"). Myślę, że błąd jest spowodowany tym, że przeglądarka wyładowuje bieżącą stronę i nie jest obiektem dokumentu. Może poczekaj 1/2 sekundy przed wykonaniem polecenia „zwrot dokumentu.czytaj stan? Pomysły?
CoolBreeze,
12

Oto moja próba stworzenia całkowicie ogólnego rozwiązania w Pythonie:

Po pierwsze, ogólna funkcja „czekaj” (jeśli chcesz, użyj WebDriverWait, uważam je za brzydkie):

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__))

Następnie rozwiązanie opiera się na fakcie, że selen rejestruje (wewnętrzny) numer identyfikacyjny dla wszystkich elementów na stronie, w tym elementu najwyższego poziomu <html>. Gdy strona odświeża się lub ładuje, otrzymuje nowy element html z nowym identyfikatorem.

Więc zakładając, że chcesz kliknąć link z tekstem „mój link”, na przykład:

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)

Aby uzyskać więcej ogólnych pomocników w języku Pythonic, wielokrotnego użytku, możesz utworzyć menedżera kontekstu:

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)

A potem możesz go użyć do praktycznie każdej interakcji z selenem:

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

Myślę, że to jest kuloodporne! Co myślisz?

Więcej informacji w poście na ten temat tutaj

hwjp
źródło
Bardzo ciekawe podejście. Jednym z wyzwań jest to, czy to zadziała przy pierwszym wczytywaniu strony, po pierwszym uruchomieniu przeglądarki. Nie ma gwarancji, że w początkowym stanie przeglądarki została załadowana jakakolwiek strona. Również w Javie nie widzę, że mamy 'id' na obiekcie - zakładam, że nie masz na myśli tego, że selen wstawia atrybut HTML id. Dodam więcej do tej odpowiedzi, gdy lepiej zbadam tę opcję. Dzięki za post!
Lukus
@hwjp Używam tego rozwiązania wiele razy z doskonałymi wynikami, ale wygląda na to, że nie działa w jednym przypadku. Pełne wyjaśnienie problemu stackoverflow.com/q/31985739/4249707
El Ruso
7

Miałem podobny problem. Musiałem poczekać, aż mój dokument będzie gotowy, ale także do zakończenia wszystkich połączeń Ajax. Drugi warunek okazał się trudny do wykrycia. W końcu sprawdziłem aktywne połączenia Ajax i zadziałało.

JavaScript:

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

Pełna metoda 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);
}
Rubanov
źródło
Czy jest coś takiego jak document.readyState == 'complete' && jQuery.active == 0React?
Rain9333
7
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
Ram Bharath
źródło
4

W przypadku C # NUnit musisz przekonwertować WebDriver na JSExecuter, a następnie wykonać skrypt, aby sprawdzić, czy stan document.ready jest kompletny, czy nie. Sprawdź poniższy kod w celach informacyjnych:

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

Będzie to czekać, aż warunek zostanie spełniony lub upłynie limit czasu.

S.Akruwala
źródło
3

Przy początkowym ładowaniu strony zauważyłem, że "Maksymalizacja" okna przeglądarki praktycznie czeka na zakończenie ładowania strony (łącznie ze źródłami)

Zastąpić:

AppDriver.Navigate().GoToUrl(url);

Z:

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

niż używać:

OpenURL(myDriver, myUrl);

Spowoduje to załadowanie strony, zaczekanie na zakończenie, zmaksymalizowanie i skupienie się na niej. Nie wiem, dlaczego tak jest, ale działa.

Jeśli chcesz poczekać na załadowanie strony po kliknięciu na następny lub jakikolwiek inny wyzwalacz nawigacji po stronie inny niż „Nawiguj ()”, odpowiedź Bena Dyera (w tym wątku) załatwi sprawę.

Roei Sabag
źródło
1

Spójrz na framework sieciowy gobelinów . Możesz tam pobrać kod źródłowy .

Chodzi o to, aby zasygnalizować gotowość strony za pomocą atrybutu body w html. Możesz wykorzystać ten pomysł zignorować skomplikowane sprawy sądowe.

<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>

Następnie utwórz rozszerzenie webdrivera Selenium (zgodnie z frameworkiem tapestry)

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
    }          
}

Użyj rozszerzenia ElementIsDisplayed napisanego przez Alistera Scotta .

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

I wreszcie stwórz test:

driver.Url = this.GetAbsoluteUrl("/Account/Login");            
driver.WaitForPageToLoad();
Tomas Kubes
źródło
1

Odpowiedź Bena Dryera nie została skompilowana na moim komputerze ( "The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").

Działająca wersja Java 8:

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

Wersja 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);
Hazel Troost
źródło
1

Wypróbowałem ten kod i działa dla mnie. Wywołuję tę funkcję za każdym razem, gdy przechodzę do innej strony

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; 
        }   
      }
 }
SOAlgorithm
źródło
1

W Nodejs możesz to uzyskać dzięki obietnicom ...

Jeśli napiszesz ten kod, możesz być pewien, że strona jest w pełni załadowana, gdy dotrzesz do wtedy ...

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

Jeśli napiszesz ten kod, będziesz nawigować, a selen poczeka 3 sekundy ...

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...

Z dokumentacji Selenium:

this.get (url) → Thenable

Planuje polecenie przejścia do podanego adresu URL.

Zwraca obietnicę, która zostanie rozwiązana po zakończeniu ładowania dokumentu .

Dokumentacja selenu (Nodejs)

sidanmor
źródło
1

Czas oczekiwania na zdarzenie document.ready nie jest całkowitym rozwiązaniem tego problemu, ponieważ ten kod jest nadal w stanie wyścigu: czasami ten kod jest uruchamiany przed przetworzeniem zdarzenia kliknięcia, więc zwraca się bezpośrednio, ponieważ przeglądarka nie została uruchomiona ładowanie nowej strony jeszcze.

Po krótkich poszukiwaniach znalazłem post na temat kozła testowego Obay , który ma rozwiązanie tego problemu. Kod C # tego rozwiązania wygląda mniej więcej tak:

 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"));

}

`Uruchamiam tę metodę bezpośrednio po pliku driver.navigate.gotourl, aby jak najszybciej uzyskać odwołanie do strony. Baw się dobrze!

Maarten Kieft
źródło
1

normalnie, gdy selen otwiera nową stronę za pomocą kliknięcia lub przesłania lub pobrania metod, będzie czekał, aż strona zostanie załadowana, ale problem polega na tym, że gdy strona ma wywołanie xhr (ajax), nigdy nie będzie czekać na załadowanie xhr, więc stworzenie nowej metody monitorowania xhr i czekania na nich to będzie dobrze.

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 == 0więc nie ma aktywnego wywołania xhrs (które działa tylko z jQuery). dla wywołania javascript ajax musisz stworzyć zmienną w swoim projekcie i zasymulować ją.

elazzam
źródło
0

Możesz napisać logikę, aby sobie z tym poradzić. Mam napisać metodę, która zwróci WebElementi ta metoda zostanie wywołana trzykrotnie lub możesz zwiększyć czas i dodać zerową kontrolę WebElementOto przykład

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;
        }
    }
Vaibhav Pandey
źródło
0

Wykonałem kod javascript, aby sprawdzić, czy dokument jest gotowy. Zaoszczędziło mi wiele czasu na debugowaniu testów selenu dla witryn, które mają renderowanie po stronie klienta.

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");
}
bertanasco
źródło
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;
    }
akhilesh gulati
źródło
0

Tak jak Rubanov napisał dla C #, ja piszę to dla Javy i jest to:

    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.");
    }
}
Krzysztof Walczewski
źródło
0

W Javie spodoba się poniżej: -

  private static boolean isloadComplete(WebDriver driver)
    {
        return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
                || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
    }
Shubham Jain
źródło
1
Byłoby lepiej połączyć polecenia JS w jedno, aby nie trzeba było dwukrotnie return document.readyState == 'loaded' || return document.readyState == 'complete'
odwiedzać
0

Poniższy kod prawdopodobnie powinien działać:

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));
vrn
źródło
0

Jeśli masz wolne połączenie ze stroną lub siecią, istnieje prawdopodobieństwo, że żadne z powyższych nie zadziała. Wypróbowałem je wszystkie i jedyne, co mi zadziałało, to zaczekanie na ostatni widoczny element na tej stronie. Weźmy na przykład stronę internetową Bing. Umieścili ikonę KAMERY (przycisk wyszukiwania według obrazu) obok głównego przycisku wyszukiwania, który jest widoczny dopiero po załadowaniu całej strony. Jeśli wszyscy to zrobili, wszystko, co musimy zrobić, to użyć jawnego oczekiwania, jak w powyższych przykładach.

user3988148
źródło
-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
Manjyot
źródło
-1

Oto coś podobnego w Rubim:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }
szmergiel
źródło
Twój kod nie działa dla mnie. Jak mogę przełączyć się na iframe i czekać na onload = "javascript: pageload (); funkcjonalnyPageLoad ();" przeładować stronę w Rubim? Otwieram ramkę iframe wewnątrz strony, mam do niej dostęp, a następnie strona ładuje się ponownie i nie mam już dostępu do ramki. Przeczytałem wiele odpowiedzi dotyczących czekania, snu, czasu, przełączania na klatkę, a następnie na rodzica, jednak nie mogę osiągnąć celu.
Amanda Cavallaro
1
Wygląda na to, że twoje pytanie dotyczy głównie tego, jak przełączyć się na iFrame, a nie czekać na załadowanie dokumentu. Lepiej będzie rozpocząć nowe pytanie, jeśli nie możesz znaleźć odpowiedzi na pytanie dotyczące pracy z elementami iFrames.
emery
-1

Możesz uśpić wątek do ponownego załadowania strony. To nie jest najlepsze rozwiązanie, ponieważ musisz oszacować, jak długo trwa ładowanie strony.

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();
Eric Fernandes
źródło
Uważam, że Thread.sleep (5000) jest często jedyną metodą, w której test działa, pomimo wszystkich zaleceń przeciwko jej stosowaniu. Żadna kombinacja oczekiwania na element nie działa dla mnie, zwłaszcza, że ​​wielu elementów nie można zidentyfikować, dopóki nie zostaną faktycznie znalezione.
Steve Staple
-1

Sprawdziłem ładowanie strony zakończone, pracuję w 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);
        }
    }
Jundat95
źródło
-1

Dla osób, które muszą czekać na pojawienie się określonego elementu. (używany C #)

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

Następnie, jeśli chcesz poczekać, na przykład jeśli w DOM istnieje class = "komunikat o błędzie", po prostu wykonaj:

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

Dla id będzie to

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

Mo D Genesis
źródło
-3

Używasz Angulara? Jeśli tak, możliwe, że webdriver nie rozpoznaje zakończenia wywołań asynchronicznych.

Polecam zajrzeć do Paul Hammants ngWebDriver . Przydałaby się metoda waitForAngularRequestsToFinish ().

Marlies
źródło
Bardzo nie używał Angulara. Ta odpowiedź została odrzucona, ponieważ wygląda na to, że nie przeczytałeś uważnie pierwotnego pytania.
zelusp
Ale nie pozwól, aby głosy wytrącały Cię z formy. Ludzie tutaj chcą dobrze. A krytyka jest w rzeczywistości formą miłości (ponieważ jeśli ktoś poświęca czas na poprawianie kogokolwiek, to dlatego, że mu zależy). Checkout Jak zadawać pytania w inteligentny sposób - te pomysły dotyczą również inteligentnego odpowiadania na pytania.
zelusp