pact 0.1.28
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/.gitignore +28 -0
- data/.rspec +2 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +83 -0
- data/LICENSE.txt +22 -0
- data/README.md +238 -0
- data/Rakefile +33 -0
- data/bin/pact +4 -0
- data/lib/pact/app.rb +32 -0
- data/lib/pact/configuration.rb +54 -0
- data/lib/pact/consumer/app_manager.rb +177 -0
- data/lib/pact/consumer/configuration_dsl.rb +71 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +79 -0
- data/lib/pact/consumer/consumer_contract_builders.rb +10 -0
- data/lib/pact/consumer/dsl.rb +98 -0
- data/lib/pact/consumer/interaction.rb +70 -0
- data/lib/pact/consumer/mock_service.rb +340 -0
- data/lib/pact/consumer/rspec.rb +43 -0
- data/lib/pact/consumer/run_condor.rb +4 -0
- data/lib/pact/consumer/run_mock_contract_service.rb +13 -0
- data/lib/pact/consumer/service_consumer.rb +22 -0
- data/lib/pact/consumer/service_producer.rb +23 -0
- data/lib/pact/consumer.rb +7 -0
- data/lib/pact/consumer_contract.rb +110 -0
- data/lib/pact/json_warning.rb +23 -0
- data/lib/pact/logging.rb +14 -0
- data/lib/pact/matchers/matchers.rb +85 -0
- data/lib/pact/matchers.rb +1 -0
- data/lib/pact/producer/configuration_dsl.rb +62 -0
- data/lib/pact/producer/matchers.rb +22 -0
- data/lib/pact/producer/pact_spec_runner.rb +57 -0
- data/lib/pact/producer/producer_state.rb +81 -0
- data/lib/pact/producer/rspec.rb +127 -0
- data/lib/pact/producer/test_methods.rb +89 -0
- data/lib/pact/producer.rb +1 -0
- data/lib/pact/rake_task.rb +64 -0
- data/lib/pact/reification.rb +26 -0
- data/lib/pact/request.rb +109 -0
- data/lib/pact/term.rb +40 -0
- data/lib/pact/verification_task.rb +57 -0
- data/lib/pact/version.rb +3 -0
- data/lib/pact.rb +5 -0
- data/lib/tasks/pact.rake +6 -0
- data/pact.gemspec +36 -0
- data/scratchpad.txt +36 -0
- data/spec/features/consumption_spec.rb +146 -0
- data/spec/features/producer_states/zebras.rb +28 -0
- data/spec/features/production_spec.rb +160 -0
- data/spec/integration/pact/configuration_spec.rb +65 -0
- data/spec/lib/pact/configuration_spec.rb +35 -0
- data/spec/lib/pact/consumer/app_manager_spec.rb +41 -0
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +87 -0
- data/spec/lib/pact/consumer/dsl_spec.rb +52 -0
- data/spec/lib/pact/consumer/interaction_spec.rb +108 -0
- data/spec/lib/pact/consumer/mock_service_spec.rb +147 -0
- data/spec/lib/pact/consumer/service_consumer_spec.rb +11 -0
- data/spec/lib/pact/consumer_contract_spec.rb +125 -0
- data/spec/lib/pact/matchers/matchers_spec.rb +354 -0
- data/spec/lib/pact/producer/configuration_dsl_spec.rb +101 -0
- data/spec/lib/pact/producer/producer_state_spec.rb +103 -0
- data/spec/lib/pact/producer/rspec_spec.rb +48 -0
- data/spec/lib/pact/reification_spec.rb +43 -0
- data/spec/lib/pact/request_spec.rb +316 -0
- data/spec/lib/pact/term_spec.rb +36 -0
- data/spec/lib/pact/verification_task_spec.rb +64 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/a_consumer-a_producer.json +34 -0
- data/spec/support/pact_rake_support.rb +41 -0
- data/spec/support/test_app_fail.json +22 -0
- data/spec/support/test_app_pass.json +21 -0
- data/tasks/pact-test.rake +19 -0
- metadata +381 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'pact/consumer'
|
3
|
+
require 'pact/consumer/rspec'
|
4
|
+
|
5
|
+
|
6
|
+
describe "A service consumer side of a pact", :pact => true do
|
7
|
+
|
8
|
+
it "goes a little something like this" do
|
9
|
+
Pact.clear_configuration
|
10
|
+
|
11
|
+
Pact.configure do | config |
|
12
|
+
config.consumer do
|
13
|
+
name "Consumer"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Pact.with_producer "Alice Service" do
|
18
|
+
mock_service :alice_service do
|
19
|
+
verify true
|
20
|
+
port 1234
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Pact.with_producer "Bob" do
|
25
|
+
mock_service :bob_service do
|
26
|
+
verify false
|
27
|
+
port 4321
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
alice_service.
|
32
|
+
upon_receiving("a retrieve Mallory request").with({
|
33
|
+
method: :get,
|
34
|
+
path: '/mallory'
|
35
|
+
}).
|
36
|
+
will_respond_with({
|
37
|
+
status: 200,
|
38
|
+
headers: { 'Content-Type' => 'text/html' },
|
39
|
+
body: Pact::Term.new(matcher: /Mallory/, generate: 'That is some good Mallory.')
|
40
|
+
})
|
41
|
+
|
42
|
+
bob_service.
|
43
|
+
upon_receiving('a create donut request').with({
|
44
|
+
method: :post,
|
45
|
+
path: '/donuts',
|
46
|
+
body: {
|
47
|
+
"name" => Pact::Term.new(matcher: /Bob/)
|
48
|
+
},
|
49
|
+
headers: {'Accept' => 'text/plain', "Content-Type" => 'application/json'}
|
50
|
+
}).
|
51
|
+
will_respond_with({
|
52
|
+
status: 201,
|
53
|
+
body: 'Donut created.'
|
54
|
+
})
|
55
|
+
bob_service.
|
56
|
+
upon_receiving('a delete charlie request').with({
|
57
|
+
method: :delete,
|
58
|
+
path: '/charlie'
|
59
|
+
}).
|
60
|
+
will_respond_with({
|
61
|
+
status: 200,
|
62
|
+
body: /deleted/
|
63
|
+
})
|
64
|
+
bob_service.
|
65
|
+
upon_receiving('an update alligators request').with({
|
66
|
+
method: :put,
|
67
|
+
path: '/alligators',
|
68
|
+
body: [{"name" => 'Roger' }]
|
69
|
+
}).
|
70
|
+
will_respond_with({
|
71
|
+
status: 200,
|
72
|
+
body: [{"name" => "Roger", "age" => 20}]
|
73
|
+
})
|
74
|
+
|
75
|
+
|
76
|
+
alice_response = Net::HTTP.get_response(URI('http://localhost:1234/mallory'))
|
77
|
+
|
78
|
+
expect(alice_response.code).to eql '200'
|
79
|
+
expect(alice_response['Content-Type']).to eql 'text/html'
|
80
|
+
expect(alice_response.body).to eql 'That is some good Mallory.'
|
81
|
+
|
82
|
+
uri = URI('http://localhost:4321/donuts')
|
83
|
+
post_req = Net::HTTP::Post.new(uri.path)
|
84
|
+
post_req['Accept'] = "text/plain"
|
85
|
+
post_req['Content-Type'] = "application/json"
|
86
|
+
post_req.body = {"name" => "Bobby"}.to_json
|
87
|
+
bob_post_response = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
88
|
+
http.request post_req
|
89
|
+
end
|
90
|
+
|
91
|
+
expect(bob_post_response.code).to eql '201'
|
92
|
+
expect(bob_post_response.body).to eql 'Donut created.'
|
93
|
+
|
94
|
+
uri = URI('http://localhost:4321/alligators')
|
95
|
+
post_req = Net::HTTP::Put.new(uri.path)
|
96
|
+
post_req['Content-Type'] = "application/json"
|
97
|
+
post_req.body = [{"name" => "Roger"}].to_json
|
98
|
+
bob_post_response = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
99
|
+
http.request post_req
|
100
|
+
end
|
101
|
+
|
102
|
+
expect(bob_post_response.code).to eql '200'
|
103
|
+
expect(bob_post_response.body).to eql([{"name" => "Roger", "age" => 20}].to_json)
|
104
|
+
expect{ bob_service.verify('goes a little something like this') }.to raise_error /do not match/
|
105
|
+
end
|
106
|
+
|
107
|
+
context "with a producer state" do
|
108
|
+
before do
|
109
|
+
Pact.clear_configuration
|
110
|
+
|
111
|
+
Pact.configure do | config |
|
112
|
+
config.consumer do
|
113
|
+
name "Consumer"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
Pact.with_producer "Zebra Service" do
|
118
|
+
mock_service :zebra_service do
|
119
|
+
verify false
|
120
|
+
port 1235
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "goes like this" do
|
126
|
+
zebra_service.
|
127
|
+
given(:the_zebras_are_here).
|
128
|
+
upon_receiving("a retrieve Mallory request").with({
|
129
|
+
method: :get,
|
130
|
+
path: '/mallory',
|
131
|
+
headers: {'Accept' => 'text/html'}
|
132
|
+
}).
|
133
|
+
will_respond_with({
|
134
|
+
status: 200,
|
135
|
+
headers: { 'Content-Type' => 'text/html' },
|
136
|
+
body: Pact::Term.new(matcher: /Mallory/, generate: 'That is some good Mallory.')
|
137
|
+
})
|
138
|
+
|
139
|
+
interactions = Pact::ConsumerContract.from_json(File.read(zebra_service.consumer_contract.pactfile_path)).interactions
|
140
|
+
interactions.first.producer_state.should eq("the_zebras_are_here")
|
141
|
+
sleep 1
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
Pact.with_consumer 'the-wild-beast-store' do
|
5
|
+
|
6
|
+
producer_state :the_zebras_are_here do
|
7
|
+
set_up do
|
8
|
+
FileUtils.mkdir_p 'tmp'
|
9
|
+
some_data = [{'name' => 'Jason'},{'name' => 'Sarah'}]
|
10
|
+
File.open("tmp/a_mock_database.json", "w") { |file| file << some_data.to_json }
|
11
|
+
end
|
12
|
+
|
13
|
+
tear_down do
|
14
|
+
FileUtils.rm_rf("tmp/a_mock_database.json")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Pact.producer_state "some other zebras are here" do
|
20
|
+
set_up do
|
21
|
+
some_data = [{'name' => 'Mark'},{'name' => 'Gertrude'}]
|
22
|
+
File.open("tmp/a_mock_database.json", "w") { |file| file << some_data.to_json }
|
23
|
+
end
|
24
|
+
|
25
|
+
tear_down do
|
26
|
+
FileUtils.rm_rf("tmp/a_mock_database.json")
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'pact/producer/rspec'
|
2
|
+
require 'pact/consumer_contract'
|
3
|
+
require 'features/producer_states/zebras'
|
4
|
+
|
5
|
+
|
6
|
+
module Pact::Producer
|
7
|
+
|
8
|
+
describe "A service production side of a pact" do
|
9
|
+
|
10
|
+
class ServiceUnderTest
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
case env['PATH_INFO']
|
14
|
+
when '/donuts'
|
15
|
+
[201, {'Content-Type' => 'application/json'}, { message: "Donut created." }.to_json]
|
16
|
+
when '/charlie'
|
17
|
+
[200, {'Content-Type' => 'application/json'}, { message: "Your charlie has been deleted" }.to_json]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class ServiceUnderTestWithFixture
|
24
|
+
|
25
|
+
def find_zebra_names
|
26
|
+
#simulate loading data from a database
|
27
|
+
data = JSON.load(File.read('tmp/a_mock_database.json'))
|
28
|
+
data.collect{ | zebra | zebra['name'] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
case env['PATH_INFO']
|
33
|
+
when "/zebra_names"
|
34
|
+
[200, {'Content-Type' => 'application/json'}, { names: find_zebra_names }.to_json]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
pact = Pact::ConsumerContract.from_json <<-EOS
|
41
|
+
{
|
42
|
+
"consumer" : { "name" : "a consumer"},
|
43
|
+
"interactions" : [
|
44
|
+
{
|
45
|
+
"description": "donut creation request",
|
46
|
+
"request": {
|
47
|
+
"method": "post",
|
48
|
+
"path": "/donuts"
|
49
|
+
},
|
50
|
+
"response": {
|
51
|
+
"body": {"message": "Donut created."},
|
52
|
+
"status": 201
|
53
|
+
}
|
54
|
+
},
|
55
|
+
{
|
56
|
+
"description": "charlie deletion request",
|
57
|
+
"request": {
|
58
|
+
"method": "delete",
|
59
|
+
"path": "/charlie"
|
60
|
+
},
|
61
|
+
"response": {
|
62
|
+
"body": {
|
63
|
+
"message": {
|
64
|
+
"json_class": "Regexp",
|
65
|
+
"o": 0,
|
66
|
+
"s": "deleted"
|
67
|
+
}
|
68
|
+
},
|
69
|
+
"status": 200
|
70
|
+
}
|
71
|
+
}
|
72
|
+
]
|
73
|
+
}
|
74
|
+
EOS
|
75
|
+
|
76
|
+
before do
|
77
|
+
Pact.configure do |config|
|
78
|
+
config.producer do
|
79
|
+
name "My Producer"
|
80
|
+
app { ServiceUnderTest.new }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
honour_consumer_contract pact
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "with a producer_state" do
|
90
|
+
|
91
|
+
context "that is a symbol" do
|
92
|
+
consumer_contract = Pact::ConsumerContract.from_json <<-EOS
|
93
|
+
{
|
94
|
+
"consumer" : { "name" : "the-wild-beast-store"},
|
95
|
+
"interactions" : [
|
96
|
+
{
|
97
|
+
"description": "donut creation request",
|
98
|
+
"request": {
|
99
|
+
"method": "delete",
|
100
|
+
"path": "/zebra_names"
|
101
|
+
},
|
102
|
+
"response": {
|
103
|
+
"body": {"names": ["Jason", "Sarah"]},
|
104
|
+
"status": 200
|
105
|
+
},
|
106
|
+
"producer_state" : "the_zebras_are_here"
|
107
|
+
}
|
108
|
+
]
|
109
|
+
}
|
110
|
+
EOS
|
111
|
+
|
112
|
+
before do
|
113
|
+
Pact.configure do |config|
|
114
|
+
config.producer do
|
115
|
+
name "My Producer"
|
116
|
+
app { ServiceUnderTestWithFixture.new }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
honour_consumer_contract consumer_contract
|
123
|
+
end
|
124
|
+
|
125
|
+
context "that is a string" do
|
126
|
+
consumer_contract = Pact::ConsumerContract.from_json <<-EOS
|
127
|
+
{
|
128
|
+
"consumer" : { "name" : "some consumer"},
|
129
|
+
"interactions" : [
|
130
|
+
{
|
131
|
+
"description": "donut creation request",
|
132
|
+
"request": {
|
133
|
+
"method": "post",
|
134
|
+
"path": "/zebra_names"
|
135
|
+
},
|
136
|
+
"response": {
|
137
|
+
"body": {"names": ["Mark", "Gertrude"]},
|
138
|
+
"status": 200
|
139
|
+
},
|
140
|
+
"producer_state" : "some other zebras are here"
|
141
|
+
}
|
142
|
+
]
|
143
|
+
}
|
144
|
+
EOS
|
145
|
+
|
146
|
+
before do
|
147
|
+
Pact.configure do |config|
|
148
|
+
config.producer do
|
149
|
+
name "ServiceUnderTestWithFixture"
|
150
|
+
app { ServiceUnderTestWithFixture.new }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
honour_consumer_contract consumer_contract
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,65 @@
|
|
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 "configure" do
|
8
|
+
|
9
|
+
before do
|
10
|
+
Pact.clear_configuration
|
11
|
+
Pact::Consumer::AppManager.instance.clear_all
|
12
|
+
|
13
|
+
Pact.configure do | config |
|
14
|
+
config.consumer do
|
15
|
+
name "My Consumer"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Pact.with_producer "My Service" do
|
20
|
+
mock_service :my_service do
|
21
|
+
port 1234
|
22
|
+
standalone true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Pact.with_producer "My Other Service" do
|
27
|
+
mock_service :my_other_service do
|
28
|
+
port 1235
|
29
|
+
standalone false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "configuration" do
|
35
|
+
it "should return the same configuration object each time" do
|
36
|
+
expect(Pact.configuration).to equal(Pact.configuration)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "consumer" do
|
41
|
+
it "should be configured" do
|
42
|
+
Pact.configuration.consumer.name.should eq "My Consumer"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "producers" do
|
47
|
+
include Pact::Consumer::ConsumerContractBuilders
|
48
|
+
|
49
|
+
it "should have defined methods in MockServices for the producers" do
|
50
|
+
my_service.should be_instance_of Pact::Consumer::ConsumerContractBuilder
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when standalone is true" do
|
54
|
+
it "is not registerd with the AppManager" do
|
55
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1234).should be_false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when standalone is false" do
|
60
|
+
it "should register the MockServices on their given ports if they are not" do
|
61
|
+
Pact::Consumer::AppManager.instance.app_registered_on?(1235).should be_true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/configuration'
|
3
|
+
|
4
|
+
describe Pact do
|
5
|
+
|
6
|
+
before do
|
7
|
+
Pact.clear_configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "configure" do
|
11
|
+
KEY_VALUE_PAIRS = {pact_dir: 'a path', log_dir: 'a dir', logger: 'a logger'}
|
12
|
+
|
13
|
+
KEY_VALUE_PAIRS.each do | key, value |
|
14
|
+
it "should allow configuration of #{key}" do
|
15
|
+
Pact.configure do | config |
|
16
|
+
config.send("#{key}=".to_sym, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
expect(Pact.configuration.send(key)).to eql(value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "configuration" do
|
25
|
+
it "should have a default pact_dir" do
|
26
|
+
expect(Pact.configuration.pact_dir).to eql File.expand_path('./spec/pacts')
|
27
|
+
end
|
28
|
+
it "should have a default log_dir" do
|
29
|
+
expect(Pact.configuration.log_dir).to eql File.expand_path('./log')
|
30
|
+
end
|
31
|
+
it "should have a default logger configured" do
|
32
|
+
expect(Pact.configuration.logger).to be_instance_of Logger
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Pact::Consumer
|
4
|
+
describe AppManager do
|
5
|
+
before do
|
6
|
+
AppManager.instance.clear_all
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "start_service_for" do
|
10
|
+
before do
|
11
|
+
AppRegistration.any_instance.stub(:spawn) # Don't want process actually spawning during the tests
|
12
|
+
end
|
13
|
+
let(:name) { 'some_service'}
|
14
|
+
context "for http://localhost" do
|
15
|
+
let(:url) { 'http://localhost:1234'}
|
16
|
+
it "starts a mock service at the given port on localhost" do
|
17
|
+
AppRegistration.any_instance.should_receive(:spawn)
|
18
|
+
AppManager.instance.register_mock_service_for name, url
|
19
|
+
AppManager.instance.spawn_all
|
20
|
+
end
|
21
|
+
|
22
|
+
it "registers the mock service as running on the given port" do
|
23
|
+
AppManager.instance.register_mock_service_for name, url
|
24
|
+
AppManager.instance.app_registered_on?(1234).should be_true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
context "for https://" do
|
28
|
+
let(:url) { 'https://localhost:1234'}
|
29
|
+
it "should throw an unsupported error" do
|
30
|
+
expect { AppManager.instance.register_mock_service_for name, url }.to raise_error "Currently only http is supported"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context "for a host other than localhost" do
|
34
|
+
let(:url) { 'http://aserver:1234'}
|
35
|
+
it "should throw an unsupported error" do
|
36
|
+
expect { AppManager.instance.register_mock_service_for name, url }.to raise_error "Currently only services on localhost are supported"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Consumer
|
7
|
+
describe ConsumerContractBuilder do
|
8
|
+
|
9
|
+
describe "initialize" do
|
10
|
+
before do
|
11
|
+
Pact.clear_configuration
|
12
|
+
Pact.configuration.stub(:pact_dir).and_return(File.expand_path(tmp_pact_dir))
|
13
|
+
FileUtils.rm_rf tmp_pact_dir
|
14
|
+
FileUtils.mkdir_p tmp_pact_dir
|
15
|
+
FileUtils.cp './spec/support/a_consumer-a_producer.json', "#{tmp_pact_dir}/a_consumer-a_producer.json"
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:tmp_pact_dir) {"./tmp/pacts"}
|
19
|
+
|
20
|
+
let(:consumer_name) { 'a consumer' }
|
21
|
+
let(:producer_name) { 'a producer' }
|
22
|
+
let(:consumer_contract_builder) {
|
23
|
+
Pact::Consumer::ConsumerContractBuilder.new(
|
24
|
+
:pactfile_write_mode => pactfile_write_mode,
|
25
|
+
:consumer_name => consumer_name,
|
26
|
+
:producer_name => producer_name,
|
27
|
+
:port => 1234)}
|
28
|
+
|
29
|
+
context "when overwriting pact" do
|
30
|
+
let(:pactfile_write_mode) {:overwrite}
|
31
|
+
it "it overwrites the existing pact file" do
|
32
|
+
expect(consumer_contract_builder.consumer_contract.interactions).to eq []
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when updating pact" do
|
37
|
+
let(:pactfile_write_mode) {:update}
|
38
|
+
it "updates the existing pact file" do
|
39
|
+
expect(consumer_contract_builder.consumer_contract.interactions.size).to eq 2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "handle_interaction_fully_defined" do
|
45
|
+
|
46
|
+
subject {
|
47
|
+
Pact::Consumer::ConsumerContractBuilder.new({:consumer_name => 'blah', :producer_name => 'blah', :port => 2222})
|
48
|
+
}
|
49
|
+
|
50
|
+
let(:interaction_hash) {
|
51
|
+
{
|
52
|
+
description: 'Test request',
|
53
|
+
request: {
|
54
|
+
method: 'post',
|
55
|
+
path: '/foo',
|
56
|
+
body: Term.new(generate: 'waffle', matcher: /ffl/),
|
57
|
+
headers: { 'Content-Type' => 'application/json' },
|
58
|
+
query: "",
|
59
|
+
},
|
60
|
+
response: {
|
61
|
+
baz: 'qux',
|
62
|
+
wiffle: 'wiffle'
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
let(:interaction_json) { JSON.dump(interaction_hash) }
|
68
|
+
|
69
|
+
let(:interaction) { Pact::Consumer::Interaction.from_hash(JSON.parse(interaction_json)) }
|
70
|
+
|
71
|
+
before do
|
72
|
+
stub_request(:post, 'localhost:2222/interactions')
|
73
|
+
end
|
74
|
+
|
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
|
+
|
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
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pact/consumer/dsl'
|
3
|
+
require 'pact/consumer/configuration_dsl'
|
4
|
+
|
5
|
+
module Pact::Consumer::DSL
|
6
|
+
describe Service do
|
7
|
+
before do
|
8
|
+
Pact.clear_configuration
|
9
|
+
Pact::Consumer::AppManager.instance.stub(:register_mock_service_for)
|
10
|
+
end
|
11
|
+
describe "configure_consumer_contract_builder" do
|
12
|
+
subject {
|
13
|
+
Service.new :mock_service do
|
14
|
+
port 1234
|
15
|
+
standalone true
|
16
|
+
verify true
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:producer_name) { 'Mock Producer'}
|
21
|
+
let(:consumer_contract_builder) { double('Pact::Consumer::ConsumerContractBuilder').as_null_object}
|
22
|
+
let(:url) { "http://localhost:1234"}
|
23
|
+
|
24
|
+
it "adds a verification to the Pact configuration" do
|
25
|
+
Pact::Consumer::ConsumerContractBuilder.stub(:new).and_return(consumer_contract_builder)
|
26
|
+
subject.configure_consumer_contract_builder({})
|
27
|
+
consumer_contract_builder.should_receive(:verify)
|
28
|
+
Pact.configuration.producer_verifications.first.call
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when standalone" do
|
32
|
+
it "does not register the app with the AppManager" do
|
33
|
+
Pact::Consumer::AppManager.instance.should_not_receive(:register_mock_service_for)
|
34
|
+
subject.configure_consumer_contract_builder({})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
context "when not standalone" do
|
38
|
+
subject {
|
39
|
+
Service.new :mock_service do
|
40
|
+
port 1234
|
41
|
+
standalone false
|
42
|
+
verify true
|
43
|
+
end
|
44
|
+
}
|
45
|
+
it "registers the app with the AppManager" do
|
46
|
+
Pact::Consumer::AppManager.instance.should_receive(:register_mock_service_for).with(producer_name, url)
|
47
|
+
subject.configure_consumer_contract_builder({:producer_name => producer_name })
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|