pact 1.41.2 → 1.44.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 682d57626c30c4ce3f4e83038a3e5ff54d0f4878
4
- data.tar.gz: 7eb5834ea442abebf6e8739a5a2746514560fdc8
2
+ SHA256:
3
+ metadata.gz: 4377cccb8581a6f7215bf6f451bf97ac5b32d9d2a2c1f0a1fd05925ae5dd2f83
4
+ data.tar.gz: e4b78191ae99e50678b1034843168edc125b1ba1a4fb2686bc25e50609b0c4dc
5
5
  SHA512:
6
- metadata.gz: 369f376d001db7fac67ed5fce394dd0672c735de178c4c940b67082e7f36e7b8f43e18f2eb91d93403c969a1c26a995c229331f14780563e18b957456951b814
7
- data.tar.gz: db56fdd2c74f3cba9dd6b1e3ec7983eb50a46888f2c6ea7a9a70f2153738be1bbd6a53894a433d70d8f8dd4329b3526334b31c825cc7bcf75d4072e962f4f506
6
+ metadata.gz: cb2ae0b2b047c760b8336401fe4c82e01df60f2f3b8c3ec8cc217b99f443269713fc7f57d425e684a4b6e59a90ce17664a1eff08653eb9d440805ebb2873e27e
7
+ data.tar.gz: 5aceeb5ae1f627fa20635cd0d1bb6d6fcc6774df37ca9bb7d083cd4b72a7ac724c55b2c96258ee11d75ab11625fb720a023974c407c1c289afe6d106abe02192
data/CHANGELOG.md CHANGED
@@ -1,3 +1,79 @@
1
+ <a name="v1.44.1"></a>
2
+ ### v1.44.1 (2020-01-20)
3
+
4
+
5
+ #### Bug Fixes
6
+
7
+ * print notices from 'pacts for verification' response to indicate why pacts are included an/or pending ([b107348](/../../commit/b107348))
8
+
9
+
10
+ <a name="v1.44.0"></a>
11
+ ### v1.44.0 (2020-01-16)
12
+
13
+
14
+ #### Features
15
+
16
+ * **message pact**
17
+ * add DSL for configuring Message Pact verifications ([a5181b6](/../../commit/a5181b6))
18
+
19
+
20
+ <a name="v1.43.1"></a>
21
+ ### v1.43.1 (2020-01-11)
22
+
23
+
24
+ #### Bug Fixes
25
+
26
+ * use configured credentials when fetching the diff with previous version ([b9deb09](/../../commit/b9deb09))
27
+ * use URI.open instead of Kernel.open ([7b3ea81](/../../commit/7b3ea81))
28
+
29
+
30
+ <a name="v1.43.0"></a>
31
+ ### v1.43.0 (2020-01-11)
32
+
33
+
34
+ #### Features
35
+
36
+ * **verify**
37
+ * allow includePendingStatus to be specified when fetching pacts ([1f5fc9c](/../../commit/1f5fc9c))
38
+
39
+
40
+ <a name="v1.42.3"></a>
41
+ ### v1.42.3 (2019-11-15)
42
+
43
+
44
+ #### Bug Fixes
45
+
46
+ * **verify**
47
+ * exit with status 0 if all pacts are in pending state ([2f7110b](/../../commit/2f7110b))
48
+
49
+
50
+ <a name="v1.42.2"></a>
51
+ ### v1.42.2 (2019-11-09)
52
+
53
+
54
+ #### Bug Fixes
55
+
56
+ * remove missed &. ([be700d8](/../../commit/be700d8))
57
+
58
+
59
+ <a name="v1.42.1"></a>
60
+ ### v1.42.1 (2019-11-09)
61
+
62
+
63
+ #### Bug Fixes
64
+
65
+ * can't use safe navigation operator because of Ruby 2.2 in Travelling Ruby for the pact-ruby-standalone ([3068ceb](/../../commit/3068ceb))
66
+
67
+
68
+ <a name="v1.42.0"></a>
69
+ ### v1.42.0 (2019-09-26)
70
+
71
+
72
+ #### Features
73
+
74
+ * use new 'pacts for verification' endpoint to retrieve pacts (#199) ([55bb935](/../../commit/55bb935))
75
+
76
+
1
77
  <a name="v1.41.2"></a>
2
78
  ### v1.41.2 (2019-09-10)
3
79
 
@@ -44,15 +44,17 @@ module Pact
44
44
  end
45
45
 
46
46
  def run_specs
47
- exit_code = if options[:pact_uri]
48
- run_with_pact_uri
47
+ exit_code = if options[:pact_uri].is_a?(String)
48
+ run_with_pact_url_string
49
+ elsif options[:pact_uri]
50
+ run_with_pact_uri_object # from pact-provider-verifier
49
51
  else
50
- run_with_configured_pacts
52
+ run_with_configured_pacts_from_pact_helper
51
53
  end
52
54
  exit exit_code
53
55
  end
54
56
 
55
- def run_with_pact_uri
57
+ def run_with_pact_url_string
56
58
  pact_repository_uri_options = {}
57
59
  pact_repository_uri_options[:username] = options[:pact_broker_username] if options[:pact_broker_username]
58
60
  pact_repository_uri_options[:password] = options[:pact_broker_password] if options[:pact_broker_password]
@@ -61,7 +63,11 @@ module Pact
61
63
  Pact::Provider::PactSpecRunner.new([pact_uri], pact_spec_options).run
62
64
  end
63
65
 
64
- def run_with_configured_pacts
66
+ def run_with_pact_uri_object
67
+ Pact::Provider::PactSpecRunner.new([options[:pact_uri]], pact_spec_options).run
68
+ end
69
+
70
+ def run_with_configured_pacts_from_pact_helper
65
71
  pact_urls = Pact.provider_world.pact_urls
66
72
  raise "Please configure a pact to verify" if pact_urls.empty?
67
73
  Pact::Provider::PactSpecRunner.new(pact_urls, pact_spec_options).run
@@ -1,7 +1,6 @@
1
1
  require 'pact/consumer/configuration/service_consumer'
2
2
 
3
3
  module Pact
4
-
5
4
  module Consumer
6
5
  module DSL
7
6
  def service_consumer name, &block
@@ -29,7 +29,7 @@ module Pact
29
29
 
30
30
  def after_suite
31
31
  if Pact.consumer_world.any_pact_examples_ran?
32
- Pact.consumer_world.consumer_contract_builders.each { | c | c.write_pact }
32
+ Pact.consumer_world.consumer_contract_builders.each(&:write_pact)
33
33
  Pact::Doc::Generate.call
34
34
  Pact::MockService::AppManager.instance.kill_all
35
35
  Pact::MockService::AppManager.instance.clear_all
@@ -37,4 +37,4 @@ module Pact
37
37
  end
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -3,7 +3,7 @@ module Pact
3
3
  class SortInteractions
4
4
 
5
5
  def self.call interactions
6
- interactions.sort{|a, b| sortable_id(a) <=> sortable_id(b)}
6
+ interactions.sort_by { |interaction| sortable_id(interaction) }
7
7
  end
8
8
 
9
9
  private
@@ -11,7 +11,6 @@ module Pact
11
11
  def self.sortable_id interaction
12
12
  "#{interaction.description.downcase} #{interaction.response.status} #{(interaction.provider_state || '').downcase}"
13
13
  end
14
-
15
14
  end
16
15
  end
17
- end
16
+ end
@@ -1,6 +1,7 @@
1
1
  require 'pact/retry'
2
2
  require 'pact/hal/authorization_header_redactor'
3
3
  require 'net/http'
4
+ require 'rack'
4
5
 
5
6
  module Pact
6
7
  module Hal
@@ -15,9 +16,11 @@ module Pact
15
16
  end
16
17
 
17
18
  def get href, params = {}, headers = {}
18
- query = params.collect{ |(key, value)| "#{CGI::escape(key)}=#{CGI::escape(value)}" }.join("&")
19
19
  uri = URI(href)
20
- uri.query = query
20
+ if params && params.any?
21
+ existing_params = Rack::Utils.parse_nested_query(uri.query)
22
+ uri.query = Rack::Utils.build_nested_query(existing_params.merge(params))
23
+ end
21
24
  perform_request(create_request(uri, 'Get', nil, headers), uri)
22
25
  end
23
26
 
@@ -33,12 +36,9 @@ module Pact
33
36
 
34
37
  def create_request uri, http_method, body = nil, headers = {}
35
38
  request = Net::HTTP.const_get(http_method).new(uri.request_uri)
36
- request['Content-Type'] = "application/json" if ['Post', 'Put', 'Patch'].include?(http_method)
37
- request['Accept'] = "application/hal+json"
38
39
  headers.each do | key, value |
39
40
  request[key] = value
40
41
  end
41
-
42
42
  request.body = body if body
43
43
  request.basic_auth username, password if username
44
44
  request['Authorization'] = "Bearer #{token}" if token
@@ -82,6 +82,10 @@ module Pact
82
82
  def success?
83
83
  __getobj__().code.start_with?("2")
84
84
  end
85
+
86
+ def json?
87
+ self['content-type'] && self['content-type'] =~ /json/
88
+ end
85
89
  end
86
90
  end
87
91
  end
data/lib/pact/hal/link.rb CHANGED
@@ -6,6 +6,15 @@ module Pact
6
6
  class Link
7
7
  attr_reader :request_method, :href
8
8
 
9
+ DEFAULT_GET_HEADERS = {
10
+ "Accept" => "application/hal+json"
11
+ }.freeze
12
+
13
+ DEFAULT_POST_HEADERS = {
14
+ "Accept" => "application/hal+json",
15
+ "Content-Type" => "application/json"
16
+ }.freeze
17
+
9
18
  def initialize(attrs, http_client)
10
19
  @attrs = attrs
11
20
  @request_method = attrs.fetch(:method, :get).to_sym
@@ -14,14 +23,14 @@ module Pact
14
23
  end
15
24
 
16
25
  def run(payload = nil)
17
- response = case request_method
18
- when :get
19
- get(payload)
20
- when :put
21
- put(payload)
22
- when :post
23
- post(payload)
24
- end
26
+ case request_method
27
+ when :get
28
+ get(payload)
29
+ when :put
30
+ put(payload)
31
+ when :post
32
+ post(payload)
33
+ end
25
34
  end
26
35
 
27
36
  def title_or_name
@@ -37,29 +46,57 @@ module Pact
37
46
  end
38
47
 
39
48
  def get(payload = {}, headers = {})
40
- wrap_response(href, @http_client.get(href, payload, headers))
49
+ wrap_response(href, @http_client.get(href, payload, DEFAULT_GET_HEADERS.merge(headers)))
50
+ end
51
+
52
+ def get!(*args)
53
+ get(*args).assert_success!
41
54
  end
42
55
 
43
56
  def put(payload = nil, headers = {})
44
- wrap_response(href, @http_client.put(href, payload ? payload.to_json : nil, headers))
57
+ wrap_response(href, @http_client.put(href, payload ? payload.to_json : nil, DEFAULT_POST_HEADERS.merge(headers)))
45
58
  end
46
59
 
47
60
  def post(payload = nil, headers = {})
48
- wrap_response(href, @http_client.post(href, payload ? payload.to_json : nil, headers))
61
+ wrap_response(href, @http_client.post(href, payload ? payload.to_json : nil, DEFAULT_POST_HEADERS.merge(headers)))
62
+ end
63
+
64
+ def post!(payload = nil, headers = {})
65
+ post(payload, headers).assert_success!
49
66
  end
50
67
 
51
68
  def expand(params)
52
69
  expanded_url = expand_url(params, href)
53
70
  new_attrs = @attrs.merge('href' => expanded_url)
54
- Link.new(new_attrs, @http_client)
71
+ Link.new(new_attrs, http_client)
72
+ end
73
+
74
+ def with_query(query)
75
+ if query && query.any?
76
+ uri = URI(href)
77
+ existing_query_params = Rack::Utils.parse_nested_query(uri.query)
78
+ uri.query = Rack::Utils.build_nested_query(existing_query_params.merge(query))
79
+ new_attrs = attrs.merge('href' => uri.to_s)
80
+ Link.new(new_attrs, http_client)
81
+ else
82
+ self
83
+ end
55
84
  end
56
85
 
57
86
  private
58
87
 
88
+ attr_reader :attrs, :http_client
89
+
59
90
  def wrap_response(href, http_response)
60
91
  require 'pact/hal/entity' # avoid circular reference
92
+ require 'pact/hal/non_json_entity'
93
+
61
94
  if http_response.success?
62
- Entity.new(href, http_response.body, @http_client, http_response)
95
+ if http_response.json?
96
+ Entity.new(href, http_response.body, @http_client, http_response)
97
+ else
98
+ NonJsonEntity.new(href, http_response.raw_body, @http_client, http_response)
99
+ end
63
100
  else
64
101
  ErrorEntity.new(href, http_response.raw_body, @http_client, http_response)
65
102
  end
@@ -0,0 +1,28 @@
1
+ module Pact
2
+ module Hal
3
+ class NonJsonEntity
4
+ def initialize(href, body, http_client, response = nil)
5
+ @href = href
6
+ @body = body
7
+ @client = http_client
8
+ @response = response
9
+ end
10
+
11
+ def success?
12
+ true
13
+ end
14
+
15
+ def response
16
+ @response
17
+ end
18
+
19
+ def body
20
+ @body
21
+ end
22
+
23
+ def assert_success!
24
+ self
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,95 @@
1
+ require 'pact/hal/entity'
2
+ require 'pact/hal/http_client'
3
+ require 'pact/provider/pact_uri'
4
+ require 'pact/errors'
5
+ require 'pact/pact_broker/fetch_pacts'
6
+
7
+ module Pact
8
+ module PactBroker
9
+ class FetchPactURIsForVerification
10
+ attr_reader :provider, :consumer_version_selectors, :provider_version_tags, :broker_base_url, :http_client_options, :http_client, :options
11
+
12
+ PACTS_FOR_VERIFICATION_RELATION = 'beta:provider-pacts-for-verification'.freeze
13
+ PACTS = 'pacts'.freeze
14
+ HREF = 'href'.freeze
15
+ LINKS = '_links'.freeze
16
+ SELF = 'self'.freeze
17
+ EMBEDDED = '_embedded'.freeze
18
+
19
+ def initialize(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
20
+ @provider = provider
21
+ @consumer_version_selectors = consumer_version_selectors || []
22
+ @provider_version_tags = provider_version_tags || []
23
+ @http_client_options = http_client_options
24
+ @broker_base_url = broker_base_url
25
+ @http_client = Pact::Hal::HttpClient.new(http_client_options)
26
+ @options = options
27
+ end
28
+
29
+ def self.call(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
30
+ new(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options).call
31
+ end
32
+
33
+ def call
34
+ if index.can?(PACTS_FOR_VERIFICATION_RELATION)
35
+ log_message
36
+ pacts_for_verification
37
+ else
38
+ # Fall back to old method of fetching pacts
39
+ consumer_version_tags = consumer_version_selectors.collect{ | selector | selector[:tag] }
40
+ FetchPacts.call(provider, consumer_version_tags, broker_base_url, http_client_options)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def index
47
+ @index_entity ||= Pact::Hal::Link.new({ "href" => broker_base_url }, http_client).get.assert_success!
48
+ end
49
+
50
+ def pacts_for_verification
51
+ pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact |
52
+ metadata = {
53
+ pending: pact["verificationProperties"]["pending"],
54
+ notices: extract_notices(pact)
55
+ }
56
+ Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata)
57
+ end
58
+ end
59
+
60
+ def pacts_for_verification_entity
61
+ index
62
+ ._link(PACTS_FOR_VERIFICATION_RELATION)
63
+ .expand(provider: provider)
64
+ .post!(query)
65
+ end
66
+
67
+ def query
68
+ q = {}
69
+ q["includePendingStatus"] = true if options[:include_pending_status]
70
+ q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any?
71
+ q["providerVersionTags"] = provider_version_tags if provider_version_tags.any?
72
+ q
73
+ end
74
+
75
+ def extract_notices(pact)
76
+ (pact["verificationProperties"]["notices"] || []).collect{ |notice| notice["text"] }.compact
77
+ end
78
+
79
+ def log_message
80
+ latest = consumer_version_selectors.any? ? "" : "latest "
81
+ message = "INFO: Fetching #{latest}pacts for #{provider} from #{broker_base_url}"
82
+ if consumer_version_selectors.any?
83
+ desc = consumer_version_selectors.collect do |selector|
84
+ all_or_latest = selector[:all] ? "all" : "latest"
85
+ # TODO support fallback
86
+ name = selector[:fallback] ? "#{selector[:tag]} (or #{selector[:fallback]} if not found)" : selector[:tag]
87
+ "#{all_or_latest} #{name}"
88
+ end.join(", ")
89
+ message << " for tags: #{desc}"
90
+ end
91
+ Pact.configuration.output_stream.puts message
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,19 +1,25 @@
1
1
  require 'pact/pact_broker/fetch_pacts'
2
- require 'pact/pact_broker/fetch_pending_pacts'
2
+ require 'pact/pact_broker/fetch_pact_uris_for_verification'
3
+ require 'pact/provider/pact_uri'
3
4
 
4
5
  #
5
- # @public Use by Pact Provider Verifier
6
+ # @public Used by Pact Provider Verifier
6
7
  #
7
8
  module Pact
8
9
  module PactBroker
9
10
  extend self
10
11
 
12
+ # Keep for backwards compatibility with pact-provider-verifier < 1.23.1
11
13
  def fetch_pact_uris *args
12
14
  Pact::PactBroker::FetchPacts.call(*args).collect(&:uri)
13
15
  end
14
16
 
15
- def fetch_pending_pact_uris *args
16
- Pact::PactBroker::FetchPendingPacts.call(*args).collect(&:uri)
17
+ def fetch_pact_uris_for_verification *args
18
+ Pact::PactBroker::FetchPactURIsForVerification.call(*args)
19
+ end
20
+
21
+ def build_pact_uri(*args)
22
+ Pact::Provider::PactURI.new(*args)
17
23
  end
18
24
  end
19
25
  end
@@ -1,4 +1,5 @@
1
1
  require 'pact/provider/configuration/service_provider_dsl'
2
+ require 'pact/provider/configuration/message_provider_dsl'
2
3
 
3
4
  module Pact
4
5
 
@@ -8,6 +9,10 @@ module Pact
8
9
  def service_provider name, &block
9
10
  Configuration::ServiceProviderDSL.build(name, &block)
10
11
  end
12
+
13
+ def message_provider name, &block
14
+ Configuration::MessageProviderDSL.build(name, &block)
15
+ end
11
16
  end
12
17
  end
13
- end
18
+ end
@@ -0,0 +1,32 @@
1
+ require 'pact/provider/configuration/service_provider_dsl'
2
+
3
+ module Pact
4
+ module Provider
5
+ module Configuration
6
+ class MessageProviderDSL < ServiceProviderDSL
7
+ class RackToMessageAdapter
8
+ def initialize(message_builder)
9
+ @message_builder = message_builder
10
+ end
11
+
12
+ def call(env)
13
+ request_body_json = JSON.parse(env['rack.input'].read)
14
+ contents = @message_builder.call(request_body_json['description'])
15
+ [200, {"Content-Type" => "application/json"}, [{ contents: contents }.to_json]]
16
+ end
17
+ end
18
+
19
+ def initialize name
20
+ super
21
+ @mapper_block = lambda { |args| }
22
+ end
23
+
24
+ dsl do
25
+ def builder &block
26
+ self.app_block = lambda { RackToMessageAdapter.new(block) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,6 +1,6 @@
1
1
  require 'pact/shared/dsl'
2
2
  require 'pact/provider/world'
3
- require 'pact/pact_broker/fetch_pacts'
3
+ require 'pact/pact_broker/fetch_pact_uris_for_verification'
4
4
  require 'pact/errors'
5
5
 
6
6
  module Pact
@@ -14,10 +14,11 @@ module Pact
14
14
  # in parent scope, it will clash with these ones,
15
15
  # so put an underscore in front of the name to be safer.
16
16
 
17
- attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_basic_auth_options, :_verbose
17
+ attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_tags, :_basic_auth_options, :_verbose
18
18
 
19
- def initialize(provider_name)
19
+ def initialize(provider_name, provider_version_tags)
20
20
  @_provider_name = provider_name
21
+ @_provider_version_tags = provider_version_tags
21
22
  @_consumer_version_tags = []
22
23
  @_verbose = false
23
24
  end
@@ -45,10 +46,27 @@ module Pact
45
46
  private
46
47
 
47
48
  def create_pact_verification
48
- fetch_pacts = Pact::PactBroker::FetchPacts.new(_provider_name, _consumer_version_tags, _pact_broker_base_url, _basic_auth_options.merge(verbose: _verbose))
49
+ fetch_pacts = Pact::PactBroker::FetchPactURIsForVerification.new(
50
+ _provider_name,
51
+ consumer_version_selectors,
52
+ _provider_version_tags,
53
+ _pact_broker_base_url,
54
+ _basic_auth_options.merge(verbose: _verbose)
55
+ )
56
+
49
57
  Pact.provider_world.add_pact_uri_source fetch_pacts
50
58
  end
51
59
 
60
+ def consumer_version_selectors
61
+ # TODO support "all"
62
+ _consumer_version_tags.collect do | tag |
63
+ {
64
+ tag: tag,
65
+ latest: true
66
+ }
67
+ end
68
+ end
69
+
52
70
  def validate
53
71
  raise Pact::Error.new("Please provide a pact_broker_base_url from which to retrieve the pacts") unless _pact_broker_base_url
54
72
  end
@@ -65,7 +65,7 @@ module Pact
65
65
  end
66
66
 
67
67
  def create_pact_verification_from_broker(&block)
68
- PactVerificationFromBroker.build(name, &block)
68
+ PactVerificationFromBroker.build(name, tags, &block)
69
69
  end
70
70
 
71
71
  def finalize
@@ -5,8 +5,8 @@ module Pact
5
5
  module Help
6
6
  class Content
7
7
 
8
- def initialize pact_jsons
9
- @pact_jsons = pact_jsons
8
+ def initialize pact_sources
9
+ @pact_sources = pact_sources
10
10
  end
11
11
 
12
12
  def text
@@ -15,7 +15,7 @@ module Pact
15
15
 
16
16
  private
17
17
 
18
- attr_reader :pact_jsons
18
+ attr_reader :pact_sources
19
19
 
20
20
  def help_text
21
21
  temp_dir = Pact.configuration.tmp_dir
@@ -28,7 +28,7 @@ module Pact
28
28
  end
29
29
 
30
30
  def pact_diffs
31
- pact_jsons.collect do | pact_json |
31
+ pact_sources.collect do | pact_json |
32
32
  PactDiff.call(pact_json)
33
33
  end.compact.join("\n")
34
34
  end
@@ -1,26 +1,24 @@
1
+ require 'pact/hal/entity'
2
+
1
3
  module Pact
2
4
  module Provider
3
5
  module Help
4
-
5
6
  class PactDiff
6
-
7
7
  class PrintPactDiffError < StandardError; end
8
8
 
9
- attr_reader :pact_json, :output
9
+ attr_reader :pact_source, :output
10
10
 
11
- def initialize pact_json
12
- @pact_json = pact_json
11
+ def initialize pact_source
12
+ @pact_source = pact_source
13
13
  end
14
14
 
15
- def self.call pact_json
16
- new(pact_json).call
15
+ def self.call pact_source
16
+ new(pact_source).call
17
17
  end
18
18
 
19
19
  def call
20
20
  begin
21
- if diff_rel && diff_url
22
- header + "\n" + get_diff
23
- end
21
+ header + "\n" + get_diff
24
22
  rescue PrintPactDiffError => e
25
23
  return e.message
26
24
  end
@@ -32,35 +30,13 @@ module Pact
32
30
  "The following changes have been made since the previous distinct version of this pact, and may be responsible for verification failure:\n"
33
31
  end
34
32
 
35
- def pact_hash
36
- @pact_hash ||= json_load(pact_json)
37
- end
38
-
39
- def links
40
- pact_hash['_links'] || pact_hash['links']
41
- end
42
-
43
- def diff_rel
44
- return nil unless links
45
- key = links.keys.find { | key | key =~ /diff/ && key =~ /distinct/ && key =~ /previous/}
46
- key ? links[key] : nil
47
- end
48
-
49
- def diff_url
50
- diff_rel['href']
51
- end
52
-
53
33
  def get_diff
54
34
  begin
55
- open(diff_url) { | file | file.read }
35
+ pact_source.hal_entity._link!("pb:diff-previous-distinct").get!(nil, "Accept" => "text/plain").body
56
36
  rescue StandardError => e
57
- raise PrintPactDiffError.new("Tried to retrieve diff with previous pact from #{diff_url}, but received response code #{e}.")
37
+ raise PrintPactDiffError.new("Tried to retrieve diff with previous pact, but received error #{e.class} #{e.message}.")
58
38
  end
59
39
  end
60
-
61
- def json_load json
62
- JSON.load(json, nil, { max_nesting: 50 })
63
- end
64
40
  end
65
41
  end
66
42
  end
@@ -9,12 +9,12 @@ module Pact
9
9
 
10
10
  HELP_FILE_NAME = 'help.md'
11
11
 
12
- def self.call pact_jsons, reports_dir = Pact.configuration.reports_dir
13
- new(pact_jsons, reports_dir).call
12
+ def self.call pact_sources, reports_dir = Pact.configuration.reports_dir
13
+ new(pact_sources, reports_dir).call
14
14
  end
15
15
 
16
- def initialize pact_jsons, reports_dir
17
- @pact_jsons = pact_jsons
16
+ def initialize pact_sources, reports_dir
17
+ @pact_sources = pact_sources
18
18
  @reports_dir = File.expand_path(reports_dir)
19
19
  end
20
20
 
@@ -25,7 +25,7 @@ module Pact
25
25
 
26
26
  private
27
27
 
28
- attr_reader :reports_dir, :pact_jsons
28
+ attr_reader :reports_dir, :pact_sources
29
29
 
30
30
  def clean_reports_dir
31
31
  raise "Cleaning report dir #{reports_dir} would delete project!" if reports_dir_contains_pwd
@@ -46,9 +46,8 @@ module Pact
46
46
  end
47
47
 
48
48
  def help_text
49
- Content.new(pact_jsons).text
49
+ Content.new(pact_sources).text
50
50
  end
51
-
52
51
  end
53
52
  end
54
53
  end
@@ -22,4 +22,3 @@ module Pact
22
22
  end
23
23
  end
24
24
  end
25
-
@@ -1,4 +1,6 @@
1
1
  require 'pact/consumer_contract/pact_file'
2
+ require 'pact/hal/http_client'
3
+ require 'pact/hal/entity'
2
4
 
3
5
  module Pact
4
6
  module Provider
@@ -17,6 +19,13 @@ module Pact
17
19
  def pact_hash
18
20
  @pact_hash ||= JSON.load(pact_json, nil, { max_nesting: 50 })
19
21
  end
22
+
23
+ def hal_entity
24
+ http_client_keys = [:username, :password, :token]
25
+ http_client_options = uri.options.reject{ |k, _| !http_client_keys.include?(k) }
26
+ http_client = Pact::Hal::HttpClient.new(http_client_options.merge(verbose: true))
27
+ Pact::Hal::Entity.new(uri, pact_hash, http_client)
28
+ end
20
29
  end
21
30
  end
22
31
  end
@@ -80,7 +80,7 @@ module Pact
80
80
  executing_with_ruby = executing_with_ruby?
81
81
 
82
82
  config.after(:suite) do | suite |
83
- Pact::Provider::Help::Write.call(jsons) if executing_with_ruby
83
+ Pact::Provider::Help::Write.call(Pact.provider_world.pact_sources) if executing_with_ruby
84
84
  end
85
85
  end
86
86
 
@@ -91,7 +91,7 @@ module Pact
91
91
  ::RSpec::Core::CommandLine.new(NoConfigurationOptions.new)
92
92
  .run(::RSpec.configuration.output_stream, ::RSpec.configuration.error_stream)
93
93
  end
94
- options[:ignore_failures] ? 0 : exit_code
94
+ (all_pacts_pending? || options[:ignore_failures]) ? 0 : exit_code
95
95
  end
96
96
 
97
97
  def rspec_runner_options
@@ -159,6 +159,10 @@ module Pact
159
159
  consumer_contract.to_json
160
160
  end
161
161
 
162
+ def all_pacts_pending?
163
+ pact_urls.all?{ | pact_url| pact_url.metadata[:pending] }
164
+ end
165
+
162
166
  def class_exists? name
163
167
  Kernel.const_get name
164
168
  rescue NameError
@@ -1,17 +1,19 @@
1
1
  module Pact
2
2
  module Provider
3
3
  class PactURI
4
- attr_reader :uri, :options
4
+ attr_reader :uri, :options, :metadata
5
5
 
6
- def initialize (uri, options={})
6
+ def initialize (uri, options = nil, metadata = nil)
7
7
  @uri = uri
8
- @options = options
8
+ @options = options || {}
9
+ @metadata = metadata || {} # make sure it's not nil if nil is passed in
9
10
  end
10
11
 
11
12
  def == other
12
13
  other.is_a?(PactURI) &&
13
14
  uri == other.uri &&
14
- options == other.options
15
+ options == other.options &&
16
+ metadata == other.metadata
15
17
  end
16
18
 
17
19
  def basic_auth?
@@ -54,7 +54,7 @@ module Pact
54
54
  end
55
55
 
56
56
  def rack_request_header_for header
57
- with_http_prefix(header.to_s.upcase).gsub('-', '_')
57
+ with_http_prefix(header.to_s.upcase).tr('-', '_')
58
58
  end
59
59
 
60
60
  def rack_request_value_for value
@@ -17,15 +17,19 @@ module Pact
17
17
  end
18
18
 
19
19
  module ClassMethods
20
+ EMPTY_ARRAY = [].freeze
20
21
 
21
22
  include ::RSpec::Core::DSL
22
23
 
23
24
  def honour_pactfile pact_uri, pact_json, options
24
- pact_description = options[:ignore_failures] ? "Pending pact" : "pact"
25
- Pact.configuration.output_stream.puts "INFO: Reading #{pact_description} at #{pact_uri}"
26
- Pact.configuration.output_stream.puts "INFO: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
25
+ Pact.configuration.output_stream.puts "INFO: Reading pact at #{pact_uri}"
26
+ (pact_uri.metadata[:notices] || EMPTY_ARRAY).each do | notice |
27
+ Pact.configuration.output_stream.puts("DEBUG: #{notice}")
28
+ end
29
+ Pact.configuration.output_stream.puts "DEBUG: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
27
30
  consumer_contract = Pact::ConsumerContract.from_json(pact_json)
28
- ::RSpec.describe "Verifying a #{pact_description} between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}", pactfile_uri: pact_uri do
31
+ suffix = pact_uri.metadata[:pending] ? " [PENDING]": ""
32
+ ::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}#{suffix}", pactfile_uri: pact_uri do
29
33
  honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri)
30
34
  end
31
35
  end
@@ -74,7 +78,7 @@ module Pact
74
78
  pact_interaction: interaction,
75
79
  pact_interaction_example_description: interaction_description_for_rerun_command(interaction),
76
80
  pact_uri: options[:pact_uri],
77
- pact_ignore_failures: options[:ignore_failures]
81
+ pact_ignore_failures: options[:pact_uri].metadata[:pending] || options[:ignore_failures]
78
82
  }
