Selenium attend que le document soit prêt

133

Quelqu'un peut-il me dire comment puis-je faire attendre le sélénium jusqu'à ce que la page se charge complètement? Je veux quelque chose de générique, je sais que je peux configurer WebDriverWait et appeler quelque chose comme «trouver» pour le faire attendre mais je ne vais pas aussi loin. J'ai juste besoin de tester que la page se charge correctement et de passer à la page suivante pour tester.

J'ai trouvé quelque chose dans .net mais je n'ai pas pu le faire fonctionner en java ...

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

Des pensées quelqu'un?

Girish
la source
Pourquoi ne voulez-vous pas utiliser wait?
Amey
7
Vous voulez dire une attente explicite? Cela prend du temps, je teste quelques 10k pages.
Girish
2
Je veux dire, ajouter une attente de correction n'est peut-être pas une bonne idée si je teste un grand nombre de liens, non?
Girish
10
Attendre un nombre fixe de secondes ne sert à rien. C'est deviner.
Anders Lindén
Étant donné que le javascript d'une page peut exécuter n'importe quel code générique, il est impossible d'écrire un programme en attendant son achèvement. C'est une forme du problème d'arrêt ( en.wikipedia.org/wiki/Halting_problem ). Toute solution ici devra faire des compromis ou être basée sur des hypothèses de la page Web sous-jacente.
speedplane

Réponses:

83

Essayez ce code:

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

Le code ci-dessus attendra jusqu'à 10 secondes pour le chargement de la page. Si le chargement de la page dépasse le temps, le fichier TimeoutException. Vous attrapez l'exception et faites vos besoins. Je ne sais pas si cela arrête le chargement de la page après l'exception levée. je n'ai pas encore essayé ce code. Je veux juste l'essayer.

C'est une attente implicite. Si vous le définissez une fois, il aura l'étendue jusqu'à ce que l'instance du pilote Web soit détruite.

Consultez la documentationWebDriver.Timeouts pour plus d'informations.

Manigandan
la source
3
Merci, alors que se passe-t-il ici si la page est chargée avant 10 secondes, attendra-t-elle toujours 10 secondes pour exécuter la ligne suivante après le chargement?
Girish
Non si votre page se charge avant 10 secondes signifie qu'elle mettra fin à la condition d'attente et exécutera la ligne précédente.
Manigandan
3
Ceci est utilisé lorsque vous prévoyez des chargements de page qui prennent trop de temps à expirer et lancent des exceptions, cela n'attend pas immédiatement le chargement d'une page ou ne définit pas une meilleure politique de chargement. Par défaut, le temps est infini, de sorte que les chargements de votre page ne lancent jamais d'exceptions et Selenium essaie toujours d'attendre qu'ils se chargent complètement.
Petr Janeček
19
Le problème avec cette méthode est qu'il est possible que le DOM ne soit pas entièrement accessible même si l'attente implicite a précédemment renvoyé avec succès un objet WebElement. Ensuite, si vous essayez de cliquer sur l'élément, vous obtiendrez une exception d'élément périmé. Donc, cette réponse n'est pas entièrement sûre.
djangofan
3
Comment ce délai d'expiration est-il lié à l'attente du chargement d'un document?
Anders Lindén
90

La solution que vous suggérez n'attend que le signal du DOMreadyStatecomplete . Mais Selenium essaie par défaut d'attendre ceux (et un peu plus) lors des chargements de page via les méthodes driver.get()et element.click(). Ils bloquent déjà, ils attendent que la page se charge complètement et ceux-ci devraient fonctionner correctement.

Le problème, évidemment, sont les redirections via des requêtes AJAX et des scripts en cours d'exécution - ceux-ci ne peuvent pas être capturés par Selenium, il n'attend pas qu'ils se terminent. De plus, vous ne pouvez pas les attraper de manière fiable via readyState- cela attend un peu, ce qui peut être utile, mais cela signalera completelongtemps avant que tout le contenu AJAX ne soit téléchargé.

Il n'y a pas de solution générale qui fonctionnerait partout et pour tout le monde, c'est pourquoi c'est difficile et tout le monde utilise quelque chose d'un peu différent.

