diff --git a/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb b/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb index 125993ec..166c5f96 100644 --- a/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +++ b/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb @@ -3,6 +3,7 @@ require 'pact/provider/pact_uri' require 'pact/errors' require 'pact/pact_broker/fetch_pacts' +require 'pact/pact_broker/notices' module Pact module PactBroker @@ -51,7 +52,8 @@ def pacts_for_verification pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact | metadata = { pending: pact["verificationProperties"]["pending"], - notices: extract_notices(pact) + notices: extract_notices(pact), + short_description: pact["shortDescription"] } Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata) end @@ -69,11 +71,12 @@ def query q["includePendingStatus"] = true if options[:include_pending_status] q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any? q["providerVersionTags"] = provider_version_tags if provider_version_tags.any? + q["includeWipPactsSince"] = options[:include_wip_pacts_since] if options[:include_wip_pacts_since] q end def extract_notices(pact) - (pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) }.compact + Notices.new((pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) }) end def symbolize_keys(hash) @@ -82,15 +85,15 @@ def symbolize_keys(hash) def log_message latest = consumer_version_selectors.any? ? "" : "latest " - message = "INFO: Fetching #{latest}pacts for #{provider} from #{broker_base_url}" + message = "INFO: Fetching pacts for #{provider} from #{broker_base_url} with the selection criteria: " if consumer_version_selectors.any? desc = consumer_version_selectors.collect do |selector| - all_or_latest = selector[:all] ? "all" : "latest" + all_or_latest = selector[:all] ? "all for tag" : "latest for tag" # TODO support fallback name = selector[:fallback] ? "#{selector[:tag]} (or #{selector[:fallback]} if not found)" : selector[:tag] "#{all_or_latest} #{name}" end.join(", ") - message << " for tags: #{desc}" + message << ": #{desc}" end Pact.configuration.output_stream.puts message end diff --git a/lib/pact/pact_broker/notices.rb b/lib/pact/pact_broker/notices.rb new file mode 100644 index 00000000..4d854bcf --- /dev/null +++ b/lib/pact/pact_broker/notices.rb @@ -0,0 +1,34 @@ +module Pact + module PactBroker + class Notices < Array + def before_verification_notices + select { | notice | notice[:when].nil? || notice[:when].start_with?('before_verification') } + end + + def before_verification_notices_text + before_verification_notices.collect{ | notice | notice[:text] } + end + + def after_verification_notices(success, published) + select { | notice | notice[:when] == "after_verification:success_#{success}_published_#{published}" || notice[:when] == "after_verification" } + .collect do | notice | + notice.merge(:when => simplify_notice_when(notice[:when])) + end + end + + def after_verification_notices_text(success, published) + after_verification_notices(success, published).collect{ | notice | notice[:text] } + end + + def all_notices(success, published) + before_verification_notices + after_verification_notices(success, published) + end + + private + + def simplify_notice_when(when_key) + when_key.split(":").first + end + end + end +end diff --git a/lib/pact/provider/pact_source.rb b/lib/pact/provider/pact_source.rb index 4d06d30c..5b29c92c 100644 --- a/lib/pact/provider/pact_source.rb +++ b/lib/pact/provider/pact_source.rb @@ -6,7 +6,7 @@ module Pact module Provider class PactSource - attr_reader :uri + attr_reader :uri # PactURI class def initialize uri @uri = uri diff --git a/lib/pact/provider/pact_spec_runner.rb b/lib/pact/provider/pact_spec_runner.rb index faaa5f46..e85a443a 100644 --- a/lib/pact/provider/pact_spec_runner.rb +++ b/lib/pact/provider/pact_spec_runner.rb @@ -122,7 +122,7 @@ def initialize_specs ignore_failures: options[:ignore_failures], request_customizer: options[:request_customizer] } - honour_pactfile pact_source.uri, ordered_pact_json(pact_source.pact_json), spec_options + honour_pactfile pact_source, ordered_pact_json(pact_source.pact_json), spec_options end end diff --git a/lib/pact/provider/rspec.rb b/lib/pact/provider/rspec.rb index 62fc30a7..6a8f2556 100644 --- a/lib/pact/provider/rspec.rb +++ b/lib/pact/provider/rspec.rb @@ -21,16 +21,20 @@ module ClassMethods include ::RSpec::Core::DSL - def honour_pactfile pact_uri, pact_json, options + def honour_pactfile pact_source, pact_json, options + pact_uri = pact_source.uri Pact.configuration.output_stream.puts "INFO: Reading pact at #{pact_uri}" - (pact_uri.metadata[:notices] || EMPTY_ARRAY).each do | notice | - Pact.configuration.output_stream.puts("DEBUG: #{notice[:text]}") + if pact_uri.metadata[:notices] + pact_uri.metadata[:notices].before_verification_notices_text.each do | text | + Pact.configuration.output_stream.puts("DEBUG: #{text}") + end end + Pact.configuration.output_stream.puts "DEBUG: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any? consumer_contract = Pact::ConsumerContract.from_json(pact_json) suffix = pact_uri.metadata[:pending] ? " [PENDING]": "" ::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}#{suffix}", pactfile_uri: pact_uri do - honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri) + honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json, pact_uri: pact_uri, pact_source: pact_source, consumer_contract: consumer_contract) end end @@ -78,7 +82,9 @@ def describe_interaction interaction, options pact_interaction: interaction, pact_interaction_example_description: interaction_description_for_rerun_command(interaction), pact_uri: options[:pact_uri], - pact_ignore_failures: options[:pact_uri].metadata[:pending] || options[:ignore_failures] + pact_source: options[:pact_source], + pact_ignore_failures: options[:pact_uri].metadata[:pending] || options[:ignore_failures], + pact_consumer_contract: options[:consumer_contract] } describe description_for(interaction), metadata do diff --git a/lib/pact/provider/rspec/json_formatter.rb b/lib/pact/provider/rspec/json_formatter.rb index 3260f3ab..5fa48b1c 100644 --- a/lib/pact/provider/rspec/json_formatter.rb +++ b/lib/pact/provider/rspec/json_formatter.rb @@ -8,19 +8,26 @@ class JsonFormatter < ::RSpec::Core::Formatters::JsonFormatter def dump_summary(summary) super(create_custom_summary(summary)) - output_hash[:summary][:notices] = pact_broker_notices(summary) + output_hash[:summary][:pacts] = pacts(summary) end def format_example(example) { :id => example.id, + :interaction_index => example.metadata[:pact_interaction].index, :description => example.description, :full_description => example.full_description, :status => calculate_status(example), :file_path => example.metadata[:file_path], :line_number => example.metadata[:line_number], :run_time => example.execution_result.run_time, - :mismatches => extract_differences(example) + :mismatches => extract_differences(example), + :pact => { + consumer_name: example.metadata[:pact_consumer_contract].consumer.name, + provider_name: example.metadata[:pact_consumer_contract].provider.name, + url: example.metadata[:pact_uri].uri, + short_description: example.metadata[:pact_uri].metadata[:short_description] + } } end @@ -54,8 +61,14 @@ def calculate_status(example) # If the JSON formatter is used by someone else and they have multiple pacts, all the notices # for the pacts will be mushed together in one collection, so it will be hard to know which notice # belongs to which pact. - def pact_broker_notices(summary) - pact_uris(summary).collect{ |pact_uri| pact_uri.metadata[:notices] }.compact.flatten + def pacts(summary) + pact_uris(summary).collect do | pact_uri | + notices = (pact_uri.metadata[:notices] && pact_uri.metadata[:notices].before_verification_notices) || [] + { + notices: notices, + url: pact_uri.uri + } + end end def pact_uris(summary) diff --git a/lib/pact/provider/verification_results/publish.rb b/lib/pact/provider/verification_results/publish.rb index f0eecd0c..3fdd1cfa 100644 --- a/lib/pact/provider/verification_results/publish.rb +++ b/lib/pact/provider/verification_results/publish.rb @@ -33,6 +33,9 @@ def call if can_publish_verification_results? tag_versions_if_configured publish_verification_results + true + else + false end end diff --git a/lib/pact/provider/verification_results/publish_all.rb b/lib/pact/provider/verification_results/publish_all.rb index 61891e1d..46312cea 100644 --- a/lib/pact/provider/verification_results/publish_all.rb +++ b/lib/pact/provider/verification_results/publish_all.rb @@ -17,7 +17,12 @@ def initialize pact_sources, test_results_hash def call verification_results.collect do | (pact_source, verification_result) | - Publish.call(pact_source, verification_result) + published = false + begin + published = Publish.call(pact_source, verification_result) + ensure + print_after_verification_notices(pact_source, verification_result, published) + end end end @@ -29,6 +34,14 @@ def verification_results end end + def print_after_verification_notices(pact_source, verification_result, published) + if pact_source.uri.metadata[:notices] + pact_source.uri.metadata[:notices].after_verification_notices_text(verification_result.success, published).each do | text | + Pact.configuration.output_stream.puts "DEBUG: #{text}" + end + end + end + attr_reader :pact_sources, :test_results_hash end end diff --git a/lib/pact/provider/verification_results/verification_result.rb b/lib/pact/provider/verification_results/verification_result.rb index a39f8ade..4e746cb9 100644 --- a/lib/pact/provider/verification_results/verification_result.rb +++ b/lib/pact/provider/verification_results/verification_result.rb @@ -4,6 +4,7 @@ module Pact module Provider module VerificationResults class VerificationResult + attr_reader :success, :provider_application_version, :test_results_hash def initialize publishable, success, provider_application_version, test_results_hash @publishable = publishable @@ -31,10 +32,6 @@ def to_json(options = {}) def to_s "[success: #{success}, providerApplicationVersion: #{provider_application_version}]" end - - private - - attr_reader :success, :provider_application_version, :test_results_hash end end end diff --git a/pact.gemspec b/pact.gemspec index 4a8f9b67..0a063042 100644 --- a/pact.gemspec +++ b/pact.gemspec @@ -44,4 +44,5 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'conventional-changelog', '~> 1.3' gem.add_development_dependency 'bump', '~> 0.5' gem.add_development_dependency 'pact-message', '~> 0.6' + gem.add_development_dependency 'rspec-its', '~> 1.3' end diff --git a/spec/integration/publish_verification_spec.rb b/spec/integration/publish_verification_spec.rb index b5a467c3..088974e8 100644 --- a/spec/integration/publish_verification_spec.rb +++ b/spec/integration/publish_verification_spec.rb @@ -20,9 +20,12 @@ end let(:pact_uri) do - instance_double('Pact::Provider::PactURI', uri: 'pact.json', options: {}) + instance_double('Pact::Provider::PactURI', uri: 'pact.json', options: {}, metadata: metadata) end + let(:metadata) { { notices: notices} } + let(:notices) { instance_double('Pact::PactBroker::Notices', after_verification_notices_text: ['hello'] ) } + let(:pact_hash) do { 'interactions' => [{}], diff --git a/spec/lib/pact/pact_broker/notices_spec.rb b/spec/lib/pact/pact_broker/notices_spec.rb new file mode 100644 index 00000000..31a69e86 --- /dev/null +++ b/spec/lib/pact/pact_broker/notices_spec.rb @@ -0,0 +1,58 @@ +require 'pact/pact_broker/notices' + +module Pact + module PactBroker + describe Notices do + + let(:notice_hashes) do + [ + { text: "foo", when: "before_verification" } + ] + end + + subject(:notices) { Notices.new(notice_hashes) } + + it "behaves like an array" do + expect(subject.size).to eq notice_hashes.size + end + + describe "before_verification_notices" do + let(:notice_hashes) do + [ + { text: "foo", when: "before_verification" }, + { text: "bar", when: "blah" }, + ] + end + + its(:before_verification_notices_text) { is_expected.to eq [ "foo" ] } + end + + describe "after_verification_notices_text" do + let(:notice_hashes) do + [ + { text: "foo", when: "after_verification:success_false_published_true" }, + { text: "bar", when: "blah" }, + ] + end + + subject { notices.after_verification_notices_text(false, true) } + + it { is_expected.to eq [ "foo" ] } + end + + describe "after_verification_notices" do + let(:notice_hashes) do + [ + { text: "meep", when: "after_verification" }, + { text: "foo", when: "after_verification:success_false_published_true" }, + { text: "bar", when: "blah" }, + ] + end + + subject { notices.after_verification_notices(false, true) } + + it { is_expected.to eq [{ text: "meep", when: "after_verification" }, { text: "foo", when: "after_verification" }] } + end + end + end +end diff --git a/spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb b/spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb index 4c762acb..1eec32d4 100644 --- a/spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb +++ b/spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb @@ -74,6 +74,7 @@ body: { "_embedded" => { "pacts" => [{ + "shortDescription" => "a description", "verificationProperties" => { "pending" => Pact.like(true), "notices" => Pact.each_like("text" => "some text") @@ -94,7 +95,8 @@ pending: true, notices: [ text: "some text" - ] + ], + short_description: "a description" } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8b316a0f..9800ca85 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,5 @@ require 'rspec' +require 'rspec/its' require 'fakefs/spec_helpers' require 'pact' require 'webmock/rspec'