1

I am trying to access a certain row based on the column data and then click the link in that row. How do I achieve this? I've been stuck on this for 5 days.

I am new to Selenium but I have tried looping through the list of elements but then would get a StaleElementReferenceException: stale element is not attached to the DOM.

I saw on the selenium website and a few other questions similar to this that it means the element or the page has updated so the reference to that element may not be correct so I've tried a few things:

I tried using Expected Conditions refresh and then reinitialized the element but that only worked sometimes and i would still get the error I've tried adding a try and catch but that didn't seem to work and I'm also not entirely show if I did it correctly.

I also wanted to see if I could ditch the for loop all together and just find an element in the list that had the 3 attributes that I needed using selenium's "contain" but I'm not sure if that's even something it can do

The Structure of the table is as follows:

<div _ngcontent-c9 class="no-wrap" id="SummaryList">
  <div class="row">
    <div class="col">
      <a>Some Text</a>
    </div>
    <div class="col">
      Value1
    </div>
    <div class="col">
      Value2
    </div>
    <div class="col">
      Value3
    </div>
  </div>
  <div class="row">
    <div class="col">
      <a>Some Text</a>
    </div>
    <div class="col">
      Value1A
    </div>
    <div class="col">
      Value2B
    </div>
    <div class="col">
      Value3C
    </div>
  </div>
</div>

The function giving me issues -pseudocode

public void validateInfo(String val1, String val2, String val3){
    List<WebElement> rowDetail = driver.findElements(By.xpath("//*[@id=\"SummaryList\"]/div/div"));
    int rowSize = rowDetail.size();
    for(int i = 0; i<rowSize; i++){
        rowDetail = driver.findElements(By.xpath("//*[@id=\"SummaryList\"]/div/div"));
       //if row values equal to val1,val2&val3
       //then click the a tag in that row and break
   }
}

I expect to find the correct row with the 3 parameters passed in and click on the a tag in that row to move on to the next step.

Error: org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

Martina Carter
  • 409
  • 5
  • 18
  • If it is your first click I am still not sure why you would see _StaleElementReferenceException_ – undetected Selenium Sep 10 '19 at 14:23
  • Well, is there a way that I can find the specific row with 3 values in the columns? each row has multiple columns but they are unique based one 3 of them. – Martina Carter Sep 10 '19 at 14:30
  • Yes, you can find the specific row with 3 values in the columns, but the row itself is not clickable, how can you face _StaleElementReferenceException_? – undetected Selenium Sep 10 '19 at 14:32
  • well how do I do that? because for some reason when I use the for loop and iterate through the rows, I get that error, even though im not manipulating the rows in anyway. one of the 3 values is also a link but the text value of that link needs to be checked along with the other 2 column values – Martina Carter Sep 10 '19 at 14:36
  • So is your usecase like: Click on the column with linkText as `Some Text` when the next 3 columns contains texts as `Value1`, `Value2` **and** `Value3`? – undetected Selenium Sep 10 '19 at 14:41
  • yes, it is. I was hoping to do something along the lines of "contains" Value1, Value2 and Value 3 – Martina Carter Sep 10 '19 at 17:52
  • @DebanjanB does it matter that the data elements in the table are generated using angular? – Martina Carter Sep 11 '19 at 13:02
  • yes, very much, **angular** elements requires a **waiter** – undetected Selenium Sep 11 '19 at 13:03
  • Old, but just in case anyone was wondering, I was facing my issue because I was testing an Angular page which I guess would of been relevant info to mention at the time. I used NgWebDriver which allowed me to wait until angular was done before the webdriver tried accessing any of the elements. – Martina Carter Sep 17 '19 at 19:00

2 Answers2

0

StaleElementReferenceException means that your DOM tree has been changed and found element are out of date. Try following code, it will retry click until success or timeout:

public void validateInfo(String val1, String val2, String val3){
        new WebDriverWait(driver, timeout)
            .ignoring(StaleElementReferenceException.class)
            .until(new Predicate<WebDriver>() {
                @Override
                public boolean apply(@Nullable WebDriver driver) {
                    List<WebElement> rowDetail = driver.findElements(By.xpath("//*[@id=\"SummaryList\"]/div/div"));
                    int rowSize = rowDetail.size();
                    for(int i = 0; i<rowSize; i++){
                        WebElement element = rowDetail.get(i);
                        if (element.getAttribute("value").startWith(val)) {
                            rowDetail.get(i).click(); 
                        }

                        // rowDetail = driver.findElements(By.xpath("//*[@id=\"SummaryList\"]/div/div"));
                        //if row values equal to val1,val2&val3
                        //then click the a tag in that row and break
                    }
                    return true;
                }
            });
}
i.bondarenko
  • 3,442
  • 3
  • 11
  • 21
0

It might be something to do with you trying to override an already stored WebElement. Looking at your code though, you seem to be trying to replace the WebElement list with the same list and aren't actually iterating through the elements within it. Try this:

    List<WebElement> rows = driver.findElements(By.xpath("//*[@id='SummaryList']//*[@class='row']"));
    for(int i=1; i<rows.size(); i++) {
        String rowText = driver.findElement(By.xpath("//*[@id='SummaryList']//*[@class='row'][" + i + "]")).getText();
        if (rowText.contains(val1) && rowText.contains(val2) && rowText.contains(val3)) {
            driver.findElement(By.xpath("//*[@id='SummaryList']//*[@class='row'][" + i + "]//a")).click();
            break;
        }
    }

That should iterate through all the rows in the table and once it finds a row containing the values you supply it will click the link and break the loop

Jsmith2800
  • 1,113
  • 1
  • 9
  • 18
  • I've noticed so far that setting variables to the driver element values makes it throw this error? If i use things explicitly-- say printing out driver.findElement(By.xpath...) it would work but printing rowText wouldn't. it would throw the staleElementException – Martina Carter Sep 10 '19 at 19:36