Attendre le chargement de la page dans Selenium

240

Comment faire attendre Selenium 2.0 pour que la page se charge?

karthick kumar
la source
7
Pour moi, seule la réponse de Paul semble correcte, la plupart des réponses très votées parlent d'attendre un élément particulier.
xyz

Réponses:

138

Vous pouvez également vérifier pageloaded en utilisant le code suivant

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"));
Imran
la source
22
On pourrait penser que quelque chose comme ça serait intégré. Attendre le chargement des pages est une chose assez courante sur le Web.
PRMan
19
cela fonctionne-t-il vraiment tout le temps? Peut-être que quelque chose manque dans votre code, mais vous attendez que le dom soit prêt. Mais considérez que si votre code s'exécute trop rapidement, la page précédente peut ne pas encore être déchargée et elle reviendra vraie même si vous êtes toujours sur l'ancienne page. Ce que vous devez faire est d'attendre le déchargement de la page actuelle, puis d'appeler votre code ci-dessus. Un moyen de détecter le déchargement de page consiste à obtenir un élément Web sur la page actuelle et à attendre qu'il devienne périmé. obeythetestinggoat.com/…
George
6
FYI - Même encore ce qui précède ne garantit pas que la page est complète - juste que le dom est prêt. Tout dojo / jquery peut toujours créer des éléments de manière dynamique sur la page, vous devrez peut-être d'abord attendre les éléments dynamiques avant d'interagir avec eux.
George
3
Sachez que cette méthode ne vérifie que le DOM. Si vous utilisez Ajax ou AngularJS, cela ne fonctionnera pas car il y aura des appels asynchrones qui ne pourront pas être détectés par le document.readyState.
Homewrecker
3
Il s'agit du code C #. Cela ne fonctionne pas avec Java et la question posée sur Java .
Kingamere
89

Utiliser la classe WebDriverWait

Voir aussi ici

Vous pouvez vous attendre à montrer un élément. quelque chose comme en C #:

WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));

_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
Artem
la source
Cela a très bien fonctionné. C'est une très belle façon moderne de résoudre le problème.
CrazyDart
3
@ EmmanuelAngelo.R TimeSpan est une structure de données .Net.
rjzii
12
que faire si je ne sais pas quel élément sera sur la page?
JustGoscha
3
Cela fonctionnera pour attendre le chargement d'un élément particulier et non pour la page entière.
xyz
1
Cela ne garantit pas du tout qu'un élément sera entièrement chargé ni ne répond à la question. Comment peut-on voter pour cela?
Boris D. Teoharov
36

Si vous définissez l'attente implicite du pilote, puis appelez la findElementméthode sur un élément que vous attendez sur la page chargée, le WebDriver interrogera cet élément jusqu'à ce qu'il trouve l'élément ou atteigne la valeur de délai d'expiration.

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

source: implicit-waits

Sam
la source
3
Cela n'aidera pas à attendre le chargement de la page.
xyz
Cela signifie qu'il va essayer quelque chose pendant 10 secondes, avant de lever l'exception. il ne peut donc pas s'assurer qu'il faudra 10 secondes de retard.
skysign
1
@xyz - pourquoi cela n'aidera-t-il pas?
MasterJoe2
@ testerjoe2 il attend jusqu'à ce qu'un élément particulier soit trouvé, la question est de savoir comment attendre le chargement de la page.
xyz
35

En général, avec Selenium 2.0, le pilote Web ne doit retourner le contrôle du code appelant qu'après avoir déterminé que la page a été chargée. Si ce n'est pas le cas, vous pouvez appeler waitforelemement, qui fait un cycle d'appel findelementjusqu'à ce qu'il soit trouvé ou expire (le délai peut être défini).

