0

I am trying to test this Website. It has multiple product inside is. I want to click on first product and once the product page is open i want to go back to the previous page and then click on the second product. Once it is open i again want to go back and then do the same for all the products available on the webpage.

I wrote the below code to do so -

  driver.manage().timeouts().implicitlyWait(8000, TimeUnit.SECONDS);
   List<WebElement> product = driver.findElements(By.xpath(".//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));
   for(int i=0; i<product.size();i++){
       try{
       driver.manage().timeouts().implicitlyWait(8000, TimeUnit.SECONDS);
       product.get(i).click();
       System.out.println(i);
       System.out.println("Title is : "+driver.getTitle());
       System.out.println("Product URL is : "+driver.getCurrentUrl());
       driver.navigate().back();
       }catch(StaleElementReferenceException e){
           e.printStackTrace();
       }//catch
   }//for

After clicking on the first product/element i am getting this exception -

org.openqa.selenium.StaleElementReferenceException: stale element reference:  element is not attached to the page document
(Session info: chrome=44.0.2403.89)
(Driver info: chromedriver=2.9.248315,platform=Windows NT 6.1 SP1 x86)(WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 115 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.46.0', revision: '87c69e2', time: '2015-06-04 16:17:10'
System info: host: 'ShantanuNandan', ip: '10.0.0.4', os.name: 'Windows 7', os.arch: 'x86', os.version: '6.1', java.version: '1.8.0_45'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities [{applicationCacheEnabled=false, rotatable=false, chrome= {userDataDir=C:\Users\SHANTA~1\AppData\Local\Temp\scoped_dir6172_17060},  takesHeapSnapshot=true, databaseEnabled=false, handlesAlerts=true,  version=44.0.2403.89, platform=XP, browserConnectionEnabled=false,  nativeEvents=true, acceptSslCerts=true, locationContextEnabled=true,  webStorageEnabled=true, browserName=chrome, takesScreenshot=true,  javascriptEnabled=true, cssSelectorsEnabled=true}]
Session ID: 081ee44a67affb195766d4fc8ce165d3
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at  org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204)
at  org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:156)
at  org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:605)
at  org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:269)
at  org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:80)
at  com.Selenium_Practice.Niraame_Login_Logout_ElementDisplay.ClickAndComeBack(Niraame_Login_Logout_ElementDisplay.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at  org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at  org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175) 

I went through the same questions asked on the forum and so far did these thing. First i put Thread.sleep and page refresh to make the element available for the click. Code -

driver.navigate().back();
Thread.sleep(4000);
driver.navigate().refresh();

But again i got the same exception.

Then i put a explicitwait instead of implicit wait but again got the same exception.

Then i put continue; in the try block as well as in the the catch block but got the same exception.

I tried 2 more options but all are of no use. Please tell me where i am doing the mistake. I know why it is happening(it is happening because the DOM is not making the elements available after the first click) but not able to figure out a way by which i can get the desired result.

On chrome i am getting StaleElementReferenceException but for the firefox i am not getting any exception after the first click. The firefox browser freezes after the first click.

4 Answers 4

1

Selenium assigns internal element locator to every element you want to interact with, prior to this interaction. You can track this behaviour in execution logs. In your example, those locators are assigned when you execute driver.findElements.

If page refreshes or DOM model changes between a) these locators are assigned and b) interaction between your code and those elements, StaleElementReferenceException is thrown. This is what happens in your code. You:

  • fetch elements to a collection
  • interact with one of them, which takes you to previous page
  • navigate back
  • attempt to repeat above, while 2 page reloads already took place

Answer to your problem is called Page Object Design pattern, which is described e.g. here.

What you need to do in particular, is:

  • create ProductListPage
  • implement int getNumberOfProducts(), which will return number of products displayed on page
  • implement void clickProduct(int index), which will take you to product details page
  • create ProductDetailsPage
  • implement method to move back

In your test class, you should do for loop up to getNumberOfProducts(). In this loop, you do:

  • productListPage.clickProduct(i)
  • wait for ProductDetailsPage to be displayed (x)
  • get back to previous page
  • wait for ProductListPage to be displayed (x)

(x) - you can implement custom waitForPageToLoad() methods for those 2 page objects, which will wait until element unique for that particular page is displayed.

