Reed_Xia
Reed_Xia

Reputation: 1452

StableElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up

My code is like as following, the code is to get the elements set via xpath, and generate a list<String> with the texts of each element in the elements set. But it always throws exception during the process of adding each element's text to the new List<String>.

protected List<String> getHeaders(String path){
    List<String> headers = new ArrayList<String>();
    int count = 0;
    List<WebElement> elements = findAllByXpath(path);
    LOG.info("The length is : " + String.valueOf(elements.size()));

    for (WebElement c: elements) {
        LOG.info("->> " + String.valueOf(count));
        count++;
        headers.add(c.getText());
    }
    return headers;
}

The result is:

INFO com.xxx.test - The length is: 13
INFO com.xxx.test ->> 0
INFO com.xxx.test ->> 1
INFO com.xxx.test ->> 2
INFO com.xxx.test ->> 3
INFO com.xxx.test ->> 4
INFO com.xxx.test ->> 5

com.xxx.test -> getHeaders FAILED org.openqa.selenium.StableElementReferenceException:Element not found in the cache - perhaps the page has changed since it was looked up

Can someone help in this case? Thanks!

Upvotes: 3

Views: 541

Answers (3)

Florent B.
Florent B.

Reputation: 42528

I see 3 ways to handle your issue.

The first solution and probably the most reliable would be to find the elements once the page has reached a stable state. It could be done either by waiting for the presence of an element or by waiting for the count of elements.

A second solution would be to list again the elements when StableElementReferenceException is raised :

List<String> headers = new ArrayList<String>();
List<WebElement> elements = findAllByXpath(path);
for(int i = 0; i < elements.size(); ) {
  try {
    headers.add(elements.get(i).getText());
    i++;
  } catch (StableElementReferenceException ex) {
    elements = findAllByXpath(path);
  }
}
return headers;

And a third solution would be to get the text for all the elements with a piece of Javascript:

List<WebElement> elements = findAllByXpath(path);

ArrayList headers = (ArrayList)((JavascriptExecutor)driver).executeScript(
    "var arr = [], elements = arguments[0];" +
    "for(var i=0; i<elements.length; i++)" +
    "  arr.push(elements[i].textContent);" +
    "return arr;", elements);

return headers;

Upvotes: 3

Anuj Kumar
Anuj Kumar

Reputation: 163

Try getAttribute("innerText") or getAttribute("value")

protected List<String> getHeaders(String path){
    List<String> headers = new ArrayList<String>();
    int count = 0;
    List<WebElement> elements = findAllByXpath(path);
    LOG.info("The length is : " + String.valueOf(elements.size()));

    for (WebElement c: elements) {
        LOG.info("->> " + String.valueOf(count));
        count++;
        headers.add(c.getAttribute("innerText"));
    }
    return headers;
 }

Upvotes: 0

Mrunal Gosar
Mrunal Gosar

Reputation: 4683

Ok here's the trick.
1. Get size of the list of elements u want using elements.size();
2. Next write down a dynamic XPath such that only the indexes in the XPATH should change and that should give you the individual element.
3. Start a For Loop with i=0 to i < elements.size and in the for loop using the dynamic XPath with indexes retrieve individual elements one by one and then their text subsequently and add them to the List
Other Approach can be to explicitly wait till the page has loaded completely using WebDriverWait or other approaches of Waiting in selenium

Upvotes: 2

Related Questions