Paul Hadfield
la source
2
Ajout à la réponse de Paul. Veuillez vérifier cela aussi stackoverflow.com/questions/5858743/… .
9ikhan
27
Malheureusement, Selenium 2 n'attend pas dans tous les cas le chargement d'une page. Par exemple, WebElement: click () n'attend pas et cela est dit explicitement dans le Javadoc d'appartenance. Cependant, ils ne disent pas comment je peux vérifier qu'une nouvelle page soit chargée. If click() causes a new page to be loaded via an event or is done by sending a native event (which is a common case on Firefox, IE on Windows) then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
Sebi
Du document .. et la méthode se bloquera jusqu'à ce que le chargement soit terminé ...
xyz
2
@Karna: Oui, en théorie, cela devrait toujours et en pratique, la plupart du temps. L'utilisation du sélénium à l'époque a mis en évidence qu'il y avait des moments où il pensait que la page avait fini de se charger, mais ce n'était pas le cas. Je n'ai pas utilisé beaucoup de sélénium récemment, ce qui peut ou non être le cas.
Paul Hadfield
3
Je suis d'accord: le pilote Internet Explorer en particulier est bogué et rend le contrôle immédiatement dans certains cas, même si une page est toujours en cours de chargement. Dans mon cas, j'ai ajouté une attente en utilisant JavascriptExecutor, en attendant que document.readyState soit "complet". En raison de l'aller-retour du sélénium au navigateur, les conditions de concurrence sont atténuées, je suppose, et cela "toujours" fonctionne pour moi. Après "click ()" quand je m'attends à ce qu'une page se charge, j'attends explicitement (en utilisant WebDriverWait) le readystate. ]
dmansfield
22

Implémentation de Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
    @driver.execute_script("return document.readyState;") == "complete" 
}
allenhwkim
la source
17
Équivalent Python: WebDriverWait (pilote, 10) .until (lambda d: d.execute_script ('return document.readyState') == 'complete')
blaze
2
Python utilise le code ci-dessus mais n'oubliez pas cette ligne. | de selenium.webdriver.support.ui import WebDriverWait
t3dodson
J'ai eu un problème en cliquant sur un élément lorsque la page n'était pas complètement chargée. En Python, j'ai essayé time.sleep (30). Ça a marché. Il attendra toujours les 30 secondes maximum. J'ai ensuite essayé le code suivant et il est plus efficace maintenant, plus rapide. WebDriverWait (driver, 10) .until (lambda d: driver.find_element_by_xpath ("// div [. = 'Administration']"). Click ())
Riaz Ladhani
20

Vous pouvez supprimer la System.outligne. Il est ajouté à des fins de débogage.

WebDriver driver_;

public void waitForPageLoad() {

    Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
    wait.until(new Function<WebDriver, Boolean>() {
        public Boolean apply(WebDriver driver) {
            System.out.println("Current Window State       : "
                + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
            return String
                .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                .equals("complete");
        }
    });
}
QIKHAN
la source
Merci pour ces conseils. Je l'ajoute dans mon SeleniumHelper; cf. javabox
boly38
17

Toutes ces solutions conviennent à des cas spécifiques, mais elles souffrent d'au moins l'un des deux problèmes possibles:

  1. Ils ne sont pas assez génériques - ils veulent que vous sachiez, à l'avance, qu'une condition spécifique sera vraie pour la page que vous allez visiter (par exemple, un élément sera affiché)

  2. Ils sont ouverts à une condition de concurrence où vous utilisez un élément qui est réellement présent sur l'ancienne page ainsi que sur la nouvelle page.

Voici ma tentative d'une solution générique qui évite ce problème (en Python):

Tout d'abord, une fonction générique "wait" (utilisez un WebDriverWait si vous le souhaitez, je les trouve moches):

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

Ensuite, la solution repose sur le fait que le sélénium enregistre un numéro d'identification (interne) pour tous les éléments d'une page, y compris l' <html>élément de niveau supérieur . Lorsqu'une page est actualisée ou chargée, elle obtient un nouvel élément html avec un nouvel ID.

Donc, en supposant que vous vouliez cliquer sur un lien avec le texte "mon lien" par exemple:

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)

Pour plus d'aide générique Pythonique, réutilisable, vous pouvez créer un gestionnaire de contexte:

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)

Et puis vous pouvez l'utiliser sur à peu près n'importe quelle interaction au sélénium:

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

Je pense que c'est pare-balles! Qu'est-ce que tu penses?

Plus d'informations dans un blog à ce sujet ici

hwjp
la source
J'ai lu votre page Web avant de rechercher de nouveau plus spécifiquement le code java qui implémente votre solution. Rien jusqu'ici ...
Andrew Lorien
11

Vous pouvez également utiliser la classe: ExpectedConditionspour attendre explicitement qu'un élément apparaisse sur la page Web avant de pouvoir entreprendre toute autre action

Vous pouvez utiliser la ExpectedConditionsclasse pour déterminer si un élément est visible:

WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));

Voir ExpectedConditions class Javadocpour la liste de toutes les conditions que vous pouvez vérifier.

TedEd
la source
11

La réponse d'Imran retravaillée pour Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);

    wait.until(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver wdriver) {
            return ((JavascriptExecutor) driver).executeScript(
                "return document.readyState"
            ).equals("complete");
        }
    });
