Reputation: 87
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
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
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
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
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