Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capybara: how to find a class by using multiple attributes inside class

Tags:

capybara

I want to find first class which includes a particular text(name in this case) and button enabled inside it.

I have my source like this

 <div class="some parent class"> 
         <div class="class" id="1">
               <div class="some other name">......</div>
               <div class="button enabled">......</div>
            </div>
          <div class="class" id="2">
               <div class="name">......</div>
               <div class="button disabled">......</div>
            </div>
            <div class="class" id="3">
               <div class="name">......</div>
               <div class="button enabled">......</div>
            </div>

</div> 

I have tried

first('.class',text: 'name')

it finds first class with name but disabled button ofcourse. Then I have tried

first('.class',text: 'name', text: 'button text')

but it looks like it applies OR operator between text parameters and finds class with id 1. Is there a way to apply AND operator between text parameters or any other way to find class in which it has particular text and a button present. Also want to mention that position of these classes can be random so can not say that find last class simply.

like image 837
waqas Avatar asked Jan 30 '26 01:01

waqas


2 Answers

You could find all of the div tags that have the specified text. Then iterate through those to find the first one that also includes the enabled button:

all('.class', text: 'name').find { |div| div.has_css?('div.button.enabled') }

You might get better performance by using a single XPath expression. However, it is rather unwieldy and not likely worth the effort:

first(
  :xpath,
  '//div
    [contains(concat(" ", @class, " "), " class ")]
    [.//text()[contains(., "name")]]
    [.//div
      [contains(concat(" ", @class, " "), " button ")]
       [contains(concat(" ", @class, " "), " enabled ")]]'
)
like image 91
Justin Ko Avatar answered Jan 31 '26 20:01

Justin Ko


If you just want to match on the text contained you can use a regex for the text option

find('.class', text: /name.*button text/)

If you want to make sure it includes an actual button element and you're using Capybara v2.10+ you can use a filtering block with something like

find('.class', text: 'name'){ |node| node.has_button?('button text', wait: 0) }
like image 20
Thomas Walpole Avatar answered Jan 31 '26 18:01

Thomas Walpole



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!