79
83
 
80
84
  describe description_for(interaction), metadata do
@@ -46,7 +46,7 @@ module Pact
46
46
  def tear_down_provider_states provider_states, consumer, options = {}
47
47
  # If there are no provider state, execute with an nil state to ensure global and base states are executed
48
48
  Pact.configuration.provider_state_tear_down.call(nil, consumer, options) if provider_states.nil? || provider_states.empty?
49
- provider_states.reverse.each do | provider_state |
49
+ provider_states.reverse_each do | provider_state |
50
50
  Pact.configuration.provider_state_tear_down.call(provider_state.name, consumer, options.merge(params: provider_state.params))
51
51
  end
52
52
  end
@@ -43,7 +43,7 @@ module Pact
43
43
  end
44
44
 
45
45
  def pact_uris_from_pact_uri_sources
46
- pact_uri_sources.collect{| pact_uri_source| pact_uri_source.call }.flatten
46
+ pact_uri_sources.collect(&:call).flatten
47
47
  end
48
48
  end
49
49
  end
data/lib/pact/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Remember to bump pact-provider-proxy when this changes major version
2
2
  module Pact
3
- VERSION = "1.41.2"
3
+ VERSION = "1.44.1"
4
4
  end
data/pact.gemspec CHANGED
@@ -1,5 +1,4 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'pact/version'
5
4
 
