Espere a la carga de la página en Selenio

¿Cómo haces que Selenium 2.0 espere a que se cargue la página?

También puede verificar la página cargada usando el siguiente código

IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00)); wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete")); 

Utilice la clase WebDriverWait

Ver también aquí

Puede esperar mostrar algún elemento. algo así como 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")); 

Si configura la espera implícita del controlador, luego llama al método findElement en un elemento que espera que esté en la página cargada, el WebDriver buscará ese elemento hasta que encuentre el elemento o scope el valor de tiempo de espera.

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

fuente: espera implícita

En general, con Selenium 2.0, el controlador web solo debe devolver el control al código de llamada una vez que ha determinado que la página se ha cargado. Si no es así, puede llamar a waitforelemement , que realiza un ciclo de llamadas circulares findelement hasta que se encuentra o se agota el tiempo de espera (se puede establecer el tiempo de espera).

Implementación de Ruby:

 wait = Selenium::WebDriver::Wait.new(:timeout => 10) wait.until { @driver.execute_script("return document.readyState;") == "complete" } 

Puede eliminar la línea System.out . Se agrega para depuración.

 WebDriver driver_; public void waitForPageLoad() { Wait wait = new WebDriverWait(driver_, 30); wait.until(new Function() { 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"); } }); } 

También puede usar la clase: ExpectedConditions para esperar explícitamente a que aparezca un elemento en la página web antes de que pueda tomar medidas adicionales.

Puede usar la clase ExpectedConditions para determinar si un elemento es visible:

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

Consulte la ExpectedConditions class Javadoc de ExpectedConditions class Javadoc para ver una lista de todas las condiciones que puede verificar.

Todas estas soluciones están bien para casos específicos, pero sufren al menos uno de un par de posibles problemas:

  1. No son lo suficientemente generics: quieren que sepas, por adelantado, que alguna condición específica será cierta para la página a la que vas (por ejemplo, se mostrará algún elemento)

  2. Están abiertos a una condición de carrera en la que utilizas un elemento que está realmente presente en la página anterior, así como en la página nueva.

Aquí está mi bash de una solución genérica que evita este problema (en Python):

Primero, una función genérica de “espera” (use un WebDriverWait si lo desea, los encuentro feos):

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

A continuación, la solución se basa en el hecho de que el selenium registra un número de identificación (interno) para todos los elementos en una página, incluido el elemento nivel superior. Cuando una página se actualiza o se carga, obtiene un nuevo elemento html con una nueva ID.

Por lo tanto, supongamos que desea hacer clic en un enlace con el texto "mi enlace", por ejemplo:

 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) 

Para más ayudante Pythonic, reutilizable y genérico, puedes crear un administrador de contexto:

 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) 

Y luego puedes usarlo en prácticamente cualquier interacción de selenium:

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

¡Creo que es a prueba de balas! ¿Qué piensas?

Más información en una publicación de blog sobre esto aquí

Si desea esperar a que se cargue un elemento específico, puede usar el método isDisplayed() en un 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; } } 

(Ejemplo de la guía de inicio de 5 minutos )

La respuesta de Imran volvió a formularse para Java 7:

  WebDriverWait wait = new WebDriverWait(driver, 30); wait.until(new ExpectedCondition() { public Boolean apply(WebDriver wdriver) { return ((JavascriptExecutor) driver).executeScript( "return document.readyState" ).equals("complete"); } }); 

Esto parece ser una seria limitación de WebDriver. Obviamente, esperar por un elemento no implicará que la página se cargue, en particular, el DOM puede ser completamente comstackdo (estado preparado) mediante el cual JS todavía está ejecutándose y CSS y las imágenes todavía se están cargando.

Creo que la solución más simple es establecer una variable JS sobre el evento de carga después de que todo se haya inicializado, y verificar y esperar esta variable JS en Selenio.

Me sorprende que los predicados no fueran la primera opción, ya que normalmente sabes con qué elemento (s) interactuarás en la página que estás esperando cargar. Mi enfoque siempre ha sido construir predicados / funciones como waitForElementByID(String id) y waitForElemetVisibleByClass(String className) , etc. y luego usarlos y reutilizarlos donde sea que los necesite, ya sea para cargar una página o para cambiar el contenido de la página. Esperando que.

Por ejemplo,

