Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StaleElementReference Exception in PageFactory

I am trying to learn the PageFactory model. I understood the fact that when we do a initElements, the WebElements are located. Say for example, I click on a webelement and because of which there is a change in one of the other webelements in DOM. Now, obviously I would get a StaleElementReferenceException here. How would I resolve this issue?

Should I find that specific WebElement again knowing the fact that there can be a change in the WebElement's properties in the DOM? or is there an another way to handle this?

like image 777
user2356679 Avatar asked Jun 30 '17 04:06

user2356679


People also ask

What is Staleelementreference exception?

The stale element reference error is a WebDriver error that occurs because the referenced web element is no longer attached to the DOM. Every DOM element is represented in WebDriver by a unique identifying reference, known as a web element.

What are limitations of using PageFactory?

It restricts the usage where you need to use By type. When an web element is found then it is stored in a variable of type WebElement. Because of limitations of PageFactory , every web elements need to have type as WebElemen or List<WebElement>. If PageFactory does not find element, it throws NoSuchElementException.


2 Answers

StaleElementReferenceException

StaleElementReferenceException extends WebDriverException and indicates that the previous reference of the element is now stale and the element reference is no longer present on the DOM of the page.


Common Reasons

  • The common reasons behind facing StaleElementReferenceException are as follows:
    • The element has been deleted entirely.
    • The element is no longer attached to the DOM.
    • The webpage on which the element was part of has been refreshed.
    • The (previous) element has been deleted by a JavaScript or AjaxCall and is replaced by a (new) element with the same ID or other attributes.
  • Solution : If an (old) element has been replaced with new identical one, the simple strategy would be to use findElement() or findElements to look out for the element again.

Answering your queries

  1. When we do a initElements, the WebElements are located : When you call initElements() method, all the WebElements of that page will get initialized. For example,

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

    This line of code will initialize all the static WebElements defined within the scope of the LoginPageNew.class whenever and wherever it is invoked from your Automation Script.

  2. I click on a webelement and because of which there is a change in one of the other webelements in DOM : This is pretty much possible.

    • As an example, in general invoking click() on a <input> tag wouldn't trigger any change of any of the WebElements on the HTML DOM.
    • Where as invoking click() on a <button> tag or <a> tag may call a JavaScript or a Ajax which inturn may delete an element or can replace the (previous) element by a (new) element with the same ID or other attributes.

Conclusion

So, if WebDriver throws a StaleElementReferenceException, that implies even though the element still exists, the reference is lost. We should discard the current reference we have and replace it by locating the WebElement once again when it gets attached to the DOM. That means you have to again reinitialize the class through initElements() method which inturn reinitializes all the WebElements defined in that page.


Solution

If a old element has been replaced with new identical one, the simple strategy would be to invoke WebDriverWait inconjunction with ExpectedConditions to look out for the element.

You can find relevant detailed discussions in:

  • How to add explicit wait in PageFactory in PageObjectModel?

References

Here are the references of this discussion:

  • Stale Element Reference Exception
  • Class StaleElementReferenceException
  • Selenium: How to tell if RemoteWebDriver.findElements(By) can throw StaleElementReferenceException at all?
like image 81
undetected Selenium Avatar answered Oct 06 '22 11:10

undetected Selenium


This is a known problem with the PageFactory implementation.

If you are unlucky enough for the element to become stale in the instant between the element being found, and then the element being clicked upon, you will get this error. Unfortunately the PageFactory code does not try to find the element again if it has become stale and it throws an Exception.

I would classify this as a bug with PageFactory, it should auto re-find the element if it ever becomes stale (unless the @CacheLookup annotation is used).

The suggestion to recall initElements isn't going to fix anything, you only need to init the elements once because that binds a Java proxy class to the element in question. The page factory implementation is supposed to remove the possibility of StaleElementReferenceExceptions (hence why this is a bug)

like image 28
Ardesco Avatar answered Oct 06 '22 12:10

Ardesco