stale element reference: element is not attached to the page document selenium webdriver in chrome browser

Viewed 2451

i am learning selenium when i am executing following selenium program(selecting expected date from datepicker) i am getting stale element reference: element is not attached to the page document. I have gone through some online solutions but it is not working at the same time. I think while executing my program it is not finding the elements in DOM. Please guide me with the solution. Thanks in advance.

import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

public class skyscanner_datepicker 
{
@Test
public void calender_func() throws InterruptedException
{           
    String expected_date = "January 2018";
    String expected_day = "15";
    System.setProperty("webdriver.chrome.driver", "D://rakesh//software//selenium browser//chrome 2.30//chromedriver.exe");
    WebDriver driver = new ChromeDriver();

    driver.get("https://www.skyscanner.co.in/");
    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    driver.manage().window().maximize();
    driver.findElement(By.id("js-depart-input")).click();
    Thread.sleep(3000);     
    if(driver.findElement(By.xpath("//div[@class='popover skyscanner-datepicker depart']//span[@class='current']")).getText().equals(expected_date))
    {
        System.out.println("Date selected in if condition");
    }
    else
    {
        for(int i=1;i<=12;i++)
        {                       
        try 
        {
                driver.findElement(By.xpath("//div[@class='popover skyscanner-datepicker depart']//div[@class='calendar-info-bar datepicker_clearfix']//button[2]")).click();               
                if(driver.findElement(By.xpath("//div[@class='popover skyscanner-datepicker depart']//span[@class='current']")).getText().equals(expected_date))
                break;
                System.out.println("date get selected");                    
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }   
        }           
    }

    List<WebElement> day_list = driver.findElements(By.xpath("//div[@class='container-body']//tbody//tr//td"));
    for(WebElement a : day_list)
    {
        if(a.getText().equalsIgnoreCase(expected_day))
        {
            a.click();
        }
    }       
    driver.quit();
}

}

2 Answers

I guess that in this loop:

for(int i=1;i<=12;i++)
{                       
try 
{
        driver.findElement(By.xpath("//div[@class='popover skyscanner-datepicker depart']//div[@class='calendar-info-bar datepicker_clearfix']//button[2]")).click();               
        if(driver.findElement(By.xpath("//div[@class='popover skyscanner-datepicker depart']//span[@class='current']")).getText().equals(expected_date))
        break;
        System.out.println("date get selected");                    
} 
catch (Exception e) 
{
    e.printStackTrace();
}   
} 

you are trying to wait for same date value to appear in the element.

It almost never worked! Use explicit waits instead.


Familiarize yourself with:

and use this snippet instead of the above loop:

// wait up to 30 seconds
WebDriver wait = new WebDriverWait( driver, 30 );
final By element = By.xpath("//div[@class='popover skyscanner-datepicker depart']//span[@class='current']");
wait.until(ExpectedConditions.textToBePresentInElementLocated( element, expected_date ));

This will wait for 30 seconds for date to appear in the element, if the value does not become visible within 30 seconds, then timeout exception will be thrown.


This code retrieves all elements, then is looking in a loop for only one element, then is trying to click it:

List<WebElement> day_list = driver.findElements(By.xpath("//div[@class='container-body']//tbody//tr//td"));
for(WebElement a : day_list)
{
    if(a.getText().equalsIgnoreCase(expected_day))
    {
        a.click();
    }
}  

But why don't just look for this concrete element to become visible and clickable ?
Use this:

final String elementXpath = String.format(
    "//div[@class='container-body']//tbody//tr//td[ contains( ., '%s' ) ]",
    expected_day ); 

final By elementToClick = By.xpath( elementXpath );

// wait until element appears and becomes clickable, then click it
wait.until(ExpectedConditions.elementToBeClickable( elementToClick )).click();

StaleElementReference exception could have been caused when webdriver tries to access the element while the page is still loading. Try adding page load time out after you initialize you webdriver.

driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);

This will tell the webdriver to wait for upto 5 seconds for the page to load before moving to a next page action.

Also, the number of seconds depends on the time to completely load the web page of your application

Related