I have a Rails app that has a controller without a model/object for handling reports:
# reports_controller.rb
class ReportsController < ApplicationController
authorize_resource :class => false
def index
end
def report_title
# etc.
end
# etc.
end
User objects can have a role of either: admin, normal, or viewer. An admin can do anything, a normal user has a bunch of rules around it, and a viewer can cannot do anything with any of the app's objects, but they are allowed to view all the reports.
# ability.rb
def initialize(user)
if user.admin?
can :manage, :all
elsif user.normal?
# stuff according to business rules...
elsif user.viewer?
can [:index, :report_title, ...], :report
end
end
This works as intended (as all of the other controller have load_and_authorize_resource
), but how do I go about unit testing these lines in ability.rb? Can I do it in ability_spec.rb with my other unit tests, or do I have to test it only via requests?
By the way, testing via requests does work, I'm just wondering if it is possible to test here instead / as well.
# ability_spec.rb
RSpec.describe User do
describe "abilities" do
subject(:ability){ Ability.new(user) }
CRUD = [:create, :read, :update, :destroy]
ALL_MODELS = # a list of models
# ...
context "a report viewer" do
let(:user){ FactoryGirl.create(:user, :viewer) }
it 'cannot do anything with any objects' do
ALL_MODELS.each do |object|
CRUD.each do |action|
should_not be_able_to(action, object)
end
end
end
it 'can access all the report actions' do
# ???
end
end
end
end
Yes, you should be able to just test that ability in ability_spec.rb
. I think adding the following lines might work:
it 'can access all the report actions' do
should be_able_to :index, ReportsController
should be_able_to :report_title, ReportsController
end
if you set authorize_resource :class => ReportsController
instead of false
and use can [:index, :report_title, ...], :ReportsController
instead of the symbol :report
.
I haven't tried it, so let me know if it worked.