Search code examples
rspeccapybararspec-rails

Testing index page should have a delete link for each user when the current user is an admin


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


Solution

  • 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.