5

I am using Selenium WebDriver with java.

I am fetching all links from webpage and trying to click each link one by one. I am getting below error:

error org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up Command duration or timeout: 30.01 seconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html Build info: version: '2.25.0', revision: '17482', time: '2012-07-18 21:09:54'

and here is my code :

public void getLinks()throws Exception{
    try {
        List<WebElement> links = driver.findElements(By.tagName("a"));
        int linkcount = links.size(); 
         System.out.println(links.size()); 
          for (WebElement myElement : links){
         String link = myElement.getText(); 
         System.out.println(link);
         System.out.println(myElement);   
        if (link !=""){
             myElement.click();
             Thread.sleep(2000);
             System.out.println("third");
            }
            //Thread.sleep(5000);
          } 
        }catch (Exception e){
            System.out.println("error "+e);
        }
    }

actually, it's displaying in output

[[FirefoxDriver: firefox on XP (ce0da229-f77b-4fb8-b017-df517845fa78)] -> tag name: a]

as link, I want to eliminate these form result.

7 Answers 7

9

There is no such a good idea to have following scenario :

for (WebElement element : webDriver.findElements(locator.getBy())){
  element.click();
}

Why? Because there is no guarantee that the element.click(); will have no effect on other found elements, so the DOM may be changed, so hence the StaleElementReferenceException.

It is better to use the following scenario :

int numberOfElementsFound = getNumberOfElementsFound(locator);
for (int pos = 0; pos < numberOfElementsFound; pos++) {
  getElementWithIndex(locator, pos).click();
}

This is better because you will always take the WebElement refreshed, even the previous click had some effects on it.

EDIT : Example added

  public int getNumberOfElementsFound(By by) {
    return webDriver.findElements(by).size();
  }

  public WebElement getElementWithIndex(By by, int pos) {
    return webDriver.findElements(by).get(pos);
  }

Hope to be enough.

Sign up to request clarification or add additional context in comments.

4 Comments

can pls give me one sample example of above scenario. It will really appreciable. thanks.
@loan I am still struggling, didn't get through. May be because I'm new to selenium driver. loop is running 4 times after that it sending following error <blockquote>'error org.openqa.selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with Command duration or timeout: 30.05 seconds Build info: version: '2.25.0', revision: '17482', time: '2012-07-18 21:09:54' System info: os.name: 'Windows 7', os.arch: 'x86', os.version: '6 >
Well this is a different problem than StaleElementReferenceException. It means that you are trying to access an element which is not visibile, and most probably which is made visibile by another element. So first you have to identify which is this element, and then to make sure that it is visibile before to perform any actions on it. Or if is not mandatory, you can use .isDisplayed() method, to check if this element is proper, and then continue.
Perfect Loan, I added driver.navigate().back()
2

Credit goes to "loan".

I am also getting "stale exception" so I used 'loan' answer and works perfectly. Just if anyone need to know how to click on each link from results page try this (java)

clickAllHyperLinksByTagName("h3"); where "h3" tag contains hyperlink

 public static void clickAllHyperLinksByTagName(String tagName){
    int numberOfElementsFound = getNumberOfElementsFound(By.tagName(tagName));
    System.out.println(numberOfElementsFound);
    for (int pos = 0; pos < numberOfElementsFound; pos++) {
        getElementWithIndex(By.tagName(tagName), pos).click();
        driver.navigate().back();
    }
}

public static int getNumberOfElementsFound(By by) {
    return driver.findElements(by).size();
}

public static WebElement getElementWithIndex(By by, int pos) {
    return driver.findElements(by).get(pos);
}

Comments

2

@Then("^I will fetch the URL$") public void i_will_fetch_the_url() throws Throwable {

    List<WebElement> jobLinks =driver.findElements(By.tagName("loc"));
    
    List<String> texts = new ArrayList<String>();
    
    for (WebElement element : jobLinks) {
        texts.add(element.getText());
    }

    for(String text:texts) {

    System.out.println(text);
        Base.driver.get(text);
        
    }

2 Comments

Downvoting. Your answer is missing important parts.
please edit the answer to include clarifications (vs. doing so in a comment)
1
    WebDriver _driver = new InternetExplorerDriver();
    _driver.navigate().to("http://www.google.co.in/");
    List <WebElement> alllinks = _driver.findElements(By.tagName("a"));

    for(int i=0;i<alllinks.size();i++)
        System.out.println(alllinks.get(i).getText());

    for(int i=0;i<alllinks.size();i++){
        alllinks.get(i).click();
        _driver.navigate().back();
    }

1 Comment

I don't think that will work, having navigated away won't you get a stale object exception? I think you have to look up all the links each time, take an object and ignore the rest.
1

If you're OK using WebDriver.get() instead of WebElement.click() to test the links, an alternate approach is to save the href value of each found WebElement in a separate list. This way you avoid the StaleElementReferenceException because you're not trying to reuse subsequent WebElements after navigating away with the first WebElement.click().

Basic example:

List<String> hrefs = new ArrayList<String>();
List<WebElement> anchors = driver.findElements(By.tagName("a"));
for ( WebElement anchor : anchors ) {
    hrefs.add(anchor.getAttribute("href"));
}
for ( String href : hrefs ) {
    driver.get(href);           
}

Comments

0
//extract the link texts of each link element
        for (WebElement elements : linkElements) {
            linkTexts[i] = elements.getText();
            i++;
        }

        //test each link
        for (String t : linkTexts) {
            driver.findElement(By.linkText(t)).click();
            if (driver.getTitle().equals(notWorkingUrlTitle )) {
                System.out.println("\"" + t + "\""
                        + " is not working.");
            } else {
                System.out.println("\"" + t + "\""
                        + " is working.");
            }
            driver.navigate().back();
        }
        driver.quit();
    }

For complete Explanation Read This POST

Comments

0
List <WebElement> links = driver.findElements(By.tagName("a"));                 
int linkCount=links.size();

System.out.println("Total number of page on the webpage:"+ linkCount);
String[] texts=new String[linkCount];
int t=0;
for (WebElement text:links){
  texts[t]=text.getText();//extract text from link and put in Array
  //System.out.println(texts[t]);
  t++;
}
for (String clicks:texts) {

  driver.findElement(By.linkText(clicks)).click();
  if (driver.getTitle().equals("notWorkingUrlTitle" )) {
    System.out.println("\"" + t + "\""
    + " is not working.");
  } else {
    System.out.println("\"" + t + "\""
                       + " is working.");
  }

  driver.navigate().back();
}

driver.quit();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.