Skip to content

Commit 6c6ddb8

Browse files
committedFeb 6, 2020
feat: add pact metadata to json formatter
1 parent a771b75 commit 6c6ddb8

14 files changed

+157
-23
lines changed
 

‎lib/pact/pact_broker/fetch_pact_uris_for_verification.rb

+8-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'pact/provider/pact_uri'
44
require 'pact/errors'
55
require 'pact/pact_broker/fetch_pacts'
6+
require 'pact/pact_broker/notices'
67

78
module Pact
89
module PactBroker
@@ -51,7 +52,8 @@ def pacts_for_verification
5152
pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact |
5253
metadata = {
5354
pending: pact["verificationProperties"]["pending"],
54-
notices: extract_notices(pact)
55+
notices: extract_notices(pact),
56+
short_description: pact["shortDescription"]
5557
}
5658
Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata)
5759
end
@@ -69,11 +71,12 @@ def query
6971
q["includePendingStatus"] = true if options[:include_pending_status]
7072
q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any?
7173
q["providerVersionTags"] = provider_version_tags if provider_version_tags.any?
74+
q["includeWipPactsSince"] = options[:include_wip_pacts_since] if options[:include_wip_pacts_since]
7275
q
7376
end
7477

7578
def extract_notices(pact)
76-
(pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) }.compact
79+
Notices.new((pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) })
7780
end
7881

7982
def symbolize_keys(hash)
@@ -82,15 +85,15 @@ def symbolize_keys(hash)
8285

8386
def log_message
8487
latest = consumer_version_selectors.any? ? "" : "latest "
85-
message = "INFO: Fetching #{latest}pacts for #{provider} from #{broker_base_url}"
88+
message = "INFO: Fetching pacts for #{provider} from #{broker_base_url} with the selection criteria: "
8689
if consumer_version_selectors.any?
8790
desc = consumer_version_selectors.collect do |selector|
88-
all_or_latest = selector[:all] ? "all" : "latest"
91+
all_or_latest = selector[:all] ? "all for tag" : "latest for tag"
8992
# TODO support fallback
9093
name = selector[:fallback] ? "#{selector[:tag]} (or #{selector[:fallback]} if not found)" : selector[:tag]
9194
"#{all_or_latest} #{name}"
9295
end.join(", ")
93-
message << " for tags: #{desc}"
96+
message << ": #{desc}"
9497
end
9598
Pact.configuration.output_stream.puts message
9699
end

‎lib/pact/pact_broker/notices.rb

+34
Original file line numberDiff line numberDiff line change
@@ -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

‎lib/pact/provider/pact_source.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module Pact
66
module Provider
77
class PactSource
88

9-
attr_reader :uri
9+
attr_reader :uri # PactURI class
1010

1111
def initialize uri
1212
@uri = uri

‎lib/pact/provider/pact_spec_runner.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def initialize_specs
122122
ignore_failures: options[:ignore_failures],
123123
request_customizer: options[:request_customizer]
124124
}
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
126126
end
127127
end
128128

‎lib/pact/provider/rspec.rb

+11-5
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,20 @@ module ClassMethods
2121

2222
include ::RSpec::Core::DSL
2323

24-
def honour_pactfile pact_uri, pact_json, options
24+
def honour_pactfile pact_source, pact_json, options
25+
pact_uri = pact_source.uri
2526
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
2831
end
32+
2933
Pact.configuration.output_stream.puts "DEBUG: Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
3034
consumer_contract = Pact::ConsumerContract.from_json(pact_json)
3135
suffix = pact_uri.metadata[:pending] ? " [PENDING]": ""
3236
::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)
3438
end
3539
end
3640

@@ -78,7 +82,9 @@ def describe_interaction interaction, options
7882
pact_interaction: interaction,
7983
pact_interaction_example_description: interaction_description_for_rerun_command(interaction),
8084
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]
8288
}
8389

8490
describe description_for(interaction), metadata do

‎lib/pact/provider/rspec/json_formatter.rb

+17-4
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,26 @@ class JsonFormatter < ::RSpec::Core::Formatters::JsonFormatter
88

99
def dump_summary(summary)
1010
super(create_custom_summary(summary))
11-
output_hash[:summary][:notices] = pact_broker_notices(summary)
11+
output_hash[:summary][:pacts] = pacts(summary)
1212
end
1313

1414
def format_example(example)
1515
{
1616
:id => example.id,
17+
:interaction_index => example.metadata[:pact_interaction].index,
1718
:description => example.description,
1819
:full_description => example.full_description,
1920
:status => calculate_status(example),
2021
:file_path => example.metadata[:file_path],
2122
:line_number => example.metadata[:line_number],
2223
:run_time => example.execution_result.run_time,
23-
:mismatches => extract_differences(example)
24+
:mismatches => extract_differences(example),
25+
:pact => {
26+
consumer_name: example.metadata[:pact_consumer_contract].consumer.name,
27+
provider_name: example.metadata[:pact_consumer_contract].provider.name,
28+
url: example.metadata[:pact_uri].uri,
29+
short_description: example.metadata[:pact_uri].metadata[:short_description]
30+
}
2431
}
2532
end
2633

