I have a user controller and i want to test the index page, I'm looking for an example of the rails tutorial by michael hart'l and i copy it, this is the test (the main thing is that the index page shows all users, and the test look if the user is an admin, if yes, users should have a 'delete' link allowing admin to destroy them) :
require 'spec_helper'
describe "user pages" do
subject { page }
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in user
visit users_path
end
it { should have_title('Users') }
it { should have_content('Users') }
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
My user factory is defined like this :
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Person #{n}" }
sequence(:email) { |n| "person_#{n}@example.com"}
password "foobar"
password_confirmation "foobar"
factory :admin do
admin true
end
end
end
here there is no problem and all test are passing as well. but when i comment or i delete the following lines from the test above :
let(:user) { FactoryGirl.create(:user) }
before(:each) do
sign_in user
visit users_get_path
end
it gives me the error :
1) user pages index delete links as an admin user
Failure/Error: it { should have_link("delete", href: user_path(User.first)) }
expected #has_link?("delete", {:href=>"/users/2395"}) to return true, got false
# ./spec/requests/user_pages_spec.rb:40:in `block (5 levels) in <top (required)>'
2) user pages index delete links as an admin user should be able to delete another user
Failure/Error: click_link('delete', match: :first)
Capybara::ElementNotFound:
Unable to find link "delete"
# ./spec/requests/user_pages_spec.rb:43:in `block (6 levels) in <top (required)>'
# ./spec/requests/user_pages_spec.rb:42:in `block (5 levels) in <top (required)>'
i can't understand here why it fails, and what's the relation between the first before block and other examples in "delete links" block ? i need just a simple explanation , thank you
let
is lazily evaluated and user
is not referenced in your "delete links" examples, so without the first before
block, the regular user is not created and the corresponding delete link does not exist, causing the tests to fail. Changing the initial let
to let!
avoids this issue.