Skip to content

Commit 39e6c4a

Browse files
committed
feat: add consumer_version_selectors to pact verification DSL, and convert consumer_version_tags to selectors
1 parent 303077d commit 39e6c4a

File tree

6 files changed

+122
-19
lines changed

6 files changed

+122
-19
lines changed

lib/pact/pact_broker/fetch_pact_uris_for_verification.rb

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ def call
3939
log_message
4040
pacts_for_verification
4141
else
42+
old_selectors = consumer_version_selectors.collect do | selector |
43+
{ name: selector[:tag], all: !selector[:latest], fallback: selector[:fallbackTag]}
44+
end
4245
# Fall back to old method of fetching pacts
43-
consumer_version_tags = consumer_version_selectors.collect{ | selector | selector[:tag] }
44-
FetchPacts.call(provider, consumer_version_tags, broker_base_url, http_client_options)
46+
FetchPacts.call(provider, old_selectors, broker_base_url, http_client_options)
4547
end
4648
end
4749

lib/pact/pact_broker/pact_selection_description.rb

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ def pact_selection_description(provider, consumer_version_selectors, options, br
77
if consumer_version_selectors.any?
88
desc = consumer_version_selectors.collect do |selector|
99
all_or_latest = !selector[:latest] ? "all for tag" : "latest for tag"
10-
# TODO support fallback
1110
fallback = selector[:fallback] || selector[:fallbackTag]
1211
name = fallback ? "#{selector[:tag]} (or #{fallback} if not found)" : selector[:tag]
1312
"#{all_or_latest} #{name}"

lib/pact/provider/configuration/pact_verification_from_broker.rb

+33-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'pact/provider/world'
33
require 'pact/pact_broker/fetch_pact_uris_for_verification'
44
require 'pact/errors'
5+
require 'pact/utils/string'
56

67
module Pact
78
module Provider
@@ -14,12 +15,13 @@ class PactVerificationFromBroker
1415
# in parent scope, it will clash with these ones,
1516
# so put an underscore in front of the name to be safer.
1617

17-
attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_include_wip_pacts_since, :_verbose
18+
attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_include_wip_pacts_since, :_verbose, :_consumer_version_selectors
1819

1920
def initialize(provider_name, provider_version_tags)
2021
@_provider_name = provider_name
2122
@_provider_version_tags = provider_version_tags
2223
@_consumer_version_tags = []
24+
@_consumer_version_selectors = []
2325
@_enable_pending = false
2426
@_include_wip_pacts_since = nil
2527
@_verbose = false
@@ -35,6 +37,10 @@ def consumer_version_tags consumer_version_tags
3537
self._consumer_version_tags = *consumer_version_tags
3638
end
3739

40+
def consumer_version_selectors consumer_version_selectors
41+
self._consumer_version_selectors = *consumer_version_selectors
42+
end
43+
3844
def enable_pending enable_pending
3945
self._enable_pending = enable_pending
4046
end
@@ -73,12 +79,33 @@ def create_pact_verification
7379
end
7480

7581
def consumer_version_selectors
76-
# TODO support "all"
82+
convert_tags_to_selectors + convert_consumer_version_selectors
83+
end
84+
85+
def convert_tags_to_selectors
7786
_consumer_version_tags.collect do | tag |
78-
{
79-
tag: tag,
80-
latest: true
81-
}
87+
if tag.is_a?(Hash)
88+
{
89+
tag: tag.fetch(:name),
90+
latest: !tag[:all],
91+
fallbackTag: tag[:fallback]
92+
}
93+
elsif tag.is_a?(String)
94+
{
95+
tag: tag,
96+
latest: true
97+
}
98+
else
99+
raise Pact::Error.new("The value supplied for consumer_version_tags must be a String or a Hash. Found #{tag.class}")
100+
end
101+
end
102+
end
103+
104+
def convert_consumer_version_selectors
105+
_consumer_version_selectors.collect do | selector |
106+
selector.each_with_object({}) do | (key, value), new_selector |
107+
new_selector[Pact::Utils::String.camelcase(key.to_s).to_sym] = value
108+
end
82109
end
83110
end
84111

lib/pact/utils/string.rb

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Can't use refinements because of Travelling Ruby
2+
3+
module Pact
4+
module Utils
5+
module String
6+
7+
extend self
8+
9+
# ripped from rubyworks/facets, thank you
10+
def camelcase(string, *separators)
11+
case separators.first
12+
when Symbol, TrueClass, FalseClass, NilClass
13+
first_letter = separators.shift
14+
end
15+
16+
separators = ['_', '\s'] if separators.empty?
17+
18+
str = string.dup
19+
20+
separators.each do |s|
21+
str = str.gsub(/(?:#{s}+)([a-z])/){ $1.upcase }
22+
end
23+
24+
case first_letter
25+
when :upper, true
26+
str = str.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
27+
when :lower, false
28+
str = str.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase }
29+
end
30+
31+
str
32+
end
33+
end
34+
end
35+
end

spec/lib/pact/pact_broker/fetch_pact_uris_for_verification_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module PactBroker
1111
let(:provider) { "Foo"}
1212
let(:broker_base_url) { "http://broker.org" }
1313
let(:http_client_options) { {} }
14-
let(:consumer_version_selectors) { [{ tag: "cmaster", latest: true}] }
14+
let(:consumer_version_selectors) { [{ tag: "cmaster", latest: true, fallbackTag: 'blah' }] }
1515
let(:provider_version_tags) { ["pmaster"] }
1616

1717
subject { FetchPactURIsForVerification.call(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options)}
@@ -60,7 +60,7 @@ module PactBroker
6060
end
6161

6262
it "calls the old fetch pacts code" do
63-
expect(FetchPacts).to receive(:call).with(provider, ["cmaster"], broker_base_url, http_client_options)
63+
expect(FetchPacts).to receive(:call).with(provider, [{ name: "cmaster", all: false, fallback: "blah" }], broker_base_url, http_client_options)
6464
subject
6565
end
6666
end

spec/lib/pact/provider/configuration/pact_verification_from_broker_spec.rb

+48-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Configuration
1616
}
1717
end
1818
let(:tags) { ['master'] }
19+
let(:fetch_pacts) { double('FetchPacts') }
1920

2021
before do
2122
allow(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).and_return(fetch_pacts)
@@ -82,8 +83,6 @@ module Configuration
8283
end
8384
end
8485

85-
let(:fetch_pacts) { double('FetchPacts') }
86-
8786
it "raises an error" do
8887
expect { subject }.to raise_error Pact::Error, /Please provide a pact_broker_base_url/
8988
end
@@ -97,8 +96,6 @@ module Configuration
9796
end
9897
end
9998

100-
let(:fetch_pacts) { double('FetchPacts') }
101-
10299
it "coerces the value into an array" do
103100
expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "master", latest: true}], anything, anything, anything, anything)
104101
subject
@@ -112,22 +109,65 @@ module Configuration
112109
end
113110
end
114111