En mi clase de prueba:

 driverWait.until(textIsPresent("expectedText"); 

En mi clase de prueba padre:

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

Aunque esto parece mucho, se encarga de verificar varias veces para usted y el intervalo de la frecuencia con la que se puede establecer el control junto con el tiempo de espera máximo antes de que se agote el tiempo de espera. Además, reutilizarás dichos métodos.

En este ejemplo, la clase principal definió e inició el WebDriver driver y el WebDriver driver WebDriverWait driverWait .

Espero que esto ayude.

Utilice implícitamente esperar por la espera de cada elemento en la página hasta el momento dado.

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

esto espera por cada elemento en la página durante 30 segundos.

Otra espera es espera explícita o espera condicional en esta espera hasta la condición dada.

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

En id, proporcione el ID del elemento estático que se muestra tímidamente en la página, tan pronto como se cargue la página.

 /** * 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() { @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; } }); } 

Puede cambiar del documento a un elemento, en el caso de que solo se cambie una parte de un documento.

Esta técnica fue inspirada por la respuesta de sincebasic.

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

Y para usarlo :

 _waiter = new SeleniumWaiter(_driver); try { _waiter.waitForMe(By.xpath("//..."), 10); } catch (Exception e) { // Error } 

Espera explícitamente o espera condicional en esta espera hasta que se dé la condición.

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

Esto esperará cada elemento web durante 60 segundos.

Utilice implícitamente esperar por la espera de cada elemento en la página hasta el momento dado.

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

Esto esperará cada elemento web durante 60 segundos.

Ambos funcionan bien. Pero mi favorito personal es esperar explícitamente porque es más estable

Puede esperar explícitamente a que aparezca un elemento en la página web para poder realizar cualquier acción (como element.click ())

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

Esto es lo que utilicé para un escenario similar y funciona bien.

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

La mejor forma de esperar cargas de página al usar los enlaces de Java para WebDriver es utilizar el patrón de diseño de Página de Página con PageFactory. Esto le permite utilizar AjaxElementLocatorFactory que, para decirlo simplemente, actúa como una espera global para todos sus elementos. Tiene limitaciones en elementos tales como drop-boxes o transiciones complejas de JavaScript, pero reducirá drásticamente la cantidad de código necesario y acelerará los tiempos de prueba. Un buen ejemplo se puede encontrar en este blogpost. Se asume una comprensión básica de Core Java.

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

Solución NodeJS:

En Nodejs puedes obtenerlo a través de promesas …

Si escribe este código, puede estar seguro de que la página está completamente cargada cuando llegue al …

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

Si escribe este código, navegará, y el selenium esperará 3 segundos …

 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 documentación de Selenium:

this.get (url) → Thenable

Progtwig un comando para navegar a la URL dada.

Devuelve una promesa que se resolverá cuando el documento haya terminado de cargarse .

Documentación de selenium (Nodejs)

Puede utilizar el siguiente método existente para establecer el tiempo de pageeLoadTimeout en el ejemplo siguiente si la página tarda más de 20 segundos en cargarse, y arrojará una excepción de recarga de página

  WebDriver driver = new FirefoxDriver(); driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS) 

Puedes usar wait. básicamente hay 2 tipos de espera en selenium

  • Espera implícita
  • Espera explícita

– Espera implícita

Esto es muy simple por favor vea la syntax a continuación:

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

– espera explícita

Espera explícitamente o espera condicional en esta espera hasta que se dé la condición dada.

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

Puede usar otras propiedades como visblityOf() , visblityOfElement()

Llamada abajo Función

 public static boolean isloadComplete(WebDriver driver) { return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded") || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"); } 
 driver.asserts().assertElementFound("Page was not loaded", By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT); 

La forma más fácil es esperar un elemento que aparecerá en la página cargada.

Si desea hacer clic en algún botón que ya está después de cargar la página, puede usar await y hacer clic en:

 await().until().at.most(20, TimeUnit.Seconds).some_element.isDisplayed(); // or another condition getDriver().find(some_element).click; 

Cómo lograr que Selenium espere la carga de la página después de un clic proporciona el siguiente enfoque interesante:

  1. Almacene una referencia a un WebElement de la página anterior.
  2. Haga clic en el enlace.
  3. Siga invocando operaciones en WebElement hasta que se StaleElementReferenceException .

Código de muestra:

 WebElement link = ...; link.click(); new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) -> { try { link.isDisplayed(); return false; } catch (StaleElementReferenceException unused) { return true; } }); 

use una condición if y para cualquiera de los elementos presentes

 try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } 

Puede probar este código para dejar que la página se cargue por completo hasta que encuentre el elemento.

 public void waitForBrowserToLoadCompletely() { String state = null; String oldstate = null; try { System.out.print("Waiting for browser loading to complete"); int i = 0; while (i < 5) { Thread.sleep(1000); state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString(); System.out.print("." + Character.toUpperCase(state.charAt(0)) + "."); if (state.equals("interactive") || state.equals("loading")) break; /* * If browser in 'complete' state since last X seconds. Return. */ if (i == 1 && state.equals("complete")) { System.out.println(); return; } i++; } i = 0; oldstate = null; Thread.sleep(2000); /* * Now wait for state to become complete */ while (true) { state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString(); System.out.print("." + state.charAt(0) + "."); if (state.equals("complete")) break; if (state.equals(oldstate)) i++; else i = 0; /* * If browser state is same (loading/interactive) since last 60 * secs. Refresh the page. */ if (i == 15 && state.equals("loading")) { System.out.println("\nBrowser in " + state + " state since last 60 secs. So refreshing browser."); driver.navigate().refresh(); System.out.print("Waiting for browser loading to complete"); i = 0; } else if (i == 6 && state.equals("interactive")) { System.out.println( "\nBrowser in " + state + " state since last 30 secs. So starting with execution."); return; } Thread.sleep(4000); oldstate = state; } System.out.println(); } catch (InterruptedException ie) { ie.printStackTrace(); } } 
 private static void checkPageIsReady(WebDriver driver) { JavascriptExecutor js = (JavascriptExecutor) driver; // Initially bellow given if condition will check ready state of page. if (js.executeScript("return document.readyState").toString().equals("complete")) { System.out.println("Page Is loaded."); return; } // This loop will rotate for 25 times to check If page Is ready after // every 1 second. // You can replace your value with 25 If you wants to Increase or // decrease wait time. for (int i = 0; i < 25; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { } // To check page ready state. if (js.executeScript("return document.readyState").toString().equals("complete")) { break; } } } 

Puede usar este fragmento de código para cargar la página:

 IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00)); wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
 IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00)); wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete")); 

O puede usar el mesero para cargar cualquier elemento y hacerse visible / hacer clic en esa página, lo más probable es que se cargue al final de la carga como:

 Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement)); var element = GlobalDriver.FindElement(By.XPath(xpathOfElement)); var isSucceededed = element != null;
 Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement)); var element = GlobalDriver.FindElement(By.XPath(xpathOfElement)); var isSucceededed = element != null;