Rspec Test Failing?

Hi,

rails 3.2.11 and Capybara 2.0.2 and the latest rspec.

I have another test that has me searching for a solution … just now, I do not have one and I have spent a number of days trying out different solutions.

If I may … here is the test, spec/features:

describe “submitting a PUT request to the Employees#update action” do before { put employee_path(employee) } specify { response.should redirect_to(signin_path) }

end

It fails with this message:

         NoMethodErrror: undefined method 'put'

In this same group, I have another two tests failing both with:

        undefined local variable or method 'cookies'

and it identifies the sign_in def as the culprit:

       def sign_in(employee)

visit signin_path

fill_in “Email”, with: employee.email

fill_in “Password”, with: employee.password

click_button “Sign in”

Sign in when not using Capybara.

cookies[:remember_token] = employee.remember_token

         end

This is part of the spec/support/utilities file.

Does anyone have any ideas on how to solve this?

Thanks.

I just read that Capybara does not do integration testing ... this I found right at the bottom of the Capybara documentation page. So since all Capybara tests reside in the spec/features folder, I moved the

                     submitting a PUT request to the Employees#update

test into the spec/request folder and it passes.

Some progress .. now for the other two failing tests ... namely the:

              undefined local variable or method 'cookies'

Some more research of maybe someone has an understanding of why this test is failing and is willing to give me some guidance?

Thanks.

Hi,

specify is actually just the same as it. It’s just there because sometimes it reads better. See here: https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example_group.rb#L82

  • Mirri

Hi Andre,

Thanks for your reply ... following is the authentication_pages_spec.rb file which now resides in the spec/ features folder ... all of the tests pass except three.

         require 'spec_helper'

     describe "Authentication" do

       subject { page }

       describe "signin" do          before { visit signin_path }

         it { should have_selector('h2', text: 'Sign in') }          it { should have_title('Sign in') }

        describe "with invalid information" do           before { click_button "Sign in" }

          it { should have_title('Sign in') }           it { should have_error_message('Invalid') }

           describe "after visiting another page" do             before { click_link "Home" }              it { should_not have_selector('div.flash.error', text: 'Invalid') }           end         end

         describe "non_admin employee with valid information" do           let(:employee) { FactoryGirl.create(:employee) }           before { valid_signin(employee) }

          it { should have_title(employee.emp_full_name) }

          it { should_not have_link('Employees', href: employees_path) }           it { should_not have_link('New Employee', href: newemployee_path) }           it { should_not have_link('New Contract', href: new_contract_path) }

          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') }           end         end

        describe "admin employee with valid information" do           let(:admin) { FactoryGirl.create(:admin) }           before { valid_signin(admin) }

          it { should have_title(admin.emp_full_name) }

          it { should have_link('Employees', href: employees_path) }           it { should have_link('Profile', href: employee_path(admin)) }           it { should have_link('Settings', href: edit_employee_path(admin)) }           it { should have_link('New Employee', href: newemployee_path) }           it { should have_link('New Contract', href: new_contract_path) }

          it { should have_link('Sign out', href: signout_path) }

          it { should_not have_link('Sign in', href: signin_path) }

         describe "Employee" do             it "logs factory girl generated objects" do              admin = FactoryGirl.create( :admin )              logger.warn( admin.pretty_inspect )          end        end      end   end

       describe "Authorization" do

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

          describe "in the Employees controller" do

           describe "visting the edit page" do               before { visit edit_employee_path(employee) }               it { should have_title('Sign in') }             end

            describe "submitting to the update action" do                before { put employee_path(employee) } # the put gets us to the update                specify { response.should redirect_to(signin_path) }             end           end

          describe "as wrong employee" do             let(:employee) { FactoryGirl.create(:employee) }             let(:wrong_employee) { FactoryGirl.create(:employee, email: "wrong@example.com") }             before { sign_in employee }

            describe "visiting Employees#edit page" do               before { visit edit_employee_path(wrong_employee) }               it { should have_title('Edit') }             end

             describe "submitting a PUT request to the Employees#update action" do               before { put employee_path(wrong_employee) }               specify { response.should redirect_to(root_path) }             end           end

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

            describe "after signing in" do

              it "should render the desired protected page" do                page.should have_title('Edit')             end

              describe "when signing in again" do                 before do                  visit signin_path                   fill_in "Email", with: employee.email                   fill_in "Password", with: employee.password                   click_button "Sign in"                end

               it "should render the default (profile/show) page" do                  page.should have_title(employee.emp_full_name)               end            end         end       end     end   end

  describe "visiting employee index" do     before { visit employees_path }     it { should have_title('Sign in') }   end

  describe "Employee" do     it "logs factory girl generated objects" do       admin = FactoryGirl.create( :admin )       logger.warn( admin.pretty_inspect )     end   end end

