pact 1.46.1 → 1.53.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25ae3362c392a7deab31b4273d9d35c954822fc5e67febdccd318239831be087
4
- data.tar.gz: 89de14252d7225f678881afff334c501a2cfc1e39c191cf3b5a4da9c642c97da
3
+ metadata.gz: 36cdbcc7291013248a5b691e8dec77f7153fd3c5c75d664e5da651943a8673dc
4
+ data.tar.gz: 0a75d19524d85f5623f6f8f9b042b1e481f551a5784cb2c48e86633f2d3d7329
5
5
  SHA512:
6
- metadata.gz: cf708ab7cbebbf0dbb0df3bc196ee5bd9818218c2dd925f73f59055bf1d05fea698731b6ac2d510098eea48f05b02c49b9f7492e2a9f6cfb3064ebb8524dc7bf
7
- data.tar.gz: 223a6ed21f94fdd178794af79eb6f47371aa66e85b5f7e19140a2e51a6fcaf7cc71dfae9f1c965162bd0a8b0b1a82dff0c699a4582a1747e3ebd7e2dd17bd9f7
6
+ metadata.gz: faa46bb073cdacca555022ee518d15e13182f286f1b6d75f309f7f5d6d6692674c046ced1d3b8598d10772b7dc25d3157aa556d6ac47453753dc90607ed8575b
7
+ data.tar.gz: 360a99577f6925e21ab6ce0949bca79a3309c1a16e7dbd21ae72fe20b7c46a87eca0f422d810061d2adc594141b76ca4be831eeb8859aff29eca00fe9227f78e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,108 @@
1
+ <a name="v1.53.0"></a>
2
+ ### v1.53.0 (2020-09-11)
3
+
4
+ #### Features
5
+
6
+ * add support for the enable_pending flag ([16866f4](/../../commit/16866f4))
7
+
8
+ <a name="v1.52.0"></a>
9
+ ### v1.52.0 (2020-09-10)
10
+
11
+ #### Features
12
+
13
+ * support webdav http methods ([fa1d712](/../../commit/fa1d712))
14
+
15
+ <a name="v1.51.1"></a>
16
+ ### v1.51.1 (2020-08-12)
17
+
18
+ #### Bug Fixes
19
+
20
+ * update thor dependency (#218) ([bf3ce69](/../../commit/bf3ce69))
21
+ * bump rake dependency per CVE-2020-8130 (#219) ([09feaa6](/../../commit/09feaa6))
22
+
23
+ <a name="v1.51.0"></a>
24
+ ### v1.51.0 (2020-06-24)
25
+
26
+
27
+ #### Features
28
+
29
+ * allow individual interactions to be re-run by setting PACT_BROKER_INTERACTION_ID ([a586d80](/../../commit/a586d80))
30
+
31
+
32
+ <a name="v1.50.1"></a>
33
+ ### v1.50.1 (2020-06-15)
34
+
35
+
36
+ #### Bug Fixes
37
+
38
+ * fix integration with pact-message-ruby (#216) ([d2da13e](/../../commit/d2da13e))
39
+
40
+
41
+ <a name="v1.50.0"></a>
42
+ ### v1.50.0 (2020-04-25)
43
+
44
+
45
+ #### Features
46
+
47
+ * Set expected interactions on mock service but without writing them to pact file (#210) ([14f5327](/../../commit/14f5327))
48
+
49
+
50
+ <a name="v1.49.3"></a>
51
+ ### v1.49.3 (2020-04-22)
52
+
53
+
54
+ #### Bug Fixes
55
+
56
+ * pact selection verification options logging ([9ff59f4](/../../commit/9ff59f4))
57
+
58
+
59
+ <a name="v1.49.2"></a>
60
+ ### v1.49.2 (2020-04-08)
61
+
62
+
63
+ #### Bug Fixes
64
+
65
+ * json parser error for top level JSON values ([dafbc35](/../../commit/dafbc35))
66
+
67
+
68
+ <a name="v1.49.1"></a>
69
+ ### v1.49.1 (2020-03-21)
70
+
71
+
72
+ #### Bug Fixes
73
+
74
+ * ensure diff is included in the json output ([0bd9753](/../../commit/0bd9753))
75
+ * ensure the presence of basic auth credentials does not cause an error when displaying the path of a pact on the local filesystem ([f6a0b4d](/../../commit/f6a0b4d))
76
+
77
+
78
+ <a name="v1.49.0"></a>
79
+ ### v1.49.0 (2020-02-18)
80
+
81
+
82
+ #### Features
83
+
84
+ * use environment variables PACT_BROKER_USERNAME and PACT_BROKER_PASSWORD when verifying a pact by URL, if the environment variables are present ([308f25d](/../../commit/308f25d))
85
+
86
+
87
+ <a name="v1.48.0"></a>
88
+ ### v1.48.0 (2020-02-13)
89
+
90
+
91
+ #### Features
92
+
93
+ * use certificates from SSL_CERT_FILE and SSL_CERT_DIR environment variables in HTTP connections ([164912b](/../../commit/164912b))
94
+
95
+
96
+ <a name="v1.47.0"></a>
97
+ ### v1.47.0 (2020-02-08)
98
+
99
+
100
+ #### Features
101
+
102
+ * update json formatter output ([376e47a](/../../commit/376e47a))
103
+ * add pact metadata to json formatter ([6c6ddb8](/../../commit/6c6ddb8))
104
+
105
+
1
106
  <a name="v1.46.1"></a>
2
107
  ### v1.46.1 (2020-01-22)
3
108
 
@@ -56,9 +56,11 @@ module Pact
56
56
 
57
57
  def run_with_pact_url_string
58
58
  pact_repository_uri_options = {}
59
+ pact_repository_uri_options[:username] = ENV['PACT_BROKER_USERNAME'] if ENV['PACT_BROKER_USERNAME']
60
+ pact_repository_uri_options[:password] = ENV['PACT_BROKER_PASSWORD'] if ENV['PACT_BROKER_PASSWORD']
61
+ pact_repository_uri_options[:token] = ENV['PACT_BROKER_TOKEN']
59
62
  pact_repository_uri_options[:username] = options[:pact_broker_username] if options[:pact_broker_username]
60
63
  pact_repository_uri_options[:password] = options[:pact_broker_password] if options[:pact_broker_password]
61
- pact_repository_uri_options[:token] = ENV['PACT_BROKER_TOKEN']
62
64
  pact_uri = ::Pact::Provider::PactURI.new(options[:pact_uri], pact_repository_uri_options)
63
65
  Pact::Provider::PactSpecRunner.new([pact_uri], pact_spec_options).run
64
66
  end
@@ -6,8 +6,11 @@ module Pact
6
6
  criteria = {}
7
7
 
8
8
  criteria[:description] = Regexp.new(options[:description]) if options[:description]
9
+ criteria[:_id] = options[:pact_broker_interaction_id] if options[:pact_broker_interaction_id]
10
+ criteria[:index] = options[:interaction_index] if options[:interaction_index]
9
11
 
10
12
  provider_state = options[:provider_state]
13
+
11
14
  if provider_state
12
15
  if provider_state.length == 0
13
16
  criteria[:provider_state] = nil #Allow PACT_PROVIDER_STATE="" to mean no provider state
data/lib/pact/cli.rb CHANGED
@@ -4,6 +4,9 @@ require 'pact/provider/configuration'
4
4
 
5
5
  module Pact
6
6
  class CLI < Thor
7
+ def self.exit_on_failure? # Thor 1.0 deprecation guard
8
+ false
9
+ end
7
10
 
8
11
  desc 'verify', "Verify a pact"
9
12
  method_option :pact_helper, aliases: "-h", desc: "Pact helper file", :required => true
@@ -18,6 +21,8 @@ module Pact
18
21
  default: Pact.configuration.interactions_replay_order
19
22
  method_option :description, aliases: "-d", desc: "Interaction description filter"
20
23
  method_option :provider_state, aliases: "-s", desc: "Provider state filter"
24
+ method_option :interaction_index, type: :numeric, desc: "Index filter"
25
+ method_option :pact_broker_interaction_id, desc: "Pact Broker interaction ID filter"
21
26
  method_option :format, aliases: "-f", banner: "FORMATTER", desc: "RSpec formatter. Defaults to custom Pact formatter. [j]son may also be used."
22
27
  method_option :out, aliases: "-o", banner: "FILE", desc: "Write output to a file instead of $stdout."
23
28
 
@@ -25,6 +25,10 @@ module Pact
25
25
  @mock_service_base_url = "http://#{attributes[:host]}:#{attributes[:port]}"
26
26
  end
27
27
 
28
+ def without_writing_to_pact
29
+ interaction_builder.without_writing_to_pact
30
+ end
31
+
28
32
  def given(provider_state)
29
33
  interaction_builder.given(provider_state)
30
34
  end
@@ -13,6 +13,12 @@ module Pact
13
13
  @callback = block
14
14
  end
15
15
 
16
+ def without_writing_to_pact
17
+ interaction.metadata ||= {}
18
+ interaction.metadata[:write_to_pact] = false
19
+ self
20
+ end
21
+
16
22
  def upon_receiving description
17
23
  @interaction.description = description
18
24
  self
@@ -50,6 +50,8 @@ module Pact
50
50
  http = Net::HTTP.new(uri.host, uri.port, :ENV)
51
51
  http.set_debug_output(output_stream) if verbose
52
52
  http.use_ssl = (uri.scheme == 'https')
53
+ http.ca_file = ENV['SSL_CERT_FILE'] if ENV['SSL_CERT_FILE'] && ENV['SSL_CERT_FILE'] != ''
54
+ http.ca_path = ENV['SSL_CERT_DIR'] if ENV['SSL_CERT_DIR'] && ENV['SSL_CERT_DIR'] != ''
53
55
  http.start do |http|
54
56
  http.request request
55
57
  end
@@ -3,10 +3,13 @@ require 'pact/hal/http_client'
3
3
  require 'pact/provider/pact_uri'
4
4
  require 'pact/errors'
5
5
  require 'pact/pact_broker/fetch_pacts'
6
+ require 'pact/pact_broker/notices'
7
+ require 'pact/pact_broker/pact_selection_description'
6
8
 
7
9
  module Pact
8
10
  module PactBroker
9
11
  class FetchPactURIsForVerification
12
+ include PactSelectionDescription
10
13
  attr_reader :provider, :consumer_version_selectors, :provider_version_tags, :broker_base_url, :http_client_options, :http_client, :options
11
14
 
12
15
  PACTS_FOR_VERIFICATION_RELATION = 'beta:provider-pacts-for-verification'.freeze
@@ -19,7 +22,7 @@ module Pact
19
22
  def initialize(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
20
23
  @provider = provider
21
24
  @consumer_version_selectors = consumer_version_selectors || []
22
- @provider_version_tags = provider_version_tags || []
25
+ @provider_version_tags = [*provider_version_tags]
23
26
  @http_client_options = http_client_options
24
27
  @broker_base_url = broker_base_url
25
28
  @http_client = Pact::Hal::HttpClient.new(http_client_options)
@@ -51,7 +54,8 @@ module Pact
51
54
  pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact |
52
55
  metadata = {
53
56
  pending: pact["verificationProperties"]["pending"],
54
- notices: extract_notices(pact)
57
+ notices: extract_notices(pact),
58
+ short_description: pact["shortDescription"]
55
59
  }
56
60
  Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata)
57
61
  end
@@ -69,11 +73,12 @@ module Pact
69
73
  q["includePendingStatus"] = true if options[:include_pending_status]
70
74
  q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any?
71
75
  q["providerVersionTags"] = provider_version_tags if provider_version_tags.any?
76
+ q["includeWipPactsSince"] = options[:include_wip_pacts_since] if options[:include_wip_pacts_since]
72
77
  q
73
78
  end
74
79
 
75
80
  def extract_notices(pact)
76
- (pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) }.compact
81
+ Notices.new((pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) })
77
82
  end
78
83
 
79
84
  def symbolize_keys(hash)
@@ -81,18 +86,7 @@ module Pact
81
86
  end
82
87
 
83
88
  def log_message
84
- latest = consumer_version_selectors.any? ? "" : "latest "
85
- message = "INFO: Fetching #{latest}pacts for #{provider} from #{broker_base_url}"
86
- if consumer_version_selectors.any?
87
- desc = consumer_version_selectors.collect do |selector|
88
- all_or_latest = selector[:all] ? "all" : "latest"
89
- # TODO support fallback
90
- name = selector[:fallback] ? "#{selector[:tag]} (or #{selector[:fallback]} if not found)" : selector[:tag]
91
- "#{all_or_latest} #{name}"
92
- end.join(", ")
93
- message << " for tags: #{desc}"
94
- end
95
- Pact.configuration.output_stream.puts message
89
+ Pact.configuration.output_stream.puts "INFO: #{pact_selection_description(provider, consumer_version_selectors, options, broker_base_url)}"
96
90
  end
97
91
  end
98
92
  end
@@ -0,0 +1,34 @@
1
+ module Pact
2
+ module PactBroker
3
+ class Notices < Array
4
+ def before_verification_notices
5
+ select { | notice | notice[:when].nil? || notice[:when].start_with?('before_verification') }
6
+ end
7
+
8
+ def before_verification_notices_text
9
+ before_verification_notices.collect{ | notice | notice[:text] }
10
+ end
11
+
12
+ def after_verification_notices(success, published)
13
+ select { | notice | notice[:when] == "after_verification:success_#{success}_published_#{published}" || notice[:when] == "after_verification" }
14
+ .collect do | notice |
15
+ notice.merge(:when => simplify_notice_when(notice[:when]))
16
+ end
17
+ end
18
+
19
+ def after_verification_notices_text(success, published)
20
+ after_verification_notices(success, published).collect{ | notice | notice[:text] }
21
+ end
22
+
23
+ def all_notices(success, published)
24
+ before_verification_notices + after_verification_notices(success, published)
25
+ end
26
+
27
+ private
28
+
29
+ def simplify_notice_when(when_key)
30
+ when_key.split(":").first
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ module Pact
2
+ module PactBroker
3
+ module PactSelectionDescription
4
+ def pact_selection_description(provider, consumer_version_selectors, options, broker_base_url)
5
+ latest = consumer_version_selectors.any? ? "" : "latest "
6
+ message = "Fetching pacts for #{provider} from #{broker_base_url} with the selection criteria: "
7
+ if consumer_version_selectors.any?
8
+ desc = consumer_version_selectors.collect do |selector|
9
+ all_or_latest = !selector[:latest] ? "all for tag" : "latest for tag"
10
+ # TODO support fallback
11
+ fallback = selector[:fallback] || selector[:fallbackTag]
12
+ name = fallback ? "#{selector[:tag]} (or #{fallback} if not found)" : selector[:tag]
13
+ "#{all_or_latest} #{name}"
14
+ end.join(", ")
15
+ if options[:include_wip_pacts_since]
16
+ desc = "#{desc}, work in progress pacts created after #{options[:include_wip_pacts_since]}"
17
+ end
18
+ message << "#{desc}"
19
+ end
20
+ message
21
+ end
22
+ end
23
+ end
24
+ end
@@ -22,6 +22,33 @@ module Pact
22
22
  end
23
23
 
24
24
  dsl do
25
+ def app &block
26
+ self.app_block = block
27
+ end
28
+
29
+ def app_version application_version
30
+ self.application_version = application_version
31
+ end
32
+
33
+ def app_version_tags tags
34
+ self.tags = tags
35
+ end
36
+
37
+ def publish_verification_results publish_verification_results
38
+ self.publish_verification_results = publish_verification_results
39
+ Pact::RSpec.with_rspec_2 do
40
+ Pact.configuration.error_stream.puts "WARN: Publishing of verification results is currently not supported with rspec 2. If you would like this functionality, please feel free to submit a PR!"
41
+ end
42
+ end
43
+
44
+ def honours_pact_with consumer_name, options = {}, &block
45
+ create_pact_verification consumer_name, options, &block
46
+ end
47
+
48
+ def honours_pacts_from_pact_broker &block
49
+ create_pact_verification_from_broker &block
50
+ end
51
+
25
52
  def builder &block
26
53
  self.app_block = lambda { RackToMessageAdapter.new(block) }
27
54
  end
@@ -14,12 +14,13 @@ 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, :_provider_version_tags, :_basic_auth_options, :_verbose
17
+ attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_verbose
18
18
 
19
19
  def initialize(provider_name, provider_version_tags)
20
20
  @_provider_name = provider_name
21
21
  @_provider_version_tags = provider_version_tags
22
22
  @_consumer_version_tags = []
23
+ @_enable_pending = false
23
24
  @_verbose = false
24
25
  end
25
26
 
@@ -33,6 +34,10 @@ module Pact
33
34
  self._consumer_version_tags = *consumer_version_tags
34
35
  end
35
36
 
37
+ def enable_pending enable_pending
38
+ self._enable_pending = enable_pending
39
+ end
40
+
36
41
  def verbose verbose
37
42
  self._verbose = verbose
38
43
  end
@@ -51,7 +56,8 @@ module Pact
51
56
  consumer_version_selectors,
52
57
  _provider_version_tags,
53
58
  _pact_broker_base_url,
54
- _basic_auth_options.merge(verbose: _verbose)
59
+ _basic_auth_options.merge(verbose: _verbose),
60
+ { include_pending_status: _enable_pending }
55
61
  )
56
62
 
57
63
  Pact.provider_world.add_pact_uri_source fetch_pacts
@@ -6,7 +6,7 @@ module Pact
6
6
  module Provider
7
7
  class PactSource
8
8
 
9
- attr_reader :uri
9
+ attr_reader :uri # PactURI class
10
10
 
11
11
  def initialize uri
12
12
  @uri = uri
@@ -122,7 +122,7 @@ module Pact
122
122
  ignore_failures: options[:ignore_failures],
123
123
  request_customizer: options[:request_customizer]
124
124
  }