@@ -15,31 +14,30 @@ Gem::Specification.new do |gem|
15
14
  gem.required_ruby_version = '>= 2.0'
16
15
 
17
16
  gem.files = `git ls-files bin lib pact.gemspec CHANGELOG.md LICENSE.txt`.split($/)
18
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
19
  gem.require_paths = ["lib"]
21
20
  gem.license = 'MIT'
22
21
 
23
22
  gem.metadata = {
23
+ 'changelog_uri' => 'https://github.com/pact-foundation/pact-ruby/blob/master/CHANGELOG.md',
24
24
  'source_code_uri' => 'https://github.com/pact-foundation/pact-ruby',
25
25
  'bug_tracker_uri' => 'https://github.com/pact-foundation/pact-ruby/issues',
26
26
  'documentation_uri' => 'https://github.com/pact-foundation/pact-ruby/blob/master/README.md'
27
27
  }
28
28
 
29
- gem.add_runtime_dependency 'randexp', '~> 0.1.7'
30
- gem.add_runtime_dependency 'rspec', '>=2.14'
29
+ gem.add_runtime_dependency 'rspec', '>= 2.14'
31
30
  gem.add_runtime_dependency 'rack-test', '>= 0.6.3', '< 2.0.0'
32
31
  gem.add_runtime_dependency 'thor'