@@ -54,8 +61,14 @@ def calculate_status(example)
5461
# If the JSON formatter is used by someone else and they have multiple pacts, all the notices
5562
# for the pacts will be mushed together in one collection, so it will be hard to know which notice
5663
# belongs to which pact.
57-
def pact_broker_notices(summary)
58-
pact_uris(summary).collect{ |pact_uri| pact_uri.metadata[:notices] }.compact.flatten
64+
def pacts(summary)
65+
pact_uris(summary).collect do | pact_uri |
66+
notices = (pact_uri.metadata[:notices] && pact_uri.metadata[:notices].before_verification_notices) || []
67+
{
68+
notices: notices,
69+
url: pact_uri.uri
70+
}
71+
end
5972
end
6073

6174
def pact_uris(summary)

‎lib/pact/provider/verification_results/publish.rb

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ def call
3333
if can_publish_verification_results?
3434
tag_versions_if_configured
3535
publish_verification_results
36+
true
37+
else
38+
false
3639
end
3740
end
3841

‎lib/pact/provider/verification_results/publish_all.rb

+14-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ def initialize pact_sources, test_results_hash
1717

1818
def call
1919
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
2126
end
2227
end
2328

@@ -29,6 +34,14 @@ def verification_results
2934
end
3035
end
3136

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+
3245
attr_reader :pact_sources, :test_results_hash
3346
end
3447
end

‎lib/pact/provider/verification_results/verification_result.rb

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Pact
44
module Provider
55
module VerificationResults
66
class VerificationResult
7+
attr_reader :success, :provider_application_version, :test_results_hash
78

89
def initialize publishable, success, provider_application_version, test_results_hash
910
@publishable = publishable
@@ -31,10 +32,6 @@ def to_json(options = {})
3132
def to_s
3233
"[success: #{success}, providerApplicationVersion: #{provider_application_version}]"
3334
end
34-
35-
private
36-
37-
attr_reader :success, :provider_application_version, :test_results_hash
3835
end
3936
end
4037
end

‎pact.gemspec

+1
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ Gem::Specification.new do |gem|
4444
gem.add_development_dependency 'conventional-changelog', '~> 1.3'
4545
gem.add_development_dependency 'bump', '~> 0.5'
4646
gem.add_development_dependency 'pact-message', '~> 0.6'
47+
gem.add_development_dependency 'rspec-its', '~> 1.3'
4748
end

‎spec/integration/publish_verification_spec.rb

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
end
2121

2222
let(:pact_uri) do
23-
instance_double('Pact::Provider::PactURI', uri: 'pact.json', options: {})
23+
instance_double('Pact::Provider::PactURI', uri: 'pact.json', options: {}, metadata: metadata)
2424
end
2525

26+
let(:metadata) { { notices: notices} }
27+
let(:notices) { instance_double('Pact::PactBroker::Notices', after_verification_notices_text: ['hello'] ) }
28+
2629
let(:pact_hash) do
2730
{
2831
'interactions' => [{}],
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
require 'pact/pact_broker/notices'
2+
3+
module Pact
4+
module PactBroker
5+
describe Notices do
6+
7+
let(:notice_hashes) do
8+
[
9+
{ text: "foo", when: "before_verification" }
10+
]
11+
end
12+
13+
subject(:notices) { Notices.new(notice_hashes) }
14+
15+
it "behaves like an array" do
16+
expect(subject.size).to eq notice_hashes.size
17+
end
18+
19+
describe "before_verification_notices" do
20+
let(:notice_hashes) do
21+
[
22+
{ text: "foo", when: "before_verification" },
23+
{ text: "bar", when: "blah" },
24+
]
25+
end
26+
27+
its(:before_verification_notices_text) { is_expected.to eq [ "foo" ] }
28+
end
29+
30+
describe "after_verification_notices_text" do
31+
let(:notice_hashes) do
32+
[
33+
{ text: "foo", when: "after_verification:success_false_published_true" },
34+
{ text: "bar", when: "blah" },
35+
]
36+
end
37+
38+
subject { notices.after_verification_notices_text(false, true) }
39+
40+
it { is_expected.to eq [ "foo" ] }
41+
end
42+
43+
describe "after_verification_notices" do
44+
let(:notice_hashes) do
45+
[
46+
{ text: "meep", when: "after_verification" },
47+
{ text: "foo", when: "after_verification:success_false_published_true" },
48+
{ text: "bar", when: "blah" },
49+
]
50+
end
51+
52+
subject { notices.after_verification_notices(false, true) }
53+
54+
it { is_expected.to eq [{ text: "meep", when: "after_verification" }, { text: "foo", when: "after_verification" }] }
55+
end
56+
end
57+
end
58+
end

‎spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
body: {
7575
"_embedded" => {
7676
"pacts" => [{
77+
"shortDescription" => "a description",
7778
"verificationProperties" => {
7879
"pending" => Pact.like(true),
7980
"notices" => Pact.each_like("text" => "some text")
@@ -94,7 +95,8 @@
9495
pending: true,
9596
notices: [
9697
text: "some text"
97-
]
98+
],
99+
short_description: "a description"
98100
}
99101
end
100102

‎spec/spec_helper.rb

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'rspec'
2+
require 'rspec/its'
23
require 'fakefs/spec_helpers'
34
require 'pact'
45
require 'webmock/rspec'

0 commit comments

Comments
 (0)