Selen warten, bis das Dokument fertig ist

133

Kann mir jemand erlauben, wie ich Selen warten lassen kann, bis die Seite vollständig geladen ist? Ich möchte etwas Generisches, ich weiß, dass ich WebDriverWait konfigurieren und so etwas wie 'find' aufrufen kann, damit es wartet, aber ich gehe nicht so weit. Ich muss nur testen, ob die Seite erfolgreich geladen wurde, und mit der nächsten Seite fortfahren, um sie zu testen.

Ich habe etwas in .net gefunden, konnte es aber in Java nicht zum Laufen bringen ...

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

Irgendwelche Gedanken jemand?

Girish
quelle
Warum wollen Sie wait nicht verwenden?
Amey
7
Du meinst explizites Warten? Es ist zeitaufwändig, ich teste ungefähr 10.000 Seiten.
Girish
2
Ich meine, das Hinzufügen einer festen Wartezeit ist möglicherweise keine gute Idee, wenn ich eine große Anzahl von Links teste, oder?
Girish
10
Das Warten auf eine feste Anzahl von Sekunden nützt nichts. Das ist eine Vermutung.
Anders Lindén
Da das Javascript einer Seite jeden generischen Code ausführen kann, ist es unmöglich, ein Programm zu schreiben, um auf dessen Fertigstellung zu warten. Es ist eine Form des Halteproblems ( en.wikipedia.org/wiki/Halting_problem ). Jede Lösung hier muss Kompromisse eingehen oder auf Annahmen der zugrunde liegenden Webseite basieren.
Speedplane

Antworten:

83

Versuchen Sie diesen Code:

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

Der obige Code wartet bis zu 10 Sekunden auf das Laden der Seite. Wenn das Laden der Seite die Zeit überschreitet, wird die TimeoutException. Sie fangen die Ausnahme und tun Ihre Bedürfnisse. Ich bin nicht sicher, ob das Laden der Seite nach der ausgelösten Ausnahme beendet wird. Ich habe diesen Code noch nicht ausprobiert. Willst du es einfach versuchen.

Dies ist eine implizite Wartezeit. Wenn Sie dies einmal festlegen, hat es den Gültigkeitsbereich, bis die Web-Treiber-Instanz zerstört wird.

Weitere Informationen finden Sie in der DokumentationWebDriver.Timeouts .

Manigandan
quelle
3
Vielen Dank. Was passiert hier, wenn die Seite vor 10 Sekunden geladen wird? Wird sie noch 10 Sekunden warten, um die nächste Zeile nach dem Laden auszuführen?
Girish
Nein, wenn Ihre Seite vor 10 Sekunden geladen wird, wird die Wartebedingung beendet und die vorhergehende Zeile ausgeführt.
Manigandan
3
Dies wird verwendet, wenn Sie erwarten, dass das Laden von Seiten zu lange dauert, bis eine Zeitüberschreitung auftritt und Ausnahmen ausgelöst werden. Es wird nicht sofort auf das Laden einer Seite gewartet oder eine bessere Laderichtlinie festgelegt. Standardmäßig ist die Zeit unbegrenzt, sodass das Laden Ihrer Seite niemals Ausnahmen auslöst und Selenium immer versucht, darauf zu warten, dass sie vollständig geladen werden.
Petr Janeček
19
Das Problem bei dieser Methode besteht darin, dass das DOM möglicherweise nicht vollständig zugänglich ist, obwohl die implizite Wartezeit zuvor erfolgreich ein WebElement-Objekt zurückgegeben hat. Wenn Sie dann versuchen, auf das Element zu klicken, wird eine veraltete Elementausnahme angezeigt. Diese Antwort ist also nicht ganz sicher.
Djangofan
3
Wie hängt dieses Zeitlimit mit dem Warten auf das Laden eines Dokuments zusammen?
Anders Lindén
90

Ihre vorgeschlagene Lösung wartet nur auf das Signal von DOMreadyStatecomplete . Aber Selenium versucht standardmäßig, über die Methoden driver.get()und auf die (und ein bisschen mehr) beim Laden der Seite zu warten element.click(). Sie blockieren bereits, warten, bis die Seite vollständig geladen ist, und diese sollten in Ordnung sein.