125
- honour_pactfile pact_source.uri, ordered_pact_json(pact_source.pact_json), spec_options
125
+ honour_pactfile pact_source, ordered_pact_json(pact_source.pact_json), spec_options
126
126
  end
127
127
  end
128
128
 
@@ -29,10 +29,10 @@ module Pact
29
29
  end
30
30
 
31
31
  def to_s
32
- if(basic_auth?)
32
+ if basic_auth? && uri.start_with?('http://', 'https://')
33
33
  URI(@uri).tap { |x| x.userinfo="#{username}:*****"}.to_s
34
34
  else
35
- @uri
35
+ uri
36
36
  end
37
37
  end
38
38
  end
@@ -93,17 +93,32 @@ module Pact
93
93
 
94
94
  def interaction_rerun_command_for example
95
95
  example_description = example.metadata[:pact_interaction_example_description]
96
- if ENV['PACT_INTERACTION_RERUN_COMMAND']
96
+
97
+ _id = example.metadata[:pact_interaction]._id
98
+ index = example.metadata[:pact_interaction].index
99
+ provider_state = example.metadata[:pact_interaction].provider_state
100
+ description = example.metadata[:pact_interaction].description
101
+ pactfile_uri = example.metadata[:pactfile_uri]
102
+
103
+ if _id && ENV['PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER']
104
+ cmd = String.new(ENV['PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER'])
105
+ cmd.gsub!("<PACT_URI>", example.metadata[:pactfile_uri].to_s)
106
+ cmd.gsub!("<PACT_BROKER_INTERACTION_ID>", "#{_id}")
107
+ colorizer.wrap("#{cmd} ", ::RSpec.configuration.failure_color) + colorizer.wrap("# #{example_description}", ::RSpec.configuration.detail_color)
108
+ elsif ENV['PACT_INTERACTION_RERUN_COMMAND']
97
109
  cmd = String.new(ENV['PACT_INTERACTION_RERUN_COMMAND'])
