1

Problem Statement: I am getting Stale Element Exception when for loop executes the second time.

Description:

I am using for loop to handle table elements. In the first iteration, it will search for the required element on the page. If the element is not available on that page then it will go and search on the second page. Webdriver successfully finds the element if its available on the first page but if it's not available on the first page then it will look for the element on the second page. But here for loop fails with the exception called 'Stale Element Exception.

Error Message:

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

Code:

 List <WebElement> allAmountValues = driver.findElements(By.xpath("(//table[@width=760][@cellspacing=1])[2]/tbody/tr/td[8]/div"));

     for(int i =0;i<allAmountValues.size();i++){
       System.out.println("Value are : "+allAmountValues.get(i).getText().replaceAll("\\s+", " "));
     }



String testValue = "100000";
 System.out.println("No.of Rows in the Table : "+allAmountValues.size());                

               for (int i1 =1; i1<allAmountValues.size();i1++) {


                    String amount = allAmountValues.get(i1+1).getText().replaceAll("\\s+","");
                    //System.out.println("amount Values : "+amount);
                    System.out.println("Value are : " + allAmountValues.get(i1).getText() + "== Corresponding link is : " + clicklinks.get(i1).getText());

                    if (amount.equalsIgnoreCase(testValue)) {
                        System.out.println("Found:" +testValue);

                        clicklinks.get(i1).click();
                        waitDriver();
                        driver.navigate().back();

                      break;
                    }
                    else
                    {
                        WebElement clickNext = driver.findElement(By.xpath("//a[contains(text(), 'Next')]"));
                        clickNext.click();


                    }


               }


                for(int rw=2;rw<allAmountValues.size();rw++)
                {
                    WebElement a1 = driver.findElement(By.xpath("(//table[@width=760][@cellspacing=1])[2]/tbody/tr["+rw+"]/td[8]/div/span"));
                     String amm = a1.getText().replaceAll("\\s+", "");
                     System.out.println("Current value is:" +amm);
                     if(amm.equalsIgnoreCase("100000"))
                     {
                         WebElement a2 = driver.findElement(By.xpath("/html/body/form/div/table/tbody/tr/td/table/tbody/tr[5]/td/table/tbody/tr["+rw+"]/td[1]/div/input[6]"));
                         a2.click();
                         break;
                     }
                }
                   WebElement authoriseButton = driver.findElement(By.xpath("//input[@name='btnAuthorise']"));
                  if(authoriseButton.isEnabled())
                  {
                      authoriseButton.click();
                  }
                  else
                  {
                      System.out.println("Authorise Button is not enabled");
                  }


         }

I am facing stale element error exception on : String amount = allAmountValues.get(i1+1).getText().replaceAll("\\s+",""); this line. Any help would be appreciated.

Akki
  • 59
  • 2
  • 11

2 Answers2

1

Cause:

allAmountValues is stored initially so when you move between pages, yoou try to use the same elements stored earlier; hgence causing you StaleElementException

Solution:

You have to identify allAmountValuesagain after each time you leave a page and go back to original page.

Kushal Bhalaik
  • 3,349
  • 5
  • 23
  • 46
  • I have edited code once again. Please check. @Kushal, how do I identify the value for allAmountValues? – Akki Apr 04 '17 at 11:07
  • you have to run this again `List allAmountValues = driver.findElements(By.xpath("(//table[@width=760][@cellspacing=1])[2]/tbody/tr/td[8]/div"));` – Kushal Bhalaik Apr 04 '17 at 11:10
  • I am afraid, I do not understand. Cause it's in the loop. Could you please show me how to do it? – Akki Apr 04 '17 at 11:16
  • add `List allAmountValues = driver.findElements(By.xpath("(//table[@width=760][@cellspac‌​ing=1])[2]/tbody/tr/‌​td[8]/div"));` as first statement in for loop – Kushal Bhalaik Apr 04 '17 at 11:19
  • I have received same error as 'stale Element Exception' on same position – Akki Apr 04 '17 at 11:55
  • does your code looks like `for (int i1 =1; i1 allAmountValues = driver.findElements(By.xpath("(//table[@width=760][@cellspac‌​ing=1])[2]/tbody/tr/‌​td[8]/div")); String amount = allAmountValues.get(i1+1).getText().replaceAll("\\s+","");` – Kushal Bhalaik Apr 04 '17 at 12:01
  • Yes! it's the same. I have added to it to first line inside the for loop – Akki Apr 04 '17 at 12:05
  • Where does the flow go when you click `clickNext.click();` – Kushal Bhalaik Apr 04 '17 at 12:52
  • It goes to the next page(Only if test value ==100000 is not found) and again searches for the specified test value. This cycle goes on till web driver find the test value. Above code execute successfully when there is a test value on the first page but if it is on the second page then stale element exception will appear as an error. – Akki Apr 10 '17 at 09:57
  • is it possible for you to share your URL? – Kushal Bhalaik Apr 10 '17 at 10:03
  • I wish I could but it's internal application limited to my organization. Not visible outside. – Akki Apr 10 '17 at 12:30
0

Selenium keeps a track of all elements in form of a Reference as and when findElement/findElements is used. And while reusing the element, selenium uses that Reference instead of finding the element again in the DOM. But sometimes due the AJAX request and responses this reference is no longer fresh, hence StaleElementReferenceException is thrown.

We will have to create a separate click method and pass the element to be clicked as a parameter. The idea is to re-initialize the element and finding it again.

public void clickElement(WebElement element) {
try {
    element.click();
} catch (StaleElementReferenceException stale) {
    System.out.println("Element is stale. Clicking again");
    element = reInitializeStaleElement(element);
    element.click();
}
}
// method to re-initialize the stale element
public WebElement reInitializeStaleElement(WebElement ) {
// lets convert element to string, so we can get it's locator
String elementStr = element.toString();
elementStr = elementStr.split("->")[1];
String byType = elementStr.split(":")[0].trim();
String locator = elementStr.split(":")[1].trim();
locator = locator.substring(0, locator.length() - 1);
switch (byType) {
    case "xpath":
        return DRIVER.findElement(By.xpath(locator));
    case "css":
        return DRIVER.findElement(By.cssSelector(locator));
    case "id":
        return DRIVER.findElement(By.id(locator));
    case "name":
        return DRIVER.findElement(By.name(locator));
}
}
CodeGreen
  • 31
  • 2