selenium selenium-webdriver pageobjects page-factory staleelementreferenceexception

selenium - Excepción StaleElementReference en PageFactory



selenium-webdriver pageobjects (3)

Estoy tratando de aprender el modelo de PageFactory. Comprendí el hecho de que cuando hacemos un initElements , se encuentran los WebElements. Digamos, por ejemplo, que hago clic en un elemento web y debido a que hay un cambio en uno de los otros elementos web en DOM. Ahora, obviamente, obtendría una StaleElementReferenceException aquí. ¿Cómo resolvería este problema?

¿Debería encontrar ese WebElement específico nuevamente sabiendo el hecho de que puede haber un cambio en las propiedades del WebElement en el DOM? o hay otra forma de manejar esto?


StaleElementReferenceException

StaleElementReferenceException extiende WebDriverException e indica que la referencia anterior del elemento ahora está obsoleta y la referencia del elemento ya no está presente en el DOM de la página.

Razones comunes

  • Las razones comunes para enfrentar StaleElementReferenceException son las siguientes:
    • El elemento ha sido eliminado por completo.
    • El elemento ya no está adjunto al DOM.
    • Se ha actualizado la página web de la que formaba parte el elemento.
    • El elemento (anterior) ha sido eliminado por un JavaScript o AjaxCall y se reemplaza por un elemento (nuevo) con el mismo ID u otros atributos.
  • Solución : Si un elemento (antiguo) ha sido reemplazado por uno nuevo idéntico, la estrategia simple sería usar findElement() o findElements para buscar el elemento nuevamente.

Respondiendo tus consultas

  1. Cuando hacemos un initElements, se encuentran los WebElements : cuando llamas initElements() método initElements() , todos los WebElements de esa página se inicializarán. Por ejemplo,

    LoginPageNew login_page = PageFactory.initElements(driver, LoginPageNew.class);

    Esta línea de código inicializará todos los elementos web estáticos definidos dentro del alcance de LoginPageNew.class cada vez que se invoque desde su secuencia de comandos de automatización.

  2. Hago clic en un elemento web y debido a que hay un cambio en uno de los otros elementos web en DOM : esto es bastante posible.

    • Como ejemplo, en general, invocar click() en una etiqueta <input> no desencadenaría ningún cambio de ninguno de los WebElements en el HTML DOM .
    • Mientras que al invocar click() en una etiqueta <button> o <a> puede llamar a JavaScript o Ajax, que puede eliminar un elemento o puede reemplazar el elemento (anterior) por un elemento (nuevo) con el mismo ID u otro atributos.

Conclusión

Entonces, si WebDriver arroja una StaleElementReferenceException , eso implica que aunque el elemento aún exista, la referencia se pierde. Deberíamos descartar la referencia actual que tenemos y reemplazarla localizando el WebElement una vez más cuando se adjunte al DOM. Eso significa que debe reinicializar nuevamente la clase a través del método initElements() que inturn reinicializa todos los WebElements definidos en esa página.

Solución

Si un elemento antiguo ha sido reemplazado por uno nuevo idéntico, la estrategia simple sería invocar la WebDriverWait con ExpectedConditions para buscar el elemento.

Puede encontrar discusiones detalladas relevantes en:

Referencias

Aquí están las referencias de esta discusión:


Este es un problema conocido con la implementación de PageFactory.

Si tiene la mala suerte de que el elemento se vuelva obsoleto en el instante entre el elemento que se encuentra, y luego se hace clic en el elemento, obtendrá este error. Lamentablemente, el código de PageFactory no intenta encontrar el elemento nuevamente si se ha vuelto obsoleto y genera una excepción.

Clasificaría esto como un error con PageFactory, debería volver a encontrar automáticamente el elemento si alguna vez se vuelve obsoleto (a menos que se use la anotación @CacheLookup).

La sugerencia de recuperar initElements no va a arreglar nada, solo necesita iniciar los elementos una vez porque eso vincula una clase de proxy Java al elemento en cuestión. Se supone que la implementación de la fábrica de páginas elimina la posibilidad de StaleElementReferenceExceptions (de ahí que esto sea un error)


Stale element exception produce una Stale element exception en dos casos

El elemento ya no está adjunto al DOM . El elemento ha sido eliminado por completo.

Cuando esto sucede, envuelve su código en try catch block luego puede repetir y volver a intentar tantas veces como sea necesario hasta que tenga éxito.

public void waitForElementPresent(final By by, int timeout){ WebDriverWait wait = (WebDriverWait)new WebDriverWait(driver,timeout) .ignoring(StaleElementReferenceException.class); wait.until(new ExpectedCondition<Boolean>(){ @Override public Boolean apply(WebDriver webDriver) { WebElement element = webDriver.findElement(by); return element != null && element.isDisplayed(); } }); }