Jesse Novotny
Jesse Novotny

Reputation: 730

How to test field visibility with Capybara?

Note: This question is about using Capybara 1.1.2, not current versions.

I have a hidden text field, and a button which make it visible.

hidden text field:

<input type="text" name="Franchise Name" id="new_franchise_name" placeholder="Franchise Name" style="display:none;" />

button and js event handler which makes the the above field visible:

<button class="btn btn-medium" id="create_franchise" data-remote="true" >Create New Franchise</button>

$('#create_franchise').click(function(){
  $('#new_franchise_name').css('display', 'inline-block');
}

In my test, I have the following:

page.all('#new_franchise_name') #=> returns array with text input
Capybara.ignore_hidden_elements = true
page.all('#new_franchise_name') #=> returns empty array as expected
page.find_button('Create New Franchise').click #=> sets the input css "display:inline-block"
page.all('#new_franchise_name') #=> still returns empty array. Should include the text field

I've explored a few other methods but this seems to be the most straight-forward... except that it doesn't work. Any suggestions?

Upvotes: 0

Views: 2711

Answers (1)

Thomas Walpole
Thomas Walpole

Reputation: 49870

Note: This answer is for current (2.14.3 currently) releases of Capybara. It only came out after discussion that the OP is using Capybara 1.1.2 where behavior was significantly different

A couple of things

  1. If you're testing an app, never change Capybara.ignore_hidden_elements (just leave it at the default of true), use the visible option on the queries where you want Capybara to "see" non-visible elements. page.find('#new_franchise_name', visible: :all)

  2. Stay away from all in favor of find when you want a single element (which anything with an id should be). all has a number of shortcomings, not the least of which is that it won't wait for elements to appear unless you pass one of the count options. (first has the same shortcomings)

  3. When testing use the assertions/expectations rather than find when you don't need the element for anything else

Taking these into account your test should be written as

expect(page).not_to have_css('#new_franchise_name')  # or  .to have_no_css(...)
page.click_button('Create New Franchise')
expect(page).to have_css('#new_franchise_name')

If for some reason you have changed the default setting of Capybara.ignore_hidden_elements to false then the test could be written as

expect(page).not_to have_css('#new_franchise_name', visible: true)  # or  .to have_no_css(...)
page.click_button('Create New Franchise')
expect(page).to have_css('#new_franchise_name', visible: true)

Upvotes: 1

Related Questions