Skip to content

Commit 7dc76dc

Browse files
committedJul 25, 2018
fix: correctly handle an 'each like' inside a 'like'
Closes: pact-foundation#47 pact-foundation/pact-go#54 pact-foundation/pact-provider-verifier#24
1 parent 8913ce0 commit 7dc76dc

File tree

4 files changed

+101
-26
lines changed

4 files changed

+101
-26
lines changed
 

‎lib/pact/matching_rules/merge.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def wrap object, path
9292

9393
def handle_match_type object, path, rules
9494
log_used_rule(path, 'match', 'type')
95-
Pact::SomethingLike.new(object)
95+
Pact::SomethingLike.new(recurse(object, path))
9696
end
9797

9898
def handle_regex object, path, rules

‎lib/pact/matching_rules/v3/merge.rb

+34-18
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ def initialize expected, matching_rules, root_path
1818

1919
def call
2020
return @expected if @matching_rules.nil? || @matching_rules.empty?
21-
recurse @expected, @root_path
21+
recurse(@expected, @root_path).tap { log_ignored_rules }
2222
end
2323

2424
private
2525

2626
def standardise_paths matching_rules
2727
return matching_rules if matching_rules.nil? || matching_rules.empty?
28-
matching_rules.each_with_object({}) do | (path, rule), new_matching_rules |
29-
new_matching_rules[JsonPath.new(path).to_s] = rule
28+
matching_rules.each_with_object({}) do | (path, rules), new_matching_rules |
29+
new_matching_rules[JsonPath.new(path).to_s] = Marshal.load(Marshal.dump(rules)) # simplest way to deep clone
3030
end
3131
end
3232

@@ -47,14 +47,14 @@ def recurse_hash hash, path
4747
end
4848

4949
def recurse_array array, path
50+
51+
parent_match_rule = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first.delete('match')
5052
array_like_children_path = "#{path}[*]*"
51-
parent_match_rule = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first['match']
52-
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']
53-
min = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first['min']
53+
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.delete('match')
54+
min = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first && @matching_rules[path]['matchers'].first.delete('min')
5455

5556
if min && (children_match_rule == 'type' || (children_match_rule.nil? && parent_match_rule == 'type'))
5657
warn_when_not_one_example_item(array, path)
57-
# log_ignored_rules(path, @matching_rules[path], {'min' => min})
5858
Pact::ArrayLike.new(recurse(array.first, "#{path}[*]"), min: min)
5959
else
6060
new_array = []
@@ -82,30 +82,46 @@ def wrap object, path
8282
elsif rules['regex']
8383
handle_regex(object, path, rules)
8484
else
85-
log_ignored_rules(path, rules, {})
85+
#log_ignored_rules(path, rules, {})
8686
object
8787
end
8888
end
8989

9090
def handle_match_type object, path, rules
91-
log_ignored_rules(path, rules, {'match' => 'type'})
92-
Pact::SomethingLike.new(object)
91+
rules.delete('match')
92+
Pact::SomethingLike.new(recurse(object, path))
9393
end
9494

9595
def handle_regex object, path, rules
96-
log_ignored_rules(path, rules, {'match' => 'regex', 'regex' => rules['regex']})
97-
Pact::Term.new(generate: object, matcher: Regexp.new(rules['regex']))
96+
rules.delete('match')
97+
regex = rules.delete('regex')
98+
Pact::Term.new(generate: object, matcher: Regexp.new(regex))
9899
end
99100

100-
def log_ignored_rules path, rules, used_rules
101-
dup_rules = rules.dup
102-
used_rules.each_pair do | used_key, used_value |
103-
dup_rules.delete(used_key) if dup_rules[used_key] == used_value
101+
def log_ignored_rules
102+
@matching_rules.each do | jsonpath, rules_hash |
103+
rules_array = rules_hash["matchers"]
104+
((rules_array.length - 1)..0).each do | index |
105+
rules_array.delete_at(index) if rules_array[index].empty?
106+
end
104107
end
105-
if dup_rules.any?
106-
$stderr.puts "WARN: Ignoring unsupported matching rules #{dup_rules} for path #{path}"
108+
109+
if @matching_rules.any?
110+
@matching_rules.each do | path, rules_hash |
111+
rules_hash.each do | key, value |
112+
$stderr.puts "WARN: Ignoring unsupported #{key} #{value} for path #{path}" if value.any?
113+
end
114+
end
107115
end
108116
end
117+
118+
def find_rule(path, key)
119+
@matching_rules[path] && @matching_rules[path][key]
120+
end
121+
122+
def log_used_rule path, key, value
123+
@used_rules << [path, key, value]
124+
end
109125
end
110126
end
111127
end

‎spec/integration/matching_rules_extract_and_merge_spec.rb

+41-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
require 'pact/term'
22
require 'pact/something_like'
33
require 'pact/matching_rules/extract'
4+
require 'pact/matching_rules/v3/extract'
45
require 'pact/matching_rules/merge'
6+
require 'pact/matching_rules/v3/merge'
57
require 'pact/reification'
68

