Existe-t-il une approche universelle permettant à Selenium d'attendre que tout le contenu ajax soit chargé? (non lié à un site Web spécifique - cela fonctionne donc pour tous les sites Web ajax)
Vous devez attendre que Javascript et jQuery soient chargés pour terminer le chargement. Exécutez Javascript pour vérifier si jQuery.active
est 0
et document.readyState
est complete
, ce qui signifie que la charge de JS et jQuery est terminée.
public boolean waitForJSandJQueryToLoad() {
WebDriverWait wait = new WebDriverWait(driver, 30);
// wait for jQuery to load
ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
try {
return ((Long)((JavascriptExecutor)getDriver()).executeScript("return jQuery.active") == 0);
}
catch (Exception e) {
// no jQuery present
return true;
}
}
};
// wait for Javascript to load
ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)getDriver()).executeScript("return document.readyState")
.toString().equals("complete");
}
};
return wait.until(jQueryLoad) && wait.until(jsLoad);
}
Comme Mark Collin l'a décrit dans son livre "Mastering Selenium Webdriver", utilisez JavascriptExecutor pour déterminer si un site Web utilisant jQuery a fini de passer des appels AJAX
public class AdditionalConditions {
public static ExpectedCondition<Boolean> jQueryAJAXCallsHaveCompleted() {
return new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
return (Boolean) ((JavascriptExecutor) driver).executeScript("return (window.jQuery != null) && (jQuery.active === 0);");
}
};
}
}
J'utilise cette simple opération en itérant jusqu'à ce qu'un AJAX soit terminé. Cela fonctionne toujours pour moi.
public void waitForAjax() throws InterruptedException{
while (true)
{
Boolean ajaxIsComplete = (Boolean) ((JavascriptExecutor)driver).executeScript("return jQuery.active == 0");
if (ajaxIsComplete){
info("Ajax Call completed. ");
break;
}
Thread.sleep(150);
}
}
Je ne crois pas qu'il existe une approche universelle hors de la boîte. Je crée généralement une méthode qui effectue une .waituntilrowcount(2)
ou une waituntilvisible()
qui interroge un élément.