class Shoulda::Matchers::Independent::DelegateMethodMatcher
@private
def allow_nil
def allow_nil @expects_to_allow_nil_delegate_object = true self end
def as(delegate_method)
def as(delegate_method) @delegate_method = delegate_method self end
def build_delegating_method_prefix(prefix)
def build_delegating_method_prefix(prefix) case prefix when true, nil then delegate_object_reader_method else prefix end end
def call_delegating_method_with_delegate_method_returning(value)
def call_delegating_method_with_delegate_method_returning(value) register_subject_double_collection_to(value) Doublespeak.with_doubles_activated do subject.public_send(delegating_method, *delegated_arguments) end end
def calls_on_delegate_object
def calls_on_delegate_object delegate_object.calls end
def calls_to_delegate_method
def calls_to_delegate_method delegate_object.calls_to(delegate_method) end
def class_or_instance_method_indicator
def class_or_instance_method_indicator if subject_is_a_class? '.' else '#' end end
def class_under_test
def class_under_test if subject_is_a_class? subject else subject.class end end
def delegate_object_received_call?
def delegate_object_received_call? calls_to_delegate_method.any? end
def delegate_object_received_call_with_delegated_arguments?
def delegate_object_received_call_with_delegated_arguments? calls_to_delegate_method.any? do |call| call.args == delegated_arguments end end
def description
def description string = "delegate #{formatted_delegating_method_name} to the " + "#{formatted_delegate_object_reader_method_name} object" if expects_private_delegation? string << ' privately' end if delegated_arguments.any? string << " passing arguments #{delegated_arguments.inspect}" end if delegate_method != delegating_method string << " as #{formatted_delegate_method}" end if expects_to_allow_nil_delegate_object? string << ', allowing ' string << formatted_delegate_object_reader_method_name string << ' to return nil' end string end
def ensure_delegate_object_has_been_specified!
def ensure_delegate_object_has_been_specified! if delegate_object_reader_method.to_s.empty? raise DelegateObjectNotSpecified end end
def expects_private_delegation?
def expects_private_delegation? @expects_private_delegation end
def expects_to_allow_nil_delegate_object?
def expects_to_allow_nil_delegate_object? @expects_to_allow_nil_delegate_object end
def failed_to_allow_nil_delegate_object?
def failed_to_allow_nil_delegate_object? expects_to_allow_nil_delegate_object? && !@subject_handled_nil_delegate_object end
def failed_to_handle_private_delegation?
def failed_to_handle_private_delegation? expects_private_delegation? && !@subject_handled_private_delegation end
def failure_message
def failure_message message = "Expected #{class_under_test} to #{description}.\n\n" if failed_to_allow_nil_delegate_object? || failed_to_handle_private_delegation? message << formatted_delegating_method_name(include_module: true) message << ' did delegate to ' message << formatted_delegate_object_reader_method_name end if failed_to_allow_nil_delegate_object? message << ' when it was non-nil, but it failed to account ' message << 'for when ' message << formatted_delegate_object_reader_method_name message << ' *was* nil.' elsif failed_to_handle_private_delegation? message << ", but 'private: true' is missing." else message << 'Method calls sent to ' message << formatted_delegate_object_reader_method_name( include_module: true, ) message << ": #{formatted_calls_on_delegate_object}" end Shoulda::Matchers.word_wrap(message) end
def failure_message_when_negated
def failure_message_when_negated "Expected #{class_under_test} not to #{description}, but it did." end
def formatted_calls_on_delegate_object
def formatted_calls_on_delegate_object String.new.tap do |string| if calls_on_delegate_object.any? string << "\n\n" calls_on_delegate_object.each_with_index do |call, i| name = call.method_name args = call.args.map(&:inspect).join(', ') string << "#{i + 1}) #{name}(#{args})\n" end else string << ' (none)' end string.rstrip! end end
def formatted_delegate_method(options = {})
def formatted_delegate_method(options = {}) formatted_method_name_for(delegate_method, options) end
def formatted_delegate_object_reader_method_name(options = {})
def formatted_delegate_object_reader_method_name(options = {}) formatted_method_name_for(delegate_object_reader_method, options) end
def formatted_delegating_method_name(options = {})
def formatted_delegating_method_name(options = {}) formatted_method_name_for(delegating_method, options) end
def formatted_method_name_for(method_name, options)
def formatted_method_name_for(method_name, options) possible_class_under_test(options) + class_or_instance_method_indicator + method_name.to_s end
def in_context(context)
def in_context(context) @context = MatcherContext.new(context) self end
def initialize(delegating_method)
def initialize(delegating_method) @delegating_method = delegating_method @delegate_method = @delegating_method @delegate_object = Doublespeak::ObjectDouble.new @context = nil @subject = nil @delegate_object_reader_method = nil @delegated_arguments = [] @expects_to_allow_nil_delegate_object = false @expects_private_delegation = false end
def matches?(subject)
def matches?(subject) @subject = subject ensure_delegate_object_has_been_specified! subject_has_delegating_method? && subject_has_delegate_object_reader_method? && subject_delegates_to_delegate_object_correctly? && subject_handles_nil_delegate_object? && subject_handles_private_delegation? end
def possible_class_under_test(options)
def possible_class_under_test(options) if options[:include_module] class_under_test.to_s else '' end end
def privately_call_delegating_method_with_delegate_method_returning(value)
def privately_call_delegating_method_with_delegate_method_returning(value) register_subject_double_collection_to(value) Doublespeak.with_doubles_activated do subject.__send__(delegating_method, *delegated_arguments) end end
def register_subject_double_collection_to(returned_value)
def register_subject_double_collection_to(returned_value) double_collection = Doublespeak.double_collection_for(subject.singleton_class) double_collection.register_stub(delegate_object_reader_method). to_return(returned_value) end
def subject
def subject @subject end
def subject_delegates_to_delegate_object_correctly?
def subject_delegates_to_delegate_object_correctly? if expects_private_delegation? privately_call_delegating_method_with_delegate_method_returning(delegate_object) else call_delegating_method_with_delegate_method_returning(delegate_object) end if delegated_arguments.any? delegate_object_received_call_with_delegated_arguments? else delegate_object_received_call? end end
def subject_handles_nil_delegate_object?
def subject_handles_nil_delegate_object? @subject_handled_nil_delegate_object = if expects_to_allow_nil_delegate_object? begin call_delegating_method_with_delegate_method_returning(nil) true rescue Module::DelegationError false rescue NoMethodError => e if e.message =~ /undefined method [`']#{delegate_method}[`'] for nil/ false else raise e end end else true end end
def subject_handles_private_delegation?
def subject_handles_private_delegation? @subject_handled_private_delegation = if expects_private_delegation? begin call_delegating_method_with_delegate_method_returning(delegate_object) true rescue Module::DelegationError false rescue NoMethodError => e if e.message =~ /private method [`']#{delegating_method}[`'] called for/ true else raise e end end else true end end
def subject_has_delegate_object_reader_method?
def subject_has_delegate_object_reader_method? subject.respond_to?(delegate_object_reader_method, true) end
def subject_has_delegating_method?
def subject_has_delegating_method? if expects_private_delegation? !subject.respond_to?(delegating_method) && subject.respond_to?(delegating_method, true) else subject.respond_to?(delegating_method) end end
def subject_is_a_class?
def subject_is_a_class? if @subject @subject.is_a?(Class) else context.subject_is_a_class? end end
def to(delegate_object_reader_method)
def to(delegate_object_reader_method) @delegate_object_reader_method = delegate_object_reader_method self end
def with_arguments(*arguments)
def with_arguments(*arguments) @delegated_arguments = arguments self end
def with_prefix(prefix = nil)
def with_prefix(prefix = nil) @delegating_method = :"#{build_delegating_method_prefix(prefix)}_#{delegate_method}" delegate_method self end
def with_private
def with_private @expects_private_delegation = true self end