Module: Pact::Matchers

Included in:
Consumer::InteractionReplay, Request::Base, Request::Base
Defined in:
lib/pact/matchers/matchers.rb

Constant Summary collapse

NO_DIFF_INDICATOR =
'no difference here!'
DEFAULT_OPTIONS =

UnexpectedKey.new = ‘<key not to be present>’

{allow_unexpected_keys: true, structure: false}.freeze

Instance Method Summary collapse

Instance Method Details

#actual_array_diff(expected, actual, options) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/pact/matchers/matchers.rb', line 49

def actual_array_diff expected, actual, options
  difference = []
  diff_found = false
  length = [expected.length, actual.length].max
  length.times do | index|
    expected_item = expected.fetch(index, Pact::UnexpectedIndex.new)
    actual_item = actual.fetch(index, Pact::IndexNotFound.new)
    if (item_diff = diff(expected_item, actual_item, options)).any?
      diff_found = true
      difference << item_diff
    else
      difference << NO_DIFF_INDICATOR
    end
  end
  diff_found ? difference : {}
end

#actual_hash_diff(expected, actual, options) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/pact/matchers/matchers.rb', line 66

def actual_hash_diff expected, actual, options
  difference = expected.keys.inject({}) do |diff, key|
    if (diff_at_key = diff(expected[key], actual.fetch(key, Pact::KeyNotFound.new), options)).any?
      diff[key] = diff_at_key
    end
    diff
  end
  difference.merge(check_for_unexpected_keys(expected, actual, options))
end

#array_diff(expected, actual, options) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/pact/matchers/matchers.rb', line 41

def array_diff expected, actual, options
  if actual.is_a? Array
    actual_array_diff expected, actual, options
  else
    {expected: expected, actual: actual}
  end
end

#check_for_unexpected_keys(expected, actual, options) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/pact/matchers/matchers.rb', line 76

def check_for_unexpected_keys expected, actual, options
  if options[:allow_unexpected_keys]
    {}
  else
    (actual.keys - expected.keys).inject({}) do | diff, key |
      diff[key] = {:expected => UnexpectedKey.new, :actual => actual[key]}
      diff
    end
  end
end

#class_diff(expected, actual) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/pact/matchers/matchers.rb', line 95

def class_diff expected, actual
  if classes_match? expected, actual
    {}
  else
    {:expected => structure_diff_expected_display(expected), :actual => structure_diff_actual_display(actual)}
  end
end

#classes_match?(expected, actual) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
116
# File 'lib/pact/matchers/matchers.rb', line 111

def classes_match? expected, actual
  #There must be a more elegant way to do this
  expected.class == actual.class ||
    (expected.is_a?(TrueClass) && actual.is_a?(FalseClass)) ||
      (expected.is_a?(FalseClass) && actual.is_a?(TrueClass))
end

#diff(expected, actual, opts = {}) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/pact/matchers/matchers.rb', line 17

def diff expected, actual, opts = {}
  options = DEFAULT_OPTIONS.merge(opts)
  case expected
  when Hash then hash_diff(expected, actual, options)
  when Array then array_diff(expected, actual, options)
  when Pact::Term then diff(expected.matcher, actual, options)
  when Regexp then regexp_diff(expected, actual, options)
  when Pact::SomethingLike then diff(expected.contents, actual, options.merge(:structure => true))
  else object_diff(expected, actual, options)
  end
end

#hash_diff(expected, actual, options) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/pact/matchers/matchers.rb', line 87

def hash_diff expected, actual, options
  if actual.is_a? Hash
    actual_hash_diff expected, actual, options
  else
    {expected: expected, actual: actual}
  end
end

#object_diff(expected, actual, options) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/pact/matchers/matchers.rb', line 118

def object_diff expected, actual, options
  return class_diff(expected, actual) if options[:structure]
  if expected != actual
    {:expected => expected, :actual => actual}
  else
    {}
  end
end

#regexp_diff(regexp, actual, options) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/pact/matchers/matchers.rb', line 33

def regexp_diff regexp, actual, options
  if actual.is_a?(String) && regexp.match(actual)
    {}
  else
    {expected: regexp, actual: actual}
  end
end

#structure_diff(expected, actual) ⇒ Object



29
30
31
# File 'lib/pact/matchers/matchers.rb', line 29

def structure_diff expected, actual
  diff expected, actual, {structure: true}
end

#structure_diff_actual_display(actual) ⇒ Object



103
104
105
# File 'lib/pact/matchers/matchers.rb', line 103

def structure_diff_actual_display actual
  (actual.nil? || actual.is_a?(KeyNotFound) ) ? actual : {:class => actual.class, :value => actual }
end

#structure_diff_expected_display(expected) ⇒ Object



107
108
109
# File 'lib/pact/matchers/matchers.rb', line 107

def structure_diff_expected_display expected
  (expected.nil?) ? expected : {:class => expected.class, eg: expected}
end