Das Problem sind natürlich Weiterleitungen über AJAX-Anforderungen und das Ausführen von Skripten - diese können von Selenium nicht abgefangen werden, es wartet nicht darauf, dass sie beendet werden. Sie können sie auch nicht zuverlässig über abfangen readyState- es wartet ein wenig, was nützlich sein kann, aber es signalisiert completelange bevor der gesamte AJAX-Inhalt heruntergeladen wird.

Es gibt keine allgemeine Lösung, die überall und für alle funktionieren würde. Deshalb ist es schwierig und jeder verwendet etwas anderes.

Die allgemeine Regel besteht darin, sich darauf zu verlassen, dass WebDriver seinen Beitrag leistet, dann implizite Wartezeiten verwendet und dann explizite Wartezeiten für Elemente verwendet, die Sie auf der Seite bestätigen möchten. Es können jedoch noch viel mehr Techniken durchgeführt werden. Sie sollten auf Ihrer getesteten Seite diejenige (oder eine Kombination aus mehreren) auswählen, die in Ihrem Fall am besten funktioniert.

Weitere Informationen finden Sie in meinen beiden Antworten dazu:

Petr Janeček
quelle
20
Das ist ungenau, Selen wartet nicht und blockiert keine element.click()Anrufe.
Hwjp
3
@hwjp Möchtest du mehr ausarbeiten? Die JavaDocs sagen etwas anderes : "Wenn dadurch eine neue Seite geladen wird, versucht diese Methode zu blockieren, bis die Seite geladen wurde."
Petr Janeček
5
Bei einigen Gesprächen, die ich auf der Mailingliste geführt habe, scheint das ungenau zu sein. Selen blockiert möglicherweise .get-Aufrufe, bei denen Sie explizit eine URL anfordern, tut jedoch bei Klickaufrufen nichts Besonderes, da es nicht erkennen kann, ob Sie auf einen "echten" Hyperlink geklickt haben oder auf einen, der von Javascript abgefangen wird. ..
hwjp
4
Ich verlinke zu Beginn der Mailinglistendiskussion auf einen Fehler. Sogar die Dokumente sind nicht eindeutig: "Wenn click () [...] durch Senden eines nativen Ereignisses ausgeführt wird, wartet die Methode * nicht *"
hwjp
4
Es hängt also alles davon ab, ob der Browser "native Ereignisse" verwendet. Und es scheint, als würden die meisten von ihnen standardmäßig: code.google.com/p/selenium/wiki/… (also würde ich sagen, dass diese Dokumente bestenfalls irreführend sind. Sie werden die Mailingliste anpingen ).
Hwjp
61

Dies ist eine funktionierende Java-Version des von Ihnen angegebenen Beispiels:

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

Beispiel für 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
quelle
1
Alter, ich kopiere / füge das ein. Dieser Ausschnitt ist einfach genial. Warum habe ich nicht daran gedacht? Die Wahrheit, dass mehr als ein Paar Augäpfel immer zu einer guten Lösung führt. Vielen Dank.
Luis.espinal
2
Können Sie dies in Java 1.7 Version kompatibel setzen, da Lambda-Ausdrücke nicht unterstützen
vkrams
3
Java 1.7-Version: wait.until (neues Prädikat <WebDriver> () {public boolean apply (WebDriver-Treiber) {return ((JavascriptExecutor) -Treiber) .executeScript ("return document.readyState"). Equals ("complete");} });
LuQ
1
Wenn jemand die Lösung von @IuQ verwenden möchte, hat Predicate Importimport com.google.common.base.Predicate
Knu8
Ich habe diese Idee in einer VB-Test-App ausprobiert. Funktioniert die meiste Zeit. Manchmal wird folgende Fehlermeldung angezeigt: System.InvalidOperationException: JavaScript-Fehler (UnexpectedJavaScriptError) bei OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError (Response errorResponse) Die Test-App klickt auf den Menülink der Ebene 2 und ruft dann WaitObj.Until (Funktion D) auf D, InternetExplorerDriver) .ExecuteScript ("return document.readyState") = "complete"). Ich denke, Fehler wird verursacht, weil der Browser die aktuelle Seite entlädt und kein Dokumentobjekt ist. Warten Sie vielleicht eine halbe Sekunde, bevor Sie "document.readystate zurückgeben? Ideen?"
CoolBreeze
12

