Skip to content

Instantly share code, notes, and snippets.

@joelind
Created March 10, 2012 18:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelind/2012328 to your computer and use it in GitHub Desktop.
Save joelind/2012328 to your computer and use it in GitHub Desktop.
Simple scheme for unit testing cancan abilities
require 'spec_helper'
describe Ability do
let(:district) { Factory :district }
let(:root) { Factory :root_user }
let(:admin) { Factory :admin_user, district: district }
let(:other_admin_in_district) { Factory :admin_user, district: district }
let(:admin_in_other_district) { Factory :admin_user }
let(:contributor) { Factory :contributor_user, district: district }
let(:contributor_in_other_district) { Factory :contributor_user }
context "for a root user" do
subject { Ability.new root }
it { should be_able_to :index, User }
it { should be_able_to :manage, root }
it { should be_able_to :manage, admin }
it { should be_able_to :manage, contributor_in_other_district }
end
context "for an admin user" do
subject { Ability.new admin }
it { should be_able_to :index, User }
it { should be_able_to :admin, contributor }
it { should be_able_to :admin, other_admin_in_district }
it { should_not be_able_to :admin, contributor_in_other_district }
it { should_not be_able_to :admin, admin_in_other_district }
it { should_not be_able_to :admin, root }
end
context "for a contributor" do
subject { Ability.new contributor }
it { should_not be_able_to :index, User }
it { should_not be_able_to :admin, contributor }
it { should_not be_able_to :admin, admin }
it { should_not be_able_to :admin, root }
end
end
module CanCanMatchers
def be_able_to(permission, object)
BeAbleToMatcher.new :be_able_to, permission, object
end
class BeAbleToMatcher
attr_reader :permission
attr_reader :object
attr_reader :subject
def initialize(macro, permission, object)
@macro = macro
@permission = permission
@object = object
end
def matches?(subject)
@subject = subject
@subject.can? permission, object
end
def description
"be able to #{permission} #{object}"
end
def negative_failure_message
"Did not expect that #{subject} can? #{permission} #{object}"
end
def failure_message
"Expected that #{subject} can? #{permission} #{object}"
end
end
end
module RSpec::Matchers
include CanCanMatchers
end
@SabretWoW
Copy link

Thanks for that! I have a pretty simple permission scheme right now, so I've just been testing abilities in the User spec, but I think as it grows, I'll need to move them to a separate file.

I made a similar template for unit testing models a few years back that was incredibly polarizing. Feel free to check it out and offer feedback if you'd like: https://gist.github.com/kyletcarlson/6234923

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment