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
Equal Width Columns in CSS Grid
How to Detect "​" (Combination of Unicode) in C++ String
Fixed Header, Footer, and Sidebars with Scrolling Content Area in Center
Hiding The Toolbars Surrounding an Embedded Pdf
How to Center Multiple Divs Inside a Container in CSS
Removing Unwanted Table Cell Borders with CSS
How to Remove The Default Link Color of The HTML Hyperlink 'A' Tag
Ticks for Type="Range" HTML Input
Can Websocket Messages Arrive Out-Of-Order
What Does The Question Mark at Then End of a CSS Include Url Do
Mobile Website "Whatsapp" Button to Send Message to a Specific Number
Apply Border-Radius to Scrollbars with CSS
How to Center Content in a Bootstrap Column
How to Display a Range Input Slider Vertically
How to Insert HTML Content in Xml Document