Nigel Smith
Nigel Smith

Reputation: 143

Watir: How do I find an element where the class of that element and the class of one of its parents identifies it?

I've got html like

<div class="header"><div class="title">AAAAAAAAA</div></div>
<div class="body">
  <div class="card"><div class="xxx"><div class="yyy"><div class="title">AAAAAAAAA</div></div></div></div>
  <div class="card"><div class="xxx"><div class="yyy"><div class="zzz"><div class="title">BBBBBBBBB</div></div></div></div></div>
</div>

What I need to do to say (through watir-webdriver) "get me the element with class of 'title' and with text 'AAAAAAAAA' that is a child of an element with class 'card'". In this example, I want to find the div with class 'title' on the third line.

Its not enough to say "give me the element with text 'AAAAAAAAA' and class of 'title'" because that element may exist somewhere else in the DOM. I have to be able to identify it by its attributes, and its parents.

I'm not sure how to do this, and would really love some suggestions.

In watir-webdriver, if I write:

b.element(:class => "card").element(:class => "title", :text => "BBBBBBBBB")

Then, from what I have seen, nothing will be found, as element(:class => "card") will match the first card element, on line 3, and then the match for BBB... text will fail, because its only AAA... thats available under the first card.

I though of doing something like

b.elements(:class => "card").each { |elem| ...etc }

to find the child element I'm after, but when I find the child element, I can't use it easily. For instance, I want to be able to call visible? on it, but the result is hard to get out of that code block. I could have a local variable that I assign the visible? result to, or I could throw an error from within the block, but its not really what I'm after.

What I'm really after is:

b.elements(:class => "card").element(:class => "title", :text => "BBBBBBBBB").othermethods...

So the first method call finds all elements with class of card, and then in the second method it finds the first element under those cards that has class "title" and text "BBBBBBBBB". I know that there will be only one element with class 'title' and text "BBBBBBBBB" under a card.

However this functionality doesn't exist. Is there an easy way to achieve the same thing? I'd really appreciate a bit of guidance here. Thanks in advance.

Upvotes: 4

Views: 5326

Answers (1)

Abe Heward
Abe Heward

Reputation: 515

I won't be surprised if Justin or Željko come up with a better solution for you (and if they do then I'd like to know what it is, myself!), but here's something that, while ugly, should suffice:

target_parent_div = b.divs(class: "card").find { |div| div.div(class: "title", text: "AAAAAAAAA").exists? }
target_element = target_parent_div.div(class: "title", text: "AAAAAAAAA")

...Then use target_element for whatever you need.

Upvotes: 3

Related Questions