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