Capybara::ElementNotFound: Error

2019-06-05 05:33发布

问题:

i am following railstutorial.org tutorial i am getting the following error

  1) User pages signup with valid information should create a user
     Failure/Error: fill_in "password" , with: "foobar"
     Capybara::ElementNotFound:
       cannot fill in, no text field, text area or password field with id, name, or label 'password' found
     # (eval):2:in `fill_in'
     # ./spec/requests/user_pages_spec.rb:32:in `block (4 levels) in <top (required)>'

  2) Authentication signin with invalid information 
     Failure/Error: before { click_button "Sign in" }
     Capybara::ElementNotFound:
       no button with value or id or text 'Sign in' found
     # (eval):2:in `click_button'
     # ./spec/requests/authentication_pages_spec.rb:14:in `block (4 levels) in <top (required)>'

  3) Authentication signin with invalid information 
     Failure/Error: before { click_button "Sign in" }
     Capybara::ElementNotFound:
       no button with value or id or text 'Sign in' found
     # (eval):2:in `click_button'
     # ./spec/requests/authentication_pages_spec.rb:14:in `block (4 levels) in <top (required)>'

  4) Authentication signin with invalid information after visiting another page 
     Failure/Error: before { click_button "Sign in" }
     Capybara::ElementNotFound:
       no button with value or id or text 'Sign in' found
     # (eval):2:in `click_button'
     # ./spec/requests/authentication_pages_spec.rb:14:in `block (4 levels) in <top (required)>'

Finished in 3.67 seconds
46 examples, 4 failures

and my authentication_pages_spec.rb

require 'spec_helper'

describe "Authentication" do

  subject { page }

  describe "signin page" do
    before { visit signin_path }
    it { should have_selector('h1', text: 'Sign in') }
    it { should have_selector('title', text: 'Sign in') }
  end

  describe "signin" do
    before { visit signin_path }
    describe "with invalid information" do
      before { click_button "Sign in" }
      it { should have_selector('title', text: 'Sign in') }
      it { should have_selector('div.alert.alert-error', text: 'Invalid') }
      describe "after visiting another page" do
        before { click_link "Home" }
        it { should_not have_selector('div.alert.alert-error') }
      end
    end


    let(:user) { FactoryGirl.create(:user) }
    before do
      fill_in "Email", with: user.email
      fill_in "Password", with: user.password
      click_button "Sign in"
    end

    it{should have_selector('title', text: user.name) }
    it{should have_link('Profile', href:user_path(user))}
    it{should have_link('Sign out',href: signout_path)}
    it{should_not have_link('Sign in',href: signin_path)}
  end
end 

and app/view/sessions/new.html.erb

<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
  <div class="span6 offset3">
    <%= form_for(:session, url: sessions_path) do |f| %>
      <%= f.label :email %>
      <%= f.text_field :email %>
      <%= f.label :password %>
      <%= f.password_field :password %>
      <%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
    <% end %>
    <p>New user? <%= link_to "Sign up now!", signup_path %></p>
  </div>
</div>

回答1:

You have a missing describe block. Make your code look like this:

require 'spec_helper'

describe "Authentication" do
  subject { page }

  describe "signin page" do
    before { visit signin_path }
    it { should have_selector('h1', text: 'Sign in') }
    it { should have_selector('title', text: 'Sign in') }
  end

  describe "signin" do
    before { visit signin_path }
    describe "with invalid information" do
      before { click_button "Sign in" }
      it { should have_selector('title', text: 'Sign in') }
      it { should have_selector('div.alert.alert-error', text: 'Invalid') }
      describe "after visiting another page" do
        before { click_link "Home" }
        it { should_not have_selector('div.alert.alert-error') }
      end
    end

    # The following block is missing
    describe "with valid information" do
      let(:user) { FactoryGirl.create(:user) }
      before do
        fill_in "Email", with: user.email
        fill_in "Password", with: user.password
        click_button "Sign in"
      end

      it {should have_selector('title', text: user.name) }
      it {should have_link('Profile', href:user_path(user))}
      it{should have_link('Sign out',href: signout_path)}
      it{should_not have_link('Sign in',href: signin_path)}
     end
  end
end

Capybara usually wants you to use it's visit method before it will let you use it's fill_in method. You have forgotten to wrap your final before block in a describe block, like I have done above, and so the code from that before block actually overrides the previous before block, where you use the visit method. So that's why you have this problem. By wrapping the last bunch of assertions in a describe block, you fix the issue.



回答2:

Looks like things start to go wrong in 1), which I believe is actually handled in the spec/requests/user_pages_spec.rb file. Can you post what you have there? Also, depending on where you are in the tutorial, you might be missing a bit of the authentication_pages_spec.rb file, since Listing 8.6 under http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec-signin_tests has the factory girl call and the following "it" clauses surrounded by a describe block.