Ailette
la source
10

Cela semble être une sérieuse limitation de WebDriver. Évidemment, attendre un élément n'impliquera pas le chargement de la page, en particulier le DOM peut être entièrement construit (état déjà prêt) par lequel JS est toujours en cours d'exécution et CSS et les images sont toujours en cours de chargement.

Je crois que la solution la plus simple consiste à définir une variable JS lors de l'événement onload après que tout est initialisé et à vérifier et attendre cette variable JS dans Selenium.

sibidiba
la source
C'est simple si le site est à vous de modifier!
reinierpost
Oui, utilisez simplement un JavascriptExecutor pour exécuter jQuery.js et vous aurez alors accès aux événements de chargement de jQuery. C'est un cas rare quand cela est nécessaire. Le Webdriver standard a suffisamment de puissance pour faire 98% des attentes appropriées.
djangofan
@djangofan serait génial de voir un exemple de cela ... Je suis un gars frontal donc je ne sais pas où ni comment JavascriptExecutor est utilisé.
BradGreens
@BradGreens - Ok, regardez mon projet ici: github.com/djangofan/jquery-growl-selenium-example . Si vous avez la bande passante pour terminer cet exemple, je n'arrive pas à faire fonctionner jGrowl dans ce projet de test, bien que jQuery fonctionne correctement.
djangofan
1
@BradGreens En plus du commentaire de djangofan voir ma réponse ici: stackoverflow.com/a/24638792/730326
jmathew
9

Si vous souhaitez attendre le chargement d'un élément spécifique, vous pouvez utiliser la isDisplayed()méthode sur RenderedWebElement:

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
    // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
    RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));

    // If results have been returned, the results are displayed in a drop down.
    if (resultsDiv.isDisplayed()) {
      break;
    }
}

(Exemple tiré du Guide de démarrage en 5 minutes )

Tristan
la source
4
Un an plus tard (version actuelle de Selenium 2.23.1), il n'y RenderedWebElementen a pas dans l'API. Cependant, la isDisplayed()méthode est désormais disponible directement sur WebElement.
Petr Janeček
1
Le scrutin est terrible lorsqu'il peut être évité.
reinierpost
8

Attendez explicitement ou attendez conditionnellement dans cette attente jusqu'à ce que cette condition soit donnée.

WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));

Cela attendra chaque élément Web pendant 60 secondes.

Utilisez attendre implicitement l'attente de chaque élément de la page jusqu'à ce moment donné.

driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

Cela attendra chaque élément Web pendant 60 secondes.

Anuj Teotia
la source
5

Utilisez implicitement l'attente de chaque élément de la page jusqu'à l'heure donnée.

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

cette attente pour chaque élément sur la page pendant 30 secondes.

Une autre attente est Attendre explicitement ou attendre conditionnellement dans cette attente jusqu'à la condition donnée.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Dans id, donnez l'ID d'élément statique qui s'affiche différemment sur la page, dès que la page est chargée.

Kuldeep Yadav
la source
4

Je suis surpris que les prédicats ne soient pas le premier choix, car vous savez généralement avec quels éléments vous allez ensuite interagir sur la page que vous attendez pour charger. Mon approche a toujours été de créer des prédicats / fonctions comme waitForElementByID(String id)et waitForElemetVisibleByClass(String className), etc., puis de les utiliser et de les réutiliser là où j'en ai besoin, que ce soit pour un chargement de page ou un changement de contenu de page que j'attends.

Par exemple,

Dans ma classe de test:

