lib/pact/matchers/matchers.rb in pact-0.1.28 vs lib/pact/matchers/matchers.rb in pact-0.1.35
- old
+ new
@@ -3,12 +3,33 @@
module Pact
module Matchers
NO_DIFF_INDICATOR = 'no difference here!'
+ UNEXPECTED_KEY = '<key not to be present>'
+ DEFAULT_OPTIONS = {allow_unexpected_keys: true, structure: false}.freeze
- def diff expected, actual, options = {}
+ class KeyNotFound
+ def == other
+ other.is_a? KeyNotFound
+ end
+
+ def eql? other
+ self == other
+ end
+
+ def to_s
+ "<key not found>"
+ end
+
+ def to_json options = {}
+ to_s
+ end
+ end
+
+ 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)
@@ -29,36 +50,56 @@
end
def array_diff expected, actual, options
if actual.is_a? Array
if expected.length == actual.length
- difference = []
- diff_found = false
- expected.each_with_index do | item, index|
- if (item_diff = diff(item, actual[index], options)).any?
- diff_found = true
- difference << item_diff
- else
- difference << NO_DIFF_INDICATOR
- end
- end
- diff_found ? difference : {}
+ actual_array_diff expected, actual, options
else
{expected: expected, actual: actual}
end
else
{expected: expected, actual: actual}
end
end
- def hash_diff expected, actual, options
- if actual.is_a? Hash
- expected.keys.inject({}) do |diff, key|
- if (diff_at_key = diff(expected[key], actual[key], options)).any?
- diff[key] = diff_at_key
- end
+ def actual_array_diff expected, actual, options
+ difference = []
+ diff_found = false
+ expected.each_with_index do | item, index|
+ if (item_diff = diff(item, actual.fetch(index, KeyNotFound.new), options)).any?
+ diff_found = true
+ difference << item_diff
+ else
+ difference << NO_DIFF_INDICATOR
+ end
+ end
+ diff_found ? difference : {}
+ end
+
+ def actual_hash_diff expected, actual, options
+ difference = expected.keys.inject({}) do |diff, key|
+ if (diff_at_key = diff(expected[key], actual.fetch(key, KeyNotFound.new), options)).any?
+ diff[key] = diff_at_key
+ end
+ diff
+ end
+ difference.merge(check_for_unexpected_keys(expected, actual, options))
+ end
+
+ 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 => UNEXPECTED_KEY, :actual => actual[key]}
diff
end
+ end
+ end
+
+ def hash_diff expected, actual, options
+ if actual.is_a? Hash
+ actual_hash_diff expected, actual, options
else
{expected: expected, actual: actual}
end
end