33
- gem.add_runtime_dependency 'json','> 1.8.5'
34
32
  gem.add_runtime_dependency 'webrick'
35
33
  gem.add_runtime_dependency 'term-ansicolor', '~> 1.0'
36
34
 
37
35
  gem.add_runtime_dependency 'pact-support', '~> 1.9'
38
- gem.add_runtime_dependency 'pact-mock_service', '~> 3.0'
36
+ gem.add_runtime_dependency 'pact-mock_service', '~> 3.0', '>= 3.3.1'
39
37
 
40
38
  gem.add_development_dependency 'rake', '~> 10.0.3'
41
39
  gem.add_development_dependency 'webmock', '~> 3.0'
42
- #gem.add_development_dependency 'pry-byebug'
40
+ gem.add_development_dependency 'pry-byebug'
43
41
  gem.add_development_dependency 'fakefs', '0.5' # 0.6.0 blows up
44
42
  gem.add_development_dependency 'hashie', '~> 2.0'
45
43
  gem.add_development_dependency 'activesupport'
@@ -47,4 +45,5 @@ Gem::Specification.new do |gem|
47
45
  gem.add_development_dependency 'appraisal', '~> 2.2'
48
46
  gem.add_development_dependency 'conventional-changelog', '~> 1.3'
49
47
  gem.add_development_dependency 'bump', '~> 0.5'