driverWait.until(textIsPresent("expectedText");

Dans mon parent de classe de test:

protected Predicate<WebDriver> textIsPresent(String text){
    final String t = text;
    return new Predicate<WebDriver>(){
        public boolean apply(WebDriver driver){
            return isTextPresent(t);
        }
    };
}

protected boolean isTextPresent(String text){
    return driver.getPageSource().contains(text);
}

Bien que cela semble beaucoup, il prend soin de vérifier à plusieurs reprises pour vous et l'intervalle de fréquence de vérification peut être défini avec le temps d'attente ultime avant la fin du délai. De plus, vous réutiliserez ces méthodes.

Dans cet exemple, la classe parente a défini et lancé le WebDriver driveret le WebDriverWait driverWait.

J'espère que ça aide.

Jack Mason
la source
Cela m'aide! Merci pour cet excellent échantillon. Je l'ajoute dans mon SeleniumHelper; cf. javabox
boly38
4

La meilleure façon d'attendre le chargement des pages lors de l'utilisation des liaisons Java pour WebDriver est d'utiliser le modèle de conception d'objet de page avec PageFactory. Cela vous permet d'utiliser le AjaxElementLocatorFactoryqui pour le mettre agit simplement comme une attente globale pour tous vos éléments. Il a des limites sur des éléments tels que des boîtes de dépôt ou des transitions javascript complexes, mais il réduira considérablement la quantité de code nécessaire et accélérera les temps de test. Un bon exemple peut être trouvé dans ce blog. Une compréhension de base de Core Java est supposée.

http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html

sonhu
la source
4

Solution NodeJS:

Dans Nodejs, vous pouvez l'obtenir via des promesses ...

Si vous écrivez ce code, vous pouvez être sûr que la page est entièrement chargée lorsque vous arrivez à la ...

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

Si vous écrivez ce code, vous naviguerez et le sélénium attendra 3 secondes ...

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

De la documentation Selenium:

this.get (url) → Thénable

Planifie une commande pour naviguer vers l'URL donnée.

Renvoie une promesse qui sera résolue une fois le chargement du document terminé .

Documentation sur le sélénium (Nodejs)

Sidanmor
la source
4

Voici une version Java 8 de la réponse actuellement la plus appréciée :

WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));

myDriverest un WebDriverobjet (déclaré plus tôt).

Remarque : sachez que cette méthode ( document.readyState) vérifie uniquement le DOM.

BelovedFool
la source
4

Appelez ci-dessous Fonction dans votre script, cela attendra que la page ne soit pas chargée en utilisant javascript

public static boolean isloadComplete(WebDriver driver)
{
    return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
            || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
Shubham Jain
la source
J'ai changé le booléen pour void, mais ne fonctionne pas dans Chrome
nosequeweaponer
3
/**
 * Call this method before an event that will change the page.
 */
private void beforePageLoad() {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("document.mpPageReloaded='notYet';");
}

/**
 * Call this method after an event that will change the page.
 * 
 * @see #beforePageLoad
 * 
 *      Waits for the previous page to disappear.
 */
private void afterPageLoad() throws Exception {
    (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {

        @Override
        public boolean apply(WebDriver driver) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            Object obj = js.executeScript("return document.mpPageReloaded;");
            if (obj == null) {
                return true;
            }
            String str = (String) obj;
            if (!str.equals("notYet")) {
                return true;
            }
            return false;
        }
    });
}

Vous pouvez passer du document à un élément, dans le cas où seule une partie d'un document est modifiée.

Cette technique a été inspirée par la réponse de Sincebasic.

Marc
la source
3

SeleniumWaiter :

import com.google.common.base.Function;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWaiter {

      private WebDriver driver;

      public SeleniumWaiter(WebDriver driver) {
           this.driver = driver;
      }

      public WebElement waitForMe(By locatorname, int timeout){
           WebDriverWait wait = new WebDriverWait(driver, timeout);
           return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
      }

      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
            // TODO Auto-generated method stub
            return new Function<WebDriver, WebElement>() {
                 @Override
                 public WebElement apply(WebDriver driver) {
                      return driver.findElement(locator);
                 }
            };
      }
 }

Et pour vous l' utiliser :

_waiter = new SeleniumWaiter(_driver);

try {
   _waiter.waitForMe(By.xpath("//..."), 10);
} 
catch (Exception e) {
   // Error
}
tux23
la source
3

Vous pouvez utiliser la méthode existante ci-dessous pour définir le temps de pageeLoadTimeout dans l'exemple ci-dessous si la page prend plus de 20 secondes à charger, alors il lèvera une exception de rechargement de page

 WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
Arpan Saini
la source
2

Vous pouvez explicitement attendre qu'un élément apparaisse sur la page Web avant de pouvoir entreprendre une action (comme element.click ())

driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
  .until(new ExpectedCondition<WebElement>(){
        @Override
        public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
}});

C'est ce que j'ai utilisé pour un scénario similaire et cela fonctionne très bien.

anirus
la source
je pense que driver.get attend que la fonction onload se termine avant de retourner le contrôle au code, à moins que la page n'ait beaucoup d'ajax
goh
2

Ma façon simple:

long timeOut = 5000;
    long end = System.currentTimeMillis() + timeOut;

        while (System.currentTimeMillis() < end) {

            if (String.valueOf(
                    ((JavascriptExecutor) driver)
                            .executeScript("return document.readyState"))
                    .equals("complete")) {
                break;
            }
        }
RichardK
la source
2

