Rachel D'cruz
Rachel D'cruz

Reputation: 87

How to fix 'stale element reference exception' while trying to pick date from date-picker?

I am trying to select date from the Datepicker.Following is the code

WebDriver d=new FirefoxDriver();
Actions a=new Actions(d);
String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
       for(WebElement tr:trs) {
            List<WebElement> tds=tr.findElements(By.tagName("td"));
            for(WebElement td:tds) {
                if(date.equals(td.getText())) {
                    a.moveToElement(td).click().build().perform();

                }
            }

}

With the above code i got stale element reference exception at this line of code

"if(date.equals(td.getText())) {"

so i have changed the code to this

for(WebElement td:tds) {
                while(i<4) {
                    try {
                        if(date.equals(td.getText())) {
                            a.moveToElement(td).click().build().perform();

                        }
                        break;
                    }catch(Exception ex) {

                    }
                    System.out.println(i);
                    i++;
                }
            }

Now i am able to select the date.But the script is still throwing the stale element reference exception.The script is showing error at this line now

List<WebElement> tds=tr.findElements(By.tagName("td"));

I am working on this for the past 3 days.Any suggestions on how to solve this. Thanks in advance

Upvotes: 5

Views: 23111

Answers (4)

Aniket Wadkar
Aniket Wadkar

Reputation: 31

Found an easier way to resolve my Stale Element Reference Exceptions.

In Java with Selenium2 try the code below:

 public WebElement cleanAndRebuildElement(final WebElement ee) {
        WebElement e2;
        try {
            e2=ee;
            e2.isDisplayed();
            logger.info("Element is cleaned : Not Stale Anymore !");
        } catch (StaleElementReferenceException e) {
              e2=null;

          
        } catch(NoSuchElementException nse) {
nse.printstacktrace(); 
          }
        return e2;
    }
}

Upvotes: 1

Subh
Subh

Reputation: 4424

In your first code, after you clicked on the element, the DOM changed, as in the Date became "14", and since the both the for-loop were still iterating, hence it threw StaleElementReferenceException.

Similarly, in the second code, you did break the "inside for-loop" that was iterating the td elements, but you didn't break the "outside" one, that continued with iterating the tr elements, hence it threw StaleElementReferenceException yet again.

Resolution:- You should've come out of both the for-loops using break after the element was clicked, and hence averting the StaleElementReferenceException, in the process.

Below code shows how you could've broken out of both the for-loops without any exception:

    WebDriver d=new FirefoxDriver();
    d.manage().window().maximize(); //Maximizing window
    d.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); //Implicit wait for 20 seconds

    Actions a=new Actions(d);
    String date="14";
    int flag=0;

    d.get("http://www.eyecon.ro/bootstrap-datepicker/");
    d.findElement(By.cssSelector("div#dp3>span")).click();
    List<WebElement> trs=d.findElements(By.cssSelector("div.datepicker-days>table>tbody>tr"));
    for(WebElement tr:trs) {
        List<WebElement> tds=tr.findElements(By.tagName("td"));
        for(WebElement td:tds) {
            if(date.equals(td.getText())) {
                a.moveToElement(td).click().build().perform();
                flag=1; // Set to 1 when the required element was found and clicked.
                break; //To come out of the first for-loop
            }
        }
        if(flag==1)
            break; //Since the element was found, come out of the second for-loop.
    }

NOTE:- I have added the code for maximizing windows and providing implicit wait too, which is actually advised when you are writing selenium scripts.

Upvotes: 4

nilesh
nilesh

Reputation: 14287

You should use WebDriverWait and ExpectedConditions to tackle staleness of an element. Below is modified block of your code which I tested and it works.

 driver.findElement(By.cssSelector("div#dp3>span")).click();
 WebDriverWait wait = new WebDriverWait(driver, 30);
 List<WebElement> trs = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector("div.datepicker-days>table>tbody>tr")));
 datePicker:
 {
    for (WebElement tr : trs) {
       List<WebElement> tds = tr.findElements(By.tagName("td"));
       for (WebElement td : tds) {
                 wait.until(ExpectedConditions.not(ExpectedConditions.stalenessOf(td)));
                 if (date.equals(td.getText())) {
                        td.click();
                        break datePicker;
                 }
        }
     }
 }

For more information check WebDriverWait and ExpectedConditions here

Upvotes: 1

Deepak
Deepak

Reputation: 336

As per my understanding when you perform element.click() in for loop DOM reloaded that's why it shows stale element exception. Use following css selector[It will selected elements from expected date picker only, used this as there are multiple date pickers on page ] & apply break in for loop on matching date like below.It will select date 14 & breaks loop without exception -

String date="14";
d.get("http://www.eyecon.ro/bootstrap-datepicker/");
d.findElement(By.cssSelector("div#dp3>span")).click();
List<WebElement> trs=d.findElements(By.cssSelector(".datepicker.dropdown-menu:nth-of-type(4)>div.datepicker-days>table>tbody>tr>td"));
     for(WebElement td:trs) {
         if(date.equals(td.getText())) {
            td.click();
            break;
         }
     }

Upvotes: 0

Related Questions