How does fill_in work in Rspec/Capybara?

2019-02-21 13:17发布

问题:

I am following Michael Hartl's Ruby on Rails Tutorial. When I use rspec/capybara, the fill_in method makes me confused. I have the following view code:

 <%= f.label :name %>   
 <%= f.text_field :name %>

This is my testing code:

 fill_in "Name", with: "Example User"

It seems that label and text_field are both required for fill_in to locate the input field. If I either take off f.label or change <%= f.text_field :name %> to be <%= f.text_field :another_name %>, the test will give me ElementNotFound error. Can anyone explain how the fill_in works here? Are input field and label both required for fill_in method?

回答1:

It is stated that fill_in looks for field name, id or label text. According to ActionView::Helpers::FormHelper section of rails guides, the view code which you ask about should be translated to the following html code:

# I assume that you made a form for a @user object
<label for="user_name">
  Name
</label>
<input id="user_name" name="user[name]" type="text" />

As you see, label produced the "Name" text, which you ask for inside of your fill_in expression. But id and name properties of input field are slightly different, so you should have been using id based selector to achieve the same result:

fill_in "user_name", with: 'Example User'

So, to sum up, label field is not required, but you should watch for your html code carefully and select the appropriate parameters for fill_in expression.



回答2:

Just to add to what twonegatives posted. Here's what the capybara docs say for the fill_in() method:

The field can be found via its name [attribute], id [attribute,] or label text

http://rubydoc.info/github/jnicklas/capybara/Capybara/Node/Actions:fill_in

When I delete the 'Name' label, I can use any of the following and the tests still pass:

 fill_in 'user_name',   with: "Example User"  #locate text field by id attribute
 fill_in :user_name,    with: "Example User"  #locate text field by id attribute

 fill_in 'user[name]',  with: "Example User"  #locate text field by name attribute
 fill_in :'user[name]'  with: "Example User"  #locate text field by name attribute

In ruby, some characters cannot be used in a symbol name unless the whole symbol is quoted.

Capybara must be retrieving all the text fields (or text areas) from the page, then getting the values of the id and name attributes(easily done with something like Nokogiri) then checking if either value is equal to the first argument to fill_in() (after converting the first argument to a String via to_s()).



回答3:

I provided my 2 cents here: Capybara not finding form elements.

If you call the Rails text_field helper with underscore (:first_name), the DOM gets rendered as "First name" and its what Capybara will need. No need for an id attribute.

View: <%= form.text_field :first_name %>

Test: fill_in "First name", with: 'Elaine'