69 Stimmen

Wie kann man Selenium dazu bringen, auf eine Ajax-Antwort zu warten?

Wie kann ich Selenium dazu bringen, darauf zu warten, dass z. B. ein Kalender-Widget geladen wird? Im Moment mache ich nur eine Thread.sleep(2500) nach dem Exportieren des Testfalls in ein Junit-Programm.

46voto

Neil Aitken Punkte 7769

Ich würde verwenden

waitForElementPresent(locator)

Damit wird gewartet, bis das Element im DOM vorhanden ist.

Wenn Sie prüfen müssen, ob das Element sichtbar ist, verwenden Sie besser

waitForElementHeight(locator)

28voto

Morten Christiansen Punkte 18236

Eine allgemeinere Lösung als das Warten auf ein Element wäre es, zu warten, bis alle Verbindungen zum Server geschlossen sind. Auf diese Weise können Sie warten, bis alle Ajax-Aufrufe beendet sind, auch wenn sie keinen Callback haben und somit keine Auswirkungen auf die Seite haben. Weitere Einzelheiten finden Sie unter aquí .

Mit C# und jQuery habe ich die folgende Methode erstellt, um zu warten, bis alle AJax-Aufrufe abgeschlossen sind (wenn jemand direktere Möglichkeiten des Zugriffs auf JS-Variablen von C# hat, bitte kommentieren):

internal void WaitForAjax(int timeOut = 15)
{
    var value = "";
    RepeatUntil(
        () => value = GetJavascriptValue("jQuery.active"), 
        () => value == "0", 
        "Ajax calls did not complete before timeout"
    );
}

internal void RepeatUntil(Action repeat, Func<bool> until, string errorMessage, int timeout = 15)
{
    var end = DateTime.Now + TimeSpan.FromSeconds(timeout);
    var complete = false;

    while (DateTime.Now < end)
    {
        repeat();
        try
        {
            if (until())
            {
                complete = true;
                break;
            }
        }
        catch (Exception)
        { }
        Thread.Sleep(500);
    }
    if (!complete)
        throw new TimeoutException(errorMessage);
}

internal string GetJavascriptValue(string variableName)
{
    var id = Guid.NewGuid().ToString();
    _selenium.RunScript(String.Format(@"window.$('body').append(""<input type='text' value='""+{0}+""' id='{1}'/>"");", variableName, id));
    return _selenium.GetValue(id);
}

16voto

Nimo Punkte 7796

Wenn Sie Python verwenden, können Sie diese Funktion verwenden, die auf die Schaltfläche klickt und auf die DOM-Änderung wartet:

def click_n_wait(driver, button, timeout=5):
    source = driver.page_source
    button.click()
    def compare_source(driver):
        try:
            return source != driver.page_source
        except WebDriverException:
            pass
    WebDriverWait(driver, timeout).until(compare_source)

(CREDIT: basierend auf diese Stack-Overflow-Antwort )

4voto

toutpt Punkte 5045

Mit webdriver aka selenium2 können Sie die implizite Wartekonfiguration verwenden, wie sie unter https://www.selenium.dev/documentation/en/webdriver/waits/#implicit-wait

Java verwenden:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));

Oder mit Python:

from selenium import webdriver

ff = webdriver.Firefox()
ff.implicitly_wait(10) # seconds
ff.get("http://somedomain/url_that_delays_loading")
myDynamicElement = ff.find_element_by_id("myDynamicElement")

4voto

Artem Kislicyn Punkte 41

Das funktioniert bei mir

public  void waitForAjax(WebDriver driver) {
    new WebDriverWait(driver, 180).until(new ExpectedCondition<Boolean>(){
        public Boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            return (Boolean) js.executeScript("return jQuery.active == 0");
        }
    });
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X