Skip to content

Commit

Permalink
feat: add pact metadata to json formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Feb 6, 2020
1 parent a771b75 commit 6c6ddb8
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 23 deletions.
13 changes: 8 additions & 5 deletions lib/pact/pact_broker/fetch_pact_uris_for_verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down
34 changes: 34 additions & 0 deletions lib/pact/pact_broker/notices.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion lib/pact/provider/pact_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Pact
module Provider
class PactSource

attr_reader :uri
attr_reader :uri # PactURI class

def initialize uri
@uri = uri
Expand Down
2 changes: 1 addition & 1 deletion lib/pact/provider/pact_spec_runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
16 changes: 11 additions & 5 deletions lib/pact/provider/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
21 changes: 17 additions & 4 deletions lib/pact/provider/rspec/json_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions lib/pact/provider/verification_results/publish.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def call
if can_publish_verification_results?
tag_versions_if_configured
publish_verification_results
true
else
false
end
end

Expand Down
15 changes: 14 additions & 1 deletion lib/pact/provider/verification_results/publish_all.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions pact.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 4 additions & 1 deletion spec/integration/publish_verification_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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' => [{}],
Expand Down
58 changes: 58 additions & 0 deletions spec/lib/pact/pact_broker/notices_spec.rb
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
body: {
"_embedded" => {
"pacts" => [{
"shortDescription" => "a description",
"verificationProperties" => {
"pending" => Pact.like(true),
"notices" => Pact.each_like("text" => "some text")
Expand All @@ -94,7 +95,8 @@
pending: true,
notices: [
text: "some text"
]
],
short_description: "a description"
}
end

Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'rspec'
require 'rspec/its'
require 'fakefs/spec_helpers'
require 'pact'
require 'webmock/rspec'
Expand Down

0 comments on commit 6c6ddb8

Please sign in to comment.