79
describe "converting Pact::Term and Pact::SomethingLike to matching rules and back again" do
@@ -10,6 +12,9 @@
1012
let(:matching_rules) { Pact::MatchingRules::Extract.(expected) }
1113
let(:recreated_expected) { Pact::MatchingRules::Merge.(example, matching_rules)}
1214

15+
let(:recreated_expected_v3) { Pact::MatchingRules::V3::Merge.(example, matching_rules_v3) }
16+
let(:matching_rules_v3) { Pact::MatchingRules::V3::Extract.(expected) }
17+
1318
context "with a Pact::Term" do
1419
let(:expected) do
1520
{
@@ -21,9 +26,29 @@
2126
}
2227
end
2328

24-
it "recreates the same object hierarchy" do
29+
it "recreates the same object hierarchy with v2 matching" do
30+
expect(recreated_expected).to eq expected
31+
end
32+
33+
it "recreates the same object hierarchy with v3 matching" do
34+
expect(recreated_expected_v3).to eq expected
35+
end
36+
end
37+
38+
context "with a Pact::SomethingLike containing a Pact::ArrayLike" do
39+
let(:expected) do
40+
{
41+
body: Pact::SomethingLike.new(children: Pact::ArrayLike.new("foo", min: 2))
42+
}
43+
end
44+
45+
it "recreates the same object hierarchy with v2 matching" do
2546
expect(recreated_expected).to eq expected
2647
end
48+
49+
it "recreates the same object hierarchy with v3 matching" do
50+
expect(recreated_expected_v3).to eq expected
51+
end
2752
end
2853

2954
context "with a Pact::SomethingLike" do
@@ -37,9 +62,13 @@
3762
}
3863
end
3964

40-
it "recreates the same object hierarchy" do
65+
it "recreates the same object hierarchy with v2 matching" do
4166
expect(recreated_expected).to eq expected
4267
end
68+
69+
it "recreates the same object hierarchy with v3 matching" do
70+
expect(recreated_expected_v3).to eq expected
71+
end
4372
end
4473

4574
context "with a Pact::SomethingLike containing a Hash" do
@@ -61,9 +90,13 @@
6190
}
6291
end
6392

64-
it "recreates the same object hierarchy" do
93+
it "recreates the same object hierarchy with v2 matching" do
6594
expect(recreated_expected).to eq expected
6695
end
96+
97+
it "recreates the same object hierarchy with v3 matching" do
98+
expect(recreated_expected_v3).to eq expected
99+
end
67100
end
68101

69102
context "with a Pact::SomethingLike containing an Array" do
@@ -83,8 +116,12 @@
83116
}
84117
end
85118

86-
it "recreates the same object hierarchy" do
119+
it "recreates the same object hierarchy with v2 matching" do
87120
expect(recreated_expected).to eq expected
88121
end
122+
123+
it "recreates the same object hierarchy with v3 matching" do
124+
expect(recreated_expected_v3).to eq expected
125+
end
89126
end
90127
end

‎spec/lib/pact/matching_rules/v3/merge_spec.rb

+25-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ module V3
77
subject { Merge.(expected, matching_rules) }
88

99
before do
10-
allow($stderr).to receive(:puts)
10+
allow($stderr).to receive(:puts) do | message |
11+
raise "Was not expecting stderr to receive #{message.inspect} in this spec. This may be because of a missed rule deletion in Merge."
12+
end
1113
end
1214

1315
describe "no recognised rules" do
16+
before do
17+
allow($stderr).to receive(:puts)
18+
end
19+
1420
let(:expected) do
1521
{
1622
"_links" => {
@@ -65,6 +71,10 @@ module V3
6571
end
6672

6773
describe "type based matching" do
74+
before do
75+
allow($stderr).to receive(:puts)
76+
end
77+
6878
let(:expected) do
6979
{
7080
"name" => "Mary"
@@ -88,11 +98,19 @@ module V3
8898
subject
8999
end
90100

101+
it "does not alter the passed in rules hash" do
102+
original_matching_rules = JSON.parse(matching_rules.to_json)
103+
subject
104+
expect(matching_rules).to eq original_matching_rules
105+
end
91106
end
92107

93108
describe "regular expressions" do
94-
95109
describe "in a hash" do
110+
before do
111+
allow($stderr).to receive(:puts)
112+
end
113+
96114
let(:expected) do
97115
{
98116
"_links" => {
@@ -275,6 +293,10 @@ module V3
275293
end
276294

277295
describe "with an example array with more than one item" do
296+
before do
297+
allow($stderr).to receive(:puts)
298+
end
299+
278300
let(:expected) do
279301
{
280302

@@ -292,7 +314,7 @@ module V3
292314
}
293315
end
294316

295-
xit "doesn't warn about the min size being ignored" do
317+
it "doesn't warn about the min size being ignored" do
296318
expect(Pact.configuration.error_stream).to receive(:puts).once
297319
subject
298320
end

0 commit comments

Comments
 (0)