I'm running into an issue when I try to run the specs for all the policies. The specs all pass when I run each policy spec individually, but when I try to run them all together, the specs from the first file all pass, but I get the following error for each permit spec after.
1) BrandPolicy for an admin .permission should permit :show
Failure/Error: it { should permit(:show) }
NoMethodError:
undefined method `find_all' for nil:NilClass
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/pundit-1.1.0/lib/pundit/rspec.rb:10:in `block (2 levels) in <module:Matchers>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/matchers/dsl.rb:70:in `block (2 levels) in match'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-support-3.5.0/lib/rspec/support.rb:103:in `with_failure_notifier'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/matchers/dsl.rb:68:in `block in match'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:27:in `with_matcher'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-expectations-3.5.0/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/memoized_helpers.rb:81:in `should'
# ./spec/policies/brand_policy_spec.rb:23:in `block (4 levels) in <top (required)>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:254:in `block in run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `block in with_around_and_singleton_context_hooks'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `block in with_around_example_hooks'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `block in run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:604:in `block in run_around_example_hooks_for'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-rails-3.5.2/lib/rspec/rails/adapters.rb:127:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
# ./spec/rails_helper.rb:44:in `block (2 levels) in <top (required)>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
# ./spec/spec_helper.rb:75:in `block (2 levels) in <top (required)>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:443:in `instance_exec'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:375:in `execute_with'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:606:in `block (2 levels) in run_around_example_hooks_for'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:338:in `call'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:607:in `run_around_example_hooks_for'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/hooks.rb:464:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:453:in `with_around_example_hooks'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:496:in `with_around_and_singleton_context_hooks'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example.rb:251:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:627:in `block in run_examples'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `map'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:623:in `run_examples'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:589:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `block in run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `map'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/example_group.rb:590:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (3 levels) in run_specs'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `map'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:113:in `block (2 levels) in run_specs'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1835:in `with_suite_hooks'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:112:in `block in run_specs'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/reporter.rb:77:in `report'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:111:in `run_specs'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:87:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/gems/rspec-core-3.5.4/exe/rspec:4:in `<top (required)>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/rspec:22:in `load'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/rspec:22:in `<main>'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/ruby_executable_hooks:15:in `eval'
# /Users/jordanepps/.rvm/gems/ruby-2.3.3@tutor5/bin/ruby_executable_hooks:15:in `<main>'
Here is a sample of one of my policy specs. They all follow the same general format.
require 'rails_helper'
RSpec.describe BrandPolicy, type: :policy do
subject { BrandPolicy.new(user, Brand) }
let!(:admin_user) { create(:employee).user }
let!(:tutor_user) { create(:tutor).user }
let!(:parent_user) { create(:parent).user }
let!(:student_user) { create(:student, parent: parent_user.parent).user }
let!(:brand) { create(:brand) }
context 'for an admin' do
let(:user) { admin_user }
describe '.scope' do
it 'returns all brands' do
expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
end
end
describe '.permission' do
it { should permit(:show) }
it { should permit(:update) }
it { should permit(:create) }
it { should permit(:destroy) }
end
end
context 'for a tutor' do
let(:user) { tutor_user }
describe '.scope' do
it 'returns all brands' do
expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
end
end
describe '.permission' do
it { should permit(:show) }
it { should_not permit(:update) }
it { should_not permit(:create) }
it { should_not permit(:destroy) }
end
end
context 'for a parent' do
let(:user) { parent_user }
describe '.scope' do
it 'returns all brands' do
expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
end
end
describe '.permission' do
it { should permit(:show) }
it { should_not permit(:update) }
it { should_not permit(:create) }
it { should_not permit(:destroy) }
end
end
context 'for a student' do
let(:user) { student_user }
describe '.scope' do
it 'returns all brands' do
expect(BrandPolicy::Scope.new(user, Brand).resolve).to eq Brand.all
end
end
describe '.permission' do
it { should permit(:show) }
it { should_not permit(:update) }
it { should_not permit(:create) }
it { should_not permit(:destroy) }
end
end
end
edit: The specs from the first file all pass because it doesn't have any permit tests (lol).
Here is the pundit_matcher.rb file I'm using. It's the same custom matcher that's recommended in the guides.
RSpec::Matchers.define :permit do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message do |policy|
"#{policy.class} does not permit #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_when_negated do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end
I found this Pundit-Matchers gem and that fixed the issue.
I had a similar error using this suggested custom matcher. After reading up on it, I renamed the :permit action in the code block to :authorize, like so, and now it works like a dream!
RSpec::Matchers.define :authorize do |action|
match do |policy|
policy.public_send("#{action}?")
end
failure_message do |policy|
"#{policy.class} does not authorize #{action} on #{policy.record} for #{policy.user.inspect}."
end
failure_message_when_negated do |policy|
"#{policy.class} does not forbid #{action} on #{policy.record} for #{policy.user.inspect}."
end
end
Then I just required the default pundit/rspec and that custom pundit_matcher in my rails_helper.rb. Now it works great!
The issue is apparently a naming conflict between the custom permit matcher defined here and the built-in Pundit rspec method permit, as discussed in this post... https://github.com/elabs/pundit/issues/130. Once the custom pundit_matcher method is renamed to something else (like authorize) it works great for me. Just in case it's helpful...
Yes, you can't have both matchers included at the same time. Please see #130
Most helpful comment
I had a similar error using this suggested custom matcher. After reading up on it, I renamed the
:permitaction in the code block to:authorize, like so, and now it works like a dream!Then I just required the default
pundit/rspecand that custompundit_matcherin myrails_helper.rb. Now it works great!The issue is apparently a naming conflict between the custom
permitmatcher defined here and the built-in Pundit rspec methodpermit, as discussed in this post... https://github.com/elabs/pundit/issues/130. Once the custompundit_matchermethod is renamed to something else (likeauthorize) it works great for me. Just in case it's helpful...