pact 0.1.37 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/Gemfile.lock +6 -19
  2. data/example/zoo-app/Gemfile +1 -2
  3. data/example/zoo-app/Gemfile.lock +16 -13
  4. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +6 -6
  5. data/lib/pact/consumer/app_manager.rb +8 -28
  6. data/lib/pact/consumer/consumer_contract_builder.rb +65 -36
  7. data/lib/pact/consumer/dsl.rb +20 -10
  8. data/lib/pact/consumer/interaction_builder.rb +42 -0
  9. data/lib/pact/consumer/interactions_filter.rb +41 -0
  10. data/lib/pact/consumer/mock_service.rb +26 -19
  11. data/lib/pact/consumer/rspec.rb +2 -3
  12. data/lib/pact/consumer/server.rb +90 -0
  13. data/lib/pact/consumer.rb +6 -3
  14. data/lib/pact/consumer_contract/consumer_contract.rb +103 -0
  15. data/lib/pact/consumer_contract/interaction.rb +70 -0
  16. data/lib/pact/consumer_contract/service_consumer.rb +20 -0
  17. data/lib/pact/consumer_contract/service_provider.rb +20 -0
  18. data/lib/pact/consumer_contract.rb +1 -112
  19. data/lib/pact/{producer → provider}/dsl.rb +15 -4
  20. data/lib/pact/{producer → provider}/matchers.rb +0 -0
  21. data/lib/pact/{producer → provider}/pact_spec_runner.rb +2 -2
  22. data/lib/pact/{producer/producer_state.rb → provider/provider_state.rb} +13 -22
  23. data/lib/pact/provider/rspec.rb +128 -1
  24. data/lib/pact/{producer → provider}/test_methods.rb +12 -12
  25. data/lib/pact/{producer.rb → provider.rb} +0 -0
  26. data/lib/pact/verification_task.rb +4 -4
  27. data/lib/pact/version.rb +1 -1
  28. data/lib/pact.rb +1 -1
  29. data/pact.gemspec +1 -2
  30. data/scratchpad.txt +1 -1
  31. data/spec/features/consumption_spec.rb +15 -23
  32. data/spec/features/production_spec.rb +5 -5
  33. data/spec/features/{producer_states → provider_states}/zebras.rb +3 -3
  34. data/spec/integration/pact/consumer_configuration_spec.rb +3 -66
  35. data/spec/integration/pact/provider_configuration_spec.rb +1 -1
  36. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +59 -15
  37. data/spec/lib/pact/consumer/dsl_spec.rb +4 -5
  38. data/spec/lib/pact/consumer/interaction_builder_spec.rb +91 -0
  39. data/spec/lib/pact/consumer/interactions_spec.rb +64 -0
  40. data/spec/lib/pact/consumer/mock_service_spec.rb +2 -6
  41. data/spec/lib/pact/consumer/service_consumer_spec.rb +1 -1
  42. data/spec/lib/pact/{consumer_contract_spec.rb → consumer_contract/consumer_contract_spec.rb} +72 -28
  43. data/spec/lib/pact/{consumer → consumer_contract}/interaction_spec.rb +49 -64
  44. data/spec/lib/pact/{producer/configuration_dsl_spec.rb → provider/dsl_spec.rb} +29 -28
  45. data/spec/lib/pact/{producer/producer_state_spec.rb → provider/provider_state_spec.rb} +17 -17
  46. data/spec/lib/pact/{producer → provider}/rspec_spec.rb +1 -1
  47. data/spec/lib/pact/verification_task_spec.rb +3 -3
  48. data/spec/spec_helper.rb +1 -0
  49. data/spec/support/a_consumer-a_producer.json +1 -1
  50. data/spec/support/a_consumer-a_provider.json +34 -0
  51. data/spec/support/consumer_contract_template.json +26 -0
  52. data/spec/support/factories.rb +78 -0
  53. data/spec/support/pact_rake_support.rb +1 -1
  54. data/spec/support/test_app_fail.json +1 -1
  55. data/spec/support/test_app_pass.json +1 -1
  56. data/tasks/pact-test.rake +3 -3
  57. metadata +38 -45
  58. data/lib/pact/consumer/configuration_dsl.rb +0 -73
  59. data/lib/pact/consumer/interaction.rb +0 -74
  60. data/lib/pact/consumer/run_condor.rb +0 -4
  61. data/lib/pact/consumer/run_mock_contract_service.rb +0 -13
  62. data/lib/pact/consumer/service_consumer.rb +0 -22
  63. data/lib/pact/consumer/service_producer.rb +0 -23
  64. data/lib/pact/producer/configuration_dsl.rb +0 -62
  65. data/lib/pact/producer/rspec.rb +0 -129