La règle générale est de s'appuyer sur WebDriver pour faire sa part, puis d'utiliser des attentes implicites, puis d'utiliser des attentes explicites pour les éléments que vous souhaitez affirmer sur la page, mais il y a beaucoup plus de techniques qui peuvent être faites. Vous devez choisir celui (ou une combinaison de plusieurs d'entre eux) qui fonctionne le mieux dans votre cas, sur votre page testée.

Voir mes deux réponses à ce sujet pour plus d'informations:

Petr Janeček
la source
20
C'est inexact, Selenium n'attend pas et ne bloque pas les element.click()appels.
hwjp
3
@hwjp Voulez-vous en dire plus? Les JavaDocs disent le contraire : "Si cela provoque le chargement d'une nouvelle page, cette méthode tentera de bloquer jusqu'à ce que la page soit chargée."
Petr Janeček
5
cf certaines conversations que j'ai eues sur la liste de diffusion, il semble que ce soit inexact. le sélénium peut bloquer sur les appels .get où vous demandez explicitement une URL, mais il ne fait rien de spécial sur les appels de clic, car il ne peut pas dire si vous avez cliqué sur un "vrai" lien hypertexte ou sur un qui sera intercepté par javascript. ..
hwjp
4
J'ai un lien vers un bogue au début de la discussion sur la liste de diffusion. Même la documentation équivoque: "Si click () [...] est fait en envoyant un événement natif alors la méthode n'attendra * pas *"
hwjp
4
Donc, tout dépend si le navigateur utilise des "événements natifs". Et il semble que la plupart d'entre eux le feront, par défaut: code.google.com/p/selenium/wiki/… (donc je dirais que ces documents sont au mieux trompeurs. Enverra un ping à la liste de diffusion).
hwjp le
61

Ceci est une version Java fonctionnelle de l'exemple que vous avez donné:

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

Exemple pour 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
la source
1
Mec, je copie / colle ça. Cet extrait est tout simplement génial. Pourquoi je n'y ai pas pensé? Vérité que plus d'une paire de globes oculaires mènent toujours à une bonne solution. Merci.
luis.espinal
2
Pouvez-vous mettre cela dans la version java 1.7 compatible car les expressions lambda ne prennent pas en charge
vkrams
3
Version Java 1.7: wait.until (new Predicate <WebDriver> () {public boolean apply (pilote WebDriver) {return (pilote (JavascriptExecutor)) .executeScript ("return document.readyState"). Equals ("complete");} });
luQ le
1
Si quelqu'un veut utiliser la solution par @IuQ alors, Predicate a importimport com.google.common.base.Predicate
Knu8
J'ai essayé cette idée dans une application de test VB. Fonctionne la plupart du temps. J'obtiens parfois cette erreur: System.InvalidOperationException: erreur JavaScript (UnexpectedJavaScriptError) à OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError (Response errorResponse) L'application de test clique sur le lien de menu de niveau 2, puis appelle WaitObj.Until (Function (D) DirectCast (Function (D) DirectCast D, InternetExplorerDriver) .ExecuteScript ("return document.readyState") = "complete"). Je pense que l'erreur est causée parce que le navigateur décharge la page actuelle et n'est pas un objet de document. Peut - être attendre 1/2 sec avant de le faire « Idées document.readyState de retour?
COOLBREEZE
12

Voici ma tentative d'une solution complètement générique, en Python:

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

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 s'actualise ou se charge, 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 pythonique, réutilisable et générique, 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 de sélénium:

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

Je pense que c'est à l'épreuve des balles! Qu'est-ce que tu penses?

Plus d'informations dans un article de blog à ce sujet ici

hwjp
la source
Approche très intéressante. Un défi est de savoir si cela peut fonctionner lors du chargement initial de la page, après le premier lancement du navigateur. Il n'y a aucune garantie que l'état initial du navigateur ait une page chargée. De plus, en Java, je ne vois pas que nous avons un «id» sur l'objet - je suppose que vous ne voulez pas dire que le sélénium insère un attribut id html. J'ajouterai plus à cette réponse une fois que j'aurai exploré davantage cette option. Merci pour le post!
Lukus
@hwjp J'utilise cette solution plusieurs fois avec d'excellents résultats, mais il semble que cela ne fonctionne pas dans un cas. Explication complète du problème stackoverflow.com/q/31985739/4249707
El Ruso
7