98
- provider_state = example.metadata[:pact_interaction].provider_state
99
- description = example.metadata[:pact_interaction].description
100
- pactfile_uri = example.metadata[:pactfile_uri]
101
110
  cmd.gsub!("<PACT_URI>", pactfile_uri.to_s)
102
111
  cmd.gsub!("<PACT_DESCRIPTION>", description)
103
112
  cmd.gsub!("<PACT_PROVIDER_STATE>", "#{provider_state}")
113
+ cmd.gsub!("<PACT_INTERACTION_INDEX>", "#{index}")
104
114
  colorizer.wrap("#{cmd} ", ::RSpec.configuration.failure_color) + colorizer.wrap("# #{example_description}", ::RSpec.configuration.detail_color)
105
115
  else
106
- colorizer.wrap("* #{example_description}", ::RSpec.configuration.failure_color)
116
+ message = if _id
117
+ "* #{example_description} (to re-run just this interaction, set environment variable PACT_BROKER_INTERACTION_ID=\"#{_id}\")"
118
+ else
119
+ "* #{example_description} (to re-run just this interaction, set environment variables PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\")"
120
+ end
121
+ colorizer.wrap(message, ::RSpec.configuration.failure_color)
107
122
  end
108
123
  end
109
124
 
@@ -8,19 +8,21 @@ module Pact
8
8
 
