Rails/Rspec - testing a redirect in the controller

58,483

Solution 1

This line has problem

response.should redirect_to :back

The logic is not correct. You should expect #edit to redirect to :back path you set before, which is /scorecard. But you set :back here. In the context of Rspec, :back should be empty at each example.

To revise, just set it as

response.should redirect_to '/scorecard'

Solution 2

To make the test more readable you can do this: (rspec ~> 3.0)

expect(response).to redirect_to(action_path)

Solution 3

For testing if redirects happened, with no matching route

(just to test redirection, i used this when route is too long :D ). You can simply do like:

expect(response.status).to eq(302) #redirected
Share:
58,483
TheLegend
Author by

TheLegend

#SOreadytohelp. I am a Software Developer here in Cape Town, South Africa. I mostly work on web apps, mostly in Ruby and Rails. I started back in Nov 2011. I work for a company called Peach Payments as their head of engineering. Above all else, I love simple easy to read code. I am a student of the software development process. I find the glue that holds domains together as interesting as the domains themselves.

Updated on October 05, 2020

Comments

  • TheLegend
    TheLegend over 3 years

    So I am currently writing a test for a controller in an existing controller that just didn't have one before. What I want to test is a redirect that happens when someone is not allowed to edit something vs someone that is allowed to edit it.

    the controller action being edit

    def edit
      if [email protected]? || admin?
        @company = @scorecard.company
        @custom_css_include = "confirmation_page"
      else
        redirect_to :back
      end
    end
    

    So if a scorecard has been reviewed then only an admin can edit that score. The routes for that controller..

    # scorecards
    resources :scorecards do
      member do
        get 'report'
      end
      resources :inaccuracy_reports, :only => [:new, :create]
    end
    

    and finally the test

      require 'spec_helper'
    
      describe ScorecardsController do
    
        describe "GET edit" do
          before(:each) do
            @agency = Factory(:agency)
            @va = Factory(:va_user, :agency => @agency)
            @admin = Factory(:admin)
            @company = Factory(:company)
            @scorecard = Factory(:scorecard, :level => 1, :company => @company, :agency => @agency, :reviewed => true)
            request.env["HTTP_REFERER"] = "/scorecard"
          end
    
          context "as a admin" do
            before(:each) do
              controller.stub(:current_user).and_return @admin
            end
    
            it "allows you to edit a reviewed scorecard" do
              get 'edit', :id => @scorecard.id
              response.status.should be(200)
            end
          end
    
          context "as a va_user" do
            before(:each) do
            controller.stub(:current_user).and_return @va
          end
    
          it "does not allow you to edit a reviewed scorecard" do
            get 'edit', :id => @scorecard.id
            response.should redirect_to :back
          end
        end
      end
    end
    

    so a va when trying to edit a reviewed score will be redirected back, where an admin won't.

    but when running this through rspec I get

    ScorecardsController
      GET edit
        as a admin
          allows you to edit a reviewed scorecard
        as a va_user
          does not allow you to edit a reviewed scorecard (FAILED - 1)
    
    Failures:
    
      1) ScorecardsController GET edit as a va_user does not allow you to edit a reviewed scorecard
         Failure/Error: response.should redirect_to :back
       Expected response to be a redirect to </scorecard> but was a redirect to <http://test.host/>
         # ./spec/controllers/scorecards_controller_spec.rb:33:in `block (4 levels) in <top (required)>'
    
    Finished in 0.48517 seconds
    2 examples, 1 failure
    

    so I don't know if its working or not since I set the request.env["HTTP_REFERER"] = "/scorecard" as the place that should be the :back as it where. or am I missing the idea all together looking at httpstatus there are the 300 responses that I could use but I wouldn't know where to start?

    any help would be awesome

    EDIT

    I could test it by doing it like this

    ...
    response.status.should be(302)
    

    but I got the idea from this question and it sounds like this could be powerful as it specifies the url redirected to.

    Anyone have a working test like this?