Hier ist mein Versuch einer vollständig generischen Lösung in Python:

Zunächst eine generische "Warte" -Funktion (verwenden Sie ein WebDriverWait, wenn Sie möchten, ich finde sie hässlich):

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

Als nächstes beruht die Lösung auf der Tatsache, dass Selen eine (interne) ID-Nummer für alle Elemente auf einer Seite aufzeichnet, einschließlich des <html>Elements der obersten Ebene . Wenn eine Seite aktualisiert oder geladen wird, erhält sie ein neues HTML-Element mit einer neuen ID.

Angenommen, Sie möchten auf einen Link mit dem Text "Mein Link" klicken, zum Beispiel:

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)

Für mehr pythonische, wiederverwendbare, generische Hilfsmittel können Sie einen Kontextmanager erstellen:

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)

Und dann können Sie es für so ziemlich jede Selen-Wechselwirkung verwenden:

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

Ich denke, das ist kugelsicher! Was denken Sie?

Mehr Infos in einem Blogbeitrag dazu hier

hwjp
quelle
Sehr interessanter Ansatz. Eine Herausforderung besteht darin, ob dies beim ersten Laden der Seite nach dem ersten Start des Browsers funktioniert. Es gibt keine Garantie dafür, dass im Ausgangszustand des Browsers eine Seite geladen ist. Außerdem sehe ich in Java nicht, dass wir eine 'ID' für das Objekt haben - ich gehe davon aus, dass Sie nicht meinen, dass Selen ein HTML-ID-Attribut einfügt. Ich werde dieser Antwort mehr hinzufügen, sobald ich diese Option genauer untersucht habe. Danke für den Beitrag!
Lukus
@hwjp Ich verwende diese Lösung oft mit hervorragenden Ergebnissen, aber es sieht so aus, als würde sie in einem Fall nicht funktionieren. Vollständige Erklärung des Problems stackoverflow.com/q/31985739/4249707
El Ruso
7

Ich hatte ein ähnliches Problem. Ich musste warten, bis mein Dokument fertig war, aber auch, bis alle Ajax-Anrufe beendet waren. Die zweite Bedingung erwies sich als schwer zu erkennen. Am Ende habe ich nach aktiven Ajax-Anrufen gesucht und es hat funktioniert.

Javascript:

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

Vollständige C # -Methode:

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
quelle
Gibt es so etwas wie document.readyState == 'complete' && jQuery.active == 0für React?
Rain9333
7
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
Ram Bharath
quelle
4

Für C # NUnit müssen Sie WebDriver in JSExecuter konvertieren und dann das Skript ausführen, um zu überprüfen, ob der Status document.ready vollständig ist oder nicht. Überprüfen Sie den folgenden Code als Referenz:

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

Dies wartet, bis die Bedingung erfüllt ist oder eine Zeitüberschreitung vorliegt.

S.Akruwala
quelle
3

Beim ersten Laden der Seite ist mir aufgefallen, dass das "Maximieren" des Browserfensters praktisch wartet, bis das Laden der Seite abgeschlossen ist (einschließlich der Quellen).

Ersetzen:

AppDriver.Navigate().GoToUrl(url);

Mit:

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

als verwenden:

OpenURL(myDriver, myUrl);

Dadurch wird die Seite geladen, bis zur Fertigstellung gewartet, maximiert und darauf konzentriert. Ich weiß nicht warum es so ist, aber es funktioniert.

Wenn Sie auf das Laden der Seite warten möchten, nachdem Sie auf "Weiter" oder einen anderen Auslöser für die Seitennavigation als "Navigieren ()" geklickt haben, erledigt die Antwort von Ben Dyer (in diesem Thread) die Arbeit.