9
9
  def dump_summary(summary)
10
10
  super(create_custom_summary(summary))
11
- output_hash[:summary][:notices] = pact_broker_notices(summary)
11
+ output_hash[:summary][:pacts] = pacts(summary)
12
12
  end
13
13
 
14
14
  def format_example(example)
15
15
  {
16
16
  :id => example.id,
17
+ :interaction_index => example.metadata[:pact_interaction].index,
17
18
  :description => example.description,
18
19
  :full_description => example.full_description,
19
20
  :status => calculate_status(example),
20
21
  :file_path => example.metadata[:file_path],
21
22
  :line_number => example.metadata[:line_number],
22
23
  :run_time => example.execution_result.run_time,
23
- :mismatches => extract_differences(example)
24
+ :mismatches => extract_differences(example),
25
+ :pact_url => example.metadata[:pact_uri].uri
24
26
  }
25
27
  end
26
28
 
@@ -28,13 +30,15 @@ module Pact
28
30
  output_hash[:examples] = notification.examples.map do |example|
29
31
  format_example(example).tap do |hash|
30
32
  e = example.exception
31
- # No point providing a backtrace for a mismatch, too much noise
32
- if e && ! e.is_a?(::RSpec::Expectations::ExpectationNotMetError)
33
+ if e
33
34
  hash[:exception] = {
34
- :class => e.class.name,
35
- :message => e.message,
36
- :backtrace => e.backtrace,
35
+ class: e.class.name,
36
+ message: e.message,
37
37
  }
