5

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

Rupesh Shinde
  • 1,933
  • 12
  • 22
Rachel D'cruz
  • 87
  • 1
  • 3
  • 9
  • 1
    Possible duplicate of [Selenium WebDriver How to Resolve Stale Element Reference Exception?](http://stackoverflow.com/questions/16166261/selenium-webdriver-how-to-resolve-stale-element-reference-exception) – Narendra Chandratre Jul 15 '16 at 11:10

4 Answers4

4

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.

Subh
  • 4,354
  • 1
  • 13
  • 32
1

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

nilesh
  • 14,131
  • 7
  • 65
  • 79
  • Np. I shamelessly say that I still believe my solution is way elegant than the one accepted :) – nilesh Feb 12 '15 at 14:15
  • 1
    well it was elegant.But in the answer i have accepted he gave a clear explanation of the problem.So that's the reason i have accepted the other answer – Rachel D'cruz Feb 16 '15 at 07:56
  • @RachelD'cruz I think that's fair. I did miss on that, I thought the named `for` block makes the explanation obvious. – nilesh Feb 16 '15 at 16:00
1

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;
    }
}
  • This addresses the very reason why we get a stale element reference exception. People using Page Factory web element find hard to break and rebuild the element, for it to be refreshed. Page factory always fetches the element afresh when called upon. By reassigning the reference we are forcing Page Factory to get the element again. There is recursion in this method, please use some timeout to break the loop. After all we do not want a situation with an endless loop. – Aniket Wadkar Oct 17 '17 at 09:23
  • This way ensures that the cleaning and rebuilding of element can happen via a generic functionality and hence can be implemented seamlessly . – Aniket Wadkar May 05 '18 at 20:16
0

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;
         }
     }
Deepak
  • 336
  • 1
  • 3
  • 10