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.

1voto

Cirem Punkte 820

Hier ist eine groovige Version, die auf der Antwort von Morten Christiansen basiert.

void waitForAjaxCallsToComplete() {
    repeatUntil(
            { return getJavaScriptFunction(driver, "return (window.jQuery || {active : false}).active") },
            "Ajax calls did not complete before timeout."
    )
}

static void repeatUntil(Closure runUntilTrue, String errorMessage, int pollFrequencyMS = 250, int timeOutSeconds = 10) {
    def today = new Date()
    def end = today.time + timeOutSeconds
    def complete = false;

    while (today.time < end) {
        if (runUntilTrue()) {
            complete = true;
            break;
        }

        sleep(pollFrequencyMS);
    }
    if (!complete)
        throw new TimeoutException(errorMessage);
}

static String getJavaScriptFunction(WebDriver driver, String jsFunction) {
    def jsDriver = driver as JavascriptExecutor
    jsDriver.executeScript(jsFunction)
}

0voto

Bill Hileman Punkte 2730

Wenn das Steuerelement, auf das Sie warten, ein "Ajax"-Web-Element ist, wartet der folgende Code darauf oder auf jedes andere Ajax-Web-Element, um das Laden oder die Ausführung der erforderlichen Aktionen zu beenden, so dass Sie mit Ihren Schritten sicher fortfahren können.

    public static void waitForAjaxToFinish() {

    WebDriverWait wait = new WebDriverWait(driver, 10);

    wait.until(new ExpectedCondition<Boolean>() { 
        public Boolean apply(WebDriver wdriver) { 
            return ((JavascriptExecutor) driver).executeScript(
                    "return jQuery.active == 0").equals(true);
        }
    }); 

}

0voto

Roberto Petrilli Punkte 458

In meinem Fall schien das Problem auf Ajax-Verzögerungen zurückzuführen zu sein, war aber mit internen Iframes innerhalb der Hauptseite verbunden. In seleminum ist es möglich, mit auf interne Frames umzuschalten:

    driver.switchTo().frame("body");
    driver.switchTo().frame("bodytab");

Ich benutze Java. Danach konnte ich das Element ausfindig machen

    driver.findElement(By.id("e_46")).click();

-1voto

BatBold Punkte 21

Nachfolgend ist mein Code für fetch. Nahm mich während der Forschung, weil jQuery.active nicht mit Fetch funktioniert. Hier ist die Antwort half mir Proxy Fetch, aber seine nur für Ajax nicht Fetch Spott für Selen

public static void customPatchXMLHttpRequest(WebDriver driver) {
    try {
        if (driver instanceof JavascriptExecutor) {
            JavascriptExecutor jsDriver = (JavascriptExecutor) driver;
            Object numberOfAjaxConnections = jsDriver.executeScript("return window.openHTTPs");
            if (numberOfAjaxConnections instanceof Long) {
                return;
            }
            String script = "  (function() {" + "var oldFetch = fetch;"
                    + "window.openHTTPs = 0; console.log('starting xhttps');" + "fetch = function(input,init ){ "
                    + "window.openHTTPs++; "

                    + "return oldFetch(input,init).then( function (response) {"
                    + "      if (response.status >= 200 && response.status < 300) {"
                    + "          window.openHTTPs--;  console.log('Call completed. Remaining active calls: '+ window.openHTTPs); return response;"
                    + "      } else {"
                    + "          window.openHTTPs--; console.log('Call fails. Remaining active calls: ' + window.openHTTPs);  return response;"
                    + "      };})" + "};" + "var oldOpen = XMLHttpRequest.prototype.open;"
                    + "XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {"
                    + "window.openHTTPs++; console.log('xml ajax called');"
                    + "this.addEventListener('readystatechange', function() {" + "if(this.readyState == 4) {"
                    + "window.openHTTPs--; console.log('xml ajax complete');" + "}" + "}, false);"
                    + "oldOpen.call(this, method, url, async, user, pass);" + "}" +

                    "})();";
            jsDriver.executeScript(script);
        } else {
            System.out.println("Web driver: " + driver + " cannot execute javascript");
        }
    } catch (Exception e) {
        System.out.println(e);
    }
}

-2voto

Samuel Tian Punkte 777

Für diejenigen, die primefaces verwenden, tun Sie es einfach:

selenium.waitForCondition("selenium.browserbot.getCurrentWindow().$.active==0", defaultWaitingPeriod);

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