38
+ # No point providing a backtrace for a mismatch, too much noise
39
+ if !e.is_a?(::RSpec::Expectations::ExpectationNotMetError)
40
+ hash[:exception][:backtrace]
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -54,12 +58,22 @@ module Pact
54
58
  # If the JSON formatter is used by someone else and they have multiple pacts, all the notices
55
59
  # for the pacts will be mushed together in one collection, so it will be hard to know which notice
56
60
  # belongs to which pact.
57
- def pact_broker_notices(summary)
58
- pact_uris(summary).collect{ |pact_uri| pact_uri.metadata[:notices] }.compact.flatten
61
+ def pacts(summary)
62
+ unique_pact_metadatas(summary).collect do | example_metadata |
63
+ pact_uri = example_metadata[:pact_uri]
64
+ notices = (pact_uri.metadata[:notices] && pact_uri.metadata[:notices].before_verification_notices) || []
65
+ {
66
+ notices: notices,
67
+ url: pact_uri.uri,
68
+ consumer_name: example_metadata[:pact_consumer_contract].consumer.name,
69
+ provider_name: example_metadata[:pact_consumer_contract].provider.name,
70
+ short_description: pact_uri.metadata[:short_description]
71
+ }
72
+ end
59
73
  end
60
74
 
61
- def pact_uris(summary)
62
- summary.examples.collect(&:metadata).collect{ |metadata| metadata[:pact_uri] }.uniq
75
+ def unique_pact_metadatas(summary)
76
+ summary.examples.collect(&:metadata).group_by{ | metadata | metadata[:pact_uri].uri }.values.collect(&:first)
63
77
  end
