How to Get Index of Parent Element Using Watir Webdriver

How to get index of parent element using Watir Webdriver?

There's no way to get the index using the webdriver since they are relative to the collection of matched elements. What you can try to do is collect the elemetns text as Array and then get the index of the target text.

@@ff.divs(:class, 'A').collect(&:text).index('Text1')

Note that this will only work for simple scenarios (like your example). If you need to attack a more complex case update your example to match the real scenario.

Watir: Finding the Parent div containing a specific child

Solution 1 - Xpath

In this case, I think the easiest solution is to use xpath:

browser.div(:xpath, '//div[@class="items"][.//div[@id="specificchild"]]')

Solution 2 - Iterating Until Parent

Alternatively, you could find the specificchild element like you normally do. Then iterate item the parents until the one with class 'items' is found:

item = browser.div(:id => 'specificchild')
item = item.parent until item.class_name == 'items'

Solution 3 - Using find

Another option is getting a collection of the divs with class items and then finding the one with the specific child. It will only iterate through the divs until the desired one is found.

browser.divs(:class => 'items').find{ |item| item.div(:id => 'specificchild').exists? }

get sibling node without relying on parent index?

You could use the css adjacent sibling selector. Note that Watir-Webdriver only currently supports css selectors for elements node.

You would do the following (noting that the to_subtype is to convert it back to a TableRow rather than Element):

puts b.element(:css, "tr.datarow2_sm + tr").to_subtype.text 

Update

If you want to get the second cell in that next row, you can do one of the following:

puts b.element(:css, "tr.datarow2_sm + tr").to_subtype[1].text  
puts b.element(:css, "tr.datarow2_sm + tr").td(:index, 1).text

Accessing an element with no attributes in Watir

Disregarding the non-WATIR issues of having tags in the first place, or requesting unique attributes from your developers (or yourself), you can always access an element via its parent elements, or by index.

For example:


Text

@browser.div(:name => "content").span(:index => 1)
#this is the first span element inside this div

You can work through however many unique elements you need to before reaching the child span element, without using Xpath. Of course, you only need one unique parent element to reach that specific child element, and you work down from that to the child.

div(:how => what).table(:how => what).td(:how => what).span(:how => what).text

Another example, assuming it is the nth span on the page:
@browser.span(:index => n)

The by-index approach is very brittle and prone to breaking when any update is made to the page, however.

How to traverse DOM (children/siblings) using watir-webdriver?

Watir implements an :index feature (zero-based):

browser.div(id: 'foo').divs           # children
browser.div(id: 'foo').div(index: 6) # nth-child
browser.div(id: 'foo').parent # parent
browser.div(id: 'foo').div # first-child
browser.div(id: 'foo').div(index: -1) # last-child

next_sibling and previous_sibling are not currently implemented, please make a comment here if you think it is necessary for your code: https://github.com/watir/watir/pull/270

Note that in general you should prefer using indexes to using collections, but these also work:

browser.div(id: 'foo').divs.first
browser.div(id: 'foo').divs.last

Paperback code example (are you looking to select by text or obtain the text?):

browser.li(text: /Paperback/)  
browser.td(class: "bucket").li
browser.table(id: 'productDetailsTable').li

We've also had requests in the past to support things like direct children instead of parsing all of the descendants: https://github.com/watir/watir/issues/329

We're actively working on how we want to improve things in the upcoming versions of Watir, so if this solution does not work for you, please post a suggestion with your ideal syntax for accomplishing what you want here: https://github.com/watir/watir/issues and we'll see how we can support it.

How to get ID of an element using Watir where the child contains the string i search for

Your attempt was close. The problem is that span.parent only goes up to the <div class="resTitle">. You need to go up one more parent:

@b.div(:id, "corporaContainer").spans(:text => /corpora/).each do |span|
puts span.parent.parent.attribute_value("id")
end

(Note that I changed the text in the locator of the spans since TestAuto\s.* did not match the sample html.)

Alternatively, I sometimes find it better to find the divs that contain the span. This way you do not have to worry about the number of parents changing:

p @b.divs(:class => 'resItem')
.find_all { |div| div.span(:text => /corpora/).exists? }
.collect { |div| div.id }
#=> ["c-a06ffa6a-dc62-4640-9760-dbd661c7ffe8"]

Below is a working example. Note that there are 2 important things:

  • The list of results is loaded asynchronously. Therefore you need to wait for the list to finish loading before capturing the results. sleep(5) might work, but you are better off using an actual wait method (since it seems to take longer than 5 seconds).
  • Make sure the search text actually exists on the page. In the below example, there is no "12321 corpora" title that was mentioned in the sample html.

