From 3f68dcea76414c27eebaa9511217e2d3de2bf7c7 Mon Sep 17 00:00:00 2001 From: Sean Devine Date: Sat, 18 Feb 2023 14:21:11 +0000 Subject: [PATCH 1/4] feat: Add customizable permit description --- lib/pundit/rspec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/pundit/rspec.rb b/lib/pundit/rspec.rb index 243ebec7..221c77eb 100644 --- a/lib/pundit/rspec.rb +++ b/lib/pundit/rspec.rb @@ -5,6 +5,10 @@ module RSpec module Matchers extend ::RSpec::Matchers::DSL + def self.description(&block) + @description = block.call + end + # rubocop:disable Metrics/BlockLength matcher :permit do |user, record| match_proc = lambda do |policy| @@ -33,6 +37,14 @@ module Matchers "#{record} but #{@violating_permissions.to_sentence} #{was_were} granted" end + description do + if Pundit::RSpec::Matchers.instance_variable_defined?(:@description) + Pundit::RSpec::Matchers.instance_variable_get(:@description) + else + super() + end + end + if respond_to?(:match_when_negated) match(&match_proc) match_when_negated(&match_when_negated_proc) From f5e7ca36c049177c0e9be9e1f70fdccfde85a7dd Mon Sep 17 00:00:00 2001 From: Sean Devine Date: Sat, 18 Feb 2023 14:38:35 +0000 Subject: [PATCH 2/4] docs: Update the README about description customization --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 29cc0bc9..9097e39d 100644 --- a/README.md +++ b/README.md @@ -783,6 +783,14 @@ describe PostPolicy do end ``` +You can customize the description used for the `permit` matcher: + +``` ruby +Pundit::RSpec::Matchers.description do + "permit the user" +end +``` + An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this [excellent post](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/) and implemented in the third party [pundit-matchers](https://github.com/punditcommunity/pundit-matchers) gem. From 4ca1e4516496194a71ba9d60a43e3028b8a165cd Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Sun, 19 Feb 2023 22:09:17 -0600 Subject: [PATCH 3/4] chore: adjust interface, update readme --- README.md | 25 ++++++++++++++++++++++++- lib/pundit/rspec.rb | 16 +++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 9097e39d..85416dc3 100644 --- a/README.md +++ b/README.md @@ -786,11 +786,34 @@ end You can customize the description used for the `permit` matcher: ``` ruby -Pundit::RSpec::Matchers.description do +Pundit::RSpec::Matchers.description = "permit the user" +``` + +given the spec + +```ruby +permissions :update?, :show? do + it { expect(policy).to permit(user, record) } end ``` +will change the output from + +``` +update? and show? + is expected to permit # and # +``` + +to + +``` +update? and show? + is expected to permit the user +``` + +which may be desirable when distributing policy specs as documentation. + An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this [excellent post](http://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/) and implemented in the third party [pundit-matchers](https://github.com/punditcommunity/pundit-matchers) gem. diff --git a/lib/pundit/rspec.rb b/lib/pundit/rspec.rb index 221c77eb..c88407d2 100644 --- a/lib/pundit/rspec.rb +++ b/lib/pundit/rspec.rb @@ -5,8 +5,14 @@ module RSpec module Matchers extend ::RSpec::Matchers::DSL - def self.description(&block) - @description = block.call + def self.default_description=(default_description) + @default_description = default_description + end + + def self.default_description + return @default_description if instance_variable_defined?(:@default_description) + + nil end # rubocop:disable Metrics/BlockLength @@ -38,11 +44,7 @@ def self.description(&block) end description do - if Pundit::RSpec::Matchers.instance_variable_defined?(:@description) - Pundit::RSpec::Matchers.instance_variable_get(:@description) - else - super() - end + Pundit::RSpec::Matchers.default_description || super() end if respond_to?(:match_when_negated) From 86c72511c21cdf9b8b97bb2a314b3d8f97248aa4 Mon Sep 17 00:00:00 2001 From: Greg Fletcher Date: Wed, 8 May 2024 18:24:10 -0400 Subject: [PATCH 4/4] refactor: Update proposed change to address feedback from Pundit maintainers --- lib/pundit/rspec.rb | 14 +++++++------- spec/policies/post_policy_spec.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/pundit/rspec.rb b/lib/pundit/rspec.rb index c88407d2..5becb308 100644 --- a/lib/pundit/rspec.rb +++ b/lib/pundit/rspec.rb @@ -5,14 +5,14 @@ module RSpec module Matchers extend ::RSpec::Matchers::DSL - def self.default_description=(default_description) - @default_description = default_description - end + class << self + attr_writer :description - def self.default_description - return @default_description if instance_variable_defined?(:@default_description) + def description(user, record) + return @description.call(user, record) if defined?(@description) && @description.respond_to?(:call) - nil + @description + end end # rubocop:disable Metrics/BlockLength @@ -44,7 +44,7 @@ def self.default_description end description do - Pundit::RSpec::Matchers.default_description || super() + Pundit::RSpec::Matchers.description(user, record) || super() end if respond_to?(:match_when_negated) diff --git a/spec/policies/post_policy_spec.rb b/spec/policies/post_policy_spec.rb index 54e301e0..912fe74b 100644 --- a/spec/policies/post_policy_spec.rb +++ b/spec/policies/post_policy_spec.rb @@ -18,5 +18,32 @@ should permit(user, other_post) end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end + + it "uses the default description if not overridden" do + expect(permit(user, own_post).description).to eq("permit #{user.inspect} and #{own_post.inspect}") + end + + context "when the matcher description is overridden" do + after do + Pundit::RSpec::Matchers.description = nil + end + + it "sets a custom matcher description with a Proc" do + allow(user).to receive(:role).and_return("default_role") + allow(own_post).to receive(:id).and_return(1) + + Pundit::RSpec::Matchers.description = lambda { |user, record| + "permit user with role #{user.role} to access record with ID #{record.id}" + } + + description = permit(user, own_post).description + expect(description).to eq("permit user with role default_role to access record with ID 1") + end + + it "sets a custom matcher description with a string" do + Pundit::RSpec::Matchers.description = "permit user" + expect(permit(user, own_post).description).to eq("permit user") + end + end end end