3
votes

I have been trying to set up Capybara to test a form but I keep getting the error
cannot fill in, no text field, text area or password field with id, name, or label 'Name' found

Here is what I have in my view:

<%= form_for(@user) do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  ...
  <%= f.submit "Create Account", class: "btn btn-large btn-primary" %>
<% end %>

which renders the following html:

<label for="user_name">Name</label>
<input id="user_name" name="user[name]" size="30" type="text" />

So it seems like it should be finding the field based on the label.

Here is what my user_pages_test.rb file has (I am using Test::Unit and shoulda-context):

context "sign up page" do
  should "add user to database when fields are filled in" do
    fill_in "Name", with: "Bubbles"
    ...
    click_button "Create Account"
  end
end

Here is what I've tried so far:

1) changing the call to fill_in to match the id with fill_in "user_name", with: "Bubbles"
2) changing the call to fill_in to page.fill_in "Name", with: "Bubbles" to match the example in the documentation
3) changing the view to manually add the id "Name" with <%= f.text_field :name, id: "Name" %> (this answer)
4) changing the call to get sign_up_path to get "/sign_up" (in case it was an issue with the routing)

All these still give me the same error, which makes me think that the page isn't being loaded correctly for some reason. However, I have a different (passing) test in the same context that asserts the page has the correct title, so I know the page does get loaded correctly (in the setup).

Based on this (and according to this answer), it seems like the problem might just be that the fill_in method isn't waiting for the page to load before trying to access the fields. According to this suggestion, I added the line puts page.body in my test to see that the HTML was being loaded completely before it was trying to fill in the fields, and got the following output:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

So, I was pretty sure that fill_in just wasn't waiting for the page to load. I then tried

5) changing the Capybara.default_wait_time according to this answer, but this had no effect. I tried setting it in the ActionDispatch::IntegrationTest class in the test_helper file (where Capybara is included), and also in the test itself.

Then I tried adding puts page.body in the passing test (both before and after it asserts the correct title), and I got the same output. THEN, I found this answer, and finally got the console to print out the page's HTML. I tried one more thing to get Capybara to fill in the fields:

6) changed the call to fill_in to say @response.fill_in, since @response seems to do what I thought the page variable was supposed to do.

So, I have two questions about this:

1) What does the page variable actually refer to? The doctype declaration for my app is just <!DOCTYPE html>, so I have no idea where it gets the old one from.

2) Why isn't Capybara able to find/fill_in these fields?

1
does it help to visit the page before filling in? it has solved similar issues for me but I haven't figured out why.... :-)froderik
also - what driver are you using? the form isn't loaded dynamically?froderik
If this is the signup form, is there any chance you have these fields/ids repeated (perhaps hidden) on the page as a login form? If there's another field with these values Capybara may have trouble.cjspurgeon
I would try adding this as the first line of your test: Capybara.current_driver = Capybara.javascript_driver and then putting a sleep 10 right before the fill_in line. That should make the test run in a firefox window using selenium and you can look at the page to make sure the fields are visible.cjspurgeon
@froderik - yep, that's exactly what I needed to do. I didn't think I needed it with a call to get sign_up_path in the setup. If you submit this as an answer I'll accept it (you should probably link to this question, which links to this helpful article. The fifth paragraph in that article also explains why page.body wasn't working for me).bentrevor

1 Answers

1
votes

You need to use the visit method to get the page object setup properly. The capybara documentation indicates that '/' is visited by default and if you want to visit some other page you need to do an explicit call. It may also be helpful to read a bit about the difference between visit and get.