Do you have an example of how you would test it with minitest? Or minitest spec?
This is how I'm testing my policies using MiniTest. I've created a few helper functions:
# test_helper.rb
def assert_permit(user, record, action)
msg = "User #{user.inspect} should be permitted to #{action} #{record}, but isn't permitted"
assert permit(user, record, action), msg
end
def refute_permit(user, record, action)
msg = "User #{user.inspect} should NOT be permitted to #{action} #{record}, but is permitted"
refute permit(user, record, action), msg
end
def permit(user, record, action)
cls = self.class.superclass.to_s.gsub(/Test/, '')
cls.constantize.new(user, record).public_send("#{action.to_s}?")
end
And then for each policy file:
# post_policy_test.rb
require 'test_helper'
class PostPolicyTest < ActiveSupport::TestCase
before do
@account = build_stubbed(:account)
@administrator = build_stubbed(:administrator, account: @account)
@employee = build_stubbed(:employee, account: @account)
@post = build_stubbed(:post, account: @account)
end
describe "for an administrator" do
it { assert_permit @administrator, :post, :index }
it { assert_permit @administrator, @post, :show }
it { assert_permit @administrator, @post, :new }
it { assert_permit @administrator, @post, :create }
it { assert_permit @administrator, @post, :edit }
it { assert_permit @administrator, @post, :update }
it { assert_permit @administrator, @post, :destroy }
end
describe "for an employee" do
it { refute_permit @employee, :post, :index }
it { refute_permit @employee, @post, :show }
it { refute_permit @employee, @post, :new }
it { refute_permit @employee, @post, :create }
it { refute_permit @employee, @post, :edit }
it { refute_permit @employee, @post, :update }
it { refute_permit @employee, @post, :destroy }
end
describe "for a guest" do
it { refute_permit nil, :post, :index }
it { refute_permit nil, @post, :show }
it { refute_permit nil, @post, :new }
it { refute_permit nil, @post, :create }
it { refute_permit nil, @post, :edit }
it { refute_permit nil, @post, :update }
it { refute_permit nil, @post, :destroy }
end
end
Hope this helps. If anybody has improvements, please share.
ah cool! Looks really nice. Will give it a try
:+1: @pbougie Thanks for sharing!
It comes close to the Gist I found here: https://gist.github.com/promisedlandt/9800713
However I actually prefer your approach. Thank you.
For anybody who has nested describe issues in the future, based on the issue described here and the solution I came up with, if you're having nested describe problems, then try changing your permit method to
def permit(user, record, action)
test_name = self.class.ancestors.select { |a| a.to_s.match(/PolicyTest/) }.first
klass = test_name.to_s.gsub(/Test/, '')
klass.constantize.new(user, record).public_send("#{action.to_s}?")
end
Hope that helps!
Unfortunately this didn't work as expected. My test classes also use a describe block at the top-level (unlike the above example), i.e.
describe PostPolicy do
...
end
Therefore my permit() method is as follows:
def permit(user, record, action)
index = self.class.name.index('Policy')
klass = self.class.name[0, index+6]
klass.constantize.new(user, record).public_send("#{action.to_s}?")
end
This solution seems to work for namespaced policies and nested describe blocks.
Most helpful comment
This is how I'm testing my policies using MiniTest. I've created a few helper functions:
And then for each policy file:
Hope this helps. If anybody has improvements, please share.