pact 0.1.28 → 0.1.35
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|