Search code examples
seleniumselenium-webdriverstaleelementreferenceexception

Getting StaleElementReferenceException when iterating through a list of WebElements


I was trying to automate the following scenario:

  • go to amazon.com
  • search for headphones
  • add all the bestsellers in the first results page to the cart

The steps I've followed to script this scenario:

  • go to amazon.com
  • enter the text "headphones" in the search field
  • click on search button
  • click on a link that is tagged as 'bestseller'
  • click on 'add to cart' button
  • navigate back to the results page
  • click on another link that is tagged as 'bestseller'
  • click on 'add to cart' button
  • navigate back to the results page

All the bestsellers has the same xpath:

//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span

So I've implemented this a list of WebElements as follows:

List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));

I've implemented the clicking on a link and adding to the cart using loop in 3 ways as follows:

for(WebElement product: bestsellers) {
    product.click();
    clickOnAddToCartButton();
    driver.navigate().back();
}



for(int i=0; i<bestsellers.size(); i++) {
        System.out.println(bestsellers.size());
        bestsellers.get(i).click();
        clickOnAddToCartButton();
        driver.navigate().back();

    }



Iterator<WebElement> i = bestsellers.iterator();
    while(i.hasNext()) {
        WebElement product = i.next();
        wait.until(ExpectedConditions.elementToBeClickable(product));

        product.click();
        clickOnAddToCartButton();
        driver.navigate().back();
    }

There are 3 elements in the list 'bestsellers' When I had run the script. When the loop is executed, the first element is getting clicked and added to the cart and the driver navigates back to the results page. Then I'm getting staleElementReferenceException using the above 3 ways.

Update: I've implemented the scenario as follows:

for(int i=0; i<bestsellers.size(); i++) {

        System.out.println("Current :" + i);
        wait.until(ExpectedConditions.elementToBeClickable(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")));
        driver.findElements(By.xpath(".//span[.='Best Seller']/../../../../../../../../following-sibling::div/div/following-sibling::div/div/div/div/div/div/h2/a/span")).get(i).click();
        clickOnAddToCartButton();
        //clickOnViewCart();
        try {
            wait.until(ExpectedConditions.elementToBeClickable(cartButton));
        }catch(TimeoutException e) {
            wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));
        }
        if(i==(bestsellers.size()-1)) {
            try {
                wait.until(ExpectedConditions.elementToBeClickable(cartButton));    
                cartButton.click();
                break;
            }catch(TimeoutException e) {
                wait.until(ExpectedConditions.elementToBeClickable(viewCartButton));    
                viewCartButton.click();
                break;
            }
        }

        driver.navigate().back();

Solution

  • The moment you click on the element or back() in the browser the element reference will updated in the selenium so you can not point to the elements with the old references and which led to the StatleElementException.

    Consider this approach when you have to iterate through multiple elements interaction.

    List<WebElement> bestsellers = driver.findElements(By.xpath("xpath of bestsellers"));
    for(int i=0; i<bestsellers.size(); i++) {
        System.out.println("Current Seller " + i);
        // here you are getting the elements each time you iterate, which will get the
        // latest element references
        driver.findElements(By.xpath("xpath of bestsellers")).get(i).click();
        clickOnAddToCartButton();
        driver.navigate().back();
    
    }