Get StaleElementReferenceException when trying to print the link names

advertisements

I'm trying to print first 5 pages links displayed in google search.. But getting StateElementReferenceException Not sure which one went wrong..

    public class GoogleCoInTest {

    static WebDriver driver = null;
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("webdriver.gecko.driver", "D:\\bala back up\\personel\\selenium\\Jars\\Drivers\\geckodriver.exe");
        driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.google.co.in/");
        //driver.findElement(By.xpath("//input[class='gsfi']")).sendKeys("Banduchode");;
        WebElement search=driver.findElement(By.cssSelector("input#lst-ib"));
        search.sendKeys("Banduchode");
        search.sendKeys(Keys.ENTER);
        printLinksName();
        List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[@id='nav']/tbody/tr/td/a"));

        for(int i=0;i<5;i++){
            System.out.println(fiveLinks.get(i).getText());
            fiveLinks.get(i).click();
            Thread.sleep(5000);
            printLinksName();

        }
    }   

    public static void printLinksName() throws InterruptedException{

        List<WebElement> allLinks=driver.findElements(By.xpath("//*[@id='rso']/div/div/div/div/div/h3/a"));
        System.out.println(allLinks.size()); 

        //print all list
        for(int i=0;i<allLinks.size();i++){
            System.out.println("Sno"+(i+1)+":"+allLinks.get(i).getText());

        }
    }
}

it prints fine till 2nd page , but there after I am getting

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: The element reference of <a class="fl"> stale: either the element is no longer attached to the DOM or the page has been refreshed
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html


Here is the Answer to your Question:

  1. Your script prints the result from the first 2 pages as expected.
  2. When you call printLinksName() for the first time it works.
  3. Next, you are storing the 10 PageNumbers in a Generic List of type WebElement.
  4. First time within the for() loop you are clicking on the WebElement of Page 2 and then printing all the links by calling printLinksName().
  5. While you are in the second iteration within for() loop, the reference of List<WebElement> fiveLinks is lost as the DOM have changed. Hence, you see StateElementReferenceException.

Solution

A simple solution to avoid StateElementReferenceException would be to move the line of code List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[@id='nav']/tbody/tr/td/a")); with in the for() loop. So your code block will look like:

    import java.util.List;
    import java.util.concurrent.TimeUnit;

    import org.openqa.selenium.By;
    import org.openqa.selenium.Keys;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.firefox.FirefoxDriver;

    public class Q44970712_stale
    {

        static WebDriver driver = null;

        public static void main(String[] args)  throws InterruptedException
        {
        System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
        driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get("https://www.google.co.in/");
        //driver.findElement(By.xpath("//input[class='gsfi']")).sendKeys("Banduchode");;
        WebElement search=driver.findElement(By.cssSelector("input#lst-ib"));
        search.sendKeys("Banduchode");
        search.sendKeys(Keys.ENTER);
        printLinksName();

        for(int i=0;i<5;i++)
        {
            List<WebElement> fiveLinks=driver.findElements(By.xpath(".//*[@id='nav']/tbody/tr/td/a"));
            System.out.println(fiveLinks.get(i).getText());
            fiveLinks.get(i).click();
            Thread.sleep(5000);
            printLinksName();
        }
        }

        public static void printLinksName() throws InterruptedException
        {
            List<WebElement> allLinks=driver.findElements(By.xpath("//*[@id='rso']/div/div/div/div/div/h3/a"));
            System.out.println(allLinks.size()); 

            //print all list
            for(int i=0;i<allLinks.size();i++)
            {
            System.out.println("Sno"+(i+1)+":"+allLinks.get(i).getText());

            }
        }

    }

Note: In this simple solution when you finish printing the second page, next when you will create List<WebElement> fiveLinks through xpath with .//*[@id='nav']/tbody/tr/td/a for second time, Page 1 is the first element which gets stored in the fiveLinks List. Hence you may be again redirected to Page 1. To avoid that you may consider to take help of xpath with proper indexing.

Let me know if this Answers your Question.