问题
I am following Railstutorial (chapter 9) The test for" delete links " is passed for first time but from the next time it starts giving some kind of errors like:
Failures:
1) User pages index delete links as an admin user
Failure/Error: sign_in admin
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/support/utilities.rb:20:in `sign_in'
# ./spec/requests/user_pages_spec.rb:38:in `block (5 levels) in <top (required)>'
2) User pages index delete links as an admin user
Failure/Error: sign_in admin
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/support/utilities.rb:20:in `sign_in'
# ./spec/requests/user_pages_spec.rb:38:in `block (5 levels) in <top (required)>'
3) User pages index delete links as an admin user should be able to delete another user
Failure/Error: sign_in admin
Capybara::ElementNotFound:
Unable to find field "Email"
# ./spec/support/utilities.rb:20:in `sign_in'
# ./spec/requests/user_pages_spec.rb:38:in `block (5 levels) in <top (required)>'
Finished in 0.81336 seconds
4 examples, 3 failures
Failed examples:
rspec ./spec/requests/user_pages_spec.rb:48 # User pages index delete links as an admin user
rspec ./spec/requests/user_pages_spec.rb:42 # User pages index delete links as an admin user
rspec ./spec/requests/user_pages_spec.rb:43 # User pages index delete links as an admin user should be able to delete another user
Randomized with seed 11884
Here is the content of utilities.rb file
include ApplicationHelper
def full_title(page_title)
base_title = "Welcome to Family & Friends"
if page_title.empty?
base_title
else
" #{base_title} | #{page_title} "
end
end
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
Part of user_pages_spec.rb file where the error is indicating
describe "delete links" do
it { should_not have_link('delete') }
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect do
click_link('delete', match: :first)
end.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
sessions_helper.rb file where definition of sign_in is present
module SessionsHelper
def sign_in(user)
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
def signed_in?
!current_user.nil?
end
def current_user=(user)
@current_user = user
end
def current_user
remember_token = User.encrypt(cookies[:remember_token])
@current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user == current_user
end
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
session.delete(:return_to)
end
def store_location
session[:return_to] = request.url if request.get?
end
end
I have even tried with fill_in "email_id" as suggested in similar posts but not worked in this case
thanks!!
Here is the Content of new.html.erb which html is rendering for signin
<% provide(:title, "Sign in") %>
<h2>Sign in</h2>
<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:
Old question but I ran into this problem as well when working through the tutorial. What's messing up the tests is the state from the previous examples is leaking into the "as an admin user" example.
describe "User Pages" do
subject { page }
describe "index" do
let(:user) { FactoryGirl.create(:user) }
# This is messing up the lower examples
before(:each) do
sign_in user
visit users_path
end
To see this in action you can add visit signin_path
then save_and_open_page
in the before block prior to calling the sign_in helper.
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
visit signin_path
save_and_open_page
sign_in admin
visit users_path
end
When my browser rendered the page I discovered the previously signed in user never got signed out, so visiting the sign in page just redirects you to the profile page of that user and there is no email field on the user profile page. That's why Capybara reports Unable to find field "Email"
.
To fix it I added a sign_out helper to my utilities.rb file.
def sign_out
first(:link, "Sign Out").click
end
And I call it before sign_in admin
in the example
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_out
sign_in admin
visit users_path
end
All my tests passed after this.
回答2:
I also had this problem. Unfortunately, I also could not get the proposed sign_out function to work. Even though save_and_open_page (after installing gem "launchy") showed a "Sign Out" link, the test reported that it could not find one on the page. I ended up solving the test as follows:
- I moved the "delete links" block out of the "index" block altogether.
- I recreated the 30 test users at the start of my new "delete links" block
- I moved the test for absence of delete links on a non-admin users page back up to a new block inside the "pagination" block.
(Of course, two mysteries remain: 1) I have no idea why the code could possibly work the way the book shows it. So why doesn't everyone working through the book have this problem? 2) Why wouldn't my sign_out function find the "Sign Out" link that clearly showed on the page with save_and_open_page. Sometimes you just have to move on to keep making progress. At least it works now.)
Here is the code after making those changes. It passes all the tests now:
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in user
visit users_path
end
it { should have_title('All users') }
it { should have_content('All users') }
describe "pagination" do
before(:all) { 30.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
it { should have_selector('div.pagination') }
it "should list each user" do
User.paginate(page: 1).each do |user|
expect(page).to have_selector('li', text: user.name)
end
end
describe "non-admin user should not have delete links" do
it { should_not have_link('delete', href: user_path(User.first)) }
end
end
end
# fhj: I could not get this to work as done in the book (i.e. placing this
# above inside the "index" block). It could not execute sign_in admin
# because it was already signed in as a non-admin user. I tried the
# suggestion to create a sign_out helper function, but I could not make
# that work either. By moving it outside of the block and recreating
# the 30 test users, I was able to get it to pass the tests.
# I also created the "non-admin user should not have delete links" block
# at the end of the "pagination" block above to test for that case properly.
describe "delete links" do
before(:all) { 30.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect do
click_link('delete', match: :first)
end.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
来源:https://stackoverflow.com/questions/19357399/capybaraelementnotfound-unable-to-find-field-email-railstutorialchapter-9