Back to Repositories

Testing Post Authorization Policies in Pundit

This RSpec test suite validates the authorization logic in Pundit’s PostPolicy, focusing on permission checks for post updates and views. The tests ensure proper access control between users and their posts while verifying custom matcher descriptions.

Test Coverage Overview

The test suite comprehensively covers PostPolicy authorization rules, specifically for update? and show? permissions.

Key areas tested include:
  • Permission validation for users accessing their own posts
  • Permission denial for accessing others’ posts
  • Default and custom matcher description handling

Implementation Analysis

The testing approach utilizes RSpec’s behavior-driven development patterns with Pundit’s authorization framework.

Technical implementation features:
  • Double objects for user and post mocking
  • Shared example groups for permission testing
  • Custom matcher configuration for flexible descriptions

Technical Details

Testing infrastructure includes:
  • RSpec as the primary testing framework
  • Pundit::RSpec::Matchers for authorization testing
  • Test doubles for dependency isolation
  • Custom matcher description overrides

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolation of test subjects using doubles
  • Proper cleanup of global state in after blocks
  • Clear test case organization and naming
  • Comprehensive error case coverage
  • Flexible test descriptions for improved readability

varvet/pundit

spec/policies/post_policy_spec.rb

            
# frozen_string_literal: true

require "spec_helper"

RSpec.describe PostPolicy do
  let(:user) { double }
  let(:own_post) { double(user: user) }
  let(:other_post) { double(user: double) }
  subject { described_class }

  permissions :update?, :show? do
    it "is successful when all permissions match" do
      should permit(user, own_post)
    end

    it "fails when any permissions do not match" do
      expect do
        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