Example:

require 'watir-webdriver'

# Title to search for:
title_text = /UniAdm/

# Go to the Corpora page:
@b = Watir::Browser.new :ff
@b.goto "https://www.letsmt.eu/Corpora.aspx"

# Wait for the results to load:
container = @b.div(:id, "corporaContainer")
container.div(:class => 'resItem').wait_until_present

# Find the matching ids:
p container.divs(:class => 'resItem')
.find_all { |div| div.span(:class => 'theText', :text => title_text).exists? }
.collect { |div| div.id }
#=> ["c-87ee80a9-e529-48b2-92be-bc8d76375478", "c-f139e781-4789-41f9-82e8-914e0e3eff81", "c-e17641d2-9364-4e87-9047-ba35580dc32f"]

How to get ID of an element using Watir where the child contains the string i search for

Your attempt was close. The problem is that span.parent only goes up to the <div class="resTitle">. You need to go up one more parent:

@b.div(:id, "corporaContainer").spans(:text => /corpora/).each do |span|
puts span.parent.parent.attribute_value("id")
end

(Note that I changed the text in the locator of the spans since TestAuto\s.* did not match the sample html.)

Alternatively, I sometimes find it better to find the divs that contain the span. This way you do not have to worry about the number of parents changing:

p @b.divs(:class => 'resItem')
.find_all { |div| div.span(:text => /corpora/).exists? }
.collect { |div| div.id }
#=> ["c-a06ffa6a-dc62-4640-9760-dbd661c7ffe8"]

Below is a working example. Note that there are 2 important things:

  • The list of results is loaded asynchronously. Therefore you need to wait for the list to finish loading before capturing the results. sleep(5) might work, but you are better off using an actual wait method (since it seems to take longer than 5 seconds).
  • Make sure the search text actually exists on the page. In the below example, there is no "12321 corpora" title that was mentioned in the sample html.

Example:

require 'watir-webdriver'

# Title to search for:
title_text = /UniAdm/

# Go to the Corpora page:
@b = Watir::Browser.new :ff
@b.goto "https://www.letsmt.eu/Corpora.aspx"

# Wait for the results to load:
container = @b.div(:id, "corporaContainer")
container.div(:class => 'resItem').wait_until_present

# Find the matching ids:
p container.divs(:class => 'resItem')
.find_all { |div| div.span(:class => 'theText', :text => title_text).exists? }
.collect { |div| div.id }
#=> ["c-87ee80a9-e529-48b2-92be-bc8d76375478", "c-f139e781-4789-41f9-82e8-914e0e3eff81", "c-e17641d2-9364-4e87-9047-ba35580dc32f"]

How do I access unidentified nested menu elements using watir and firefox?

The error is correct since you have no link tag in that code with a class of sub-level. The things with that class are li (List Item) elements which contain link elements (aka 'anchor' hence the a tag)

Try something like this (depending on which link you want to click)

browser.li(:class => 'sub-level', :text => 'Assessments').link.click
browser.li(:class => 'sub-level', :text => 'Main').link.click

For more on ways to identify elements, especially if they do not have a handy ID, Class etc, see the answers to this SO question: How to get index of parent element using Watir Webdriver? and the answers (all three) to this question also: Accessing an element with no attributes in Watir

Cant get text of a TD by index

I am guessing that the problem is the header row in the thead. The table head is probably something like:

<thead>
<tr id="0">
<th class>heading1</th>
<th class>heading2</th>
<th class>heading3</th>
<th class>heading4</th>
</tr>
<thead>

Notice that there is a tr. table.rows will therefore include the header row. Also notice that it is using th instead of td cells. It is likely here that watir cannot find the td with index 2, because there are no tds at all in this row.

Assuming this is the problem, you have a couple solutions.

Solution 1 - Make th and td equivalent by using cells

Inside the loop, use cell instead of td:

rows.each {|tr| 
if tr.cell( :index =>2).text == string #Note the change here
puts " Found #{string}"
string="cellK"
end
}

Table#cell matches td and th cells. This means that cell(:index, 2) would match the 3rd td or th in the row. When watir checks the header row, it will now find a value.

Solution 2 - Ignore the thead

When getting the rows to check, confine the rows collection to only include rows in the tbody:

rows = browser.table.tbody.rows

This would then ignore the riws in the thead that are causing the problem.



Related Topics



Leave a reply



Submit