pact-support 1.4.0 → 1.7.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 +115 -0
- data/lib/pact/configuration.rb +4 -0
- data/lib/pact/consumer_contract/consumer_contract.rb +19 -8
- data/lib/pact/consumer_contract/http_consumer_contract_parser.rb +37 -0
- data/lib/pact/consumer_contract/interaction.rb +52 -57
- data/lib/pact/consumer_contract/interaction_parser.rb +23 -0
- data/lib/pact/consumer_contract/interaction_v2_parser.rb +28 -0
- data/lib/pact/consumer_contract/interaction_v3_parser.rb +61 -0
- data/lib/pact/consumer_contract/pact_file.rb +24 -24
- data/lib/pact/consumer_contract/query_hash.rb +2 -0
- data/lib/pact/consumer_contract/query_string.rb +2 -2
- data/lib/pact/consumer_contract/request.rb +1 -5
- data/lib/pact/consumer_contract/string_with_matching_rules.rb +17 -0
- data/lib/pact/matchers/multipart_form_diff_formatter.rb +41 -0
- data/lib/pact/matching_rules/merge.rb +30 -14
- data/lib/pact/matching_rules/v3/extract.rb +94 -0
- data/lib/pact/matching_rules/v3/merge.rb +128 -0
- data/lib/pact/matching_rules.rb +19 -6
- data/lib/pact/reification.rb +6 -3
- data/lib/pact/shared/multipart_form_differ.rb +14 -0
- data/lib/pact/specification_version.rb +18 -0
- data/lib/pact/support/version.rb +1 -1
- data/script/release.sh +1 -1
- data/spec/fixtures/multipart-form-diff.txt +9 -0
- data/spec/fixtures/not-a-pact.json +3 -0
- data/spec/fixtures/pact-http-v2.json +36 -0
- data/spec/fixtures/pact-http-v3.json +36 -0
- data/spec/integration/matching_rules_extract_and_merge_spec.rb +41 -4
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +54 -31
- data/spec/lib/pact/consumer_contract/http_consumer_contract_parser_spec.rb +25 -0
- data/spec/lib/pact/consumer_contract/interaction_parser_spec.rb +62 -0
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -23
- data/spec/lib/pact/consumer_contract/pact_file_spec.rb +9 -0
- data/spec/lib/pact/consumer_contract/query_hash_spec.rb +23 -0
- data/spec/lib/pact/matchers/multipart_form_diff_formatter_spec.rb +36 -0
- data/spec/lib/pact/matching_rules/merge_spec.rb +20 -7
- data/spec/lib/pact/matching_rules/v3/extract_spec.rb +238 -0
- data/spec/lib/pact/matching_rules/v3/merge_spec.rb +386 -0
- data/spec/lib/pact/matching_rules_spec.rb +82 -0
- data/spec/lib/pact/reification_spec.rb +18 -5
- data/spec/lib/pact/shared/multipart_form_differ_spec.rb +39 -0
- data/tasks/spec.rake +0 -1
- metadata +35 -3
|
@@ -3,50 +3,73 @@ require 'pact/consumer_contract'
|
|
|
3
3
|
|
|
4
4
|
module Pact
|
|
5
5
|
describe ConsumerContract do
|
|
6
|
+
describe "from_uri" do
|
|
7
|
+
context "when the URL does not point to a valid pact" do
|
|
8
|
+
subject { ConsumerContract.from_uri('spec/fixtures/not-a-pact.json') }
|
|
9
|
+
|
|
10
|
+
it "raises a helpful error" do
|
|
11
|
+
expect { subject }.to raise_error UnrecognizePactFormatError, /Please check that spec/
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "from_hash" do
|
|
17
|
+
context "when the hash is not a valid pact" do
|
|
18
|
+
subject { ConsumerContract.from_hash({'foo' => 'bar'}) }
|
|
19
|
+
|
|
20
|
+
it "raises a helpful error" do
|
|
21
|
+
expect { subject }.to raise_error UnrecognizePactFormatError, 'This document does not use a recognised Pact format: {"foo"=>"bar"}'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
6
25
|
|
|
7
26
|
describe ".from_json" do
|
|
27
|
+
|
|
8
28
|
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
29
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
30
|
+
context "with an HTTP contract" do
|
|
31
|
+
context "when the top level object is a ConsumerContract" do
|
|
32
|
+
let(:string) { '{"interactions":[{"request": {"path":"/path", "method" : "get"}, "response": {"status" : 200}}], "consumer": {"name" : "Bob"} , "provider": {"name" : "Mary"} }' }
|
|
15
33
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
it "should create a Pact" do
|
|
35
|
+
expect(loaded_pact).to be_instance_of ConsumerContract
|
|
36
|
+
end
|
|
19
37
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
it "should have interactions" do
|
|
39
|
+
expect(loaded_pact.interactions).to be_instance_of Array
|
|
40
|
+
end
|
|
23
41
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
42
|
+
it "should have a consumer" do
|
|
43
|
+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
|
|
44
|
+
end
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
expect(loaded_pact).to be_instance_of ConsumerContract
|
|
46
|
+
it "should have a provider" do
|
|
47
|
+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
|
|
48
|
+
end
|
|
33
49
|
end
|
|
34
50
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
context "with old 'producer' key" do
|
|
52
|
+
let(:string) { File.read('./spec/support/a_consumer-a_producer.json')}
|
|
53
|
+
it "should create a Pact" do
|
|
54
|
+
expect(loaded_pact).to be_instance_of ConsumerContract
|
|
55
|
+
end
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
it "should have interactions" do
|
|
58
|
+
expect(loaded_pact.interactions).to be_instance_of Array
|
|
59
|
+
end
|
|
42
60
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
61
|
+
it "should have a consumer" do
|
|
62
|
+
expect(loaded_pact.consumer).to be_instance_of Pact::ServiceConsumer
|
|
63
|
+
end
|
|
47
64
|
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
it "should have a provider" do
|
|
66
|
+
expect(loaded_pact.provider).to be_instance_of Pact::ServiceProvider
|
|
67
|
+
expect(loaded_pact.provider.name).to eq "an old producer"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should have a provider_state" do
|
|
71
|
+
expect(loaded_pact.interactions.first.provider_state).to eq 'state one'
|
|
72
|
+
end
|
|
50
73
|
end
|
|
51
74
|
end
|
|
52
75
|
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
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'pact/consumer_contract/interaction_parser'
|
|
2
|
+
|
|
3
|
+
module Pact
|
|
4
|
+
describe InteractionParser do
|
|
5
|
+
describe ".call" do
|
|
6
|
+
|
|
7
|
+
let(:request) { {method: 'get', path: 'path'} }
|
|
8
|
+
let(:response) { {} }
|
|
9
|
+
|
|
10
|
+
context "when providerState has been used instead of provider_state" do
|
|
11
|
+
|
|
12
|
+
subject { InteractionParser.call('response' => response, 'request' => request, 'providerState' => 'some state') }
|
|
13
|
+
|
|
14
|
+
it "recognises the provider state" do
|
|
15
|
+
expect(subject.provider_state).to eq 'some state'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context "when there are matching rules" do
|
|
20
|
+
let(:hash) { load_json_fixture 'interaction-with-matching-rules.json' }
|
|
21
|
+
|
|
22
|
+
subject { InteractionParser.call(hash, pact_specification_version: Pact::SpecificationVersion.new("2")) }
|
|
23
|
+
|
|
24
|
+
it "merges the rules with the example for the request" do
|
|
25
|
+
expect(subject.request.body['name']).to be_instance_of(Pact::Term)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "merges the rules with the example for the response" do
|
|
29
|
+
expect(subject.response.body['_links']['self']['href']).to be_instance_of(Pact::Term)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when the request body is a String" do
|
|
34
|
+
let(:hash) { { 'request' => request, 'response' => response } }
|
|
35
|
+
subject { InteractionParser.call(hash, pact_specification_version: Pact::SpecificationVersion.new("3")) }
|
|
36
|
+
|
|
37
|
+
let(:request) { { 'method' => 'get', 'path' => 'path' , 'body' => "<xml></xml>", 'matchingRules' => {"body" => {"foo" => "bar"} } } }
|
|
38
|
+
|
|
39
|
+
it "returns an interaction with an StringWithMatchingRules in the request" do
|
|
40
|
+
expect(subject.request.body).to be_a(Pact::StringWithMatchingRules)
|
|
41
|
+
expect(subject.request.body).to eq "<xml></xml>"
|
|
42
|
+
expect(subject.request.body.matching_rules).to eq "foo" => "bar"
|
|
43
|
+
expect(subject.request.body.pact_specification_version).to eq Pact::SpecificationVersion.new("3")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when the response body is a String" do
|
|
48
|
+
let(:hash) { { 'request' => request, 'response' => response } }
|
|
49
|
+
subject { InteractionParser.call(hash, pact_specification_version: Pact::SpecificationVersion.new("3")) }
|
|
50
|
+
|
|
51
|
+
let(:response) { { 'status' => '200', 'body' => "<xml></xml>", 'matchingRules' => {"body" => {"foo" => "bar"} } } }
|
|
52
|
+
|
|
53
|
+
it "returns an interaction with an StringWithMatchingRules in the response" do
|
|
54
|
+
expect(subject.response.body).to be_a(Pact::StringWithMatchingRules)
|
|
55
|
+
expect(subject.response.body).to eq "<xml></xml>"
|
|
56
|
+
expect(subject.response.body.matching_rules).to eq "foo" => "bar"
|
|
57
|
+
expect(subject.response.body.pact_specification_version).to eq Pact::SpecificationVersion.new("3")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -52,30 +52,7 @@ module Pact
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
describe "from_hash" do
|
|
56
|
-
context "when providerState has been used instead of provider_state" do
|
|
57
55
|
|
|
58
|
-
subject { Interaction.from_hash('response' => response, 'request' => request, 'providerState' => 'some state') }
|
|
59
|
-
|
|
60
|
-
it "recognises the provider state" do
|
|
61
|
-
expect(subject.provider_state).to eq 'some state'
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
context "when there are matching rules" do
|
|
66
|
-
let(:hash) { load_json_fixture 'interaction-with-matching-rules.json' }
|
|
67
|
-
|
|
68
|
-
subject { Interaction.from_hash hash }
|
|
69
|
-
|
|
70
|
-
it "merges the rules with the example for the request" do
|
|
71
|
-
expect(subject.request.body['name']).to be_instance_of(Pact::Term)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "merges the rules with the example for the response" do
|
|
75
|
-
expect(subject.response.body['_links']['self']['href']).to be_instance_of(Pact::Term)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
56
|
|
|
80
57
|
describe "request_modifies_resource_without_checking_response_body?" do
|
|
81
58
|
|
|
@@ -25,6 +25,15 @@ module Pact
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
describe 'with backslashes to a local path' do
|
|
29
|
+
let(:windows_path) { 'spec\support\a_consumer-a_provider.json' }
|
|
30
|
+
let(:unix_path) { 'spec/support/a_consumer-a_provider.json' }
|
|
31
|
+
|
|
32
|
+
it 'transforms them to forward slashes' do
|
|
33
|
+
expect(PactFile.read(windows_path)).to eq PactFile.read(unix_path)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
28
37
|
context 'without basic authentication' do
|
|
29
38
|
before do
|
|
30
39
|
stub_request(:get, uri_without_userinfo).to_return(body: pact_content)
|
|
@@ -72,6 +72,15 @@ module Pact
|
|
|
72
72
|
expect(subject.difference(other).keys).to contain_exactly(:"param[a]", :"param[a][aa]", :"param[a][bb]")
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
context "when there is an ArrayLike" do
|
|
77
|
+
let(:query) { { param: Pact.each_like("1") } }
|
|
78
|
+
let(:other) { QueryString.new('param=1¶m=2') }
|
|
79
|
+
|
|
80
|
+
it 'returns an empty diff' do
|
|
81
|
+
expect(subject.difference(other)).to be_empty
|
|
82
|
+
end
|
|
83
|
+
end
|
|
75
84
|
end
|
|
76
85
|
end
|
|
77
86
|
|
|
@@ -82,6 +91,20 @@ module Pact
|
|
|
82
91
|
end
|
|
83
92
|
|
|
84
93
|
describe "#to_json" do
|
|
94
|
+
context "when the query contains an ArrayLike" do
|
|
95
|
+
let(:query) { { foo: Pact.each_like("1"), bar: "2" } }
|
|
96
|
+
let(:expected_json) do
|
|
97
|
+
{
|
|
98
|
+
foo: Pact.each_like("1"),
|
|
99
|
+
bar: ["2"]
|
|
100
|
+
}.to_json
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "serialises the ArrayLike without wrapping an array around it" do
|
|
104
|
+
expect(subject.to_json).to eq expected_json
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
85
108
|
context "when the query contains a Pact::Term" do
|
|
86
109
|
let(:term) { Pact::Term.new(generate: "thing", matcher: /th/) }
|
|
87
110
|
let(:query) { { param: term } }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'pact/matchers/multipart_form_diff_formatter'
|
|
2
|
+
|
|
3
|
+
module Pact
|
|
4
|
+
module Matchers
|
|
5
|
+
describe MultipartFormDiffFormatter do
|
|
6
|
+
describe ".call" do
|
|
7
|
+
subject { MultipartFormDiffFormatter.call(diff, options)}
|
|
8
|
+
|
|
9
|
+
let(:diff) do
|
|
10
|
+
{
|
|
11
|
+
headers: header_diff,
|
|
12
|
+
body: body_diff
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:header_diff) do
|
|
17
|
+
{
|
|
18
|
+
"Content-Type" => Difference.new("foo", "bar", "Wrong header")
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:body_diff) do
|
|
23
|
+
Difference.new("foo", "bar", "A message")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let(:options) { {} }
|
|
27
|
+
|
|
28
|
+
let(:expected_output) { File.read("spec/fixtures/multipart-form-diff.txt")}
|
|
29
|
+
|
|
30
|
+
it "formats the diff" do
|
|
31
|
+
expect(subject).to eq expected_output
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -7,10 +7,16 @@ module Pact
|
|
|
7
7
|
subject { Merge.(expected, matching_rules, "$.body") }
|
|
8
8
|
|
|
9
9
|
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 call to log_used_rule in Merge."
|
|
12
|
+
end
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
describe "no recognised rules" do
|
|
16
|
+
before do
|
|
17
|
+
allow($stderr).to receive(:puts)
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
let(:expected) do
|
|
15
21
|
{
|
|
16
22
|
"_links" => {
|
|
@@ -63,6 +69,10 @@ module Pact
|
|
|
63
69
|
end
|
|
64
70
|
|
|
65
71
|
describe "type based matching" do
|
|
72
|
+
before do
|
|
73
|
+
allow($stderr).to receive(:puts)
|
|
74
|
+
end
|
|
75
|
+
|
|
66
76
|
let(:expected) do
|
|
67
77
|
{
|
|
68
78
|
"name" => "Mary"
|
|
@@ -89,6 +99,10 @@ module Pact
|
|
|
89
99
|
describe "regular expressions" do
|
|
90
100
|
|
|
91
101
|
describe "in a hash" do
|
|
102
|
+
before do
|
|
103
|
+
allow($stderr).to receive(:puts)
|
|
104
|
+
end
|
|
105
|
+
|
|
92
106
|
let(:expected) do
|
|
93
107
|
{
|
|
94
108
|
"_links" => {
|
|
@@ -178,6 +192,7 @@ module Pact
|
|
|
178
192
|
"$.body.alligators[*].*" => { 'match' => 'type'}
|
|
179
193
|
}
|
|
180
194
|
end
|
|
195
|
+
|
|
181
196
|
it "creates a Pact::ArrayLike at the appropriate path" do
|
|
182
197
|
expect(subject["alligators"]).to be_instance_of(Pact::ArrayLike)
|
|
183
198
|
expect(subject["alligators"].contents).to eq 'name' => 'Mary'
|
|
@@ -259,6 +274,10 @@ module Pact
|
|
|
259
274
|
end
|
|
260
275
|
|
|
261
276
|
describe "with an example array with more than one item" do
|
|
277
|
+
before do
|
|
278
|
+
allow(Pact.configuration.error_stream).to receive(:puts)
|
|
279
|
+
end
|
|
280
|
+
|
|
262
281
|
let(:expected) do
|
|
263
282
|
{
|
|
264
283
|
|
|
@@ -277,13 +296,7 @@ module Pact
|
|
|
277
296
|
}
|
|
278
297
|
end
|
|
279
298
|
|
|
280
|
-
xit "doesn't warn about the min size being ignored" do
|
|
281
|
-
expect(Pact.configuration.error_stream).to receive(:puts).once
|
|
282
|
-
subject
|
|
283
|
-
end
|
|
284
|
-
|
|
285
299
|
it "warns that the other items will be ignored" do
|
|
286
|
-
allow(Pact.configuration.error_stream).to receive(:puts)
|
|
287
300
|
expect(Pact.configuration.error_stream).to receive(:puts).with(/WARN: Only the first item/)
|
|
288
301
|
subject
|
|
289
302
|
end
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
require 'pact/matching_rules/v3/extract'
|
|
2
|
+
require 'pact/support'
|
|
3
|
+
|
|
4
|
+
module Pact
|
|
5
|
+
module MatchingRules::V3
|
|
6
|
+
describe Extract do
|
|
7
|
+
|
|
8
|
+
describe ".call" do
|
|
9
|
+
|
|
10
|
+
subject { Extract.call(matchable) }
|
|
11
|
+
|
|
12
|
+
context "with a Pact::SomethingLike" do
|
|
13
|
+
let(:matchable) do
|
|
14
|
+
{
|
|
15
|
+
body: Pact::SomethingLike.new(foo: 'bar', alligator: { name: 'Mary' })
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:rules) do
|
|
20
|
+
{
|
|
21
|
+
"$.body" => {
|
|
22
|
+
"matchers" => [ {"match" => "type"} ]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "creates a rule that matches by type" do
|
|
28
|
+
expect(subject).to eq rules
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "with a Pact::Term" do
|
|
33
|
+
let(:matchable) do
|
|
34
|
+
{
|
|
35
|
+
body: {
|
|
36
|
+
alligator: {
|
|
37
|
+
name: Pact::Term.new(generate: 'Mary', matcher: /.*a/)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
let(:rules) do
|
|
44
|
+
{
|
|
45
|
+
"$.body.alligator.name" => {
|
|
46
|
+
"matchers" => [ {"match" => "regex", "regex" => ".*a"} ]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "creates a rule that matches by regex" do
|
|
52
|
+
expect(subject).to eq rules
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "with a Pact::SomethingLike containing a Term" do
|
|
57
|
+
let(:matchable) do
|
|
58
|
+
{
|
|
59
|
+
body: Pact::SomethingLike.new(
|
|
60
|
+
foo: 'bar',
|
|
61
|
+
alligator: { name: Pact::Term.new(generate: 'Mary', matcher: /.*a/) }
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
let(:rules) do
|
|
67
|
+
{
|
|
68
|
+
"$.body" => {
|
|
69
|
+
"matchers" => [ {"match" => "type"} ]
|
|
70
|
+
},
|
|
71
|
+
"$.body.alligator.name" => {
|
|
72
|
+
"matchers" => [ {"match" => "regex", "regex"=>".*a"} ]
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "the match:regex overrides the match:type" do
|
|
78
|
+
expect(subject).to eq rules
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "with a Pact::SomethingLike containing an array" do
|
|
83
|
+
let(:matchable) do
|
|
84
|
+
{
|
|
85
|
+
body: Pact::SomethingLike.new(
|
|
86
|
+
alligators: [
|
|
87
|
+
{name: 'Mary'},
|
|
88
|
+
{name: 'Betty'}
|
|
89
|
+
]
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
let(:rules) do
|
|
95
|
+
{
|
|
96
|
+
"$.body" => {
|
|
97
|
+
"matchers" => [ {"match" => "type"} ]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "lists a rule for each item" do
|
|
103
|
+
expect(subject).to eq rules
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "with an ArrayLike" do
|
|
108
|
+
let(:matchable) do
|
|
109
|
+
{
|
|
110
|
+
body: {
|
|
111
|
+
alligators: Pact::ArrayLike.new(
|
|
112
|
+
name: 'Fred'
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
let(:rules) do
|
|
119
|
+
{
|
|
120
|
+
"$.body.alligators" => {
|
|
121
|
+
"matchers" => [ {"min" => 1} ]
|
|
122
|
+
},
|
|
123
|
+
"$.body.alligators[*].*" => {
|
|
124
|
+
"matchers" => [ {"match" => "type"} ]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "lists a rule for all items" do
|
|
130
|
+
expect(subject).to eq rules
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "with an ArrayLike with a Pact::Term inside" do
|
|
135
|
+
let(:matchable) do
|
|
136
|
+
{
|
|
137
|
+
body: {
|
|
138
|
+
alligators: Pact::ArrayLike.new(
|
|
139
|
+
name: 'Fred',
|
|
140
|
+
phoneNumber: Pact::Term.new(generate: '1234567', matcher: /\d+/)
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
let(:rules) do
|
|
147
|
+
{
|
|
148
|
+
"$.body.alligators" => {
|
|
149
|
+
"matchers" => [ {"min" => 1} ]
|
|
150
|
+
},
|
|
151
|
+
"$.body.alligators[*].*" => {
|
|
152
|
+
"matchers" => [ {"match" => "type"} ]
|
|
153
|
+
},
|
|
154
|
+
"$.body.alligators[*].phoneNumber" => {
|
|
155
|
+
"matchers" => [ {"match" => "regex", "regex" => "\\d+"} ]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "lists a rule that specifies that the regular expression must match" do
|
|
161
|
+
expect(subject).to eq rules
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
context "with a Pact::QueryString containing a Pact::Term" do
|
|
166
|
+
let(:matchable) do
|
|
167
|
+
{
|
|
168
|
+
query: Pact::QueryString.new(Pact::Term.new(generate: 'foobar', matcher: /foo/))
|
|
169
|
+
}
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
let(:rules) do
|
|
173
|
+
{
|
|
174
|
+
"$.query" => {
|
|
175
|
+
"matchers" => [ {"match" => "regex", "regex" => "foo"} ]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "lists a rule that specifies that the regular expression must match" do
|
|
181
|
+
expect(subject).to eq rules
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context "with a Pact::QueryHash containing a Pact::Term" do
|
|
186
|
+
let(:matchable) do
|
|
187
|
+
{
|
|
188
|
+
query: Pact::QueryHash.new(bar: Pact::Term.new(generate: 'foobar', matcher: /foo/))
|
|
189
|
+
}
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
let(:rules) do
|
|
193
|
+
{
|
|
194
|
+
"$.query.bar[0]" => {
|
|
195
|
+
"matchers" => [ {"match" => "regex", "regex" => "foo"} ]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "lists a rule that specifies that the regular expression must match" do
|
|
201
|
+
expect(subject).to eq rules
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context "with no special matching" do
|
|
206
|
+
let(:matchable) do
|
|
207
|
+
{
|
|
208
|
+
body: { alligator: { name: 'Mary' } }
|
|
209
|
+
}
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
let(:rules) do
|
|
213
|
+
{}
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
it "does not create any rules" do
|
|
218
|
+
expect(subject).to eq rules
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
context "with a key containing a dot" do
|
|
223
|
+
let(:matchable) do
|
|
224
|
+
{
|
|
225
|
+
"key" => {
|
|
226
|
+
"key.with.dots" => Pact::SomethingLike.new("foo")
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "uses square brackets notation for the key with dots" do
|
|
232
|
+
expect(subject.keys).to include "$.key['key.with.dots']"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|