Capybara: Calling #fill_in on a fillable_field Capybara::Node::Element doesn't work

Created on 4 Oct 2017  路  7Comments  路  Source: teamcapybara/capybara

Meta

  • Capybara Version:

    • 2.15.1

  • Driver Information (and browser if relevant):

    • selenium-webdriver 3.6.0

    • Chrome 61.0.3163.100 (Official Build) (64-bit)

    • ChromeDriver 2.32.498513

Expected Behavior

Field should be filled.

Actual Behavior

Raises Capybara::ElementNotFound Exception: Unable to find visible field nil that is not disabled

Steps to reproduce

When(/\AI populate "([^"]*)" with "([^"]*)"\z/) do |field_locator, value|
  field = find_field(field_locator)
  if field.matches_selector?(:fillable_field)
    field.fill_in(:with => value)
  elsif field.matches_selector?(:checkbox)
    if [ '0', '', 'nil', 'false', 'unchecked', 'no' ].include?(value.to_s.downcase)
      field.uncheck
    else
      field.check
    end
  elsif field.matches_selector?(:radio_button)
    field.choose(value)
  elsif field.matches_selector?(:select)
    field.select(value)
  elsif field.matches_selector?(:file_field)
    field.attach_file(File.expand_path(value))
  else
    warn "Unknown field type for #{field.inspect}."
    field.set(value)
  end
end

When(/\AI populate "([^"]*)" with the following:\z/) do |form, fields|
  within(form) do
      fields.rows_hash.each do |name, value|
      step %{I populate "#{name}" with "#{value}"}
    end
  end
end
  Given I populate "#new_user_session" with the following:
    | user_session_email    | [email protected] |
    | user_session_password | password        |

Suspected problem in Capybara

This error occurs to be occurring because the #fill_in method runs find(:fillable_field, locator, options) in the context of the element and find appears to only look at descendants of the current element (of which there are obviously none). Intuitively, however, #fill_in should performed on the current object given the way I invoke it.

NB: I imagine similar issues also exist in the other form fill methods invoked in my (not yet fully tested) step definition.

All 7 comments

Looking into this more, one could argue I should be using the #set method for everything, but this is rather unintuitive considering I can't use it for <select>s, and #check, #uncheck and #choose have added functionality with regard to the :allow_label_click option that I would have to duplicate, should I need it.

@mvastola This isn't an issue in Capybara, you're just using it wrong. As you stated, if you have already located the element you want to interact with , you call set on it (which you can call on checkboxes, etc with true or false). fill_in as documented - http://www.rubydoc.info/gems/capybara/Capybara/Node/Actions#fill_in-instance_method - finds a field a fills it in, it doesn't act on the current scope element

Why you would ever write a cucumber step as

Given I populate "some_check_box_id" with "unchecked"

is beyond me though.

If you really want the step you've defined you could just change it to call the methods with the field_locator - e.g. instead of field.fill_in(with: value) do fill_in(field_locator, with: value) although you're going a long way to generalize cucumber steps that really shouldn't be.

Haha. I wouldn't write

Given I populate "some_check_box_id" with "unchecked"

in long form, but I wrote the step to work with checkboxes too so I could fill in a whole web form (checkboxes included) if I supply the inputs in the tabular format.

Anywho, I can accept I'm not using it as it was intended. It just seemed a bit unintuitive because you'd think calling #fill_in on an object of a class literally named Element would let you fill in said element. Not a huge deal though.

@mvastola This isn't an issue in Capybara, you're just using it wrong. As you stated, if you have already located the element you want to interact with , you call set on it (which you can call on checkboxes, etc with true or false). fill_in as documented - http://www.rubydoc.info/gems/capybara/Capybara/Node/Actions#fill_in-instance_method - finds a field a fills it in, it doesn't act on the current scope element

The documentation must've been updated since this was written, because now it shows two examples:

# will fill in a descendant fillable field with name, id, or label text matching 'Name'
page.fill_in 'Name', with: 'Bob'

# will fill in `el` if it's a fillable field
el.fill_in with: 'Tom'

So el.fill_in with: 'Tom' should work but it doesn't, at least for me (using Capybara 2.18.0)

Looks like 3.7.0 introduced support for calling fill_in on the current element.

@dpashkevich You're using 2.18 and looking at the docs for 3.13.x, there are big differences between those two versions. The ability to call fill_in on the element you want filled in was added in 3.7

Nevermind - you apparently figured that out --- 2.18 was released a year ago -- it's pretty obsolete at this point

Was this page helpful?
0 / 5 - 0 ratings