La meilleure façon que j'ai vue est d'utiliser le stalenessOf attendue, d'attendre que l'ancienne page devienne périmée.

Exemple:

WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);

WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));

Il faudra attendre dix secondes pour que l'ancienne balise HTML devienne périmée, puis lèvera une exception si cela ne se produit pas.

forresthopkinsa
la source
1
un WebElement devenu obsolète n'implique pas le chargement d'une nouvelle page.
Corey Goldberg
Bien sûr, mais cela signifie que l'ancienne page est terminée de déchargement. D'après mon expérience, il est tout aussi important de savoir quand l'ancienne page a été déchargée ou si elle s'est arrêtée pour une raison quelconque.
forresthopkinsa
Bien sûr, j'utilise généralement stalenessOf en conjonction avec d'autres tests pour obtenir le processus de déchargement / chargement complet.
forresthopkinsa
2

J'utilise node + selenium-webdriver (dont la version est maintenant 3.5.0). ce que je fais pour cela est:

var webdriver = require('selenium-webdriver'),
    driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
  return state === 'complete';
}))
yuwanlin
la source
2

Vous pouvez utiliser l'attente. il y a essentiellement 2 types d'attente dans le sélénium

  • Attente implicite
  • Attente explicite

- Attente implicite

C'est très simple, veuillez consulter la syntaxe ci-dessous:

driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

- Attente explicite

Attendez explicitement ou attendez conditionnellement dans cette attente jusqu'à ce qu'une condition donnée se produise.

WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

Vous pouvez utiliser d'autres propriétés comme visblityOf(),visblityOfElement()

iamsankalp89
la source
2

Dans mon cas, j'ai utilisé ce qui suit pour connaître l'état de chargement de la page. Dans notre application, des gifs de chargement sont présents et je les écoute comme suit pour éliminer les temps d'attente indésirables dans le script.

public static void processing(){ 
    WebDriverWait wait = new WebDriverWait(driver, 30);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
    wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}

Où le xpath localise le gif dans le DOM HTML. Après cela, vous pouvez également implémenter vos méthodes d'action Cliquez sur.

public static void click(WebElement elementToBeClicked){
    WebDriverWait wait = new WebDriverWait(driver, 45);
    wait.until(ExpectedConditions.visibilityOf(element));
    wait.until(ExpectedConditions.elementToBeClickable(element)); 
    wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click(); 
 }
Praveen
la source
2

Man toutes ces réponses nécessitent trop de code. Cela devrait être une chose simple car c'est assez courant.

Pourquoi ne pas simplement injecter du javascript simple avec le pilote Web et vérifier. C'est la méthode que j'utilise dans ma classe Webscraper. Le javascript est assez basique même si vous ne connaissez pas js.

    def js_get_page_state(self):        
    """
    Javascript for getting document.readyState
    :return: Pages state.

    More Info: https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
    """
    ready_state = self.driver.execute_script('return document.readyState')
    if ready_state == 'loading':
        self.logger.info("Loading Page...")
    elif ready_state == 'interactive':
        self.logger.info("Page is interactive")
    elif ready_state == 'complete':
        self.logger.info("The page is fully loaded!")
    return ready_state
Bruce Wayne
la source
1

Comment faire pour que Selenium attende le chargement de la page après un clic fournit l'approche intéressante suivante:

  1. Stockez une référence à un WebElementde l'ancienne page.
  2. Cliquer sur le lien.
  3. Continuez d'appeler des opérations sur le WebElementjusqu'à ce que StaleElementReferenceExceptionsoit lancé.

Exemple de code:

WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
{
    try
    {
        link.isDisplayed();
        return false;
    }
    catch (StaleElementReferenceException unused)
    {
        return true;
    }
});
Gili
la source
Bonne idée! Je n'ai jamais pensé aborder cette situation en vérifiant le contraire d'un chargement de page réussi, d'un déchargement de page réussi (faute d'un meilleur terme). Bien que ce soit la meilleure option, cela dépend du fait que StaleElementReferenceException prend moins de temps, etc. que d'attendre un chargement réussi. Néanmoins, une autre bonne façon de le faire.
Joseph Orlando
4
Cela ne vous dira pas si la page actuelle est chargée, cela vous dira si la dernière page (spécifiquement un élément) est déchargée . Vous devrez toujours attendre le chargement de la page actuelle. BTW, vous pouvez remplacer votre code ci-dessus par new WebDriverWait(driver, 10).until(ExpectedConditions.stalenessOf(element)).
JeffC