Class: ActionPolicy::RSpec::BeAuthorizedTo

Inherits:
RSpec::Matchers::BuiltIn::BaseMatcher
  • Object
show all
Defined in:
lib/action_policy/rspec/be_authorized_to.rb

Overview

Authorization matcher ‘be_authorized_to`.

Verifies that a block of code has been authorized using specific policy.

Example:

# in controller/request specs
subject { patch :update, id: product.id }

it "is authorized" do
  expect { subject }
    .to be_authorized_to(:manage?, product)
    .with(ProductPolicy)
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rule, target) ⇒ BeAuthorizedTo

Returns a new instance of BeAuthorizedTo.



25
26
27
28
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 25

def initialize(rule, target)
  @rule = rule
  @target = target
end

Instance Attribute Details

#actual_callsObject (readonly)

Returns the value of attribute actual_calls.



23
24
25
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 23

def actual_calls
  @actual_calls
end

#contextObject (readonly)

Returns the value of attribute context.



23
24
25
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 23

def context
  @context
end

#policyObject (readonly)

Returns the value of attribute policy.



23
24
25
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 23

def policy
  @policy
end

#ruleObject (readonly)

Returns the value of attribute rule.



23
24
25
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 23

def rule
  @rule
end

#targetObject (readonly)

Returns the value of attribute target.



23
24
25
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 23

def target
  @target
end

Instance Method Details

#actual_calls_messageObject



70
71
72
73
74
75
76
77
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 70

def actual_calls_message
  if actual_calls.empty?
    "no authorization calls have been made"
  else
    "the following calls were encountered:\n" \
    "#{formatted_calls}"
  end
end

#does_not_match?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 57

def does_not_match?(*)
  raise "This matcher doesn't support negation"
end

#failure_messageObject



63
64
65
66
67
68
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 63

def failure_message
  "expected #{formatted_record} " \
  "to be authorized with #{policy}##{rule}, " \
  "#{context ? "and context #{context.inspect}, " : ""}" \
  "but #{actual_calls_message}"
end

#formatted_callsObject



79
80
81
82
83
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 79

def formatted_calls
  actual_calls.map do
    " - #{_1.inspect}"
  end.join("\n")
end

#formatted_record(record = target) ⇒ Object



85
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 85

def formatted_record(record = target) = ::RSpec::Support::ObjectFormatter.format(record)

#match(_expected, actual) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 40

def match(_expected, actual)
  raise "This matcher only supports block expectations" unless actual.is_a?(Proc)

  @policy ||= ::ActionPolicy.lookup(target)
  @context ||= nil

  begin
    ActionPolicy::Testing::AuthorizeTracker.tracking { actual.call }
  rescue ActionPolicy::Unauthorized
    # we don't want to care about authorization result
  end

  @actual_calls = ActionPolicy::Testing::AuthorizeTracker.calls

  actual_calls.any? { _1.matches?(policy, rule, target, context) }
end

#supports_block_expectations?Boolean

Returns:

  • (Boolean)


61
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 61

def supports_block_expectations?() = true

#with(policy) ⇒ Object



30
31
32
33
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 30

def with(policy)
  @policy = policy
  self
end

#with_context(context) ⇒ Object



35
36
37
38
# File 'lib/action_policy/rspec/be_authorized_to.rb', line 35

def with_context(context)
  @context = context
  self
end