Roei Sabag
quelle
1

Schauen Sie sich das Tapisserie- Web-Framework an. Dort können Sie den Quellcode herunterladen .

Die Idee ist, durch das HTML-Attribut des Körpers zu signalisieren, dass die Seite bereit ist. Sie können diese Idee verwenden, um komplizierte Klagefälle zu ignorieren.

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

Und dann erstellen Sie eine Erweiterung des Selenium-Webdrivers (gemäß Tapisserie-Framework).

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

Verwenden Sie die Erweiterung ElementIsDisplayed von Alister Scott .

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

Und schließlich Test erstellen:

driver.Url = this.GetAbsoluteUrl("/Account/Login");            
driver.WaitForPageToLoad();
Tomas Kubes
quelle
1

Die Antwort von Ben Dryer wurde auf meinem Computer nicht kompiliert ( "The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").

Funktionierende Java 8-Version:

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

Java 7 Version:

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

Ich habe diesen Code ausprobiert und er funktioniert bei mir. Ich rufe diese Funktion jedes Mal auf, wenn ich auf eine andere Seite wechsle

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; 
        }   
      }
 }
SOAlgorithmus
quelle
1

In Nodejs können Sie es über Versprechen bekommen ...

Wenn Sie diesen Code schreiben, können Sie sicher sein, dass die Seite vollständig geladen ist, wenn Sie zum ...

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

Wenn Sie diesen Code schreiben, navigieren Sie und Selen wartet 3 Sekunden ...

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

Aus der Selendokumentation:

this.get (url) → Thenable

Plant einen Befehl zum Navigieren zur angegebenen URL.

Gibt ein Versprechen zurück, das aufgelöst wird, wenn das Dokument vollständig geladen wurde .

Selendokumentation (Nodejs)

Sidanmor
quelle
1

Das Warten auf das Ereignis document.ready ist nicht die vollständige Lösung für dieses Problem, da sich dieser Code noch in einem Race-Zustand befindet: Manchmal wird dieser Code ausgelöst, bevor das Klickereignis verarbeitet wird, sodass er direkt zurückkehrt, da der Browser nicht gestartet wurde Laden Sie die neue Seite noch.

Nach einigem Suchen fand ich auf Obay die Testziege , die eine Lösung für dieses Problem hat. Der c # -Code für diese Lösung lautet ungefähr so:

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

}