48
+ gem.add_development_dependency 'pact-message'
50
49
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.41.2
4
+ version: 1.44.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Fraser
@@ -12,22 +12,8 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2019-09-09 00:00:00.000000000 Z
15
+ date: 2020-01-20 00:00:00.000000000 Z
16
16
  dependencies:
17
- - !ruby/object:Gem::Dependency
18
- name: randexp
19
- requirement: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - "~>"
22
- - !ruby/object:Gem::Version
23
- version: 0.1.7
24
- type: :runtime
25
- prerelease: false
26
- version_requirements: !ruby/object:Gem::Requirement
27
- requirements:
28
- - - "~>"
29
- - !ruby/object:Gem::Version
30
- version: 0.1.7
31
17
  - !ruby/object:Gem::Dependency
32
18
  name: rspec
33
19
  requirement: !ruby/object:Gem::Requirement
@@ -76,20 +62,6 @@ dependencies:
76
62
  - - ">="
77
63
  - !ruby/object:Gem::Version
78
64
  version: '0'
79
- - !ruby/object:Gem::Dependency
80
- name: json
81
- requirement: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">"
84
- - !ruby/object:Gem::Version
85
- version: 1.8.5
86
- type: :runtime
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ">"
91
- - !ruby/object:Gem::Version
92
- version: 1.8.5
93
65
  - !ruby/object:Gem::Dependency
