Reputation: 4906
What is the proper way to uncheck a checkbox in Capybara integration tests? I have a list of checkboxes that I need to uncheck. I have selected them all using all
:
checkboxes = all("input[type='checkbox']")
In order uncheck each one I use each
. According to the information I have found on the StackOverflow there should be three ways to uncheck a checkbox:
uncheck(field)
field.click
field.set(false)
In order to test whether these different methods I created the following tests (each of these was in a separate scenario on the same page):
Using uncheck
it succeeded:
checkboxes = all("input[type='checkbox']")
checkboxes.each { |field| expect(field.checked?).to eq("checked") }
checkboxes.each { |field| uncheck(field[:id]) }
checkboxes.each { |field| expect(field.checked?).to eq(nil) }
puts page.body
save_and_open_page
Using click
it failed, so I assume this is an improper way of unchecking the field:
checkboxes = all("input[type='checkbox']")
checkboxes.each { |field| expect(field.checked?).to eq("checked") }
checkboxes.each { |field| field.click }
checkboxes.each { |field| expect(field.checked?).to eq(nil) }
puts page.body
save_and_open_page
Using set(false)
it succeeded:
checkboxes = all("input[type='checkbox']")
checkboxes.each { |field| expect(field.checked?).to eq("checked") }
checkboxes.each { |field| field.set(false) }
checkboxes.each { |field| expect(field.checked?).to eq(nil) }
puts page.body
save_and_open_page
I figured I would just use uncheck
, but then I noticed something strange: the page.body still showed the checkbox as checked, even though I had asserted in the test that checked?
was nil. save_and_open_page
showed the same thing. It appeared as if the checkboxes had not changed since the page was loaded.
Questions:
uncheck
and set(false)
altering the form HTML? In
order form my test to pass some element associated with field
had
to be unchecked. Is there some disconnect between page.body
and
what uncheck
deals with?uncheck
is part of the API and is easy to use it seems to be the proper function to call for this sort of thing, but the fact that it's not changing page.body
concerns me.Related questions:
Thanks in advance!
Upvotes: 3
Views: 4473
Reputation: 49880
Capybara implements #uncheck
as find(...).set(false)
so calling set(false)
on an existing element or uncheck
with a locator string are doing the same thing to the element, and will leave a box unchecked if it was already unchecked. If you are using a JS capable driver (not the default rack-test driver) calling #click
on a checkbox will toggle the state (unless some JS is capturing/blocking the clicks), so if you want the box unchecked you want to be using uncheck
or set(false)
As for why it doesn't update the html, you are experiencing the difference between html attributes and properties. Calling uncheck
on the box changes the 'checked' property of the element, but that won't change the attribute (attribute remains at initial state, property is current state). That is expected and correct, the property is what gets submitted with your form.
Note: the fact that #checked? is returning "checked" rather than true
for the rack_test driver is a bug, and will be fixed in the next Capybara release. You should be using something like expect(field).to be_checked
rather than eq('checked') to not have issues in the future
Note: save_and_open_page - saves the html (attribute) and then loads it - it does not save the properties of elements, so it very well may show checkboxes in a state that they aren't actually in during the test
Upvotes: 8