`Ich feuere diese Methode direkt nach dem driver.navigate.gotourl ab, damit sie so schnell wie möglich einen Verweis auf die Seite erhält. Viel Spass damit!

Maarten Kieft
quelle
1

Wenn Selenium eine neue Seite mit einem Klick öffnet oder Methoden sendet oder abruft, wartet es normalerweise, bis die Seite geladen ist. Das Problem ist jedoch, dass die Seite, wenn sie einen xhr-Aufruf (Ajax) hat, niemals auf das Laden des xhr wartet Erstellen einer neuen Methode, um ein xhr zu überwachen und auf sie zu warten, wird es das Gute sein.

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 == 0Das ist also kein aktiver xhrs-Aufruf (der nur mit jQuery funktioniert). Für einen Javascript-Ajax-Aufruf müssen Sie eine Variable in Ihrem Projekt erstellen und simulieren.

Elazzam
quelle
0

Sie können eine Logik schreiben, um dies zu handhaben. Ich habe eine Methode geschrieben, die das zurückgibt, WebElementund diese Methode wird dreimal aufgerufen, oder Sie können die Zeit verlängern und eine Nullprüfung für hinzufügen. WebElementHier ist ein Beispiel

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

Ich habe einen Javascript-Code ausgeführt, um zu überprüfen, ob das Dokument bereit ist. Ich habe viel Zeit beim Debuggen von Selentests für Websites mit clientseitigem Rendering gespart.

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

Wie Rubanov für C # geschrieben hat, schreibe ich es für Java und es ist:

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

In Java wird es wie folgt aussehen: -

  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
quelle
1
Es wäre besser, die JS-Befehle zu einem zu kombinieren, damit Sie die Seite nicht zweimal aufrufen müssen, z. B.return document.readyState == 'loaded' || return document.readyState == 'complete'
JeffC
0

Der folgende Code sollte wahrscheinlich funktionieren:

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

Wenn Sie eine langsame Seiten- oder Netzwerkverbindung haben, funktioniert wahrscheinlich keine der oben genannten Funktionen. Ich habe sie alle ausprobiert und das einzige, was für mich funktioniert hat, ist auf das letzte sichtbare Element auf dieser Seite zu warten. Nehmen Sie zum Beispiel die Bing-Webseite. Sie haben ein KAMERASymbol (Schaltfläche "Nach Bild suchen") neben der Hauptsuchschaltfläche platziert, das erst sichtbar wird, nachdem die gesamte Seite geladen wurde. Wenn alle das getan haben, müssen wir nur explizit warten, wie in den obigen Beispielen.

user3988148
quelle
-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
quelle
-1

Hier ist etwas Ähnliches in Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }
Schmirgel
quelle
Ihr Code funktioniert bei mir nicht. Wie wechsle ich do iframe und warte auf onload = "javascript: pageload (); functionPageLoad ();" um die Seite in Ruby neu zu laden? Ich öffne den Iframe innerhalb einer Seite, habe Zugriff darauf, lade die Seite neu und kann nicht mehr auf den Frame zugreifen. Ich habe viele Antworten bezüglich Warten, Schlafen, Zeit gelesen, zum Frame und dann zum Elternteil gewechselt, aber ich kann mein Ziel nicht erreichen.
Amanda Cavallaro
1
Es hört sich so an, als ob es bei Ihrer Frage in erster Linie darum geht, wie Sie zum iFrame wechseln, und nicht darum, auf das Laden des Dokuments zu warten. Es ist möglicherweise besser, eine neue Frage zu starten, wenn Sie die Lösung in einer Frage zur Arbeit mit iFrames nicht finden.
Schmirgel
-1

Sie können den Thread in den Ruhezustand versetzen, bis die Seite neu geladen wird. Dies ist nicht die beste Lösung, da Sie eine Schätzung benötigen, wie lange das Laden der Seite dauert.

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
quelle
Ich finde, dass Thread.sleep (5000) oft die einzige Methode ist, mit der ein Test funktioniert, trotz aller Empfehlungen gegen die Verwendung. Für mich funktioniert keine Kombination aus Warten auf Element, zumal viele Elemente erst identifiziert werden können, wenn sie tatsächlich gefunden wurden.
Steve Staple
-1

Ich habe überprüft, ob das Laden der Seite abgeschlossen ist, und arbeite in Selen 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
quelle
-1

Für die Leute, die warten müssen, bis ein bestimmtes Element auftaucht. (verwendet c #)

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

Wenn Sie beispielsweise warten möchten, ob im DOM eine class = "error-message" vorhanden ist, tun Sie einfach Folgendes:

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

Für id wird es dann sein

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

Mo D Genesis
quelle
-3

Verwenden Sie Angular? Wenn Sie es sind, erkennt der Webdriver möglicherweise nicht, dass die asynchronen Aufrufe beendet wurden.

Ich empfehle Paul Hammants ngWebDriver . Die Methode waitForAngularRequestsToFinish () könnte nützlich sein.

Marlies
quelle
Er benutzte Angular sehr viel nicht. Diese Antwort wurde abgelehnt, weil Sie die ursprüngliche Frage anscheinend nicht sorgfältig gelesen haben.
Zelusp
Aber lassen Sie sich nicht von Stimmen aus der Form bringen. Die Leute hier meinen es gut. Und Kritik ist eigentlich eine Form der Liebe (denn wenn sich jemand die Zeit nimmt, jemanden zu korrigieren, liegt es daran, dass er sich darum kümmert). Kasse So stellen Sie Fragen auf intelligente Weise - Diese Ideen gelten auch für die intelligente Beantwortung von Fragen.
Zelusp