Search code examples
ruby-on-railscheckboxcapybarapoltergeist

Capybara (poltergeist) cannot find checkbox in form


I cannot get Capybara for find a checkbox element.

I've tried all the usual ways:

find_field
check
find
click_on

It's as if the element isn't there. If I select the parent element, and look at it's innerHTML the checkbox is included:

(byebug) all(:css, '.checkbox.form-group').last['innerHTML']
\n    <input type=\"checkbox\" id=\"google_agreed_to_terms_at\" value=\"1\" required=\"true\" ng-model=\"agreed_to_terms\" required-notification=\"Please agree to the terms and conditions\" class=\"ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required\" bs-validation=\"\">\

but selecting the child elements it's not there:

(byebug) all(:css, '.checkbox.form-group').last.all :xpath, './*'
[#<Capybara::Node::Element tag="label" 
path="//HTML[1]/BODY[1]/DIV[2]/DIV[1]/DIV[2]/FORM[1]/DIV[1]/LABEL[1]">]

I feel like I'm going mad.

Here's the relevant code (copied from save_and_open_page)

<div class="checkbox form-group">
  <input type="checkbox" id="agreed_to_terms_at" value="1" required="true" ng-model="agreed_to_terms" required-notification="Please agree to the terms and conditions" class="ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" bs-validation="">
  <label class="label-light" for="agreed_to_terms_at">
     I have read and agree to the terms</label>
</div>

I thought maybe rails was generating slightly non-compliant HTML, so I've gone to writing the checkbox by hand, but it didn't help.

What's going on here?


Solution

  • The checkbox is hidden to allow for uniform styling across all browsers. Since you have a label element correctly associated you can tell check to click the label instead of the actual checkbox

    check('agreed_to_terms_at', allow_label_click: true)
    

    which will click the checkbox if visible and if not it will click the label. If you want it to only click the label you can do

    find(:label, 'I have read and agree').click
    

    Or

    find(:label, for:'agreed_to_terms_at').click