Search code examples
ruby-on-railscapybararspec-rails

How to get Capybara to check a checkbox by its label


Capybara is not finding my checkbox's label, and I know I'm referencing it correctly by it's label. What am I doing wrong, or is this a bug in Capybara?

According to http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions:check, "The check box can be found via name, id or label text."

Here's the section of my request spec I ran:

describe "with valid information" do   

it_should_behave_like "all item pages"

before { valid_create_item }

it "should create an item" do
    expect { click_button submit }.to change(Item, :count).by(1)
end

describe "after saving the item" do
    before { click_button submit }

    it { should have_link('Sign out') }
    it { should have_selector('h1', text: "Items") }
    it { should have_title("Items") }
    it { should have_success_message }
end      

describe "and options selected" do

    before do
        puts page.html
        check('Option 1')
        click_button "Save changes"
    end

    it { should have_title("Items") }
    it { should have_success_message }
    it { should have_link('Sign out', href: signout_path) }
    specify { expect(item.reload.options.find_by_name("Option 1")).to eq true }
end

And here's a gist of the resulting test, including the html generated for the page: https://gist.github.com/anonymous/11270055

According to the test results, Capybara couldn't find the checkbox labelled "Option 1", when it's clearly in the generated html.

As a sidenote, I've also noticed I can fill in a form by it's label with Capybara only when I let the rails FormHelper display a field's default label text.

For example: The FormHelper label text for a field called "email_address" appears as "Email address", and fill_in "Email address", with: "blahblah@blah.com" works. If I don't use the FormHelper to generate the label, and instead make the label "Email", fill_in "Email", with: "blahblah@blah.com" doesn't work, because Capybara can't find the field labeled "Email". It seems this behavior is consistent with all form elements (or at least with text fields and checkboxes -- the only ones I've tested so far).


Solution

  • The html for Option 1 looks like:

    <label class="control-label" for="__Option:0x000001061be660_">Option 1</label>
    <div class="controls">
      <input id="options_" name="options[]" type="checkbox" value="1" />
    </div>
    

    The problem is that the label and checkbox are not properly associated with each other:

    • The label has a for attribute of "__Option:0x000001061be660_"
    • The checkbox has an id attribute of "options_"

    As a result, Capybara finds the label "Option 1", but not one that is associated to a checkbox.

    The page needs to be updated so that the label for attribute and checkbox id attribute match. For example:

    <label class="control-label" for="__Option:0x000001061be660_">Option 1</label>
    <div class="controls">
      <input id="__Option:0x000001061be660_" name="options[]" type="checkbox" value="1" />
    </div>