64
78
 
65
79
  def create_custom_summary(summary)
@@ -21,16 +21,20 @@ module Pact
21
21
 
22
22
  include ::RSpec::Core::DSL
23
23
 
24
- def honour_pactfile pact_uri, pact_json, options
24
+ def honour_pactfile pact_source, pact_json, options
25
+ pact_uri = pact_source.uri
25
26
  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[:text]}")
27
+ if pact_uri.metadata[:notices]
28
+ pact_uri.metadata[:notices].before_verification_notices_text.each do | text |
29
+ Pact.configuration.output_stream.puts("DEBUG: #{text}")
30
+ end
28
31
  end
32
+
29
33
  Pact.configuration.output_stream.puts "DEBUG: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
30
34
  consumer_contract = Pact::ConsumerContract.from_json(pact_json)
31
35
  suffix = pact_uri.metadata[:pending] ? " [PENDING]": ""
32
36
  ::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}#{suffix}", pactfile_uri: pact_uri do
33
- honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri)
37
+ honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri, pact_source: pact_source, consumer_contract: consumer_contract)
34
38
  end
35
39
  end
36
40
 
@@ -78,7 +82,9 @@ module Pact
78
82
  pact_interaction: interaction,
79
83
  pact_interaction_example_description: interaction_description_for_rerun_command(interaction),
80
84
  pact_uri: options[:pact_uri],
81
- pact_ignore_failures: options[:pact_uri].metadata[:pending] || options[:ignore_failures]
85
+ pact_source: options[:pact_source],
86
+ pact_ignore_failures: options[:pact_uri].metadata[:pending] || options[:ignore_failures],
87
+ pact_consumer_contract: options[:consumer_contract]
82
88
  }
83
89
 
84
90
  describe description_for(interaction), metadata do
@@ -21,7 +21,11 @@ module Pact
21
21
 
22
22
  logger.info "Sending #{request.method.upcase} request to path: \"#{request.path}\" with headers: #{request.headers}, see debug logs for body"
23
23
  logger.debug "body :#{request.body}"
24
- response = self.send(request.method.downcase, *args)
24
+ response = if self.respond_to?(:custom_request)
25
+ self.custom_request(request.method.upcase, *args)
26
+ else
27
+ self.send(request.method.downcase, *args)
28
+ end
25
29
  logger.info "Received response with status: #{response.status}, headers: #{response.headers}, see debug logs for body"
26
30
  logger.debug "body: #{response.body}"
27
31
  end
@@ -29,7 +33,9 @@ module Pact
29
33
  def parse_body_from_response rack_response
30
34
  case rack_response.headers['Content-Type']
31
35
  when /json/
32
- JSON.load(rack_response.body)
36
+ # For https://github.com/pact-foundation/pact-net/issues/237
37
+ # Only required for the pact-ruby-standalone ¯\_(ツ)_/¯
38
+ JSON.load("[#{rack_response.body}]").first
33
39
  else