@@ -19,7 +19,7 @@ module Pact
19
19
  module Consumer
20
20
 
21
21
  class InteractionList
22
- include Singleton
22
+ #include Singleton
23
23
 
24
24
  attr_reader :interactions
25
25
  attr_reader :unexpected_requests
@@ -112,9 +112,10 @@ module Pact
112
112
 
113
113
  include RackHelper
114
114
 
115
- def initialize name, logger
115
+ def initialize name, logger, interaction_list
116
116
  @name = name
117
117
  @logger = logger
118
+ @interaction_list = interaction_list
118
119
  end
119
120
 
120
121
  def match? env
@@ -123,7 +124,7 @@ module Pact
123
124
  end
124
125
 
125
126
  def respond env
126
- InteractionList.instance.clear
127
+ @interaction_list.clear
127
128
  @logger.info "Cleared interactions before example \"#{params_hash(env)['example_description']}\""
128
129
  [200, {}, ['Deleted interactions']]
129
130
  end
@@ -131,9 +132,10 @@ module Pact
131
132
 
132
133
  class InteractionPost
133
134
 
134
- def initialize name, logger
135
+ def initialize name, logger, interaction_list
135
136
  @name = name
136
137
  @logger = logger
138
+ @interaction_list = interaction_list
137
139
  end
138
140
 
139
141
  def match? env
@@ -143,7 +145,7 @@ module Pact
143
145
 
144
146
  def respond env
145
147
  interactions = Hashie::Mash.new(JSON.load(env['rack.input'].string))
146
- InteractionList.instance.add interactions
148
+ @interaction_list.add interactions
147
149
  @logger.info "Added interaction to #{@name}"
148
150
  @logger.ap interactions
149
151
  [200, {}, ['Added interactions']]
@@ -197,9 +199,10 @@ module Pact
197
199
  include Pact::Matchers
198
200
  include RequestExtractor
199
201
 
200
- def initialize name, logger
202
+ def initialize name, logger, interaction_list
201
203
  @name = name
202
204
  @logger = logger
205
+ @interaction_list = interaction_list
203
206
  end
204
207
 
205
208
  def match? env
@@ -217,7 +220,7 @@ module Pact
217
220
  @logger.info "#{@name} received request"
218
221
  @logger.ap actual_request.as_json
219
222
  candidates = []
220
- matching_interactions = InteractionList.instance.interactions.select do |interaction|
223
+ matching_interactions = @interaction_list.interactions.select do |interaction|
221
224
  expected_request = Request::Expected.from_hash(interaction.request.merge(:description => interaction.description))
222
225
  candidates << expected_request if expected_request.matches_route? actual_request
223
226
  expected_request.match actual_request
@@ -231,7 +234,7 @@ module Pact
231
234
  handle_unrecognised_request(actual_request, candidates)
232
235
  else
233
236
  response = response_from(matching_interactions.first.response)
234
- InteractionList.instance.register_matched matching_interactions.first
237
+ @interaction_list.register_matched matching_interactions.first
235
238
  @logger.info "Found matching response on #{@name}:"
236
239
  @logger.ap response
237
240
  response
@@ -239,7 +242,7 @@ module Pact
239
242
  end
240
243
 
241
244
  def handle_unrecognised_request request, candidates
242
- InteractionList.instance.register_unexpected request
245
+ @interaction_list.register_unexpected request
243
246
  @logger.error "No interaction found on #{@name} amongst expected requests \"#{candidates.map(&:description).join(', ')}\""
244
247
  @logger.error 'Interaction diffs for that route:'
245
248
  interaction_diff = candidates.map do |candidate|
@@ -267,9 +270,10 @@ module Pact
267
270
  class MissingInteractionsGet
268
271
  include RackHelper
269
272
 
270
- def initialize name, logger
273
+ def initialize name, logger, interaction_list
271
274
  @name = name
272
275
  @logger = logger
276
+ @interaction_list = interaction_list
273
277
  end
274
278
 
275
279
  def match? env
@@ -278,7 +282,7 @@ module Pact
278
282
  end
279
283
 
280
284
  def respond env
