user3868832
user3868832

Reputation: 620

Rails: how to write an anonymous spec controller to test authorisation

I have a controller, AdminController, which sets the various authorisation levels for the rest of the CMS. Because there are no controller actions, just methods, I began to research ways to test these against controllers.

The conclusion I came to was that they needed to be tested independently of the controllers they are used in (I want to to steer clear of integration testing if possible, like capybara etc).

I found some articles like this one to help me along.

So far I have written this spec which is failing with the errors below. I am not sure about it to be honest and wanted to here what SO community had to say on what I am trying to achieve.

describe AdminController do
    
    controller do
      before_filter :authorize_fixture_uploader!

      def index 
        render text: 'Hello World'
      end 
    end
    
    let(:admin){FactoryGirl.create(:admin)}

    describe "authentication" do 
      before do
        sign_in admin
        allow(controller).to receive(:current_admin).and_return(admin)
      end
    
      describe "authorize_fixture_uploader! helper" do 

        context "signed in" do 
          before do 
            allow(:admin).to receive(:authorize_fixture_uploader!).and_return(false)
            get :index 
          end

          it "redirects do admin_home_path" do 
            expect(response).to redirect_to admin_home_path
          end
        end
      end
    end
   end

and here is the controller

class AdminController < ApplicationController

  before_filter :authenticate_admin!


  def authorize_fixture_uploader!
    unless current_admin.fixture_uploader?
      return redirect_to(admin_home_path)
    end
  end
end

This test is giving me the error

  1) AdminController authentication authorize_fixture_uploader! helper signed in redirects do admin_home_path
     Failure/Error: allow(:admin).to receive(:authorize_fixture_uploader?).and_return(false)
     TypeError:
       can't define singleton

I am worried its because my whole approach to this is wrong. Help would most certainly be appreciated.

Updated thanks to @blelump's answer.

I had a type which was causing the first issue. But Now I am getting error

   undefined method `authorize_fixture_uploader?' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1::Nested_1:0x007f9357857108>

The logic behind this i throwing me a bit. How am I to test these methods independent of the controllers they are used?

Upvotes: 0

Views: 362

Answers (2)

user3868832
user3868832

Reputation: 620

Aside from the poor attention detail highlight by blelump above, the real flaw in my approach was the lack of routes. I found a very useful article from pivotal labs http://pivotallabs.com/adding-routes-for-tests-specs-with-rails-3/ which saved the day.

Read the article, but it essentially boils down to this.

require 'spec_helper'

class InheritsFromAdminController < AdminController
  def show
    render :text => "foo"
  end
end

describe InheritsFromAdminController do

  before do
    Rails.application.routes.draw do

      # add the route that you need in order to test
      match '/foo' => "inherits_from_admin#show"

      # re-drawing routes means that you lose any routes you defined in routes.rb
      # so you have to add those back here if your controller references them
      match '/login' => "sessions/new", :as => login

    end
  end

  after do

    # be sure to reload routes after the tests run, otherwise all your 
    # other controller specs will fail
    Rails.application.reload_routes!

  end

  it "requires logged-in users" do
    get :show
    response.should redirect_to("/login")
  end
end

Upvotes: 0

blelump
blelump

Reputation: 3243

You have a typo:

allow(:admin).to receive(:authorize_fixture_uploader!).and_return(false)

Now you're trying to add authorize_fixture_uploader! to Symbol. Just start with controller variable:

allow(controller).to receive(:authorize_fixture_uploader!).and_return(false)

Upvotes: 1

Related Questions