34
40
  rack_response.body
35
41
  end
@@ -33,6 +33,9 @@ module Pact
33
33
  if can_publish_verification_results?
34
34
  tag_versions_if_configured
35
35
  publish_verification_results
36
+ true
37
+ else
38
+ false
36
39
  end
37
40
  end
38
41
 
@@ -17,7 +17,12 @@ module Pact
17
17
 
18
18
  def call
19
19
  verification_results.collect do | (pact_source, verification_result) |
20
- Publish.call(pact_source, verification_result)
20
+ published = false
21
+ begin
22
+ published = Publish.call(pact_source, verification_result)
23
+ ensure
24
+ print_after_verification_notices(pact_source, verification_result, published)
25
+ end
21
26
  end
22
27
  end
23
28
 
@@ -29,6 +34,14 @@ module Pact
29
34
  end
30
35
  end
31
36
 
37
+ def print_after_verification_notices(pact_source, verification_result, published)
38
+ if pact_source.uri.metadata[:notices]
39
+ pact_source.uri.metadata[:notices].after_verification_notices_text(verification_result.success, published).each do | text |
40
+ Pact.configuration.output_stream.puts "DEBUG: #{text}"
41
+ end
42
+ end
43
+ end
44
+
32
45
  attr_reader :pact_sources, :test_results_hash
33
46
  end
34
47
  end
@@ -4,6 +4,7 @@ module Pact
4
4
  module Provider
5
5
  module VerificationResults
6
6
  class VerificationResult
7
+ attr_reader :success, :provider_application_version, :test_results_hash
7
8
 
8
9
  def initialize publishable, success, provider_application_version, test_results_hash
9
10
  @publishable = publishable
@@ -31,10 +32,6 @@ module Pact
31
32
  def to_s
32
33
  "[success: #{success}, providerApplicationVersion: #{provider_application_version}]"
33
34
  end
34
-
35
- private
36
-
37
- attr_reader :success, :provider_application_version, :test_results_hash
38
35
  end
39
36
  end
40
37
  end
@@ -7,6 +7,7 @@ module Pact
7
7
  module TaskHelper
8
8
 
9
9
  PACT_INTERACTION_RERUN_COMMAND = "bundle exec rake pact:verify:at[<PACT_URI>] PACT_DESCRIPTION=\"<PACT_DESCRIPTION>\" PACT_PROVIDER_STATE=\"<PACT_PROVIDER_STATE>\""
10
+ PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER = "bundle exec rake pact:verify:at[<PACT_URI>] PACT_BROKER_INTERACTION_ID=\"<PACT_BROKER_INTERACTION_ID>\""
10
11
 
11
12
  extend self
12
13
 
@@ -34,6 +35,8 @@ module Pact
34
35
  command_parts << "--backtrace" if ENV['BACKTRACE'] == 'true'
35
36
  command_parts << "--description #{Shellwords.escape(ENV['PACT_DESCRIPTION'])}" if ENV['PACT_DESCRIPTION']
36
37
  command_parts << "--provider-state #{Shellwords.escape(ENV['PACT_PROVIDER_STATE'])}" if ENV['PACT_PROVIDER_STATE']
38
+ command_parts << "--pact-broker-interaction-id #{Shellwords.escape(ENV['PACT_BROKER_INTERACTION_ID'])}" if ENV['PACT_BROKER_INTERACTION_ID']
39
+ command_parts << "--interaction-index #{Shellwords.escape(ENV['PACT_INTERACTION_INDEX'])}" if ENV['PACT_INTERACTION_INDEX']
37
40
  command_parts.flatten.join(" ")
38
41
  end
39
42
 
@@ -41,7 +44,9 @@ module Pact
41
44
  Pact.configuration.output_stream.puts command
42
45
  temporarily_set_env_var 'PACT_EXECUTING_LANGUAGE', 'ruby' do
43
46
  temporarily_set_env_var 'PACT_INTERACTION_RERUN_COMMAND', PACT_INTERACTION_RERUN_COMMAND do
44
- exit_status = system(command) ? 0 : 1
47
+ temporarily_set_env_var 'PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER', PACT_INTERACTION_RERUN_COMMAND_FOR_BROKER do
48
+ exit_status = system(command) ? 0 : 1
49
+ end
45
50
  end
46
51
  end
47
52
  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.46.1"
3
+ VERSION = "1.53.0"
4
4
  end
data/pact.gemspec CHANGED
@@ -28,14 +28,14 @@ Gem::Specification.new do |gem|
28
28
 