281
- number_of_missing_interactions = InteractionList.instance.missing_interactions.size
285
+ number_of_missing_interactions = @interaction_list.missing_interactions.size
282
286
  @logger.info "Number of missing interactions for mock \"#{@name}\" = #{number_of_missing_interactions}"
283
287
  [200, {}, ["#{number_of_missing_interactions}"]]
284
288
  end
@@ -289,10 +293,11 @@ module Pact
289
293
 
290
294
  include RackHelper
291
295
 
292
- def initialize name, logger, log_description
296
+ def initialize name, logger, log_description, interaction_list
293
297
  @name = name
294
298
  @logger = logger
295
299
  @log_description = log_description
300
+ @interaction_list = interaction_list
296
301
  end
297
302
 
298
303
  def match? env
@@ -301,12 +306,12 @@ module Pact
301
306
  end
302
307
 
303
308
  def respond env
304
- if InteractionList.instance.all_matched?
309
+ if @interaction_list.all_matched?
305
310
  @logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
306
311
  [200, {}, ['Interactions matched']]
307
312
  else
308
313
  @logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". Interaction diffs:"
309
- @logger.ap InteractionList.instance.interaction_diffs, :warn
314
+ @logger.ap @interaction_list.interaction_diffs, :warn
310
315
  [500, {}, ["Actual interactions do not match expected interactions for mock #{@name}. See #{@log_description} for details."]]
311
316
  end
312
317
  end
@@ -329,15 +334,17 @@ module Pact
329
334
  "standard out/err"
330
335
  end
331
336
 
337
+ interaction_list = InteractionList.new
338
+
332
339
  @name = options.fetch(:name, "MockService")
333
340
  @handlers = [
334
341
  StartupPoll.new(@name, @logger),
335
342
  CapybaraIdentify.new(@name, @logger),
336
- MissingInteractionsGet.new(@name, @logger),
337
- VerificationGet.new(@name, @logger, log_description),
338
- InteractionPost.new(@name, @logger),
339
- InteractionDelete.new(@name, @logger),
340
- InteractionReplay.new(@name, @logger)
343
+ MissingInteractionsGet.new(@name, @logger, interaction_list),
344
+ VerificationGet.new(@name, @logger, log_description, interaction_list),
345
+ InteractionPost.new(@name, @logger, interaction_list),
346
+ InteractionDelete.new(@name, @logger, interaction_list),
347
+ InteractionReplay.new(@name, @logger, interaction_list)
341
348
  ]
342
349
  end
343
350
 
@@ -1,7 +1,6 @@
1
1
  require_relative '../configuration'
2
2
  require_relative '../consumer'
3
3
  require_relative 'dsl'
4
- require_relative 'configuration_dsl'
5
4
  require 'pact/consumer/consumer_contract_builder'
6
5
 
7
6
  module Pact
@@ -31,8 +30,8 @@ RSpec.configure do |config|
31
30
  config.after :each, :pact => true do | example |
32
31
  example_description = "#{example.example.example_group.description} #{example.example.description}"
33
32
  Pact.configuration.logger.info "Verifying interactions for #{example_description}"
34
- Pact.configuration.producer_verifications.each do | producer_verification |
35
- producer_verification.call example_description
33
+ Pact.configuration.provider_verifications.each do | provider_verification |
34
+ provider_verification.call example_description
36
35
  end
37
36
  end
38
37
 
