Question

I am having a problem with the Rails Tutorial (rails 3). I'm currently on 9.28 rSpec tests and I have been in constant search to figure out what I did to make these two errors.

 user@ubuntu:~/rails_projects/sample_app$ bundle exec rspec spec/
 ......................F.F............................................

 Failures:

 1) Authentication authorization in the Users controller visiting the edit page 
 Failure/Error: before { visit edit_user_path(user) }
 NameError:
   undefined local variable or method `user' for #<RSpec::Core::ExampleGroup::Nested_3::Nested_3::Nested_2::Nested_1:0x9685354>
 # ./spec/requests/authentication_pages_spec.rb:75:in `block (5 levels) in <top (required)>'

 2) Authentication authorization in the Users controller submitting to the update action 
 Failure/Error: before { put user_path(user) }
 NameError:
   undefined local variable or method `user' for #<RSpec::Core::ExampleGroup::Nested_3::Nested_3::Nested_2::Nested_3:0x9b12034>
 # ./spec/requests/authentication_pages_spec.rb:85:in `block (5 levels) in <top (required)>'

 Finished in 10.86 seconds
 69 examples, 2 failures

 Failed examples:

 rspec ./spec/requests/authentication_pages_spec.rb:76 # Authentication authorization in the Users controller visiting the edit page 
 rspec ./spec/requests/authentication_pages_spec.rb:86 # Authentication authorization in the Users controller submitting to the update action 

This is the authentication spec:

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: full_title('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: full_title('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



    describe "valid information" do
      let (:user) { FactoryGirl.create(:user) }
      before { sign_in user }


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

      describe "followed by signout" do
        before { click_link "Sign out" }
        it { should have_link('Sign in',    href: signin_path) }
      end
    end
  end

  describe "authorization" do

    describe "for non-signed-in users" do
      let(:user) { FactoryGirl.create(:user) }

      describe "when attempting to visit a protected page" do
        before do
          visit edit_user_path(user)
          fill_in "Email",    with: user.email
          fill_in "Password", with: user.password
          click_button "Sign in"
        end

        describe "after signing in" do

          it "should render the desired protected page" do
            expect(page).to have_selector('title', text: ('Edit user'))

          end
        end
      end
    end

    describe "in the Users controller" do

      describe "visiting the edit page" do
        before { visit edit_user_path(user) }
        it { should have_selector('title', text: full_title('Sign in')) }
      end

      describe "visiting the user index" do
        before { visit users_path }
        it { should have_selector('title', text: full_title('Sign in')) }
      end

      describe "submitting to the update action" do
        before { put user_path(user) }
        specify { response.should redirect_to(signin_path) }
      end
    end


    describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
      before { sign_in user, no_capybara: true }

      describe "submitting a GET request to the Users#edit action" do
        before { get edit_user_path(wrong_user) }
        specify { expect(response.body).not_to match(full_title('Edit user')) }
        specify { expect(response).to redirect_to(root_url) }
      end

      describe "submitting a PUT request to the Users#update action" do
        before { put user_path(wrong_user) }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
  end
end

Really I have been trying to figure this out for quite sometime, if it is possible to walk through explanation ( if it is not typo ) would be awesome. Starting to grasp Rails but not quite there.

Was it helpful?

Solution

If you reindent the messy spec code, you can see that you are missing the user definition in your describe "in the Users controller" block.

Seeing that you are using the user in all three describe blocks in the Authorization, I'd move it one level up, so you'll end up with:

describe "authorization" do
  let(:user) { FactoryGirl.create(:user) }

  describe "for non-signed-in users" do
    ...
  end

  describe "in the Users controller" do
    ...
  end

  describe "as wrong user" do
    let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
    before { sign_in user, no_capybara: true }

    ...
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top