29
29
  gem.add_runtime_dependency 'rspec', '~> 3.0'
30
30
  gem.add_runtime_dependency 'rack-test', '>= 0.6.3', '< 2.0.0'
31
- gem.add_runtime_dependency 'thor', '~> 0.20'
31
+ gem.add_runtime_dependency 'thor', '>= 0.20', '< 2.0'
32
32
  gem.add_runtime_dependency 'webrick', '~> 1.3'
33
33
  gem.add_runtime_dependency 'term-ansicolor', '~> 1.0'
34
34
 
35
35
  gem.add_runtime_dependency 'pact-support', '~> 1.9'
36
36
  gem.add_runtime_dependency 'pact-mock_service', '~> 3.0', '>= 3.3.1'
37
37
 
38
- gem.add_development_dependency 'rake', '~> 10.0'
38
+ gem.add_development_dependency 'rake', '~> 13.0'
39
39
  gem.add_development_dependency 'webmock', '~> 3.0'
40
40
  gem.add_development_dependency 'fakefs', '0.5' # 0.6.0 blows up
41
41
  gem.add_development_dependency 'hashie', '~> 2.0'
@@ -44,4 +44,5 @@ Gem::Specification.new do |gem|
44
44
  gem.add_development_dependency 'conventional-changelog', '~> 1.3'
45
45
  gem.add_development_dependency 'bump', '~> 0.5'
46
46
  gem.add_development_dependency 'pact-message', '~> 0.6'
47
+ gem.add_development_dependency 'rspec-its', '~> 1.3'
47
48
  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.46.1
4
+ version: 1.53.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Fraser
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2020-01-22 00:00:00.000000000 Z
15
+ date: 2020-09-11 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rspec
@@ -52,16 +52,22 @@ dependencies:
52
52
  name: thor
53
53
  requirement: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - "~>"
55
+ - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: '0.20'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
58
61
  type: :runtime
59
62
  prerelease: false
60
63
  version_requirements: !ruby/object:Gem::Requirement
61
64
  requirements:
62
- - - "~>"
65
+ - - ">="
63
66
  - !ruby/object:Gem::Version
64
67
  version: '0.20'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '2.0'
65
71
  - !ruby/object:Gem::Dependency
66
72
  name: webrick
67
73
  requirement: !ruby/object:Gem::Requirement
@@ -130,14 +136,14 @@ dependencies:
130
136
  requirements:
131
137
  - - "~>"
132
138
  - !ruby/object:Gem::Version
133
- version: '10.0'
139
+ version: '13.0'
134
140
  type: :development
135
141
  prerelease: false
136
142
  version_requirements: !ruby/object:Gem::Requirement
137
143
  requirements:
138
144
  - - "~>"
139
145
  - !ruby/object:Gem::Version
140
- version: '10.0'
146
+ version: '13.0'
141
147
  - !ruby/object:Gem::Dependency
142
148
  name: webmock
143
149
  requirement: !ruby/object:Gem::Requirement
@@ -250,6 +256,20 @@ dependencies:
250
256
  - - "~>"
251
257
  - !ruby/object:Gem::Version
252
258
  version: '0.6'
259
+ - !ruby/object:Gem::Dependency
260
+ name: rspec-its
261
+ requirement: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - "~>"
264
+ - !ruby/object:Gem::Version
265
+ version: '1.3'
266
+ type: :development
267
+ prerelease: false
268
+ version_requirements: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - "~>"
271
+ - !ruby/object:Gem::Version
272
+ version: '1.3'
253
273
  description: Enables consumer driven contract testing, providing a mock service and
254
274
  DSL for the consumer project, and interaction playback and verification for the
255
275
  service provider project.
@@ -304,6 +324,8 @@ files:
304
324
  - lib/pact/pact_broker.rb
305
325
  - lib/pact/pact_broker/fetch_pact_uris_for_verification.rb
306
326
  - lib/pact/pact_broker/fetch_pacts.rb
327
+ - lib/pact/pact_broker/notices.rb
328
+ - lib/pact/pact_broker/pact_selection_description.rb
307
329
  - lib/pact/project_root.rb
308
330
  - lib/pact/provider.rb
309
331
  - lib/pact/provider/configuration.rb
@@ -381,8 +403,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
381
403
  - !ruby/object:Gem::Version
382
404
  version: '0'
383
405
  requirements: []
384
- rubyforge_project:
385
- rubygems_version: 2.7.7
406
+ rubygems_version: 3.1.4
386
407
  signing_key:
387
408
  specification_version: 4
388
409
  summary: Enables consumer driven contract testing, providing a mock service and DSL