J'avais un problème similaire. J'avais besoin d'attendre que mon document soit prêt mais aussi que tous les appels Ajax soient terminés. La deuxième condition s'est avérée difficile à détecter. En fin de compte, j'ai vérifié les appels Ajax actifs et cela a fonctionné.

Javascript:

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

Méthode C # complète:

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
la source
Y a-t-il quelque chose comme document.readyState == 'complete' && jQuery.active == 0pour React?
Rain9333
7
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
Ram Bharat
la source
4

Pour C # NUnit, vous devez convertir WebDriver en JSExecuter, puis exécuter le script pour vérifier si l'état de document.ready est complet ou non. Vérifiez le code ci-dessous pour référence:

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

Cela attendra que la condition soit satisfaite ou que le délai expire.

S.Akruwala
la source
3

Pour le chargement initial de la page, j'ai remarqué que "Maximiser" la fenêtre du navigateur attend pratiquement que le chargement de la page soit terminé (y compris les sources)

Remplacer:

AppDriver.Navigate().GoToUrl(url);

Avec:

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

que d'utiliser:

OpenURL(myDriver, myUrl);

Cela chargera la page, attendra qu'elle soit terminée, l'agrandira et se concentrera dessus. Je ne sais pas pourquoi c'est comme ça mais ça marche.

Si vous voulez attendre le chargement de la page après avoir cliqué sur suivant ou sur tout autre déclencheur de navigation de page autre que "Naviguer ()", la réponse de Ben Dyer (dans ce fil) fera le travail.

Roei Sabag
la source
1

Jetez un œil au framework web tapestry . Vous pouvez y télécharger le code source .

L'idée est de signaler que la page est prête par l'attribut html du corps. Vous pouvez utiliser cette idée pour ignorer les cas de poursuites compliqués.

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

Et puis créer une extension de Selenium webdriver (selon le framework tapestry)

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

Utilisez l'extension ElementIsDisplayed écrite par Alister Scott .

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

Et enfin créer un test:

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

La réponse de Ben Dryer n'a pas été compilée sur ma machine ( "The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").

Version de travail de Java 8:

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

Version Java 7:

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
la source
1

J'ai essayé ce code et cela fonctionne pour moi. J'appelle cette fonction chaque fois que je passe à une autre page

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; 
        }   
      }
 }
SOAlgorithme
la source
1

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

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

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

À partir de la documentation Selenium:

this.get (url) → Thenable

Planifie une commande pour accéder à l'URL donnée.

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

Documentation Selenium (Nodejs)

Sidanmor
la source
1

L'attente de l'événement document.ready n'est pas la solution complète à ce problème, car ce code est toujours dans une condition de concurrence: parfois, ce code est déclenché avant le traitement de l'événement de clic, donc cela retourne directement, car le navigateur n'a pas démarré chargement de la nouvelle page pour le moment.

Après quelques recherches, j'ai trouvé un article sur Obay, la chèvre de test , qui a une solution à ce problème. Le code c # pour cette solution est quelque chose comme ceci:

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

}

