0
<table>
  <tr id="tr1">
    <td id="td1">1</td>
    <td id="td2">2</td>
    <td id="td3">3</td>
    <td id="td4">4</td>
    <td id="td5">5</td>
    <td id="td6">6</td>
    <td id="td7">7</td>
    <td id="td8">8</td>
    <td id="td9">9</td>
    <td id="td10">10</td>
  </tr>
  <tr id="tr2">
    <td id="td1">11</td>
    <td id="td2">22</td>

  </tr>
</table>

I'm retrieving the 'tr1' element using,

WebDriverWait wait = new WebDriverWait(driver, 5);
tableHeaderRow = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("tr1"))); 

Then I'm getting the 'td' list and iterating through the td elements.

List<WebElement> headersList = tableHeaderRow.findElements(By.tagName("td"));
System.out.println("Size :" + headersList.size()); //10

The list size is 10 here.

headersList.forEach(td -> System.out.println(td.getTagName()));

But when I'm iterating through the list, I'm getting a StaleElementReferenceException after iterating through 4 or 5 elements.

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

The issue is, even though the 'tr1' is loaded, the tds are not completely loaded, when iteration happens. The wait is only checking the mentioned parent element (tr1) loading.

Is there a proper way to handle this issue. Wait until the parent element and all the child elements are loaded.

Guy
  • 46,488
  • 10
  • 44
  • 88
Aki T
  • 612
  • 2
  • 7
  • 17

2 Answers2

0

To ensure that both the parent and child elements are loaded, instead of presenceOfElementLocated() you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use either of the following Locator Strategies:

  • Using cssSelector:

    System.out.println(new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("td.journalTable-journalPost>a.htext-small"))).size());
    
  • Using xpath:

    System.out.println(new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//tr[@id='tr1']//td"))).size());
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Tried the xpath method. Still getting the same error randomly. cssSelector method is bit unclear. – Aki T Mar 04 '20 at 20:25
  • This won't work because Selenium doesn't know how many elements are going to be dynamically loaded in the table. It will only wait for elements that already exist in the DOM but aren't yet visible. If 5 become visible before the last 5 are loaded into the DOM this will fail. – JeffC Mar 05 '20 at 00:56
-1

Try use .visibilityOfAllElementsLocatedBy for wait the element, and collect it in the list.

Use this xpath : //tr[@id='tr1']//td.

Try the following code:

WebDriverWait wait = new WebDriverWait(driver, 5);
List<WebElement> elements = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//tr[@id='tr1']//td")));
System.out.println("Size :" + elements.size());
frianH
  • 7,295
  • 6
  • 20
  • 45