pact 0.1.28 → 0.1.35
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.
- data/Gemfile.lock +5 -5
- data/README.md +52 -53
- data/example/zoo-app/Gemfile +15 -0
- data/example/zoo-app/Gemfile.lock +77 -0
- data/example/zoo-app/lib/zoo_app/animal_service_client.rb +36 -0
- data/example/zoo-app/lib/zoo_app/models/alligator.rb +15 -0
- data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +100 -0
- data/example/zoo-app/spec/service_providers/animal_service_spec.rb +92 -0
- data/example/zoo-app/spec/service_providers/pact_helper.rb +11 -0
- data/example/zoo-app/spec/spec_helper.rb +8 -0
- data/lib/pact/consumer/configuration_dsl.rb +2 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +13 -12
- data/lib/pact/consumer/dsl.rb +51 -2
- data/lib/pact/consumer/interaction.rb +15 -12
- data/lib/pact/consumer/mock_service.rb +31 -9
- data/lib/pact/consumer/mock_service_client.rb +47 -0
- data/lib/pact/consumer/rspec.rb +2 -1
- data/lib/pact/consumer_contract.rb +2 -1
- data/lib/pact/matchers/matchers.rb +59 -18
- data/lib/pact/producer/dsl.rb +61 -0
- data/lib/pact/producer/producer_state.rb +7 -0
- data/lib/pact/producer/rspec.rb +2 -0
- data/lib/pact/provider/rspec.rb +1 -0
- data/lib/pact/request.rb +42 -6
- data/lib/pact/verification_task.rb +2 -5
- data/lib/pact/version.rb +1 -1
- data/spec/features/consumption_spec.rb +56 -18
- data/spec/features/production_spec.rb +7 -16
- data/spec/integration/pact/consumer_configuration_spec.rb +144 -0
- data/spec/integration/pact/provider_configuration_spec.rb +24 -0
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +13 -13
- data/spec/lib/pact/consumer/dsl_spec.rb +1 -0
- data/spec/lib/pact/consumer/interaction_spec.rb +34 -0
- data/spec/lib/pact/consumer_contract_spec.rb +13 -2
- data/spec/lib/pact/matchers/matchers_spec.rb +32 -12
- data/spec/lib/pact/producer/rspec_spec.rb +1 -1
- data/spec/lib/pact/request_spec.rb +43 -1
- data/spec/support/pact_rake_support.rb +5 -8
- metadata +17 -10
- data/spec/integration/pact/configuration_spec.rb +0 -65
@@ -2,29 +2,24 @@ require 'net/http'
|
|
2
2
|
require 'pact/consumer'
|
3
3
|
require 'pact/consumer/rspec'
|
4
4
|
|
5
|
-
|
6
5
|
describe "A service consumer side of a pact", :pact => true do
|
7
6
|
|
8
7
|
it "goes a little something like this" do
|
9
8
|
Pact.clear_configuration
|
10
9
|
|
11
|
-
Pact.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Pact.with_producer "Alice Service" do
|
18
|
-
mock_service :alice_service do
|
19
|
-
verify true
|
20
|
-
port 1234
|
10
|
+
Pact.service_consumer "Consumer" do
|
11
|
+
has_pact_with "Alice Service" do
|
12
|
+
mock_service :alice_service do
|
13
|
+
verify true
|
14
|
+
port 1234
|
15
|
+
end
|
21
16
|
end
|
22
|
-
end
|
23
17
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
has_pact_with "Bob" do
|
19
|
+
mock_service :bob_service do
|
20
|
+
verify false
|
21
|
+
port 4321
|
22
|
+
end
|
28
23
|
end
|
29
24
|
end
|
30
25
|
|
@@ -109,12 +104,12 @@ describe "A service consumer side of a pact", :pact => true do
|
|
109
104
|
Pact.clear_configuration
|
110
105
|
|
111
106
|
Pact.configure do | config |
|
112
|
-
config.
|
107
|
+
config.service_consumer do
|
113
108
|
name "Consumer"
|
114
109
|
end
|
115
110
|
end
|
116
111
|
|
117
|
-
Pact.
|
112
|
+
Pact.with_service_provider "Zebra Service" do
|
118
113
|
mock_service :zebra_service do
|
119
114
|
verify false
|
120
115
|
port 1235
|
@@ -142,5 +137,48 @@ describe "A service consumer side of a pact", :pact => true do
|
|
142
137
|
end
|
143
138
|
end
|
144
139
|
|
140
|
+
context "with a async interaction with producer" do
|
141
|
+
before do
|
142
|
+
Pact.clear_configuration
|
143
|
+
|
144
|
+
Pact.configure do | config |
|
145
|
+
config.service_consumer do
|
146
|
+
name "Consumer"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
Pact.with_service_provider "Zebra Service" do
|
151
|
+
mock_service :zebra_service do
|
152
|
+
verify true
|
153
|
+
port 1239
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it "goes like this" do
|
159
|
+
zebra_service.
|
160
|
+
given(:the_zebras_are_here).
|
161
|
+
upon_receiving("a retrieve Mallory request").with({
|
162
|
+
method: :get,
|
163
|
+
path: '/mallory'
|
164
|
+
}).
|
165
|
+
will_respond_with({
|
166
|
+
status: 200
|
167
|
+
})
|
168
|
+
|
169
|
+
async_interaction { Net::HTTP.get_response(URI('http://localhost:1239/mallory'))}
|
170
|
+
|
171
|
+
zebra_service.wait_for_interactions wait_max_seconds: 1, poll_interval: 0.1
|
172
|
+
end
|
173
|
+
|
174
|
+
def async_interaction
|
175
|
+
Thread.new do
|
176
|
+
sleep 0.2
|
177
|
+
yield
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
145
183
|
end
|
146
184
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'pact/
|
1
|
+
require 'pact/provider/rspec'
|
2
2
|
require 'pact/consumer_contract'
|
3
3
|
require 'features/producer_states/zebras'
|
4
4
|
|
@@ -74,11 +74,8 @@ module Pact::Producer
|
|
74
74
|
EOS
|
75
75
|
|
76
76
|
before do
|
77
|
-
Pact.
|
78
|
-
|
79
|
-
name "My Producer"
|
80
|
-
app { ServiceUnderTest.new }
|
81
|
-
end
|
77
|
+
Pact.service_provider "My Provider" do
|
78
|
+
app { ServiceUnderTest.new }
|
82
79
|
end
|
83
80
|
end
|
84
81
|
|
@@ -110,11 +107,8 @@ module Pact::Producer
|
|
110
107
|
EOS
|
111
108
|
|
112
109
|
before do
|
113
|
-
Pact.
|
114
|
-
|
115
|
-
name "My Producer"
|
116
|
-
app { ServiceUnderTestWithFixture.new }
|
117
|
-
end
|
110
|
+
Pact.service_provider "My Provider" do
|
111
|
+
app { ServiceUnderTestWithFixture.new }
|
118
112
|
end
|
119
113
|
end
|
120
114
|
|
@@ -144,11 +138,8 @@ module Pact::Producer
|
|
144
138
|
EOS
|
145
139
|
|
146
140
|
before do
|
147
|
-
Pact.
|
148
|
-
|
149
|
-
name "ServiceUnderTestWithFixture"
|
150
|
-
app { ServiceUnderTestWithFixture.new }
|
151
|
-
end
|
141
|
+
Pact.service_provider "ServiceUnderTestWithFixture" do
|
142
|
+
app { ServiceUnderTestWithFixture.new }
|
152
143
|
end
|
153
144
|
end
|
154
145
|
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/configuration'
|
3
|
+
require 'pact/consumer/dsl'
|
4
|
+
require 'pact/consumer/configuration_dsl'
|
5
|
+
require 'pact/producer/configuration_dsl'
|
6
|
+
|
7
|
+
describe "consumer side" do
|
8
|
+
describe "configure" do
|
9
|
+
|
10
|
+
class TestHelper
|
11
|
+
include Pact::Consumer::ConsumerContractBuilders
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:application) { double("App")}
|
15
|
+
|
16
|
+
before do
|
17
|
+
Pact.clear_configuration
|
18
|
+
Pact::Consumer::AppManager.instance.clear_all
|
19
|
+
#Don't want processes actually spawning
|
20
|
+
Pact::Consumer::AppRegistration.any_instance.stub(:spawn)
|
21
|
+
|
22
|
+
my_app = application
|
23
|
+
|
24
|
+
Pact.service_consumer "My Consumer" do
|
25
|
+
app my_app
|
26
|
+
port 1111
|
27
|
+
|
28
|
+
has_pact_with "My Service" do
|
29
|
+
mock_service :my_service do
|
30
|
+
port 1234
|
31
|
+
standalone true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
has_pact_with "My Other Service" do
|
36
|
+
mock_service :my_other_service do
|
37
|
+
port 1235
|
38
|
+
standalone false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "consumer" do
|
46
|
+
|
47
|
+
subject { TestHelper.new.my_service.consumer_contract.consumer }
|
48
|
+
|
49
|
+
it "should be configured" do
|
50
|
+
expect(subject).to be_instance_of Pact::Consumer::ServiceConsumer
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have the right name" do
|
54
|
+
expect(subject.name).to eq "My Consumer"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have registered the app" do
|
58
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1111).should be_true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "producers" do
|
63
|
+
|
64
|
+
subject { TestHelper.new.my_service }
|
65
|
+
|
66
|
+
it "should have defined methods in MockServices for the producers" do
|
67
|
+
subject.should be_instance_of Pact::Consumer::ConsumerContractBuilder
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when standalone is true" do
|
71
|
+
it "is not registerd with the AppManager" do
|
72
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1234).should be_false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when standalone is false" do
|
77
|
+
it "should register the MockServices on their given ports if they are not" do
|
78
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1235).should be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
describe "deprecated configure" do
|
86
|
+
|
87
|
+
before do
|
88
|
+
Pact.clear_configuration
|
89
|
+
Pact::Consumer::AppManager.instance.clear_all
|
90
|
+
|
91
|
+
Pact.configure do | config |
|
92
|
+
config.service_consumer do
|
93
|
+
name "My Consumer"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
Pact.with_service_provider "My Service" do
|
98
|
+
mock_service :my_service do
|
99
|
+
port 1234
|
100
|
+
standalone true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Pact.with_service_provider "My Other Service" do
|
105
|
+
mock_service :my_other_service do
|
106
|
+
port 1235
|
107
|
+
standalone false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "configuration" do
|
113
|
+
it "should return the same configuration object each time" do
|
114
|
+
expect(Pact.configuration).to equal(Pact.configuration)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "deprecated consumer" do
|
119
|
+
it "should be configured" do
|
120
|
+
Pact.configuration.consumer.name.should eq "My Consumer"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "producers" do
|
125
|
+
include Pact::Consumer::ConsumerContractBuilders
|
126
|
+
|
127
|
+
it "should have defined methods in MockServices for the producers" do
|
128
|
+
my_service.should be_instance_of Pact::Consumer::ConsumerContractBuilder
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when standalone is true" do
|
132
|
+
it "is not registerd with the AppManager" do
|
133
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1234).should be_false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when standalone is false" do
|
138
|
+
it "should register the MockServices on their given ports if they are not" do
|
139
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1235).should be_true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/provider/rspec'
|
3
|
+
|
4
|
+
describe "provider side" do
|
5
|
+
describe "configure" do
|
6
|
+
|
7
|
+
class TestHelper
|
8
|
+
include Pact::Producer::RSpec::InstanceMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:application) { double("App")}
|
12
|
+
before do
|
13
|
+
app_block = ->{ application }
|
14
|
+
Pact.service_provider "My Provider" do
|
15
|
+
app &app_block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "makes the app available to the tests" do
|
20
|
+
expect(TestHelper.new.app).to be(application)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -38,12 +38,12 @@ module Pact
|
|
38
38
|
it "updates the existing pact file" do
|
39
39
|
expect(consumer_contract_builder.consumer_contract.interactions.size).to eq 2
|
40
40
|
end
|
41
|
-
end
|
42
|
-
end
|
41
|
+
end
|
42
|
+
end
|
43
43
|
|
44
44
|
describe "handle_interaction_fully_defined" do
|
45
45
|
|
46
|
-
subject {
|
46
|
+
subject {
|
47
47
|
Pact::Consumer::ConsumerContractBuilder.new({:consumer_name => 'blah', :producer_name => 'blah', :port => 2222})
|
48
48
|
}
|
49
49
|
|
@@ -64,23 +64,23 @@ module Pact
|
|
64
64
|
}
|
65
65
|
}
|
66
66
|
|
67
|
-
let(:interaction_json) {
|
67
|
+
let(:interaction_json) { interaction.to_json_for_mock_service }
|
68
68
|
|
69
|
-
let(:interaction) { Pact::Consumer::Interaction.from_hash(JSON.parse(
|
69
|
+
let(:interaction) { Pact::Consumer::Interaction.from_hash(JSON.parse(interaction_hash.to_json)) }
|
70
70
|
|
71
71
|
before do
|
72
72
|
stub_request(:post, 'localhost:2222/interactions')
|
73
73
|
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
it "posts the interaction with generated response to the mock service" do
|
76
|
+
subject.handle_interaction_fully_defined interaction
|
77
|
+
WebMock.should have_requested(:post, 'localhost:2222/interactions').with(body: interaction_json)
|
78
|
+
end
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
it "updates the Producer's Pactfile" do
|
81
|
+
subject.consumer_contract.should_receive(:update_pactfile)
|
82
|
+
subject.handle_interaction_fully_defined interaction
|
83
|
+
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
@@ -41,6 +41,40 @@ module Pact
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
+
describe "as_json_for_mock_service" do
|
45
|
+
let(:as_json_with_options ) { {:opts => 'blah'} }
|
46
|
+
let(:request) { double(Pact::Request::Expected, :as_json_with_options => {:opts => 'blah'})}
|
47
|
+
let(:response) { double('response') }
|
48
|
+
let(:generated_response ) { double('generated_response', :to_json => 'generated_response') }
|
49
|
+
subject { Interaction.new(:description => 'description', :request => request, :response => response, :producer_state => 'ignored')}
|
50
|
+
let(:expected_hash) { {:response => generated_response, :request => as_json_with_options, :description => '' } }
|
51
|
+
|
52
|
+
before do
|
53
|
+
Reification.stub(:from_term).with(response).and_return(generated_response)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "generates an actual response" do
|
57
|
+
Reification.should_receive(:from_term).with(response).and_return(generated_response)
|
58
|
+
expect(subject.as_json_for_mock_service[:response]).to eq generated_response
|
59
|
+
end
|
60
|
+
|
61
|
+
it "includes the options in the request" do
|
62
|
+
expect(subject.as_json_for_mock_service[:request]).to eq as_json_with_options
|
63
|
+
end
|
64
|
+
|
65
|
+
it "does not send the producer state" do
|
66
|
+
expect(subject.as_json_for_mock_service.key?(:producer_state)).to be_false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "includes the description" do
|
70
|
+
expect(subject.as_json_for_mock_service[:description]).to eq 'description'
|
71
|
+
end
|
72
|
+
|
73
|
+
it "doesn't have any other keys" do
|
74
|
+
expect(subject.as_json_for_mock_service.keys).to eq [:response, :request, :description]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
44
78
|
describe "to JSON" do
|
45
79
|
|
46
80
|
let(:parsed_result) do
|
@@ -11,9 +11,18 @@ module Pact
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def silence_warnings
|
15
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
16
|
+
yield
|
17
|
+
ensure
|
18
|
+
$VERBOSE = old_verbose
|
19
|
+
end
|
20
|
+
|
14
21
|
before do
|
15
22
|
@backup_version = Pact::VERSION
|
16
|
-
|
23
|
+
silence_warnings do
|
24
|
+
Pact::VERSION = "1.0"
|
25
|
+
end
|
17
26
|
DateTime.stub(:now).and_return(DateTime.strptime("2013-08-15T13:27:13+10:00"))
|
18
27
|
end
|
19
28
|
|
@@ -27,7 +36,9 @@ module Pact
|
|
27
36
|
end
|
28
37
|
|
29
38
|
after do
|
30
|
-
|
39
|
+
silence_warnings do
|
40
|
+
Pact::VERSION = @backup_version
|
41
|
+
end
|
31
42
|
end
|
32
43
|
end
|
33
44
|
|
@@ -5,6 +5,26 @@ require 'pact/matchers'
|
|
5
5
|
describe Pact::Matchers do
|
6
6
|
include Pact::Matchers
|
7
7
|
|
8
|
+
describe 'option {allow_unexpected_keys: false}' do
|
9
|
+
context "when an unexpected key is found" do
|
10
|
+
let(:expected) { {:a => 1} }
|
11
|
+
let(:actual) { {:a => 1, :b => 2} }
|
12
|
+
let(:difference) { {:b => {:expected => '<key not to be present>', :actual => 2 }} }
|
13
|
+
it "returns it in the diff" do
|
14
|
+
expect(diff(expected, actual, allow_unexpected_keys: false)).to eq difference
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "expecting key to be present with nil value and not finding key" do
|
20
|
+
let(:expected) { {a: nil} }
|
21
|
+
let(:actual) { {} }
|
22
|
+
let(:difference) { {a: {expected: nil, actual: Pact::Matchers::KeyNotFound.new }} }
|
23
|
+
it "returns the key in the diff" do
|
24
|
+
expect(diff(expected, actual)).to eq difference
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
8
28
|
describe 'structure_diff' do
|
9
29
|
let(:expected) {
|
10
30
|
{a: 'a string', b: 1, c: nil, d: [{e: 'thing'}], f: {g: 10}}
|
@@ -40,14 +60,14 @@ describe Pact::Matchers do
|
|
40
60
|
let(:difference) { {:a=>{:expected=>{:class=>Fixnum, :eg=>1}, :actual=>{:class=>Hash, :value=>{:b=>1}}}} }
|
41
61
|
it "returns the diff" do
|
42
62
|
expect(structure_diff(expected, actual)).to eq difference
|
43
|
-
end
|
63
|
+
end
|
44
64
|
end
|
45
65
|
context "and an array is found" do
|
46
66
|
let(:actual) { {a: [1] } }
|
47
67
|
let(:difference) { {:a=>{:expected=>{:class=>Fixnum, :eg=>1}, :actual=>{:class=>Array, :value=>[1]}}} }
|
48
68
|
it "returns the diff" do
|
49
69
|
expect(structure_diff(expected, actual)).to eq difference
|
50
|
-
end
|
70
|
+
end
|
51
71
|
end
|
52
72
|
end
|
53
73
|
|
@@ -61,7 +81,7 @@ describe Pact::Matchers do
|
|
61
81
|
:expected=> { :class=>String, :eg=>"Mary" },
|
62
82
|
:actual=> { :class=>Fixnum, :value=>1} }
|
63
83
|
}
|
64
|
-
]
|
84
|
+
]
|
65
85
|
}
|
66
86
|
it "returns the diff" do
|
67
87
|
expect(structure_diff(expected, actual)).to eq difference
|
@@ -77,7 +97,7 @@ describe Pact::Matchers do
|
|
77
97
|
let(:difference) { {:a=>{:expected=>nil, :actual=>{:class=>String, :value=>"a string"}}} }
|
78
98
|
it "returns the diff" do
|
79
99
|
expect(structure_diff(expected, actual)).to eq difference
|
80
|
-
end
|
100
|
+
end
|
81
101
|
end
|
82
102
|
end
|
83
103
|
|
@@ -88,8 +108,8 @@ describe Pact::Matchers do
|
|
88
108
|
let(:difference) { {:a=>{:expected=>/p/, :actual=>"banana"}} }
|
89
109
|
it "returns the diff" do
|
90
110
|
expect(structure_diff(expected, actual)).to eq difference
|
91
|
-
end
|
92
|
-
end
|
111
|
+
end
|
112
|
+
end
|
93
113
|
end
|
94
114
|
end
|
95
115
|
|
@@ -122,7 +142,7 @@ describe Pact::Matchers do
|
|
122
142
|
end
|
123
143
|
context "when the actual value is an hash" do
|
124
144
|
let(:actual) { {b: 'c'} }
|
125
|
-
let(:difference) { { a: {expected:"b", actual:
|
145
|
+
let(:difference) { { a: {expected:"b", actual: Pact::Matchers::KeyNotFound.new}} }
|
126
146
|
it "should return the diff" do
|
127
147
|
expect(diff(subject, actual)).to eql(difference)
|
128
148
|
end
|
@@ -261,17 +281,17 @@ describe Pact::Matchers do
|
|
261
281
|
end
|
262
282
|
|
263
283
|
context "when the expected value is a String matcher" do
|
264
|
-
|
284
|
+
|
265
285
|
end
|
266
286
|
|
267
287
|
context "when the expected value is a Number matcher" do
|
268
|
-
|
288
|
+
|
269
289
|
end
|
270
290
|
context "when the expected value is an array with a matcher" do
|
271
|
-
|
291
|
+
|
272
292
|
end
|
273
293
|
context "when the expected value is a hash with a matcher" do
|
274
|
-
|
294
|
+
|
275
295
|
end
|
276
296
|
|
277
297
|
context "when an expected value is nil but not nil is found" do
|
@@ -286,7 +306,7 @@ describe Pact::Matchers do
|
|
286
306
|
context "a deep mismatch" do
|
287
307
|
subject { {a: {b: { c: [1,2]}, d: { e: Pact::Term.new(matcher: /a/)}}, f: 1, g: {h: 99}} }
|
288
308
|
let(:actual) { {a: {b: { c: [1,2]}, d: { e: 'food'}}, f: "thing"} }
|
289
|
-
let(:difference) { {:a=>{:d=>{:e=>{:expected=>/a/, :actual=>"food"}}}, :f=>{:expected=>1, :actual=>"thing"}, :g=>{:expected=>{:h=>99}, :actual=>
|
309
|
+
let(:difference) { {:a=>{:d=>{:e=>{:expected=>/a/, :actual=>"food"}}}, :f=>{:expected=>1, :actual=>"thing"}, :g=>{:expected=>{:h=>99}, :actual=> Pact::Matchers::KeyNotFound.new}} }
|
290
310
|
|
291
311
|
it 'should return the diff' do
|
292
312
|
expect(diff(subject, actual)).to eql(difference)
|
@@ -45,9 +45,34 @@ module Pact
|
|
45
45
|
describe Request::Expected do
|
46
46
|
it_behaves_like "a request"
|
47
47
|
|
48
|
+
describe "as_json_with_options" do
|
49
|
+
subject { Request::Expected.new(:get, '/path', {:header => 'value'}, {:body => 'yeah'}, "query", options) }
|
50
|
+
context "with options" do
|
51
|
+
let(:options) { {some: 'options'} }
|
52
|
+
it "includes the options" do
|
53
|
+
expect(subject.as_json_with_options[:options]).to eq options
|
54
|
+
end
|
55
|
+
end
|
56
|
+
context "without options" do
|
57
|
+
let(:options) { {} }
|
58
|
+
it "does not include the options" do
|
59
|
+
expect(subject.as_json_with_options.key?(:options)).to be_false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
describe "as_json" do
|
64
|
+
subject { Request::Expected.new(:get, '/path', {:header => 'value'}, {:body => 'yeah'}, "query", {some: 'options'}) }
|
65
|
+
context "with options" do
|
66
|
+
it "does not include the options" do
|
67
|
+
expect(subject.as_json.key?(:options)).to be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
48
72
|
describe "matching to actual requests" do
|
49
73
|
|
50
|
-
subject { Request::Expected.new(expected_method, expected_path, expected_headers, expected_body, expected_query) }
|
74
|
+
subject { Request::Expected.new(expected_method, expected_path, expected_headers, expected_body, expected_query, options) }
|
75
|
+
let(:options) { {} }
|
51
76
|
|
52
77
|
let(:expected_method) { 'get' }
|
53
78
|
let(:expected_path) { '/foo' }
|
@@ -307,6 +332,23 @@ module Pact
|
|
307
332
|
expect(subject.match actual_request).to be_false
|
308
333
|
end
|
309
334
|
end
|
335
|
+
|
336
|
+
context "when unexpected keys are found in the body" do
|
337
|
+
let(:expected_body) { {a: 1} }
|
338
|
+
let(:actual_body) { {a: 1, b: 2} }
|
339
|
+
context "when allowing unexpected keys" do
|
340
|
+
let(:options) { {'allow_unexpected_keys_in_body' => true} } #From json, these will be strings
|
341
|
+
it "matches" do
|
342
|
+
expect(subject.match actual_request).to be_true
|
343
|
+
end
|
344
|
+
end
|
345
|
+
context "when not allowing unexpected keys" do
|
346
|
+
let(:options) { {'allow_unexpected_keys_in_body' => false} }
|
347
|
+
it "does not match" do
|
348
|
+
expect(subject.match actual_request).to be_false
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
310
352
|
end
|
311
353
|
end
|
312
354
|
|
@@ -12,17 +12,14 @@ module Pact
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
Pact.
|
16
|
-
|
17
|
-
name "Some Producer"
|
18
|
-
app { TestApp.new }
|
19
|
-
end
|
15
|
+
Pact.service_provider "Some Producer" do
|
16
|
+
app { TestApp.new }
|
20
17
|
end
|
21
18
|
|
22
19
|
|
23
20
|
#one with a top level consumer
|
24
|
-
Pact.
|
25
|
-
|
21
|
+
Pact.provider_states_for 'some-test-consumer' do
|
22
|
+
provider_state "the weather is sunny" do
|
26
23
|
set_up do
|
27
24
|
WEATHER ||= {}
|
28
25
|
WEATHER[:current_state] = 'sunny'
|
@@ -31,7 +28,7 @@ module Pact
|
|
31
28
|
end
|
32
29
|
|
33
30
|
#one without a top level consumer
|
34
|
-
Pact.
|
31
|
+
Pact.provider_state "the weather is cloudy" do
|
35
32
|
set_up do
|
36
33
|
WEATHER ||= {}
|
37
34
|
WEATHER[:current_state] = 'cloudy'
|