The possible problem I can see here is lack of return link on product details page, so you applied workaround with browser back button. This will be a problem if you have to automate it with SafariDriver, where interaction with browser back and forward buttons is not implemented.

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

1 Comment

can you provide a link where i can see some sample codes. The link which you have provided was not much helpfull for me.
1

StaleElementRefreshException is happening because when you are navigating back to the previous page, the DOM is getting refreshed, and the List elements are getting stale.

You can just add the code for creating the list (which you've added before) in the for loop again. So, whenever the page gets navigated back to the former one, the list gets refreshed again.

Please see the below updated code:

driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
List<WebElement> product = driver.findElements(By.xpath(".//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));
for(int i=0; i<product.size();i++){
   try{
       //For Refreshing the list each time page gets navigated back.
       product = driver.findElements(By.xpath(".//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));

       product.get(i).click();
       System.out.println(i);
       System.out.println("Title is : "+driver.getTitle());
       System.out.println("Product URL is : "+driver.getCurrentUrl());
       driver.navigate().back();
       }catch(StaleElementReferenceException e){
           e.printStackTrace();
       }//catch
   }//for

Few Suggestions:

  1. Please avoid using an implicit wait time that long. It was 8000 seconds, which roughly equals to 2 hrs and 22mins. Clearly it's too much to wait for an element.. :)
  2. If you want to use implicit wait, you can use it at the beginning. As once set, the wait time applies to every time the driver tries to find an element. No need to add it each time. And, If you want to wait more than the implicitly given time, you can use explicit wait for the concerned WebElement. Please follow this link for better understanding; http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits

Comments

1
  public void ClickAndComeBack() throws InterruptedException, IOException{
   driver.manage().timeouts().implicitlyWait(8000, TimeUnit.SECONDS);
   List<WebElement> productLink = driver.findElements(By.xpath(".//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));
   String[] str = new String[productLink.size()];
   for(int i=0; i<productLink.size();i++){
       str[i]=productLink.get(i).getAttribute("href");
   }//for
   int i=0;
   for(String strr: str){
       driver.manage().timeouts().implicitlyWait(8000, TimeUnit.SECONDS);
       driver.get(strr);
       System.out.println("Title is : "+driver.getTitle());
       System.out.println("Product URL is : "+driver.getCurrentUrl());
       File src = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
       FileUtils.copyFile(src, new File("D:\\NiraameProductScreenShot\\pic"+i+".jpeg"), true);
       i++;
       driver.navigate().back();
       Thread.sleep(4000);
   }//for
 }//ClickAndComeBack

Here in first for loop i am storing all href inside a string array. And in the second loop i am putting the stored array in the driver.get() method of webdriver. So far the code is works perfectly fine for me now.

Comments

0

I was also trying for this question from yesterday. It worked for me. Here is the working code.

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.firefox.FirefoxDriver;
import org.openqa.selenium.remote.service.DriverService;

public class clickOnAllTabOfPage {

    public static void main(String[] args) {
        WebDriver driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        driver.get("http://niraame.com/beauty.html");   
        List <WebElement> Items = driver.findElements(By.xpath("//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));
        int lenght=Items.size();
        for (int i=0; i<lenght; i++) {      
            try {
                Items.get(i).click();
                System.out.println("i value :"+i+ "|title is :" +driver.getTitle() + "|Item Url is :"+driver.getCurrentUrl());
                driver.navigate().back();
                Items = driver.findElements(By.xpath("//*[@class='products-grid products-grid--max-4-col first last odd']/li/a"));

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("Opened all the links on the Page and hence closing the browser");
        driver.quit();
    }
}

Console Output enter image description here

4 Comments

Only 1 st product is getting clicked again and again. I figured out another way after reading the documentation provided by "automatictester" and i got a break through. I am posting the code as an possible answer.
I think you have not tried my code. Before posting the code, i have tested it and it is working fine. Its is clicking all the products on the page and I have attached the console output for the references. Please have a look on it.
I tried your code Hari and it is working fine. I missed Items = driver.findElements(By.xpath("//*[@class='products-grid products-grid--max-4-col first last odd']/li/a")); line of code in for loop. I corrected it and now its working fine.
Thanks Shantanu for the Confirmation. Can you please accept the Answer.

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.