Kevin K
Kevin K

Reputation: 2227

Capybara / Rspec / FactoryGirl spec failing when the code does work as intended

Having trouble with a rspec spec. The actual code seems to be working fine, but my spec is still failing. I'm using FactoryGirl, Rspec and Capybara. This is part of spec/features/admin/admin_users_spec.rb:

require 'spec_helper'

describe "Admin::Users" do

  subject { page }

  context "When admin signed in" do
    let(:admin) { FactoryGirl.create(:admin) }
    let(:user) { FactoryGirl.create(:user) }

    before { sign_in admin }

    context "when visiting admin users" do

      before { visit admin_users_path }

      it_should_behave_like "admin visiting admin page"
      it { should have_content('- User Index') }
      it { should have_content(user.email) }  # This test is failing
    end
  end
end

The test that is failing has the comment.

Here is my factories for users.

require 'faker'

FactoryGirl.define do 
  factory :user do
    email         { Faker::Internet.email }
    admin         false
    super_admin   false
    password      "password"
    password_confirmation "password"
    confirmed_at  Time.now

    factory (:admin) do
      admin true
    end

    factory (:super_admin) do 
      admin true
      super_admin true
    end
  end
end

The idea that when you go to the index for users in the admin dashboard, admins should see a list of users. So in addition to the current admin, I create another user to populate the test database. Here is a sample failure message:

Failures:

  1) Admin::Users When admin signed in when visiting admin users should text "[email protected]"
     Failure/Error: it { should have_content(user.email) }
       expected to find text "[email protected]" in "Under The Gun Theater Admin Edit profile Logout Dashboard Users Posts Pages Shows Classes People Photos Admin Dashboard - User Index Email Roles Last Logged In [email protected] admin May 18, 2014 11:59 Logged in as [email protected]"
     # ./spec/features/admin/admin_users_spec.rb:53:in `block (4 levels) in <top (required)>' 

As you can see, the table that is generated on the page only includes the admin's email address. The other user "[email protected]" is not found. Again, when I actually log into the app it works, so I'm not sure why this test is not working.

Upvotes: 0

Views: 1335

Answers (2)

sgrif
sgrif

Reputation: 3822

Your user is not being created until after you've loaded the page. lets are lazy in RSpec. The user record gets created on this line:

it { should have_content(user.email) } 

which will always fail since the user wasn't created before the time that the page was loaded. You can change let(:user) to let!(:user), which will run it eagerly before the test. You might want to consider a different structure though, which helps avoid these issues:

admin = create(:user, :admin)
user = create(:user)

sign_in admin
visit admin_users_path

expect(page).to have_content('- User Index')
expect(page).to have_content(user.email)

Upvotes: 2

kiddorails
kiddorails

Reputation: 13014

Use let! instead of let for user.

let is lazily evaluated, that is, user won't come into existence till something is called upon it. let! helps out in sorting this issue by eagerly evaluating the block.

let!(:user) { FactoryGirl.create(:user) }

Read more about let and let! here.

OR, you can create a user manually in before block as:

before do
  @user = FactoryGirl.create(:user)
  sign_in admin
end
#corresponding test:
it { should have_content(@user.email) }  # This test should pass

Upvotes: 4

Related Questions