@@ -0,0 +1,90 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'rack'
4
+
5
+ # Copied shamelessly from Capybara
6
+ module Pact
7
+ class Server
8
+ class Middleware
9
+ attr_accessor :error
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ if env["PATH_INFO"] == "/__identify__"
17
+ [200, {}, [@app.object_id.to_s]]
18
+ else
19
+ begin
20
+ @app.call(env)
21
+ rescue StandardError => e
22
+ @error = e unless @error
23
+ raise e
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ class << self
30
+ def ports
31
+ @ports ||= {}
32
+ end
33
+ end
34
+
35
+ attr_reader :app, :port
36
+
37
+ def initialize(app, port)
38
+ @app = app
39
+ @middleware = Middleware.new(@app)
40
+ @server_thread = nil # supress warnings
41
+ @port = port
42
+ end
43
+
44
+ def reset_error!
45
+ @middleware.error = nil
46
+ end
47
+
48
+ def error
49
+ @middleware.error
50
+ end
51
+
52
+ def host
53
+ "localhost"
54
+ end
55
+
56
+ def responsive?
57
+ return false if @server_thread && @server_thread.join(0)
58
+
59
+ res = Net::HTTP.start(host, @port) { |http| http.get('/__identify__') }
60
+
61
+ if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
62
+ return res.body == @app.object_id.to_s
63
+ end
64
+ rescue SystemCallError
65
+ return false
66
+ end
67
+
68
+ def run_default_server(app, port)
69
+ require 'rack/handler/webrick'
70
+ Rack::Handler::WEBrick.run(app, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
71
+ end
72
+
73
+ def boot
74
+ unless responsive?
75
+ Pact::Server.ports[@app.object_id] = @port
76
+
77
+ @server_thread = Thread.new do
78
+ run_default_server(@middleware, @port)
79
+ end
80
+
81
+ Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
82
+ end
83
+ rescue Timeout::Error
84
+ raise "Rack application timed out during boot"
85
+ else
86
+ self
87
+ end
88
+
89
+ end
90
+ end
data/lib/pact/consumer.rb CHANGED
@@ -1,7 +1,10 @@
1
- require_relative 'consumer/interaction'
1
+ require_relative 'consumer_contract'
2
2
  require_relative 'consumer/consumer_contract_builder'
3
+ require_relative 'consumer/consumer_contract_builders'
4
+ require_relative 'consumer/dsl'
5
+ require_relative 'consumer/interaction_builder'
3
6
  require_relative 'consumer/mock_service'
7
+ require_relative 'consumer/mock_service_client'
4
8
  require_relative 'consumer/app_manager'
5
9
  require_relative 'term'
6
- require_relative 'request'
7
- require_relative 'consumer_contract'
10
+ require_relative 'request'
@@ -0,0 +1,103 @@
1
+ require 'pact/consumer_contract'
2
+ require 'pact/logging'
3
+ require 'pact/json_warning'
4
+ require 'date'
5
+ require 'pact/version'
6
+ require_relative 'service_consumer'
7
+ require_relative 'service_provider'
8
+ require_relative 'interaction'
9
+
10
+ module Pact
11
+ class ConsumerContract
12
+
13
+ include Pact::Logging
14
+ include Pact::JsonWarning
15
+
16
+ attr_accessor :interactions
17
+ attr_accessor :consumer
18
+ attr_accessor :provider
19
+
20
+ def initialize(attributes = {})
21
+ @interactions = attributes[:interactions] || []
22
+ @consumer = attributes[:consumer]
23
+ @provider = attributes[:provider]
24
+ end
25
+
26
+ def as_json(options = {})
27
+ {
28
+ provider: @provider.as_json,
29
+ consumer: @consumer.as_json,
30
+ interactions: @interactions.collect(&:as_json),
31
+ metadata: {
32
+ pact_gem: {
33
+ version: Pact::VERSION
34
+ }
35
+ }
36
+ }
37
+ end
38
+
39
+ def to_json(options = {})
40
+ as_json(options).to_json(options)
41
+ end
42
+
43
+ def self.from_hash(obj)
44
+ new({
45
+ :interactions => obj['interactions'].collect { |hash| Interaction.from_hash(hash)},
46
+ :consumer => ServiceConsumer.from_hash(obj['consumer']),
47
+ :provider => ServiceProvider.from_hash(obj['provider'] || {})
48
+ })
49
+ end
50
+
51
+ def self.from_json string
52
+ deserialised_object = JSON.load(maintain_backwards_compatiblity_with_producer_keys(string))
53
+ from_hash(deserialised_object)
54
+ end
55
+
56
+ def self.maintain_backwards_compatiblity_with_producer_keys string
57
+ string.gsub('"producer":', '"provider":').gsub('"producer_state":', '"provider_state":')
58
+ end
59
+
60
+ def find_interaction criteria
61
+ interactions = find_interactions criteria
62
+ if interactions.size == 0
63
+ raise "Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
64
+ elsif interactions.size > 1
65
+ raise "Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
66
+ end
67
+ interactions.first
68
+ end
69
+
70
+ def find_interactions criteria
71
+ interactions.select{ | interaction| interaction.matches_criteria?(criteria)}
72
+ end
73
+
74
+ def each
75
+ interactions.each do | interaction |
76
+ yield interaction
77
+ end
78
+ end
79
+
80
+ def pact_file_name
81
+ "#{filenamify(consumer.name)}-#{filenamify(provider.name)}.json"
82
+ end
83
+
84
+ def pactfile_path
85
+ raise 'You must first specify a consumer and service name' unless (consumer && consumer.name && provider && provider.name)
86
+ @pactfile_path ||= File.join(Pact.configuration.pact_dir, pact_file_name)
87
+ end
88
+
89
+ def update_pactfile
90
+ logger.debug "Updating pact file for #{provider.name} at #{pactfile_path}"
91
+ check_for_active_support_json
92
+ File.open(pactfile_path, 'w') do |f|
93
+ f.write JSON.pretty_generate(self)
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def filenamify name
100
+ name.downcase.gsub(/\s/, '_')
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,70 @@
1
+ require 'pact/request'
2
+
3
+ module Pact
4
+ class Interaction
5
+
6
+ attr_accessor :description, :request, :response, :provider_state
7
+
8
+ def initialize attributes = {}
9
+ @description = attributes[:description]
10
+ @request = attributes[:request]
11
+ @response = attributes[:response]
12
+ @provider_state = attributes[:provider_state]
13
+ end
14
+
15
+ def self.from_hash hash
16
+ new(:description => hash['description'],
17
+ :provider_state => hash['provider_state'],
18
+ :request => Pact::Request::Expected.from_hash(hash['request']),
19
+ :response => hash['response']
20
+ )
21
+ end
22
+
23
+ def as_json
24
+ {
25
+ :description => @description,
26
+ :request => @request.as_json,
27
+ :response => @response,
28
+ }.tap{ | hash | hash[:provider_state] = @provider_state if @provider_state }
29
+ end
30
+
31
+ def to_json(options = {})
32
+ as_json.to_json(options)
33
+ end
34
+
35
+ def as_json_for_mock_service
36
+ {:response => Reification.from_term(response), :request => @request.as_json_with_options, :description => description }.
37
+ tap{ | hash | hash[:provider_state] = @provider_state if @provider_state }
38
+ end
39
+
40
+ def to_json_for_mock_service
41
+ as_json_for_mock_service.to_json
42
+ end
43
+
44
+ # Move this to interaction
45
+ def matches_criteria? criteria
46
+ criteria.each do | key, value |
47
+ unless match_criterion self.send(key.to_s), value
48
+ return false
49
+ end
50
+ end
51
+ true
52
+ end
53
+
54
+ def match_criterion target, criterion
55
+ target == criterion || (criterion.is_a?(Regexp) && criterion.match(target))
56
+ end
57
+
58
+ def == other
59
+ other.is_a?(Interaction) && as_json == other.as_json
60
+ end
61
+
62
+ def eq? other
63
+ self == other
64
+ end
65
+
66
+ def to_s
67
+ to_json
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,20 @@
1
+ module Pact
2
+ class ServiceConsumer
3
+ attr_accessor :name
4
+ def initialize options
5
+ @name = options[:name]
6
+ end
7
+
8
+ def to_s
9
+ name
10
+ end
11
+
12
+ def as_json options = {}
13
+ {name: name}
14
+ end
15
+
16
+ def self.from_hash obj
17
+ ServiceConsumer.new(:name => obj['name'])
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Pact
2
+ class ServiceProvider
3
+ attr_accessor :name
4
+ def initialize options
5
+ @name = options[:name] || '[provider name unknown - please update the pact gem in the consumer project to the latest version and regenerate the pacts]'
6
+ end
7
+
8
+ def to_s
9
+ name
10
+ end
11
+
12
+ def as_json options = {}
13
+ {name: name}
14
+ end
15
+
16
+ def self.from_hash obj
17
+ ServiceProvider.new(:name => obj['name'])
18
+ end
19
+ end
20
+ end
@@ -1,112 +1 @@
1
- require 'pact/consumer/service_consumer'
2
- require 'pact/consumer/service_producer'
3
- require 'pact/consumer/interaction'
4
- require 'pact/logging'
5
- require 'pact/json_warning'
6
- require 'date'
7
- require 'pact/version'
8
-
9
- module Pact
10
- class ConsumerContract
11
-
12
- include Pact::Logging
13
- include Pact::JsonWarning
14
-
15
- attr_accessor :interactions
16
- attr_accessor :consumer
17
- attr_accessor :producer
18
-
19
- def initialize(attributes = {})
20
- @interactions = attributes[:interactions] || []
21
- @consumer = attributes[:consumer]
22
- @producer = attributes[:producer]
23
- end
24
-
25
- def as_json(options = {})
26
- {
27
- producer: @producer.as_json,
28
- consumer: @consumer.as_json,
29
- interactions: @interactions.collect(&:as_json),
30
- metadata: {
31
- pact_gem: {
32
- version: Pact::VERSION
33
- }
34
- }
35
- }
36
- end
37
-
38
- def to_json(options = {})
39
- as_json(options).to_json(options)
40
- end
41
-
42
- def self.from_hash(obj)
43
- new({
44
- :interactions => obj['interactions'].collect { |hash| Pact::Consumer::Interaction.from_hash(hash)},
45
- :consumer => Pact::Consumer::ServiceConsumer.from_hash(obj['consumer']),
46
- :producer => Pact::Consumer::ServiceProducer.from_hash(obj['producer'] || {})
47
- })
48
- end
49
-
50
- def self.from_json string
51
- deserialised_object = JSON.load(string)
52
- from_hash(deserialised_object)
53
- end
54
-
55
- def find_interaction criteria
56
- interactions = find_interactions criteria
57
- if interactions.size == 0
58
- raise "Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{producer.name}."
59
- elsif interactions.size > 1
60
- raise "Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{producer.name}."
61
- end
62
- interactions.first
63
- end
64
-
65
- def find_interactions criteria
66
- interactions.select{ | interaction| match_criteria? interaction, criteria}
67
- end
68
-
69
- def each
70
- interactions.each do | interaction |
71
- yield interaction
72
- end
73
- end
74
-
75
- # Move this to interaction
76
- def match_criteria? interaction, criteria
77
- criteria.each do | key, value |
78
- unless match_criterion interaction.send(key.to_s), value
79
- return false
80
- end
81
- end
82
- true
83
- end
84
-
85
- def match_criterion target, criterion
86
- target == criterion || (criterion.is_a?(Regexp) && criterion.match(target))
87
- end
88
-
89
- def pact_file_name
90
- "#{filenamify(consumer.name)}-#{filenamify(producer.name)}.json"
91
- end
92
-
93
- def pactfile_path
94
- raise 'You must first specify a consumer and service name' unless (consumer && consumer.name && producer && producer.name)
95
- @pactfile_path ||= File.join(Pact.configuration.pact_dir, pact_file_name)
96
- end
97
-
98
- def update_pactfile
99
- logger.debug "Updating pact file for #{producer.name} at #{pactfile_path}"
100
- check_for_active_support_json
101
- File.open(pactfile_path, 'w') do |f|
102
- f.write JSON.pretty_generate(self)
103
- end
104
- end
105
-
106
- private
107
-
108
- def filenamify name
109
- name.downcase.gsub(/\s/, '_')
110
- end
111
- end
112
- end
1
+ require 'pact/consumer_contract/consumer_contract'
@@ -1,12 +1,21 @@
1
1
  module Pact
2
2
 
3
- module Producer
3
+ module Provider
4
4
  module DSL
5
5
 
6
+ #TODO: Move this into a module, out of configuration
6
7
  module Configuration
7
8
  def provider= provider
8
- @producer = provider
9
+ @provider = provider
9
10
  end
11
+
12
+ def provider
13
+ if defined? @provider
14
+ @provider
15
+ else
16
+ raise "Please configure your provider. See the Provider section in the README for examples."
17
+ end
18
+ end
10
19
  end
11
20
 
12
21
  Pact::Configuration.send(:include, Configuration)
@@ -39,8 +48,8 @@ module Pact
39
48
  end
40
49
 
41
50
  def validate
42
- raise "Please provide a name for the Producer" unless @name
43
- raise "Please configure an app for the Producer" unless @app_block
51
+ raise "Please provide a name for the Provider" unless @name && !@name.strip.empty?
52
+ raise "Please configure an app for the Provider" unless @app_block
44
53
  end
45
54
 
46
55
  def name name
@@ -59,3 +68,5 @@ module Pact
59
68
  end
60
69
  end
61
70
  end
71
+
72
+ Pact.send(:extend, Pact::Provider::DSL)
File without changes
@@ -5,10 +5,10 @@ require 'rspec/core/formatters/documentation_formatter'
5
5
  require_relative 'rspec'
6
6
 
7
7
  module Pact
8
- module Producer
8
+ module Provider
9
9
  class PactSpecRunner
10
10
 
11
- extend Pact::Producer::RSpec::ClassMethods
11
+ extend Pact::Provider::RSpec::ClassMethods
12
12
 
13
13
  def self.run(spec_definitions, options = {})
14
14
  initialize_specs spec_definitions