`Je lance cette méthode directement après le driver.navigate.gotourl, afin qu'il obtienne une référence de la page dès que possible. Aie du plaisir avec ça!

Maarten Kieft
la source
1

Normalement, lorsque le sélénium ouvre une nouvelle page à partir d'un clic ou soumet ou récupère des méthodes, il attendra que la page soit chargée, mais le problème est que lorsque la page a un appel xhr (ajax), il n'attendra jamais que le xhr soit chargé, donc créer une nouvelle méthode pour surveiller un xhr et les attendre, ce sera le bien.

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 == 0il n'y a donc pas d'appel xhrs actif (qui ne fonctionne qu'avec jQuery). pour l'appel javascript ajax, vous devez créer une variable dans votre projet et la simuler.

elazzam
la source
0

Vous pouvez écrire une logique pour gérer cela. J'ai écrit une méthode qui renverra le WebElementet cette méthode sera appelée trois fois ou vous pouvez augmenter le temps et ajouter une vérification nulle pour WebElementVoici un exemple

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
la source
0

J'ai exécuté un code javascript pour vérifier si le document est prêt. Cela m'a fait gagner beaucoup de temps en déboguant les tests de sélénium pour les sites qui ont un rendu côté client.

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
la source
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
la source
0

Comme Rubanov a écrit pour C #, je l'écris pour Java, et c'est:

    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
la source
0

En Java, ce sera comme ci-dessous: -

  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
la source
1
Il serait préférable de combiner les commandes JS en une seule afin de ne pas avoir à frapper la page deux fois, par exemplereturn document.readyState == 'loaded' || return document.readyState == 'complete'
JeffC
0

Le code suivant devrait probablement fonctionner:

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

Si votre page ou votre connexion réseau est lente, il est probable qu'aucune des solutions ci-dessus ne fonctionnera. Je les ai tous essayés et la seule chose qui a fonctionné pour moi est d'attendre le dernier élément visible sur cette page. Prenons par exemple la page Web Bing. Ils ont placé une icône CAMERA (bouton de recherche par image) à côté du bouton de recherche principal qui n'est visible qu'après le chargement de la page complète. Si tout le monde a fait cela, alors tout ce que nous avons à faire est d'utiliser une attente explicite comme dans les exemples ci-dessus.

user3988148
la source
-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
la source
-1

Voici quelque chose de similaire, dans Ruby:

wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { @driver.execute_script('return document.readyState').eql?('complete') }
émeri
la source
Votre code ne fonctionne pas pour moi. Comment puis-je passer à l'iframe et attendre onload = "javascript: pageload (); functionalPageLoad ();" recharger la page en Ruby? Je me retrouve à ouvrir l'iframe à l'intérieur d'une page, j'y ai accès, puis la page se recharge et je ne peux plus accéder au cadre. J'ai lu de nombreuses réponses concernant l'attente, le sommeil, l'heure, le passage au cadre puis au parent, mais je ne parviens pas à atteindre mon objectif.
Amanda Cavallaro
1
Il semble que votre question porte principalement sur la façon de passer à l'iFrame, pas sur l'attente du chargement du document. Il peut être préférable de commencer une nouvelle question si vous ne trouvez pas la solution dans une question sur l'utilisation d'iFrames.
émeri
-1

Vous pouvez faire dormir le fil jusqu'à ce que la page soit rechargée. Ce n'est pas la meilleure solution, car vous devez avoir une estimation du temps de chargement de la page.

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
la source
Je trouve que Thread.sleep (5000) est souvent la seule méthode qui permet à un test de fonctionner, malgré toutes les recommandations contre son utilisation. Aucune combinaison d'attente d'élément ne fonctionne pour moi, d'autant plus que de nombreux éléments ne peuvent être identifiés tant qu'ils n'ont pas été trouvés.
Steve Staple
-1

J'ai vérifié que le chargement de la page était terminé, je travaille dans Selenium 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
la source
-1

Pour les personnes qui ont besoin d'attendre qu'un élément spécifique apparaisse. (utilisé c #)

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

Ensuite, si vous voulez attendre par exemple si un class = "error-message" existe dans le DOM, vous faites simplement:

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

Pour id, ce sera alors

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

Mo D Genèse
la source
-3

Utilisez-vous Angular? Si c'est le cas, il est possible que le pilote Web ne reconnaisse pas que les appels asynchrones sont terminés.

Je recommande de regarder Paul Hammants ngWebDriver . La méthode waitForAngularRequestsToFinish () pourrait être utile.

Marlies
la source
Il n'utilisait vraiment pas Angular. Cette réponse a été rejetée car il semble que vous n'avez pas lu attentivement la question d'origine.
zelusp le
Mais ne laissez pas les votes vous déformer. Les gens ici veulent bien dire. Et la critique est en fait une forme d'amour (car si quelqu'un prend le temps de corriger quelqu'un, c'est parce qu'il se soucie). Commander Comment poser des questions de manière intelligente - ces idées s'appliquent également pour répondre aux questions de manière intelligente.
zelusp le