115-
let(:fetch_pacts) { double('FetchPacts') }
116-
117112
it "creates an instance of FetchPacts with an emtpy array for the consumer_version_tags" do
118113
expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [], anything, anything, anything, anything)
119114
subject
120115
end
121116
end
122117

123-
context "when no verbose flag is provided" do
118+
context "when the old format of selector is supplied to the consumer_verison_tags" do
119+
let(:tags) { [{ name: 'main', all: true, fallback: 'fallback' }] }
120+
124121
subject do
125122
PactVerificationFromBroker.build(provider_name, provider_version_tags) do
126123
pact_broker_base_url base_url
124+
consumer_version_tags tags
127125
end
128126
end
129127

130-
let(:fetch_pacts) { double('FetchPacts') }
128+
it "converts them to selectors" do
129+
expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "main", latest: false, fallbackTag: 'fallback'}], anything, anything, anything, anything)
130+
subject
131+
end
132+
end
133+
134+
context "when an invalid class is used for the consumer_version_tags" do
135+
let(:tags) { [true] }
136+
137+
subject do
138+
PactVerificationFromBroker.build(provider_name, provider_version_tags) do
139+
pact_broker_base_url base_url
140+
consumer_version_tags tags
141+
end
142+
end
143+
144+
it "raises an error" do
145+
expect { subject }.to raise_error Pact::Error, "The value supplied for consumer_version_tags must be a String or a Hash. Found TrueClass"
146+
end
147+
end
148+
149+
context "when consumer_version_selectors are provided" do
150+
let(:tags) { [{ tag: 'main', latest: true, fallback_tag: 'fallback' }] }
151+
152+
subject do
153+
PactVerificationFromBroker.build(provider_name, provider_version_tags) do
154+
pact_broker_base_url base_url
155+
consumer_version_selectors tags
156+
end
157+
end
158+
159+
it "converts the casing of the key names" do
160+
expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "main", latest: true, fallbackTag: 'fallback'}], anything, anything, anything, anything)
161+
subject
162+
end
163+
end
164+
165+
context "when no verbose flag is provided" do
166+
subject do
167+
PactVerificationFromBroker.build(provider_name, provider_version_tags) do
168+
pact_broker_base_url base_url
169+
end
170+
end
131171

132172
it "creates an instance of FetchPactURIsForVerification with verbose: false" do
133173
expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, anything, anything, anything, hash_including(verbose: false), anything)

0 commit comments

Comments
 (0)