pact 0.1.37 → 1.0.0

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