94
66
  name: webrick
95
67
  requirement: !ruby/object:Gem::Requirement
@@ -139,6 +111,9 @@ dependencies:
139
111
  - - "~>"
140
112
  - !ruby/object:Gem::Version
141
113
  version: '3.0'
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 3.3.1
142
117
  type: :runtime
143
118
  prerelease: false
144
119
  version_requirements: !ruby/object:Gem::Requirement
@@ -146,6 +121,9 @@ dependencies:
146
121
  - - "~>"
147
122
  - !ruby/object:Gem::Version
148
123
  version: '3.0'
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 3.3.1
149
127
  - !ruby/object:Gem::Dependency
150
128
  name: rake
151
129
  requirement: !ruby/object:Gem::Requirement
@@ -174,6 +152,20 @@ dependencies:
174
152
  - - "~>"
175
153
  - !ruby/object:Gem::Version
176
154
  version: '3.0'
155
+ - !ruby/object:Gem::Dependency
156
+ name: pry-byebug
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
177
169
  - !ruby/object:Gem::Dependency
178
170
  name: fakefs
179
171
  requirement: !ruby/object:Gem::Requirement
@@ -272,6 +264,20 @@ dependencies:
272
264
  - - "~>"
273
265
  - !ruby/object:Gem::Version
274
266
  version: '0.5'
