1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
module Bogus
class Interaction < Struct.new(:method, :args, :return_value, :error, :has_result)
attr_accessor :arguments
def self.same?(opts = {})
InteractionComparator.new(opts).same?
end
def initialize(method, args, &block)
self.method = method
self.args = args
if block_given?
evaluate_return_value(block)
self.has_result = true
end
end
private
def evaluate_return_value(block)
self.return_value = block.call
rescue => e
self.error = e.class
end
class InteractionComparator
attr_reader :recorded, :stubbed
def initialize(opts = {})
@recorded = opts.fetch(:recorded)
@stubbed = opts.fetch(:stubbed)
end
def same?
return false unless recorded.method == stubbed.method
return false unless same_result?
same_args?
end
private
def same_args?
ArgumentComparator.new(recorded: recorded.args, stubbed: stubbed.args).same?
end
def same_result?
return true unless recorded.has_result && stubbed.has_result
recorded.return_value == stubbed.return_value && recorded.error == stubbed.error
end
end
class ArgumentComparator
attr_reader :recorded, :stubbed
def initialize(opts = {})
@recorded = opts.fetch(:recorded)
@stubbed = opts.fetch(:stubbed)
end
def same?
return true if with_matcher_args?
stubbed == recorded_without_defaults
end
private
def recorded_without_defaults
without_defaults = recorded.reject{|v| DefaultValue == v}
remove_default_keywords(without_defaults)
end
def remove_default_keywords(recorded)
return recorded unless recorded_has_keyword?
positional = recorded[0...-1]
keyword = recorded.last
without_defaults = keyword.reject{|_, v| DefaultValue == v}
return positional if without_defaults.empty?
positional + [without_defaults]
end
def with_matcher_args?
WithArguments.matches?(stubbed: stubbed, recorded: recorded_without_defaults)
end
def recorded_has_keyword?
last_recorded = recorded.last
return false unless last_recorded.is_a?(Hash)
last_recorded.values.any? { |v| DefaultValue == v }
end
end
end
end
|