diff --git a/CHANGELOG.md b/CHANGELOG.md index ec4bb4c9..5f6ed6da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Improve the `NotAuthorizedError` message to include the policy class. Furthermore, in the case where the record passed is a class instead of an instance, the class name is given. (#812) - Add customizable permit matcher description (#806) +- Add support for filter_run_when_matching :focus with permissions helper. (#820) ## 2.3.2 (2024-05-08) diff --git a/README.md b/README.md index 10cfadb0..a1b59868 100644 --- a/README.md +++ b/README.md @@ -821,6 +821,14 @@ PostPolicy is expected to permit user with role admin to access record with ID 130 ``` +### Focus Support + +If your RSpec config has `filter_run_when_matching :focus`, you may tag the `permissions` helper like so: + +``` +permissions :show?, :focus do +``` + ### Scope Specs Pundit does not provide a DSL for testing scopes. Test them like you would a regular Ruby class! diff --git a/lib/pundit/rspec.rb b/lib/pundit/rspec.rb index 5becb308..1244031e 100644 --- a/lib/pundit/rspec.rb +++ b/lib/pundit/rspec.rb @@ -69,7 +69,15 @@ def permissions module DSL def permissions(*list, &block) - describe(list.to_sentence, permissions: list, caller: caller) { instance_eval(&block) } + metadata = { permissions: list, caller: caller } + + if list.last == :focus + list.pop + metadata[:focus] = true + end + + description = list.to_sentence + describe(description, metadata) { instance_eval(&block) } end end diff --git a/spec/dsl_spec.rb b/spec/dsl_spec.rb new file mode 100644 index 00000000..6e8fadd4 --- /dev/null +++ b/spec/dsl_spec.rb @@ -0,0 +1,28 @@ +require "spec_helper" + +RSpec.describe "Pundit RSpec DSL" do + let(:fake_rspec) do + double = class_double(RSpec::ExampleGroups) + double.extend(::Pundit::RSpec::DSL) + double + end + let(:block) { proc { "block content" } } + + it "calls describe with the correct metadata and without :focus" do + expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array) } + expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block| + expect(block.call).to eq("block content") + end + + fake_rspec.permissions(:item1, :item2, &block) + end + + it "calls describe with the correct metadata and with :focus" do + expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array), focus: true } + expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block| + expect(block.call).to eq("block content") + end + + fake_rspec.permissions(:item1, :item2, :focus, &block) + end +end