Capybara not finding form elements

2019-02-25 09:38发布

问题:

It is the first time I'm trying out Capybara, and I can't seem to find why it can't find my form elements.

Every time I try to find a form element,

When /^they submit a resolution in Markdown$/ do
  visit "/resolutions/new"
  fill_in "title", :with => "Title"
  fill_in "libelle", :with => "Some text here\n\nNew paragraph"
  click_button "Submit"
end

it has no clue where it is,

Scenario: Submission of a resolution                 # features/resolutions.feature:5
    Given the user is a member                       # features/step_definitions/user_steps.rb:26
    When they submit a resolution in Markdown        # features/step_definitions/resolution_steps.rb:8
      cannot fill in, no text field, text area or password field with id, name, or label 'title' found (Capybara::ElementNotFound)
      (eval):2:in `fill_in'
      ./features/step_definitions/resolution_steps.rb:10:in `/^they submit a resolution in Markdown$/'
      features/resolutions.feature:7:in `When they submit a resolution in Markdown'

even though it is present on the page

<%= form_for(@resolution) do |f| %>
  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :libelle %><br />
    <%= f.text_area :libelle %>
  </div>
  <div class="actions">
    <%= f.submit "Submit" %>
  </div>
<% end %>

and it seems to have rendered correctly.

Started GET "/resolutions/new" for 127.0.0.1 at 2012-07-06 00:47:24 -0400
  [1m[36m (0.0ms)[0m  [1mSAVEPOINT active_record_1[0m
  [1m[35m (0.2ms)[0m  UPDATE "users" SET "last_sign_in_at" = '2012-07-06 04:47:24.980196', "current_sign_in_at" = '2012-07-06 04:47:24.980196', "last_sign_in_ip" = '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = '2012-07-06 04:47:24.980658' WHERE "users"."email" = 'alexandre@membres.jndq.ca'
  [1m[36m (0.0ms)[0m  [1mRELEASE SAVEPOINT active_record_1[0m
Processing by ResolutionsController#new as HTML
  Rendered resolutions/_form.html.erb (3.8ms)
  Rendered resolutions/new.html.erb within layouts/application (4.9ms)
Completed 200 OK in 18ms (Views: 7.9ms | ActiveRecord: 0.2ms)
  [1m[35m (0.2ms)[0m  rollback transaction
  [1m[36m (0.0ms)[0m  [1mbegin transaction[0m
  [1m[35m (0.0ms)[0m  SAVEPOINT active_record_1
  [1m[36mUser Exists (0.1ms)[0m  [1mSELECT 1 FROM "users" WHERE "users"."email" = 'normand@pq.ui' LIMIT 1[0m
  [1m[35mSQL (0.3ms)[0m  INSERT INTO "users" ("authentication_token", "clearance", "confirmation_sent_at", "confirmation_token", "confirmed_at", "created_at", "current_sign_in_at", "current_sign_in_ip", "email", "facebook_uid", "id", "last_sign_in_at", "last_sign_in_ip", "name", "parent", "remember_created_at", "sign_in_count", "unconfirmed_email", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["authentication_token", nil], ["clearance", 9], ["confirmation_sent_at", nil], ["confirmation_token", nil], ["confirmed_at", nil], ["created_at", Fri, 06 Jul 2012 04:47:25 UTC +00:00], ["current_sign_in_at", nil], ["current_sign_in_ip", nil], ["email", "normand@pq.ui"], ["facebook_uid", nil], ["id", nil], ["last_sign_in_at", nil], ["last_sign_in_ip", nil], ["name", "Normand Portequi"], ["parent", nil], ["remember_created_at", nil], ["sign_in_count", 0], ["unconfirmed_email", nil], ["updated_at", Fri, 06 Jul 2012 04:47:25 UTC +00:00]]
  [1m[36m (0.0ms)[0m  [1mRELEASE SAVEPOINT active_record_1[0m

It seems something obvious, but I can't find it. I had found this question, but the answer was quite useless. Even after reviewing the Devise+Cucumber example app, I can't find what's wrong.

This is killing me and my tests. Any ideas?

回答1:

Try adding puts page.body after visit "/resolutions/new" and see what your stack trace tells you. You'll be able to see the id of the form fields. For example, although one of my columns is called "name", the id in the rendered html is "user_name".



回答2:

I was having a similar problem and it turns out that what I needed to do was add the "id:" field to the form element itself.

For example, you have:

<div class="field">
  <%= f.label :title %><br />
  <%= f.text_field :title %>
</div>

But if you change it to:

<div class="field">
  <%= f.label :title %><br />
  <%= f.text_field :title, id:"title" %>
</div>

Note that I added an "id" field on the text_field element. I'm not sure why Capybara didn't find the label, but this is what worked for me. Hope it helps you (or someone else).



回答3:

This is a wild guess, but I think you need to wait. Not sure if 'fill_in' waits for the page to be available. I know 'find' waits automatically.

Try increasing

Capybara.default_wait_time


回答4:

If your Rails view looks like this:

<%= form.text_field :first_name %>

Try calling the element by capitalizing the first portion followed by a space and then lowercasing the rest.

fill_in "First name", with: 'Elaine'

This should do it, no id attribute necessary.