267
+ - !ruby/object:Gem::Dependency
268
+ name: pact-message
269
+ requirement: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - ">="
272
+ - !ruby/object:Gem::Version
273
+ version: '0'
274
+ type: :development
275
+ prerelease: false
276
+ version_requirements: !ruby/object:Gem::Requirement
277
+ requirements:
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ version: '0'
275
281
  description: Enables consumer driven contract testing, providing a mock service and
276
282
  DSL for the consumer project, and interaction playback and verification for the
277
283
  service provider project.
@@ -322,14 +328,16 @@ files:
322
328
  - lib/pact/hal/entity.rb
323
329
  - lib/pact/hal/http_client.rb
324
330
  - lib/pact/hal/link.rb
331
+ - lib/pact/hal/non_json_entity.rb
325
332
  - lib/pact/pact_broker.rb
333
+ - lib/pact/pact_broker/fetch_pact_uris_for_verification.rb
326
334
  - lib/pact/pact_broker/fetch_pacts.rb
327
- - lib/pact/pact_broker/fetch_pending_pacts.rb
328
335
  - lib/pact/project_root.rb
329
336
  - lib/pact/provider.rb
330
337
  - lib/pact/provider/configuration.rb
331
338
  - lib/pact/provider/configuration/configuration_extension.rb
