Skip to content

Commit

Permalink
feat: read matching rules from v3 format
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Mar 19, 2018
1 parent caaa67b commit 07013de
Show file tree
Hide file tree
Showing 3 changed files with 503 additions and 0 deletions.
112 changes: 112 additions & 0 deletions lib/pact/matching_rules/v3/merge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
require 'pact/array_like'
require 'pact/matching_rules/jsonpath'

module Pact
module MatchingRules
module V3
class Merge

def self.call expected, matching_rules, root_path = '$'
new(expected, matching_rules, root_path).call
end

def initialize expected, matching_rules, root_path
@expected = expected
@matching_rules = standardise_paths(matching_rules)
@root_path = JsonPath.new(root_path).to_s
end

def call
return @expected if @matching_rules.nil? || @matching_rules.empty?
recurse @expected, @root_path
end

private

def standardise_paths matching_rules
return matching_rules if matching_rules.nil? || matching_rules.empty?
matching_rules.each_with_object({}) do | (path, rule), new_matching_rules |
new_matching_rules[JsonPath.new(path).to_s] = rule
end
end

def recurse expected, path
case expected
when Hash then recurse_hash(expected, path)
when Array then recurse_array(expected, path)
else
expected
end
end

def recurse_hash hash, path
hash.each_with_object({}) do | (k, v), new_hash |
new_path = path + "['#{k}']"
new_hash[k] = recurse(wrap(v, new_path), new_path)
end
end

def recurse_array array, path
array_like_children_path = "#{path}[*]*"
parent_match_rule = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first['match']
children_match_rule = @matching_rules[array_like_children_path] && @matching_rules[array_like_children_path]['matchers'] && @matching_rules[array_like_children_path]['matchers'].first && @matching_rules[array_like_children_path]['matchers'].first['match']
min = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first['min']

if min && (children_match_rule == 'type' || (children_match_rule.nil? && parent_match_rule == 'type'))
warn_when_not_one_example_item(array, path)
# log_ignored_rules(path, @matching_rules[path], {'min' => min})
Pact::ArrayLike.new(recurse(array.first, "#{path}[*]"), min: min)
else
new_array = []
array.each_with_index do | item, index |
new_path = path + "[#{index}]"
new_array << recurse(wrap(item, new_path), new_path)
end
new_array
end
end

def warn_when_not_one_example_item array, path
unless array.size == 1
Pact.configuration.error_stream.puts "WARN: Only the first item will be used to match the items in the array at #{path}"
end
end

def wrap object, path
rules = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first
array_rules = @matching_rules["#{path}[*]*"] && @matching_rules["#{path}[*]*"]['matchers'] && @matching_rules["#{path}[*]*"]['matchers'].first
return object unless rules || array_rules

if rules['match'] == 'type' && !rules.has_key?('min')
handle_match_type(object, path, rules)
elsif rules['regex']
handle_regex(object, path, rules)
else
log_ignored_rules(path, rules, {})
object
end
end

def handle_match_type object, path, rules
log_ignored_rules(path, rules, {'match' => 'type'})
Pact::SomethingLike.new(object)
end

def handle_regex object, path, rules
log_ignored_rules(path, rules, {'match' => 'regex', 'regex' => rules['regex']})
Pact::Term.new(generate: object, matcher: Regexp.new(rules['regex']))
end

def log_ignored_rules path, rules, used_rules
dup_rules = rules.dup
used_rules.each_pair do | used_key, used_value |
dup_rules.delete(used_key) if dup_rules[used_key] == used_value
end
if dup_rules.any?
$stderr.puts "WARN: Ignoring unsupported matching rules #{dup_rules} for path #{path}"
end
end
end
end
end
end
27 changes: 27 additions & 0 deletions spec/fixtures/pact-v3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"consumer": {
"name": "Consumer"
},
"provider": {
"name": "Provider"
},
"messages": [
{
"contents": {
"foo": "bar"
},
"description": "Published credit data",
"metaData": {
"contentType": "application/json"
},
"providerState": "or maybe 'scenario'? not sure about this",
"matchingRules": {
"body": {
"$.foo": {
"matchers": [{"match" : "type"}]
}
}
}
}
]
}
Loading

0 comments on commit 07013de

Please sign in to comment.