Cristian M
Cristian M

Reputation: 357

Watir is unable to locate elements from a collection

I've just run into this, and it is a bit of a struggle in handling elements from collections. In my case, I am trying to parse through a table and check the values contained in the cells of a column. Here is the code:

def check_cells_values(table, cell_index)
 table.rows.each do |row|
   row.cells[cell_index].text.should == some_value
 end
end

On the "row.cells[cell_index].text.should == some_value" line the tests fail with this error:

Watir::Exception::UnknownObjectException: unable to locate element, using {:element=>#<Selenium::WebDriver::Element:0x7b40a27fd80f640e id="{af57e857-69ed-5345-a4ae-5ab80dff364a}">}

It is enough to simply iterate through the rows and outputting the text from each row. After some rows (randomly), it fails with the same message.

I found this link (https://jkotests.wordpress.com/unable-to-locate-element/) where Justin covers this issue, but I didn't find anywhere something tied to collections of elements.

Update: Here is a row example of one table that I am parsing.

  <tr class="dataRow even  first" onclick="highlightElem(this)" onmouseover="if (window.hiOn){hiOn(this);} " onmouseout="if (window.hiOff){hiOff(this);} " onblur="if (window.hiOff){hiOff(this);}" onfocus="if (window.hiOn){hiOn(this);}">
      <td class="dataCell  " id="someid3" colspan="1"><a href="/url">8882</a></td>
      <td class="dataCell  " id="someid2" colspan="1">
           <label>Some kind of service</label></td>
      <td class="dataCell  " id="someid6" colspan="1"></td><td class="dataCell  " id="someid7" colspan="1"><input class="btn" id="someid8" onclick="A4J.AJAX.Submit('pgToolOffer:pgForm',event,{'similarityGroupingId':'someid8','oncomplete':function(request,event,data){UpdatePopupPosition();},'parameters':{'selectedRatePlan':'Annual','selectedOfferFriendlyName':'Some service 50$','someid8':'someid8','selectedProduct':'Service Descrition','selectedOfferCode':'product\duration\x2DDG275'} } );return false;" value="Show Offer Details" type="button"></td>
  </tr>

Upvotes: 1

Views: 829

Answers (2)

Antesser
Antesser

Reputation: 669

The First Option (strict code):

table.rows.each do |row| #We'll take each row
  cell = row[given_index] #We'll take one cell of the taken row
  puts cell.text #We'll do some stuff with the text of the cell
end

The Second Option (let's try to relocate table constantly):

i = 0
table.rows.length.times do
  table = b.table(id: "table")
  puts table[i][given_index].text
  i = i+1
end

Upvotes: 0

Chuck van der Linden
Chuck van der Linden

Reputation: 6660

I suspect that client-side javascript code on the page is still building the table, or updating it at the point your automation interacts with it.

As a way of trying to see if that is the case, I'd try briefly inserting a big wait, like 10 or 15 seconds, before that code to see if it starts behaving. I normally avoid syncing using sleeps (because they are either too short (flakey tests) or too long (slow tests). But for troubleshooting and debugging it can be a fast way to identify sync issues.

If that makes a difference you know you have a sync issue, and can then look deeper into how you can tell when the page is done updating itself. Usually that means looking for some element to exist that is created right near the end up that update, and having your code wait until it see's that element on the page before proceeding. For pages that use jQuery you can also get the jQuery.active value (open ajax requests) and wait for it to go to zero and stay there for a half second or so, as a way of telling that the page is done with client side ajax requests and is likely in a proper state for the test to proceed.

Upvotes: 1

Related Questions