pact 0.1.37 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +6 -19
- data/example/zoo-app/Gemfile +1 -2
- data/example/zoo-app/Gemfile.lock +16 -13
- data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +6 -6
- data/lib/pact/consumer/app_manager.rb +8 -28
- data/lib/pact/consumer/consumer_contract_builder.rb +65 -36
- data/lib/pact/consumer/dsl.rb +20 -10
- data/lib/pact/consumer/interaction_builder.rb +42 -0
- data/lib/pact/consumer/interactions_filter.rb +41 -0
- data/lib/pact/consumer/mock_service.rb +26 -19
- data/lib/pact/consumer/rspec.rb +2 -3
- data/lib/pact/consumer/server.rb +90 -0
- data/lib/pact/consumer.rb +6 -3
- data/lib/pact/consumer_contract/consumer_contract.rb +103 -0
- data/lib/pact/consumer_contract/interaction.rb +70 -0
- data/lib/pact/consumer_contract/service_consumer.rb +20 -0
- data/lib/pact/consumer_contract/service_provider.rb +20 -0
- data/lib/pact/consumer_contract.rb +1 -112
- data/lib/pact/{producer → provider}/dsl.rb +15 -4
- data/lib/pact/{producer → provider}/matchers.rb +0 -0
- data/lib/pact/{producer → provider}/pact_spec_runner.rb +2 -2
- data/lib/pact/{producer/producer_state.rb → provider/provider_state.rb} +13 -22
- data/lib/pact/provider/rspec.rb +128 -1
- data/lib/pact/{producer → provider}/test_methods.rb +12 -12
- data/lib/pact/{producer.rb → provider.rb} +0 -0
- data/lib/pact/verification_task.rb +4 -4
- data/lib/pact/version.rb +1 -1
- data/lib/pact.rb +1 -1
- data/pact.gemspec +1 -2
- data/scratchpad.txt +1 -1
- data/spec/features/consumption_spec.rb +15 -23
- data/spec/features/production_spec.rb +5 -5
- data/spec/features/{producer_states → provider_states}/zebras.rb +3 -3
- data/spec/integration/pact/consumer_configuration_spec.rb +3 -66
- data/spec/integration/pact/provider_configuration_spec.rb +1 -1
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +59 -15
- data/spec/lib/pact/consumer/dsl_spec.rb +4 -5
- data/spec/lib/pact/consumer/interaction_builder_spec.rb +91 -0
- data/spec/lib/pact/consumer/interactions_spec.rb +64 -0
- data/spec/lib/pact/consumer/mock_service_spec.rb +2 -6
- data/spec/lib/pact/consumer/service_consumer_spec.rb +1 -1
- data/spec/lib/pact/{consumer_contract_spec.rb → consumer_contract/consumer_contract_spec.rb} +72 -28
- data/spec/lib/pact/{consumer → consumer_contract}/interaction_spec.rb +49 -64
- data/spec/lib/pact/{producer/configuration_dsl_spec.rb → provider/dsl_spec.rb} +29 -28
- data/spec/lib/pact/{producer/producer_state_spec.rb → provider/provider_state_spec.rb} +17 -17
- data/spec/lib/pact/{producer → provider}/rspec_spec.rb +1 -1
- data/spec/lib/pact/verification_task_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -0
- data/spec/support/a_consumer-a_producer.json +1 -1
- data/spec/support/a_consumer-a_provider.json +34 -0
- data/spec/support/consumer_contract_template.json +26 -0
- data/spec/support/factories.rb +78 -0
- data/spec/support/pact_rake_support.rb +1 -1
- data/spec/support/test_app_fail.json +1 -1
- data/spec/support/test_app_pass.json +1 -1
- data/tasks/pact-test.rake +3 -3
- metadata +38 -45
- data/lib/pact/consumer/configuration_dsl.rb +0 -73
- data/lib/pact/consumer/interaction.rb +0 -74
- data/lib/pact/consumer/run_condor.rb +0 -4
- data/lib/pact/consumer/run_mock_contract_service.rb +0 -13
- data/lib/pact/consumer/service_consumer.rb +0 -22
- data/lib/pact/consumer/service_producer.rb +0 -23
- data/lib/pact/producer/configuration_dsl.rb +0 -62
- data/lib/pact/producer/rspec.rb +0 -129
@@ -1,40 +1,33 @@
|
|
1
1
|
module Pact
|
2
|
-
module
|
2
|
+
module Provider
|
3
3
|
|
4
4
|
module DSL
|
5
|
-
def
|
6
|
-
|
5
|
+
def provider_state name, &block
|
6
|
+
ProviderState.provider_state(name, &block).register
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def provider_states_for name, &block
|
10
|
+
ProviderState.current_namespaces << name
|
11
11
|
instance_eval(&block)
|
12
|
-
|
12
|
+
ProviderState.current_namespaces.pop
|
13
13
|
end
|
14
|
-
|
15
|
-
alias_method :provider_states_for, :with_consumer
|
16
|
-
alias_method :provider_state, :producer_state
|
17
14
|
end
|
18
15
|
|
19
|
-
class
|
16
|
+
class ProviderState
|
20
17
|
|
21
18
|
attr_accessor :name
|
22
19
|
attr_accessor :namespace
|
23
20
|
|
24
|
-
def self.producer_state name, &block
|
25
|
-
ProducerState.new(name, current_namespaces.join('.'), &block)
|
26
|
-
end
|
27
|
-
|
28
21
|
def self.provider_state name, &block
|
29
|
-
|
22
|
+
ProviderState.new(name, current_namespaces.join('.'), &block)
|
30
23
|
end
|
31
24
|
|
32
|
-
def self.register name,
|
33
|
-
|
25
|
+
def self.register name, provider_state
|
26
|
+
provider_states[name] = provider_state
|
34
27
|
end
|
35
28
|
|
36
|
-
def self.
|
37
|
-
@@
|
29
|
+
def self.provider_states
|
30
|
+
@@provider_states ||= {}
|
38
31
|
end
|
39
32
|
|
40
33
|
def self.current_namespaces
|
@@ -43,7 +36,7 @@ module Pact
|
|
43
36
|
|
44
37
|
def self.get name, options = {}
|
45
38
|
fullname = options[:for] ? "#{options[:for]}.#{name}" : name
|
46
|
-
(
|
39
|
+
(provider_states[fullname] || provider_states[fullname.to_sym]) || provider_states[name]
|
47
40
|
end
|
48
41
|
|
49
42
|
def register
|
@@ -84,5 +77,3 @@ module Pact
|
|
84
77
|
end
|
85
78
|
end
|
86
79
|
end
|
87
|
-
|
88
|
-
Pact.send(:extend, Pact::Producer::DSL)
|
data/lib/pact/provider/rspec.rb
CHANGED
@@ -1 +1,128 @@
|
|
1
|
-
require '
|
1
|
+
require 'open-uri'
|
2
|
+
require 'pact/consumer_contract'
|
3
|
+
require 'pact/json_warning'
|
4
|
+
require_relative 'matchers'
|
5
|
+
require_relative 'test_methods'
|
6
|
+
require 'pact/provider/dsl'
|
7
|
+
|
8
|
+
module Pact
|
9
|
+
module Provider
|
10
|
+
module RSpec
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def app
|
14
|
+
Pact.configuration.provider.app
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
|
20
|
+
include Pact::JsonWarning
|
21
|
+
|
22
|
+
def honour_pactfile pactfile_uri, options = {}
|
23
|
+
describe "Pact in #{pactfile_uri}" do
|
24
|
+
consumer_contract = Pact::ConsumerContract.from_json(read_pact_from(pactfile_uri, options))
|
25
|
+
honour_consumer_contract consumer_contract, options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def honour_consumer_contract consumer_contract, options = {}
|
30
|
+
check_for_active_support_json
|
31
|
+
describe_consumer_contract consumer_contract, options.merge({:consumer => consumer_contract.consumer.name})
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def describe_consumer_contract consumer_contract, options
|
37
|
+
consumer_contract.interactions.each do |interaction|
|
38
|
+
describe_interaction_with_provider_state interaction, options
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def describe_interaction_with_provider_state interaction, options
|
43
|
+
if interaction.provider_state
|
44
|
+
describe "Given #{interaction.provider_state}" do
|
45
|
+
describe_interaction interaction, options
|
46
|
+
end
|
47
|
+
else
|
48
|
+
describe_interaction interaction, options
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def describe_interaction interaction, options
|
53
|
+
|
54
|
+
describe description_for(interaction) do
|
55
|
+
|
56
|
+
before do
|
57
|
+
set_up_provider_state interaction.provider_state, options[:consumer]
|
58
|
+
replay_interaction interaction
|
59
|
+
end
|
60
|
+
|
61
|
+
after do
|
62
|
+
tear_down_provider_state interaction.provider_state, options[:consumer]
|
63
|
+
end
|
64
|
+
|
65
|
+
describe_response interaction.response
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def describe_response response
|
71
|
+
describe "returns a response which" do
|
72
|
+
if response['status']
|
73
|
+
it "has status code #{response['status']}" do
|
74
|
+
expect(last_response.status).to eql response['status']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if response['headers']
|
79
|
+
describe "includes headers" do
|
80
|
+
response['headers'].each do |name, value|
|
81
|
+
it "\"#{name}\" with value \"#{value}\"" do
|
82
|
+
expect(last_response.headers[name]).to match_term value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
if response['body']
|
89
|
+
it "has a matching body" do
|
90
|
+
logger.debug "Response body is #{last_response.body}"
|
91
|
+
expect(parse_entity_from_response(last_response)).to match_term response['body']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def description_for interaction
|
98
|
+
"#{interaction.description} to #{interaction.request.path}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def read_pact_from uri, options = {}
|
102
|
+
pact = open(uri) { | file | file.read }
|
103
|
+
if options[:save_pactfile_to_tmp]
|
104
|
+
save_pactfile_to_tmp pact, File.basename(uri)
|
105
|
+
end
|
106
|
+
pact
|
107
|
+
rescue StandardError => e
|
108
|
+
$stderr.puts "Error reading file from #{uri}"
|
109
|
+
$stderr.puts "#{e.to_s} #{e.backtrace.join("\n")}"
|
110
|
+
raise e
|
111
|
+
end
|
112
|
+
|
113
|
+
def save_pactfile_to_tmp pact, name
|
114
|
+
FileUtils.mkdir_p Pact.configuration.tmp_dir
|
115
|
+
File.open(Pact.configuration.tmp_dir + "/#{name}", "w") { |file| file << pact}
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
RSpec.configure do |config|
|
124
|
+
config.extend Pact::Provider::RSpec::ClassMethods
|
125
|
+
config.include Pact::Provider::RSpec::InstanceMethods
|
126
|
+
config.include Pact::Provider::TestMethods
|
127
|
+
config.include Pact::Provider::TestMethods
|
128
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'pact/logging'
|
2
2
|
require 'rack/test'
|
3
3
|
require 'pact/reification'
|
4
|
-
require 'pact/
|
4
|
+
require 'pact/provider/provider_state'
|
5
5
|
|
6
6
|
module Pact
|
7
|
-
module
|
7
|
+
module Provider
|
8
8
|
module TestMethods
|
9
9
|
|
10
10
|
include Pact::Logging
|
@@ -19,15 +19,15 @@ module Pact
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
if
|
24
|
-
|
22
|
+
def set_up_provider_state provider_state_name, consumer
|
23
|
+
if provider_state_name
|
24
|
+
get_provider_state(provider_state_name, consumer).set_up
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
if
|
30
|
-
|
28
|
+
def tear_down_provider_state provider_state_name, consumer
|
29
|
+
if provider_state_name
|
30
|
+
get_provider_state(provider_state_name, consumer).tear_down
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -77,12 +77,12 @@ module Pact
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
def
|
81
|
-
unless
|
80
|
+
def get_provider_state provider_state_name, consumer
|
81
|
+
unless provider_state = ProviderState.get(provider_state_name, :for => consumer)
|
82
82
|
extra = consumer ? " for consumer \"#{consumer}\"" : ""
|
83
|
-
raise "Could not find a
|
83
|
+
raise "Could not find a provider state defined for \"#{provider_state_name}\"#{extra}. Have you required the provider state file in your spec?"
|
84
84
|
end
|
85
|
-
|
85
|
+
provider_state
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rake/tasklib'
|
2
|
-
require 'pact/
|
2
|
+
require 'pact/provider/pact_spec_runner'
|
3
3
|
|
4
4
|
=begin
|
5
5
|
To create a rake pact:verify:<something> task
|
@@ -33,15 +33,15 @@ module Pact
|
|
33
33
|
yield self
|
34
34
|
|
35
35
|
namespace :pact do
|
36
|
-
desc "Verify
|
36
|
+
desc "Verify provider against the consumer pacts for #{name}"
|
37
37
|
task "verify:#{name}" do
|
38
|
-
exit_status =
|
38
|
+
exit_status = Provider::PactSpecRunner.run(pact_spec_config)
|
39
39
|
fail failure_message if exit_status != 0
|
40
40
|
end
|
41
41
|
|
42
42
|
def failure_message
|
43
43
|
"\n* * * * * * * * * * * * * * * * * * *\n" +
|
44
|
-
"
|
44
|
+
"Provider did not honour pact file.\nSee\n * #{Pact.configuration.log_path}\n * #{Pact.configuration.tmp_dir}\nfor logs and pact files." +
|
45
45
|
"\n* * * * * * * * * * * * * * * * * * *\n\n"
|
46
46
|
end
|
47
47
|
end
|
data/lib/pact/version.rb
CHANGED
data/lib/pact.rb
CHANGED
data/pact.gemspec
CHANGED
@@ -19,12 +19,11 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.license = 'MIT'
|
20
20
|
|
21
21
|
gem.add_runtime_dependency 'randexp', '~> 0.1.7'
|
22
|
-
gem.add_runtime_dependency 'hashie', '~> 2.0
|
22
|
+
gem.add_runtime_dependency 'hashie', '~> 2.0'
|
23
23
|
gem.add_runtime_dependency 'rspec', '~> 2.12'
|
24
24
|
gem.add_runtime_dependency 'find_a_port', '~> 1.0.1'
|
25
25
|
gem.add_runtime_dependency 'rack-test', '~> 0.6.2'
|
26
26
|
gem.add_runtime_dependency 'awesome_print', '~> 1.1.0'
|
27
|
-
gem.add_runtime_dependency 'capybara', '~> 2.1.0'
|
28
27
|
gem.add_runtime_dependency 'thor'
|
29
28
|
gem.add_runtime_dependency 'thin'
|
30
29
|
gem.add_runtime_dependency 'json' #Not locking down a version because buncher gem requires 1.6, while other projects use 1.7.
|
data/scratchpad.txt
CHANGED
@@ -99,20 +99,16 @@ describe "A service consumer side of a pact", :pact => true do
|
|
99
99
|
expect{ bob_service.verify('goes a little something like this') }.to raise_error /do not match/
|
100
100
|
end
|
101
101
|
|
102
|
-
context "with a
|
102
|
+
context "with a provider state" do
|
103
103
|
before do
|
104
104
|
Pact.clear_configuration
|
105
105
|
|
106
|
-
Pact.
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
Pact.with_service_provider "Zebra Service" do
|
113
|
-
mock_service :zebra_service do
|
114
|
-
verify false
|
115
|
-
port 1235
|
106
|
+
Pact.service_consumer "Consumer" do
|
107
|
+
has_pact_with "Zebra Service" do
|
108
|
+
mock_service :zebra_service do
|
109
|
+
verify false
|
110
|
+
port 1235
|
111
|
+
end
|
116
112
|
end
|
117
113
|
end
|
118
114
|
end
|
@@ -132,25 +128,21 @@ describe "A service consumer side of a pact", :pact => true do
|
|
132
128
|
})
|
133
129
|
|
134
130
|
interactions = Pact::ConsumerContract.from_json(File.read(zebra_service.consumer_contract.pactfile_path)).interactions
|
135
|
-
interactions.first.
|
131
|
+
interactions.first.provider_state.should eq("the_zebras_are_here")
|
136
132
|
sleep 1
|
137
133
|
end
|
138
134
|
end
|
139
135
|
|
140
|
-
context "with a async interaction with
|
136
|
+
context "with a async interaction with provider" do
|
141
137
|
before do
|
142
138
|
Pact.clear_configuration
|
143
139
|
|
144
|
-
Pact.
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
Pact.with_service_provider "Zebra Service" do
|
151
|
-
mock_service :zebra_service do
|
152
|
-
verify true
|
153
|
-
port 1239
|
140
|
+
Pact.service_consumer "Consumer" do | config |
|
141
|
+
has_pact_with "Zebra Service" do
|
142
|
+
mock_service :zebra_service do
|
143
|
+
verify true
|
144
|
+
port 1239
|
145
|
+
end
|
154
146
|
end
|
155
147
|
end
|
156
148
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'pact/provider/rspec'
|
2
2
|
require 'pact/consumer_contract'
|
3
|
-
require 'features/
|
3
|
+
require 'features/provider_states/zebras'
|
4
4
|
|
5
5
|
|
6
|
-
module Pact::
|
6
|
+
module Pact::Provider
|
7
7
|
|
8
8
|
describe "A service production side of a pact" do
|
9
9
|
|
@@ -83,7 +83,7 @@ module Pact::Producer
|
|
83
83
|
|
84
84
|
end
|
85
85
|
|
86
|
-
describe "with a
|
86
|
+
describe "with a provider_state" do
|
87
87
|
|
88
88
|
context "that is a symbol" do
|
89
89
|
consumer_contract = Pact::ConsumerContract.from_json <<-EOS
|
@@ -100,7 +100,7 @@ module Pact::Producer
|
|
100
100
|
"body": {"names": ["Jason", "Sarah"]},
|
101
101
|
"status": 200
|
102
102
|
},
|
103
|
-
"
|
103
|
+
"provider_state" : "the_zebras_are_here"
|
104
104
|
}
|
105
105
|
]
|
106
106
|
}
|
@@ -131,7 +131,7 @@ module Pact::Producer
|
|
131
131
|
"body": {"names": ["Mark", "Gertrude"]},
|
132
132
|
"status": 200
|
133
133
|
},
|
134
|
-
"
|
134
|
+
"provider_state" : "some other zebras are here"
|
135
135
|
}
|
136
136
|
]
|
137
137
|
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
Pact.
|
4
|
+
Pact.provider_states_for 'the-wild-beast-store' do
|
5
5
|
|
6
|
-
|
6
|
+
provider_state :the_zebras_are_here do
|
7
7
|
set_up do
|
8
8
|
FileUtils.mkdir_p 'tmp'
|
9
9
|
some_data = [{'name' => 'Jason'},{'name' => 'Sarah'}]
|
@@ -16,7 +16,7 @@ Pact.with_consumer 'the-wild-beast-store' do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
Pact.
|
19
|
+
Pact.provider_state "some other zebras are here" do
|
20
20
|
set_up do
|
21
21
|
some_data = [{'name' => 'Mark'},{'name' => 'Gertrude'}]
|
22
22
|
File.open("tmp/a_mock_database.json", "w") { |file| file << some_data.to_json }
|
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'pact/configuration'
|
3
3
|
require 'pact/consumer/dsl'
|
4
|
-
require 'pact/consumer/configuration_dsl'
|
5
|
-
require 'pact/producer/configuration_dsl'
|
6
4
|
|
7
5
|
describe "consumer side" do
|
8
6
|
describe "configure" do
|
@@ -47,7 +45,7 @@ describe "consumer side" do
|
|
47
45
|
subject { TestHelper.new.my_service.consumer_contract.consumer }
|
48
46
|
|
49
47
|
it "should be configured" do
|
50
|
-
expect(subject).to be_instance_of Pact::
|
48
|
+
expect(subject).to be_instance_of Pact::ServiceConsumer
|
51
49
|
end
|
52
50
|
|
53
51
|
it "should have the right name" do
|
@@ -59,11 +57,11 @@ describe "consumer side" do
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
62
|
-
describe "
|
60
|
+
describe "providers" do
|
63
61
|
|
64
62
|
subject { TestHelper.new.my_service }
|
65
63
|
|
66
|
-
it "should have defined methods in MockServices for the
|
64
|
+
it "should have defined methods in MockServices for the providers" do
|
67
65
|
subject.should be_instance_of Pact::Consumer::ConsumerContractBuilder
|
68
66
|
end
|
69
67
|
|
@@ -80,65 +78,4 @@ describe "consumer side" do
|
|
80
78
|
end
|
81
79
|
end
|
82
80
|
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
81
|
end
|
@@ -7,23 +7,26 @@ module Pact
|
|
7
7
|
describe ConsumerContractBuilder do
|
8
8
|
|
9
9
|
describe "initialize" do
|
10
|
+
SUPPORT_PACT_FILE = './spec/support/a_consumer-a_provider.json'
|
10
11
|
before do
|
11
12
|
Pact.clear_configuration
|
12
13
|
Pact.configuration.stub(:pact_dir).and_return(File.expand_path(tmp_pact_dir))
|
13
14
|
FileUtils.rm_rf tmp_pact_dir
|
14
15
|
FileUtils.mkdir_p tmp_pact_dir
|
15
|
-
FileUtils.cp
|
16
|
+
FileUtils.cp SUPPORT_PACT_FILE, "#{tmp_pact_dir}/a_consumer-a_provider.json"
|
16
17
|
end
|
17
18
|
|
19
|
+
let(:expected_interactions) { ConsumerContract.from_json(File.read(SUPPORT_PACT_FILE)).interactions }
|
20
|
+
|
18
21
|
let(:tmp_pact_dir) {"./tmp/pacts"}
|
19
22
|
|
20
23
|
let(:consumer_name) { 'a consumer' }
|
21
|
-
let(:
|
24
|
+
let(:provider_name) { 'a provider' }
|
22
25
|
let(:consumer_contract_builder) {
|
23
26
|
Pact::Consumer::ConsumerContractBuilder.new(
|
24
27
|
:pactfile_write_mode => pactfile_write_mode,
|
25
28
|
:consumer_name => consumer_name,
|
26
|
-
:
|
29
|
+
:provider_name => provider_name,
|
27
30
|
:port => 1234)}
|
28
31
|
|
29
32
|
context "when overwriting pact" do
|
@@ -31,20 +34,51 @@ module Pact
|
|
31
34
|
it "it overwrites the existing pact file" do
|
32
35
|
expect(consumer_contract_builder.consumer_contract.interactions).to eq []
|
33
36
|
end
|
37
|
+
|
38
|
+
it "uses an DistinctInteractionsFilter to handle new interactions" do
|
39
|
+
Pact::Consumer::DistinctInteractionsFilter.should_receive(:new).with([])
|
40
|
+
consumer_contract_builder
|
41
|
+
end
|
34
42
|
end
|
35
43
|
|
36
44
|
context "when updating pact" do
|
37
45
|
let(:pactfile_write_mode) {:update}
|
38
|
-
it "
|
39
|
-
expect(consumer_contract_builder.consumer_contract.interactions
|
46
|
+
it "loads the interactions from the existing pact file" do
|
47
|
+
expect(consumer_contract_builder.consumer_contract.interactions).to eq expected_interactions
|
48
|
+
end
|
49
|
+
|
50
|
+
it "uses an UpdatableInteractionsFilter to handle new interactions" do
|
51
|
+
Pact::Consumer::UpdatableInteractionsFilter.should_receive(:new).with(expected_interactions)
|
52
|
+
consumer_contract_builder
|
40
53
|
end
|
41
54
|
end
|
55
|
+
|
56
|
+
context "when an error occurs deserializing the existing pactfile" do
|
57
|
+
let(:pactfile_write_mode) {:update}
|
58
|
+
let(:error) { RuntimeError.new('some error')}
|
59
|
+
let(:line1) { /Could not load existing consumer contract from .* due to some error/ }
|
60
|
+
let(:line2) {'Creating a new file.'}
|
61
|
+
before do
|
62
|
+
ConsumerContract.stub(:from_json).and_raise(error)
|
63
|
+
$stderr.should_receive(:puts).with(line1)
|
64
|
+
$stderr.should_receive(:puts).with(line2)
|
65
|
+
Pact.configuration.logger.should_receive(:warn).with(line1)
|
66
|
+
Pact.configuration.logger.should_receive(:warn).with(line2)
|
67
|
+
end
|
68
|
+
it "logs the error" do
|
69
|
+
consumer_contract_builder
|
70
|
+
end
|
71
|
+
|
72
|
+
it "continues with a new file" do
|
73
|
+
expect(consumer_contract_builder.consumer_contract.interactions).to eq []
|
74
|
+
end
|
75
|
+
end
|
42
76
|
end
|
43
77
|
|
44
78
|
describe "handle_interaction_fully_defined" do
|
45
79
|
|
46
80
|
subject {
|
47
|
-
Pact::Consumer::ConsumerContractBuilder.new({:consumer_name => 'blah', :
|
81
|
+
Pact::Consumer::ConsumerContractBuilder.new({:consumer_name => 'blah', :provider_name => 'blah', :port => 2222})
|
48
82
|
}
|
49
83
|
|
50
84
|
let(:interaction_hash) {
|
@@ -66,21 +100,31 @@ module Pact
|
|
66
100
|
|
67
101
|
let(:interaction_json) { interaction.to_json_for_mock_service }
|
68
102
|
|
69
|
-
let(:interaction) { Pact::
|
103
|
+
let(:interaction) { Pact::Interaction.from_hash(JSON.parse(interaction_hash.to_json)) }
|
70
104
|
|
71
105
|
before do
|
72
106
|
stub_request(:post, 'localhost:2222/interactions')
|
73
107
|
end
|
74
108
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
109
|
+
it "posts the interaction with generated response to the mock service" do
|
110
|
+
subject.handle_interaction_fully_defined interaction
|
111
|
+
WebMock.should have_requested(:post, 'localhost:2222/interactions').with(body: interaction_json)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "adds the interaction to the consumer contract" do
|
115
|
+
subject.handle_interaction_fully_defined interaction
|
116
|
+
expect(subject.consumer_contract.interactions).to eq [interaction]
|
117
|
+
end
|
118
|
+
|
119
|
+
it "updates the provider's pactfile" do
|
120
|
+
subject.consumer_contract.should_receive(:update_pactfile)
|
121
|
+
subject.handle_interaction_fully_defined interaction
|
122
|
+
end
|
79
123
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
124
|
+
it "resets the interaction_builder to nil" do
|
125
|
+
subject.should_receive(:interaction_builder=).with(nil)
|
126
|
+
subject.handle_interaction_fully_defined interaction
|
127
|
+
end
|
84
128
|
end
|
85
129
|
end
|
86
130
|
end
|