332
339
  - lib/pact/provider/configuration/dsl.rb
340
+ - lib/pact/provider/configuration/message_provider_dsl.rb
333
341
  - lib/pact/provider/configuration/pact_verification.rb
334
342
  - lib/pact/provider/configuration/pact_verification_from_broker.rb
335
343
  - lib/pact/provider/configuration/service_provider_config.rb
@@ -381,6 +389,7 @@ homepage: https://github.com/pact-foundation/pact-ruby
381
389
  licenses:
382
390
  - MIT
383
391
  metadata:
392
+ changelog_uri: https://github.com/pact-foundation/pact-ruby/blob/master/CHANGELOG.md
384
393
  source_code_uri: https://github.com/pact-foundation/pact-ruby
385
394
  bug_tracker_uri: https://github.com/pact-foundation/pact-ruby/issues
386
395
  documentation_uri: https://github.com/pact-foundation/pact-ruby/blob/master/README.md
@@ -400,7 +409,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
400
409
  version: '0'
401
410
  requirements: []
402
411
  rubyforge_project:
403
- rubygems_version: 2.6.14.3
412
+ rubygems_version: 2.7.7
404
413
  signing_key:
405
414
  specification_version: 4
406
415
  summary: Enables consumer driven contract testing, providing a mock service and DSL
@@ -1,58 +0,0 @@
1
- require 'pact/hal/entity'
2
- require 'pact/hal/http_client'
3
- require 'pact/provider/pact_uri'
4
- require 'pact/errors'
5
-
6
- module Pact
7
- module PactBroker
8
- class FetchPendingPacts
9
- attr_reader :provider, :tags, :broker_base_url, :http_client_options, :http_client, :index_entity
10
-
11
- PENDING_PROVIDER_RELATION = 'beta:pending-provider-pacts'.freeze
12
- WIP_PROVIDER_RELATION = 'beta:wip-provider-pacts'.freeze # deprecated
13
- PACTS = 'pacts'.freeze
14
- PB_PACTS = 'pb:pacts'.freeze
15
- HREF = 'href'.freeze
16
-
17
- def initialize(provider, broker_base_url, http_client_options)
18
- @provider = provider
19
- @http_client_options = http_client_options
20
- @broker_base_url = broker_base_url
21
- @http_client = Pact::Hal::HttpClient.new(http_client_options)
22
- end
23
-
24
- def self.call(provider, broker_base_url, http_client_options)
25
- new(provider, broker_base_url, http_client_options).call
26
- end
27
-
28
- def call
29
- if index.success?
30
- pending_pacts_for_provider
31
- else
32
- raise Pact::Error.new("Error retrieving #{broker_base_url} status=#{index_entity.response.code} #{index_entity.response.raw_body}")
33
- end
34
- end
35
-
36
- private
37
-
38
- def index
39
- @index_entity ||= Pact::Hal::Link.new({ "href" => broker_base_url }, http_client).get.assert_success!
40
- end
41
-
42
- def pending_pacts_for_provider
43
- link = index_entity._link(WIP_PROVIDER_RELATION, PENDING_PROVIDER_RELATION)
44
- if link
45
- get_pact_urls(link.expand(provider: provider).get)
46
- else
47
- []
48
- end
49
- end
50
-
51
- def get_pact_urls(link_by_provider)
52
- link_by_provider.fetch(PB_PACTS, PACTS).collect do |pact|
53
- Pact::Provider::PactURI.new(pact[HREF], http_client_options)
54
- end
55
- end
56
- end
57
- end
58
- end