pact-support 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/pact/consumer_contract/consumer_contract.rb +15 -9
- data/lib/pact/consumer_contract/http_consumer_contract_parser.rb +37 -0
- data/lib/pact/consumer_contract/interaction.rb +32 -4
- data/lib/pact/matching_rules.rb +10 -5
- data/lib/pact/matching_rules/v3/merge.rb +112 -0
- data/lib/pact/specification_version.rb +18 -0
- data/lib/pact/support/version.rb +1 -1
- data/spec/fixtures/pact-http-v2.json +36 -0
- data/spec/fixtures/pact-http-v3.json +36 -0
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +35 -32
- data/spec/lib/pact/consumer_contract/http_consumer_contract_parser_spec.rb +25 -0
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +1 -1
- data/spec/lib/pact/matching_rules/v3/merge_spec.rb +364 -0
- data/spec/lib/pact/matching_rules_spec.rb +82 -0
- data/tasks/spec.rake +0 -1
- metadata +15 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbfe3583ddef289cebbe55fdfe7319853eb2c88b
|
4
|
+
data.tar.gz: cacbf113d031f4af3552ca441d12b1f47c1decf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f100ad0607607f0ef0de629774b4f8fa4eb6a66ff0b556335a510111fa64c0f494cc86c7f8e52d455ceedb683263c57b00b669ee51029c8ce32e97ebabb7a67b
|
7
|
+
data.tar.gz: 50691e89980a9fb1af2b38ac5f9b1c1b50d31e0476816ea36cda7715cf9b797bb0230713f837356dd3f6414b0b948a9ac2a9be111cb8587f29b47cf7f17b6f77
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
<a name="v1.5.0"></a>
|
2
|
+
### v1.5.0 (2018-03-23)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* parse pacts without a specification version as v2 ([a69b5e6](/../../commit/a69b5e6))
|
7
|
+
* locate matching rules correctly for v3 pacts ([0f22db2](/../../commit/0f22db2))
|
8
|
+
* read matching rules from v3 format ([07013de](/../../commit/07013de))
|
9
|
+
* allow different consumer contract parsers to be registered ([531ab3a](/../../commit/531ab3a))
|
10
|
+
* update message classes to support pact-message ([2e48892](/../../commit/2e48892))
|
11
|
+
* add request and response to message ([93839cf](/../../commit/93839cf))
|
12
|
+
|
13
|
+
* **message contracts**
|
14
|
+
* dynamically mix in new and from_hash into Pact::Message ([c0c3ad5](/../../commit/c0c3ad5))
|
15
|
+
* read message pact into Ruby object ([6573bd4](/../../commit/6573bd4))
|
16
|
+
|
17
|
+
|
1
18
|
<a name="v1.3.1"></a>
|
2
19
|
### v1.3.1 (2018-03-19)
|
3
20
|
|
@@ -10,9 +10,9 @@ require 'pact/consumer_contract/service_consumer'
|
|
10
10
|
require 'pact/consumer_contract/service_provider'
|
11
11
|
require 'pact/consumer_contract/interaction'
|
12
12
|
require 'pact/consumer_contract/pact_file'
|
13
|
+
require 'pact/consumer_contract/http_consumer_contract_parser'
|
13
14
|
|
14
15
|
module Pact
|
15
|
-
|
16
16
|
class ConsumerContract
|
17
17
|
|
18
18
|
include SymbolizeKeys
|
@@ -29,13 +29,19 @@ module Pact
|
|
29
29
|
@provider = attributes[:provider]
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.add_parser consumer_contract_parser
|
33
|
+
parsers << consumer_contract_parser
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.parsers
|
37
|
+
@parsers ||= [Pact::HttpConsumerContractParser.new]
|
38
|
+
end
|
39
|
+
|
32
40
|
def self.from_hash(hash)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
:interactions => hash[:interactions].collect { |h| Interaction.from_hash(h)}
|
38
|
-
)
|
41
|
+
parsers.each do | parser |
|
42
|
+
return parser.call(hash) if parser.can_parse?(hash)
|
43
|
+
end
|
44
|
+
raise Pact::Error.new("No consumer contract parser found for hash: #{hash}")
|
39
45
|
end
|
40
46
|
|
41
47
|
def self.from_json string
|
@@ -54,9 +60,9 @@ module Pact
|
|
54
60
|
def find_interaction criteria
|
55
61
|
interactions = find_interactions criteria
|
56
62
|
if interactions.size == 0
|
57
|
-
raise "Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
|
63
|
+
raise Pact::Error.new("Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}.")
|
58
64
|
elsif interactions.size > 1
|
59
|
-
raise "Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
|
65
|
+
raise Pact::Error.new("Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}.")
|
60
66
|
end
|
61
67
|
interactions.first
|
62
68
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'pact/specification_version'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
class HttpConsumerContractParser
|
5
|
+
include SymbolizeKeys
|
6
|
+
|
7
|
+
def call(hash)
|
8
|
+
hash = symbolize_keys(hash)
|
9
|
+
v = pact_specification_version(hash)
|
10
|
+
options = { pact_specification_version: v }
|
11
|
+
|
12
|
+
if v.after? 3
|
13
|
+
Pact.configuration.error_stream.puts "WARN: This code only knows how to parse v3 pacts, attempting to parse v#{options[:pact_specification_version]} pact using v3 code."
|
14
|
+
end
|
15
|
+
|
16
|
+
interactions = hash[:interactions].collect { |hash| Interaction.from_hash(hash, options) }
|
17
|
+
ConsumerContract.new(
|
18
|
+
:consumer => ServiceConsumer.from_hash(hash[:consumer]),
|
19
|
+
:provider => ServiceProvider.from_hash(hash[:provider]),
|
20
|
+
:interactions => interactions
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def pact_specification_version hash
|
25
|
+
# TODO handle all 3 ways of defining this...
|
26
|
+
# metadata.pactSpecificationVersion
|
27
|
+
maybe_pact_specification_version_1 = hash[:metadata] && hash[:metadata]['pactSpecification'] && hash[:metadata]['pactSpecification']['version']
|
28
|
+
maybe_pact_specification_version_2 = hash[:metadata] && hash[:metadata]['pactSpecificationVersion']
|
29
|
+
pact_specification_version = maybe_pact_specification_version_1 || maybe_pact_specification_version_2
|
30
|
+
pact_specification_version ? Pact::SpecificationVersion.new(pact_specification_version) : Pact::SpecificationVersion::NIL_VERSION
|
31
|
+
end
|
32
|
+
|
33
|
+
def can_parse?(hash)
|
34
|
+
hash.key?('interactions') || hash.key?(:interactions)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -4,9 +4,10 @@ require 'pact/symbolize_keys'
|
|
4
4
|
require 'pact/shared/active_support_support'
|
5
5
|
require 'pact/matching_rules'
|
6
6
|
require 'pact/errors'
|
7
|
+
require 'pact/specification_version'
|
7
8
|
|
8
9
|
module Pact
|
9
|
-
|
10
|
+
class Interaction
|
10
11
|
include ActiveSupportSupport
|
11
12
|
include SymbolizeKeys
|
12
13
|
|
@@ -19,10 +20,33 @@ module Pact
|
|
19
20
|
@provider_state = attributes[:provider_state] || attributes[:providerState]
|
20
21
|
end
|
21
22
|
|
22
|
-
def self.from_hash hash
|
23
|
-
|
23
|
+
def self.from_hash hash, options = {}
|
24
|
+
pact_specification_version = options[:pact_specification_version] || Pact::SpecificationVersion::NIL_VERSION
|
25
|
+
case pact_specification_version.major
|
26
|
+
when nil, 0, 1, 2 then parse_v2_interaction(hash, pact_specification_version: pact_specification_version)
|
27
|
+
else parse_v3_interaction(hash, pact_specification_version: pact_specification_version)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.parse_v2_interaction hash, options
|
32
|
+
request_hash = Pact::MatchingRules.merge(hash['request'], hash['request']['matchingRules'], options)
|
33
|
+
request = Pact::Request::Expected.from_hash(request_hash)
|
34
|
+
response_hash = Pact::MatchingRules.merge(hash['response'], hash['response']['matchingRules'], options)
|
35
|
+
response = Pact::Response.from_hash(response_hash)
|
36
|
+
new(symbolize_keys(hash).merge(request: request, response: response))
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse_v3_interaction hash, options
|
40
|
+
|
41
|
+
request_hash = hash['request'].keys.each_with_object({}) do | key, new_hash |
|
42
|
+
new_hash[key] = Pact::MatchingRules.merge(hash['request'][key], hash['request'].fetch('matchingRules', {})[key], options)
|
43
|
+
end
|
24
44
|
request = Pact::Request::Expected.from_hash(request_hash)
|
25
|
-
|
45
|
+
|
46
|
+
response_hash = hash['response'].keys.each_with_object({}) do | key, new_hash |
|
47
|
+
new_hash[key] = Pact::MatchingRules.merge(hash['response'][key], hash['response'].fetch('matchingRules', {})[key], options)
|
48
|
+
end
|
49
|
+
|
26
50
|
response = Pact::Response.from_hash(response_hash)
|
27
51
|
new(symbolize_keys(hash).merge(request: request, response: response))
|
28
52
|
end
|
@@ -36,6 +60,10 @@ module Pact
|
|
36
60
|
}
|
37
61
|
end
|
38
62
|
|
63
|
+
def http?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
39
67
|
def validate!
|
40
68
|
raise Pact::InvalidInteractionError.new(self) unless description && request && response
|
41
69
|
end
|
data/lib/pact/matching_rules.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'pact/matching_rules/extract'
|
2
2
|
require 'pact/matching_rules/merge'
|
3
|
+
require 'pact/matching_rules/v3/merge'
|
3
4
|
|
4
5
|
module Pact
|
5
6
|
module MatchingRules
|
6
7
|
|
7
8
|
# @api public Used by pact-mock_service
|
8
|
-
def self.extract object_graph
|
9
|
+
def self.extract object_graph, options = {}
|
9
10
|
Extract.(object_graph)
|
10
11
|
end
|
11
12
|
|
12
|
-
def self.merge object_graph, matching_rules
|
13
|
-
|
13
|
+
def self.merge object_graph, matching_rules, options = {}
|
14
|
+
case options[:pact_specification_version].major
|
15
|
+
when nil, 0, 1, 2
|
16
|
+
Merge.(object_graph, matching_rules)
|
17
|
+
else
|
18
|
+
V3::Merge.(object_graph, matching_rules)
|
19
|
+
end
|
14
20
|
end
|
15
|
-
|
16
21
|
end
|
17
|
-
end
|
22
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'pact/array_like'
|
2
|
+
require 'pact/matching_rules/jsonpath'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module MatchingRules
|
6
|
+
module V3
|
7
|
+
class Merge
|
8
|
+
|
9
|
+
def self.call expected, matching_rules, root_path = '$'
|
10
|
+
new(expected, matching_rules, root_path).call
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize expected, matching_rules, root_path
|
14
|
+
@expected = expected
|
15
|
+
@matching_rules = standardise_paths(matching_rules)
|
16
|
+
@root_path = JsonPath.new(root_path).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
return @expected if @matching_rules.nil? || @matching_rules.empty?
|
21
|
+
recurse @expected, @root_path
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def standardise_paths matching_rules
|
27
|
+
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
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def recurse expected, path
|
34
|
+
case expected
|
35
|
+
when Hash then recurse_hash(expected, path)
|
36
|
+
when Array then recurse_array(expected, path)
|
37
|
+
else
|
38
|
+
expected
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def recurse_hash hash, path
|
43
|
+
hash.each_with_object({}) do | (k, v), new_hash |
|
44
|
+
new_path = path + "['#{k}']"
|
45
|
+
new_hash[k] = recurse(wrap(v, new_path), new_path)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def recurse_array array, path
|
50
|
+
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']
|
54
|
+
|
55
|
+
if min && (children_match_rule == 'type' || (children_match_rule.nil? && parent_match_rule == 'type'))
|
56
|
+
warn_when_not_one_example_item(array, path)
|
57
|
+
# log_ignored_rules(path, @matching_rules[path], {'min' => min})
|
58
|
+
Pact::ArrayLike.new(recurse(array.first, "#{path}[*]"), min: min)
|
59
|
+
else
|
60
|
+
new_array = []
|
61
|
+
array.each_with_index do | item, index |
|
62
|
+
new_path = path + "[#{index}]"
|
63
|
+
new_array << recurse(wrap(item, new_path), new_path)
|
64
|
+
end
|
65
|
+
new_array
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def warn_when_not_one_example_item array, path
|
70
|
+
unless array.size == 1
|
71
|
+
Pact.configuration.error_stream.puts "WARN: Only the first item will be used to match the items in the array at #{path}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def wrap object, path
|
76
|
+
rules = @matching_rules[path] && @matching_rules[path]['matchers'] && @matching_rules[path]['matchers'].first
|
77
|
+
array_rules = @matching_rules["#{path}[*]*"] && @matching_rules["#{path}[*]*"]['matchers'] && @matching_rules["#{path}[*]*"]['matchers'].first
|
78
|
+
return object unless rules || array_rules
|
79
|
+
|
80
|
+
if rules['match'] == 'type' && !rules.has_key?('min')
|
81
|
+
handle_match_type(object, path, rules)
|
82
|
+
elsif rules['regex']
|
83
|
+
handle_regex(object, path, rules)
|
84
|
+
else
|
85
|
+
log_ignored_rules(path, rules, {})
|
86
|
+
object
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def handle_match_type object, path, rules
|
91
|
+
log_ignored_rules(path, rules, {'match' => 'type'})
|
92
|
+
Pact::SomethingLike.new(object)
|
93
|
+
end
|
94
|
+
|
95
|
+
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']))
|
98
|
+
end
|
99
|
+
|
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
|
104
|
+
end
|
105
|
+
if dup_rules.any?
|
106
|
+
$stderr.puts "WARN: Ignoring unsupported matching rules #{dup_rules} for path #{path}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Pact
|
2
|
+
class SpecificationVersion < Gem::Version
|
3
|
+
|
4
|
+
NIL_VERSION = Pact::SpecificationVersion.new('')
|
5
|
+
|
6
|
+
def major
|
7
|
+
segments.first
|
8
|
+
end
|
9
|
+
|
10
|
+
def === other
|
11
|
+
major && major == other
|
12
|
+
end
|
13
|
+
|
14
|
+
def after? other
|
15
|
+
major && other < major
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/pact/support/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"consumer": {
|
3
|
+
"name": "some-test-consumer"
|
4
|
+
},
|
5
|
+
"provider": {
|
6
|
+
"name": "an unknown provider"
|
7
|
+
},
|
8
|
+
"interactions": [
|
9
|
+
{
|
10
|
+
"description": "a test request",
|
11
|
+
"request": {
|
12
|
+
"method": "get",
|
13
|
+
"path": "/weather",
|
14
|
+
"query": ""
|
15
|
+
},
|
16
|
+
"response": {
|
17
|
+
"matchingRules": {
|
18
|
+
"$.headers.Content-Type" : {
|
19
|
+
"match": "regex", "regex": "json"
|
20
|
+
},
|
21
|
+
"$.body.message" : {
|
22
|
+
"match": "regex", "regex": "sun"
|
23
|
+
}
|
24
|
+
},
|
25
|
+
"status": 200,
|
26
|
+
"headers" : {
|
27
|
+
"Content-Type": "foo/json"
|
28
|
+
},
|
29
|
+
"body": {
|
30
|
+
"message" : "sunful"
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"provider_state": "the weather is sunny"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"consumer": {
|
3
|
+
"name": "consumer"
|
4
|
+
},
|
5
|
+
"interactions": [
|
6
|
+
{
|
7
|
+
"description": "a test request",
|
8
|
+
"providerState": "the weather is sunny",
|
9
|
+
"request": {
|
10
|
+
"method": "get",
|
11
|
+
"path": "/foo"
|
12
|
+
},
|
13
|
+
"response": {
|
14
|
+
"body": {
|
15
|
+
"foo": "bar"
|
16
|
+
},
|
17
|
+
"matchingRules": {
|
18
|
+
"body": {
|
19
|
+
"$.foo": {
|
20
|
+
"matchers": [{ "match": "type" }]
|
21
|
+
}
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"status": 200
|
25
|
+
}
|
26
|
+
}
|
27
|
+
],
|
28
|
+
"provider": {
|
29
|
+
"name": "provider"
|
30
|
+
},
|
31
|
+
"metadata": {
|
32
|
+
"pactSpecification": {
|
33
|
+
"version": "3.0"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
@@ -3,50 +3,53 @@ require 'pact/consumer_contract'
|
|
3
3
|
|
4
4
|
module Pact
|
5
5
|
describe ConsumerContract do
|
6
|
-
|
7
6
|
describe ".from_json" do
|
7
|
+
|
8
8
|
let(:loaded_pact) { ConsumerContract.from_json(string) }
|
9
|
-
context "when the top level object is a ConsumerContract" do
|
10
|
-
let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}, "response": {"status" : 200}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
context "with an HTTP contract" do
|
11
|
+
context "when the top level object is a ConsumerContract" do
|
12
|
+
let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}, "response": {"status" : 200}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
it "should create a Pact" do
|
15
|
+
expect(loaded_pact).to be_instance_of ConsumerContract
|
16
|
+
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
it "should have interactions" do
|
19
|
+
expect(loaded_pact.interactions).to be_instance_of Array
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
22
|
+
it "should have a consumer" do
|
23
|
+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
|
24
|
+
end
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
expect(loaded_pact).to be_instance_of ConsumerContract
|
26
|
+
it "should have a provider" do
|
27
|
+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
|
28
|
+
end
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
context "with old 'producer' key" do
|
32
|
+
let(:string) { File.read('./spec/support/a_consumer-a_producer.json')}
|
33
|
+
it "should create a Pact" do
|
34
|
+
expect(loaded_pact).to be_instance_of ConsumerContract
|
35
|
+
end
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
it "should have interactions" do
|
38
|
+
expect(loaded_pact.interactions).to be_instance_of Array
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
41
|
+
it "should have a consumer" do
|
42
|
+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
|
43
|
+
end
|
47
44
|
|
48
|
-
|
49
|
-
|
45
|
+
it "should have a provider" do
|
46
|
+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
|
47
|
+
expect(loaded_pact.provider.name).to eq "an old producer"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should have a provider_state" do
|
51
|
+
expect(loaded_pact.interactions.first.provider_state).to eq 'state one'
|
52
|
+
end
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'pact/consumer_contract/http_consumer_contract_parser'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
describe HttpConsumerContractParser do
|
5
|
+
describe "#call integration test" do
|
6
|
+
subject { HttpConsumerContractParser.new.call(pact_hash) }
|
7
|
+
|
8
|
+
context "with a v2 pact" do
|
9
|
+
let(:pact_hash) { load_json_fixture('pact-http-v2.json') }
|
10
|
+
|
11
|
+
it "correctly parses the pact" do
|
12
|
+
expect(subject.interactions.first.response.headers['Content-Type']).to be_a(Pact::Term)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with a v3 pact" do
|
17
|
+
let(:pact_hash) { load_json_fixture('pact-http-v3.json') }
|
18
|
+
|
19
|
+
it "correctly parses the pact" do
|
20
|
+
expect(subject.interactions.first.response.body['foo']).to be_a(Pact::SomethingLike)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -65,7 +65,7 @@ module Pact
|
|
65
65
|
context "when there are matching rules" do
|
66
66
|
let(:hash) { load_json_fixture 'interaction-with-matching-rules.json' }
|
67
67
|
|
68
|
-
subject { Interaction.from_hash hash }
|
68
|
+
subject { Interaction.from_hash hash, pact_specification_version: Pact::SpecificationVersion.new("2") }
|
69
69
|
|
70
70
|
it "merges the rules with the example for the request" do
|
71
71
|
expect(subject.request.body['name']).to be_instance_of(Pact::Term)
|
@@ -0,0 +1,364 @@
|
|
1
|
+
require 'pact/matching_rules/v3/merge'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module MatchingRules
|
5
|
+
module V3
|
6
|
+
describe Merge do
|
7
|
+
subject { Merge.(expected, matching_rules) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow($stderr).to receive(:puts)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "no recognised rules" do
|
14
|
+
let(:expected) do
|
15
|
+
{
|
16
|
+
"_links" => {
|
17
|
+
"self" => {
|
18
|
+
"href" => "http://localhost:1234/thing"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:matching_rules) do
|
25
|
+
{
|
26
|
+
"$._links.self.href" => {
|
27
|
+
"matchers" => [{ "type" => "unknown" }]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns the object at that path unaltered" do
|
33
|
+
expect(subject["_links"]["self"]["href"]).to eq "http://localhost:1234/thing"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "it logs the rules it has ignored" do
|
37
|
+
expect($stderr).to receive(:puts) do | message |
|
38
|
+
expect(message).to include("WARN")
|
39
|
+
expect(message).to include("type")
|
40
|
+
expect(message).to include("unknown")
|
41
|
+
expect(message).to include("$['_links']")
|
42
|
+
end
|
43
|
+
subject
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with nil rules" do
|
49
|
+
let(:expected) do
|
50
|
+
{
|
51
|
+
"_links" => {
|
52
|
+
"self" => {
|
53
|
+
"href" => "http://localhost:1234/thing"
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
let(:matching_rules) { nil }
|
60
|
+
|
61
|
+
it "returns the example unaltered" do
|
62
|
+
expect(subject["_links"]["self"]["href"]).to eq "http://localhost:1234/thing"
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "type based matching" do
|
68
|
+
let(:expected) do
|
69
|
+
{
|
70
|
+
"name" => "Mary"
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:matching_rules) do
|
75
|
+
{
|
76
|
+
"$.name" => {
|
77
|
+
"matchers" => [{ "match" => "type", "ignored" => "matchingrule" }]
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
it "creates a SomethingLike at the appropriate path" do
|
83
|
+
expect(subject['name']).to be_instance_of(Pact::SomethingLike)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "it logs the rules it has ignored" do
|
87
|
+
expect($stderr).to receive(:puts).with(/ignored.*matchingrule/)
|
88
|
+
subject
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "regular expressions" do
|
94
|
+
|
95
|
+
describe "in a hash" do
|
96
|
+
let(:expected) do
|
97
|
+
{
|
98
|
+
"_links" => {
|
99
|
+
"self" => {
|
100
|
+
"href" => "http://localhost:1234/thing"
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:matching_rules) do
|
107
|
+
{
|
108
|
+
"$._links.self.href" => {
|
109
|
+
"matchers" => [{ "regex" => "http:\\/\\/.*\\/thing", "match" => "regex", "ignored" => "somerule" }]
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
it "creates a Pact::Term at the appropriate path" do
|
115
|
+
expect(subject["_links"]["self"]["href"]).to be_instance_of(Pact::Term)
|
116
|
+
expect(subject["_links"]["self"]["href"].generate).to eq "http://localhost:1234/thing"
|
117
|
+
expect(subject["_links"]["self"]["href"].matcher.inspect).to eq "/http:\\/\\/.*\\/thing/"
|
118
|
+
end
|
119
|
+
|
120
|
+
it "it logs the rules it has ignored" do
|
121
|
+
expect($stderr).to receive(:puts) do | message |
|
122
|
+
expect(message).to match /ignored.*"somerule"/
|
123
|
+
expect(message).to_not match /regex/
|
124
|
+
expect(message).to_not match /"match"/
|
125
|
+
end
|
126
|
+
subject
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "with an array" do
|
131
|
+
|
132
|
+
let(:expected) do
|
133
|
+
{
|
134
|
+
"_links" => {
|
135
|
+
"self" => [{
|
136
|
+
"href" => "http://localhost:1234/thing"
|
137
|
+
}]
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
let(:matching_rules) do
|
143
|
+
{
|
144
|
+
"$._links.self[0].href" => {
|
145
|
+
"matchers" => [{ "regex" => "http:\\/\\/.*\\/thing" }]
|
146
|
+
}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
it "creates a Pact::Term at the appropriate path" do
|
151
|
+
expect(subject["_links"]["self"][0]["href"]).to be_instance_of(Pact::Term)
|
152
|
+
expect(subject["_links"]["self"][0]["href"].generate).to eq "http://localhost:1234/thing"
|
153
|
+
expect(subject["_links"]["self"][0]["href"].matcher.inspect).to eq "/http:\\/\\/.*\\/thing/"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "with an array where all elements should match by type and the rule is specified on the parent element and there is no min specified" do
|
158
|
+
let(:expected) do
|
159
|
+
{
|
160
|
+
'alligators' => [{'name' => 'Mary'}]
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
let(:matching_rules) do
|
165
|
+
{
|
166
|
+
"$.alligators" => {
|
167
|
+
"matchers" => [{ 'match' => 'type' }]
|
168
|
+
}
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
it "creates a Pact::SomethingLike at the appropriate path" do
|
173
|
+
expect(subject["alligators"]).to be_instance_of(Pact::SomethingLike)
|
174
|
+
expect(subject["alligators"].contents).to eq ['name' => 'Mary']
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "with an array where all elements should match by type and the rule is specified on the child elements" do
|
179
|
+
let(:expected) do
|
180
|
+
{
|
181
|
+
'alligators' => [{'name' => 'Mary'}]
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
let(:matching_rules) do
|
186
|
+
{
|
187
|
+
"$.alligators" => {
|
188
|
+
"matchers" => [{ 'min' => 2, 'match' => 'type' }]
|
189
|
+
},
|
190
|
+
"$.alligators[*].*" => {
|
191
|
+
"matchers" => [{ 'match' => 'type'}]
|
192
|
+
}
|
193
|
+
}
|
194
|
+
end
|
195
|
+
it "creates a Pact::ArrayLike at the appropriate path" do
|
196
|
+
expect(subject["alligators"]).to be_instance_of(Pact::ArrayLike)
|
197
|
+
expect(subject["alligators"].contents).to eq 'name' => 'Mary'
|
198
|
+
expect(subject["alligators"].min).to eq 2
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "with an array where all elements should match by type and the rule is specified on both the parent element and the child elements" do
|
203
|
+
let(:expected) do
|
204
|
+
{
|
205
|
+
'alligators' => [{'name' => 'Mary'}]
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
let(:matching_rules) do
|
210
|
+
{
|
211
|
+
"$.alligators" => {
|
212
|
+
"matchers" => [{ 'min' => 2, 'match' => 'type' }]
|
213
|
+
},
|
214
|
+
"$.alligators[*].*" => {
|
215
|
+
"matchers" => [{ 'match' => 'type' }]
|
216
|
+
}
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
it "creates a Pact::ArrayLike at the appropriate path" do
|
221
|
+
expect(subject["alligators"]).to be_instance_of(Pact::ArrayLike)
|
222
|
+
expect(subject["alligators"].contents).to eq 'name' => 'Mary'
|
223
|
+
expect(subject["alligators"].min).to eq 2
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "with an array where all elements should match by type and there is only a match:type on the parent element" do
|
228
|
+
let(:expected) do
|
229
|
+
{
|
230
|
+
'alligators' => [{'name' => 'Mary'}]
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
234
|
+
let(:matching_rules) do
|
235
|
+
{
|
236
|
+
"$.alligators" => { 'matchers' => [{'min' => 2, 'match' => 'type'}] },
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
it "creates a Pact::ArrayLike at the appropriate path" do
|
241
|
+
expect(subject["alligators"]).to be_instance_of(Pact::ArrayLike)
|
242
|
+
expect(subject["alligators"].contents).to eq 'name' => 'Mary'
|
243
|
+
expect(subject["alligators"].min).to eq 2
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "with an array where all elements should match by type nested inside another array where all elements should match by type" do
|
248
|
+
let(:expected) do
|
249
|
+
{
|
250
|
+
|
251
|
+
'alligators' => [
|
252
|
+
{
|
253
|
+
'name' => 'Mary',
|
254
|
+
'children' => [
|
255
|
+
'age' => 9
|
256
|
+
]
|
257
|
+
}
|
258
|
+
]
|
259
|
+
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
263
|
+
let(:matching_rules) do
|
264
|
+
{
|
265
|
+
"$.alligators" => { "matchers" => [{ 'min' => 2, 'match' => 'type' }] },
|
266
|
+
"$.alligators[*].children" => { "matchers" => [{ 'min' => 1, 'match' => 'type' }]},
|
267
|
+
}
|
268
|
+
end
|
269
|
+
|
270
|
+
it "creates a Pact::ArrayLike at the appropriate path" do
|
271
|
+
expect(subject["alligators"].contents['children']).to be_instance_of(Pact::ArrayLike)
|
272
|
+
expect(subject["alligators"].contents['children'].contents).to eq 'age' => 9
|
273
|
+
expect(subject["alligators"].contents['children'].min).to eq 1
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe "with an example array with more than one item" do
|
278
|
+
let(:expected) do
|
279
|
+
{
|
280
|
+
|
281
|
+
'alligators' => [
|
282
|
+
{'name' => 'Mary'},
|
283
|
+
{'name' => 'Joe'}
|
284
|
+
]
|
285
|
+
|
286
|
+
}
|
287
|
+
end
|
288
|
+
|
289
|
+
let(:matching_rules) do
|
290
|
+
{
|
291
|
+
"$.alligators" => { "matchers" => [{'min' => 2, 'match' => 'type'}] }
|
292
|
+
}
|
293
|
+
end
|
294
|
+
|
295
|
+
xit "doesn't warn about the min size being ignored" do
|
296
|
+
expect(Pact.configuration.error_stream).to receive(:puts).once
|
297
|
+
subject
|
298
|
+
end
|
299
|
+
|
300
|
+
it "warns that the other items will be ignored" do
|
301
|
+
allow(Pact.configuration.error_stream).to receive(:puts)
|
302
|
+
expect(Pact.configuration.error_stream).to receive(:puts).with(/WARN: Only the first item/)
|
303
|
+
subject
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
describe "using bracket notation for a Hash" do
|
309
|
+
let(:expected) do
|
310
|
+
{
|
311
|
+
"name" => "Mary"
|
312
|
+
}
|
313
|
+
end
|
314
|
+
|
315
|
+
let(:matching_rules) do
|
316
|
+
{
|
317
|
+
"$['name']" => { "matchers" => [{"match" => "type"}] }
|
318
|
+
}
|
319
|
+
end
|
320
|
+
|
321
|
+
it "applies the rule" do
|
322
|
+
expect(subject['name']).to be_instance_of(Pact::SomethingLike)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
describe "with a dot in the path" do
|
327
|
+
let(:expected) do
|
328
|
+
{
|
329
|
+
"first.name" => "Mary"
|
330
|
+
}
|
331
|
+
end
|
332
|
+
|
333
|
+
let(:matching_rules) do
|
334
|
+
{
|
335
|
+
"$['first.name']" => { "matchers" => [{ "match" => "type" }] }
|
336
|
+
}
|
337
|
+
end
|
338
|
+
|
339
|
+
it "applies the rule" do
|
340
|
+
expect(subject['first.name']).to be_instance_of(Pact::SomethingLike)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "with an @ in the path" do
|
345
|
+
let(:expected) do
|
346
|
+
{
|
347
|
+
"@name" => "Mary"
|
348
|
+
}
|
349
|
+
end
|
350
|
+
|
351
|
+
let(:matching_rules) do
|
352
|
+
{
|
353
|
+
"$['@name']" => { "matchers" => [ { "match" => "type" }] }
|
354
|
+
}
|
355
|
+
end
|
356
|
+
|
357
|
+
it "applies the rule" do
|
358
|
+
expect(subject['@name']).to be_instance_of(Pact::SomethingLike)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'pact/matching_rules'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module MatchingRules
|
5
|
+
describe ".merge" do
|
6
|
+
before do
|
7
|
+
allow(V3::Merge).to receive(:call)
|
8
|
+
allow(Merge).to receive(:call)
|
9
|
+
allow(Pact.configuration.error_stream).to receive(:puts)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:object) { double('object') }
|
13
|
+
let(:rules) { double('rules') }
|
14
|
+
let(:options) { { pact_specification_version: Pact::SpecificationVersion.new(pact_specification_version) } }
|
15
|
+
|
16
|
+
subject { MatchingRules.merge(object, rules, options)}
|
17
|
+
|
18
|
+
context "when the pact_specification_version is nil" do
|
19
|
+
let(:pact_specification_version) { nil }
|
20
|
+
|
21
|
+
it "calls Merge" do
|
22
|
+
expect(Merge).to receive(:call)
|
23
|
+
subject
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when the pact_specification_version starts with '1.'" do
|
28
|
+
let(:pact_specification_version) { "1.0" }
|
29
|
+
|
30
|
+
it "calls Merge" do
|
31
|
+
expect(Merge).to receive(:call)
|
32
|
+
subject
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when the pact_specification_version is with '1'" do
|
37
|
+
let(:pact_specification_version) { "1" }
|
38
|
+
|
39
|
+
it "calls Merge" do
|
40
|
+
expect(Merge).to receive(:call)
|
41
|
+
subject
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when the pact_specification_version starts with '2.'" do
|
46
|
+
let(:pact_specification_version) { "2.0" }
|
47
|
+
|
48
|
+
it "calls Merge" do
|
49
|
+
expect(Merge).to receive(:call)
|
50
|
+
subject
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when the pact_specification_version starts with '3.'" do
|
55
|
+
let(:pact_specification_version) { "3.0" }
|
56
|
+
|
57
|
+
it "calls V3::Merge" do
|
58
|
+
expect(V3::Merge).to receive(:call)
|
59
|
+
subject
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the pact_specification_version starts with '4.'" do
|
64
|
+
let(:pact_specification_version) { "4.0" }
|
65
|
+
|
66
|
+
it "calls V3::Merge" do
|
67
|
+
expect(V3::Merge).to receive(:call)
|
68
|
+
subject
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when the pact_specification_version is with '11'" do
|
73
|
+
let(:pact_specification_version) { "11" }
|
74
|
+
|
75
|
+
it "calls V3::Merge" do
|
76
|
+
expect(V3::Merge).to receive(:call)
|
77
|
+
subject
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/tasks/spec.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Fraser
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2018-03-
|
15
|
+
date: 2018-03-23 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: randexp
|
@@ -268,6 +268,7 @@ files:
|
|
268
268
|
- lib/pact/consumer_contract/consumer_contract.rb
|
269
269
|
- lib/pact/consumer_contract/file_name.rb
|
270
270
|
- lib/pact/consumer_contract/headers.rb
|
271
|
+
- lib/pact/consumer_contract/http_consumer_contract_parser.rb
|
271
272
|
- lib/pact/consumer_contract/interaction.rb
|
272
273
|
- lib/pact/consumer_contract/pact_file.rb
|
273
274
|
- lib/pact/consumer_contract/query.rb
|
@@ -302,6 +303,7 @@ files:
|
|
302
303
|
- lib/pact/matching_rules/extract.rb
|
303
304
|
- lib/pact/matching_rules/jsonpath.rb
|
304
305
|
- lib/pact/matching_rules/merge.rb
|
306
|
+
- lib/pact/matching_rules/v3/merge.rb
|
305
307
|
- lib/pact/reification.rb
|
306
308
|
- lib/pact/rspec.rb
|
307
309
|
- lib/pact/shared/active_support_support.rb
|
@@ -314,6 +316,7 @@ files:
|
|
314
316
|
- lib/pact/shared/request.rb
|
315
317
|
- lib/pact/shared/text_differ.rb
|
316
318
|
- lib/pact/something_like.rb
|
319
|
+
- lib/pact/specification_version.rb
|
317
320
|
- lib/pact/support.rb
|
318
321
|
- lib/pact/support/version.rb
|
319
322
|
- lib/pact/symbolize_keys.rb
|
@@ -323,6 +326,8 @@ files:
|
|
323
326
|
- script/release.sh
|
324
327
|
- script/update-pact-specification-v2
|
325
328
|
- spec/fixtures/interaction-with-matching-rules.json
|
329
|
+
- spec/fixtures/pact-http-v2.json
|
330
|
+
- spec/fixtures/pact-http-v3.json
|
326
331
|
- spec/integration/matching_rules_extract_and_merge_spec.rb
|
327
332
|
- spec/lib/pact/array_like_spec.rb
|
328
333
|
- spec/lib/pact/configuration_spec.rb
|
@@ -331,6 +336,7 @@ files:
|
|
331
336
|
- spec/lib/pact/consumer_contract/consumer_contract_spec.rb
|
332
337
|
- spec/lib/pact/consumer_contract/file_name_spec.rb
|
333
338
|
- spec/lib/pact/consumer_contract/headers_spec.rb
|
339
|
+
- spec/lib/pact/consumer_contract/http_consumer_contract_parser_spec.rb
|
334
340
|
- spec/lib/pact/consumer_contract/interaction_spec.rb
|
335
341
|
- spec/lib/pact/consumer_contract/pact_file_spec.rb
|
336
342
|
- spec/lib/pact/consumer_contract/query_hash_spec.rb
|
@@ -357,6 +363,8 @@ files:
|
|
357
363
|
- spec/lib/pact/matchers/unix_diff_formatter_spec.rb
|
358
364
|
- spec/lib/pact/matching_rules/extract_spec.rb
|
359
365
|
- spec/lib/pact/matching_rules/merge_spec.rb
|
366
|
+
- spec/lib/pact/matching_rules/v3/merge_spec.rb
|
367
|
+
- spec/lib/pact/matching_rules_spec.rb
|
360
368
|
- spec/lib/pact/reification_spec.rb
|
361
369
|
- spec/lib/pact/shared/dsl_spec.rb
|
362
370
|
- spec/lib/pact/shared/form_differ_spec.rb
|
@@ -420,6 +428,8 @@ specification_version: 4
|
|
420
428
|
summary: Shared code for Pact gems
|
421
429
|
test_files:
|
422
430
|
- spec/fixtures/interaction-with-matching-rules.json
|
431
|
+
- spec/fixtures/pact-http-v2.json
|
432
|
+
- spec/fixtures/pact-http-v3.json
|
423
433
|
- spec/integration/matching_rules_extract_and_merge_spec.rb
|
424
434
|
- spec/lib/pact/array_like_spec.rb
|
425
435
|
- spec/lib/pact/configuration_spec.rb
|
@@ -428,6 +438,7 @@ test_files:
|
|
428
438
|
- spec/lib/pact/consumer_contract/consumer_contract_spec.rb
|
429
439
|
- spec/lib/pact/consumer_contract/file_name_spec.rb
|
430
440
|
- spec/lib/pact/consumer_contract/headers_spec.rb
|
441
|
+
- spec/lib/pact/consumer_contract/http_consumer_contract_parser_spec.rb
|
431
442
|
- spec/lib/pact/consumer_contract/interaction_spec.rb
|
432
443
|
- spec/lib/pact/consumer_contract/pact_file_spec.rb
|
433
444
|
- spec/lib/pact/consumer_contract/query_hash_spec.rb
|
@@ -454,6 +465,8 @@ test_files:
|
|
454
465
|
- spec/lib/pact/matchers/unix_diff_formatter_spec.rb
|
455
466
|
- spec/lib/pact/matching_rules/extract_spec.rb
|
456
467
|
- spec/lib/pact/matching_rules/merge_spec.rb
|
468
|
+
- spec/lib/pact/matching_rules/v3/merge_spec.rb
|
469
|
+
- spec/lib/pact/matching_rules_spec.rb
|
457
470
|
- spec/lib/pact/reification_spec.rb
|
458
471
|
- spec/lib/pact/shared/dsl_spec.rb
|
459
472
|
- spec/lib/pact/shared/form_differ_spec.rb
|