This is the error that I am getting for three of the failures:

     ......................FFF....

    Failures:

     1) Authentication Authorization for non-signed-in employees in the Employees controller submitting to the update action      Failure/Error: before { put employee_path(employee) } # the put gets us to the update      NoMethodError:        undefined method `put' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2::Nested_1::Nested_1::Nested_2:0xb6bf3c48>      # ./spec/features/authentication_pages_spec.rb:84:in `block (6 levels) in <top (required)>'

     2) Authentication Authorization for non-signed-in employees as wrong employee visiting Employees#edit page      Failure/Error: before { sign_in employee }      NameError:        undefined local variable or method `cookies' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2::Nested_1::Nested_2::Nested_1:0xb6819438>      # ./spec/support/utilities.rb:36:in `sign_in'      # ./spec/features/authentication_pages_spec.rb:92:in `block (5 levels) in <top (required)>'

     3) Authentication Authorization for non-signed-in employees as wrong employee submitting a PUT request to the Employees#update action      Failure/Error: before { sign_in employee }      NameError:        undefined local variable or method `cookies' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_2::Nested_1::Nested_2::Nested_2:0xb6916d2c>      # ./spec/support/utilities.rb:36:in `sign_in'      # ./spec/features/authentication_pages_spec.rb:92:in `block (5 levels) in <top (required)>'

    Finished in 8.39 seconds     29 examples, 3 failures

    Failed examples:

    rspec ./spec/features/authentication_pages_spec.rb:85 # Authentication Authorization for non-signed-in employees in the Employees controller submitting to the update     action     rspec ./spec/features/authentication_pages_spec.rb:96 # Authentication Authorization for non-signed-in employees as wrong employee visiting Employees#edit page     rspec ./spec/features/authentication_pages_spec.rb:101 # Authentication Authorization for non-signed-in employees as wrong employee submitting a PUT request to the     Employees#update action

and here is the utilities.rb file to be found in the spec/support folder:

     include ApplicationHelper

     def valid_signin(employee)        fill_in "Email", with: employee.email        fill_in "Password", with: employee.password        click_button "Sign in"      end

     RSpec::Matchers.define :have_error_message do |message|        match do |page|          page.should have_selector('div.flash.error', text: message)        end      end

     Rspec::Matchers.define :be_accessible do |attribute|        match do |response|          response.class.accessible_attributes.include?(attribute)        end        description { "be accessible :#{attribute}" }        failure_message_for_should { ":#{attribute} should be accessible" }        failure_message_for_should_not{ ":#{attribute} should not be accessible" }      end

     Rspec::Matchers::define :have_title do |text|        match do |page|          Capybara.string(page.body).has_selector?('title', text: text)        end      end

     def sign_in(employee)        visit signin_path        fill_in "Email", with: employee.email        fill_in "Password", with: employee.password        click_button "Sign in"        # Sign in when not using Capybara.        cookies[:remember_token] = employee.remember_token      end

     def valid_signin(admin)        fill_in "Email", with: admin.email        fill_in "Password", with: admin.password        click_button "Sign in"      end

I did try and move the:

                  describe "submitting to the update action" do

test to the spec/request folder and it passes in the request folder but fails in the features folder and I think that has something to do with the fact that Capybara does not do integration tests or to put it another way ... you cannot get access to your controller using Capybara ... that is just me speculating.

Thanks for having a look at this.

Thanks Mirri for you post ... I had a look at the link ... are they saying that 'specify' has now been superceded by 'it'?

Nope, just an alias.

So basically I think you are near the solution:

request tests, allow you to test requests(like put and others):

when you doing integration testing at a feature level you dont make requests(you would have instantiate the controller which is not correct), you can instead maybe visit a page that makes that put request you want to test the redirect happening. does that makes sense to you?

Hi Andre,

Thanks for your reply.

I did see a 'put_via_redirect'.

So I would have to rewrite the test and use this command and it would be testing the redirect which is a way to test the put?

I will give that a try.

Thanks again.

That seems like it :slight_smile:

also about your cookie problem, is there anything that might look like this: ruby on rails - RSpec vs. Cookies - The test fails even if the applications works (simulating logged user) - Stack Overflow

all the best,

Andre

Hey Andre,

Thanks for your link .. I have seen it before but I did not have the same issue, but I am thinking that it might well be worth my effort to explore using sessions instead of cookies.

Thanks again.