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 4bab2308..97856f25 100644 --- a/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +++ b/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb @@ -39,9 +39,11 @@ def call log_message pacts_for_verification else + old_selectors = consumer_version_selectors.collect do | selector | + { name: selector[:tag], all: !selector[:latest], fallback: selector[:fallbackTag]} + end # Fall back to old method of fetching pacts - consumer_version_tags = consumer_version_selectors.collect{ | selector | selector[:tag] } - FetchPacts.call(provider, consumer_version_tags, broker_base_url, http_client_options) + FetchPacts.call(provider, old_selectors, broker_base_url, http_client_options) end end diff --git a/lib/pact/pact_broker/pact_selection_description.rb b/lib/pact/pact_broker/pact_selection_description.rb index 39adb1df..0a61e1c8 100644 --- a/lib/pact/pact_broker/pact_selection_description.rb +++ b/lib/pact/pact_broker/pact_selection_description.rb @@ -7,7 +7,6 @@ def pact_selection_description(provider, consumer_version_selectors, options, br if consumer_version_selectors.any? desc = consumer_version_selectors.collect do |selector| all_or_latest = !selector[:latest] ? "all for tag" : "latest for tag" - # TODO support fallback fallback = selector[:fallback] || selector[:fallbackTag] name = fallback ? "#{selector[:tag]} (or #{fallback} if not found)" : selector[:tag] "#{all_or_latest} #{name}" diff --git a/lib/pact/provider/configuration/pact_verification_from_broker.rb b/lib/pact/provider/configuration/pact_verification_from_broker.rb index d60317b2..a832cb9f 100644 --- a/lib/pact/provider/configuration/pact_verification_from_broker.rb +++ b/lib/pact/provider/configuration/pact_verification_from_broker.rb @@ -2,6 +2,7 @@ require 'pact/provider/world' require 'pact/pact_broker/fetch_pact_uris_for_verification' require 'pact/errors' +require 'pact/utils/string' module Pact module Provider @@ -14,12 +15,13 @@ class PactVerificationFromBroker # in parent scope, it will clash with these ones, # so put an underscore in front of the name to be safer. - attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_include_wip_pacts_since, :_verbose + 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 def initialize(provider_name, provider_version_tags) @_provider_name = provider_name @_provider_version_tags = provider_version_tags @_consumer_version_tags = [] + @_consumer_version_selectors = [] @_enable_pending = false @_include_wip_pacts_since = nil @_verbose = false @@ -35,6 +37,10 @@ def consumer_version_tags consumer_version_tags self._consumer_version_tags = *consumer_version_tags end + def consumer_version_selectors consumer_version_selectors + self._consumer_version_selectors = *consumer_version_selectors + end + def enable_pending enable_pending self._enable_pending = enable_pending end @@ -73,12 +79,33 @@ def create_pact_verification end def consumer_version_selectors - # TODO support "all" + convert_tags_to_selectors + convert_consumer_version_selectors + end + + def convert_tags_to_selectors _consumer_version_tags.collect do | tag | - { - tag: tag, - latest: true - } + if tag.is_a?(Hash) + { + tag: tag.fetch(:name), + latest: !tag[:all], + fallbackTag: tag[:fallback] + } + elsif tag.is_a?(String) + { + tag: tag, + latest: true + } + else + raise Pact::Error.new("The value supplied for consumer_version_tags must be a String or a Hash. Found #{tag.class}") + end + end + end + + def convert_consumer_version_selectors + _consumer_version_selectors.collect do | selector | + selector.each_with_object({}) do | (key, value), new_selector | + new_selector[Pact::Utils::String.camelcase(key.to_s).to_sym] = value + end end end diff --git a/lib/pact/utils/string.rb b/lib/pact/utils/string.rb new file mode 100644 index 00000000..ddead806 --- /dev/null +++ b/lib/pact/utils/string.rb @@ -0,0 +1,35 @@ +# Can't use refinements because of Travelling Ruby + +module Pact + module Utils + module String + + extend self + + # ripped from rubyworks/facets, thank you + def camelcase(string, *separators) + case separators.first + when Symbol, TrueClass, FalseClass, NilClass + first_letter = separators.shift + end + + separators = ['_', '\s'] if separators.empty? + + str = string.dup + + separators.each do |s| + str = str.gsub(/(?:#{s}+)([a-z])/){ $1.upcase } + end + + case first_letter + when :upper, true + str = str.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase } + when :lower, false + str = str.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase } + end + + str + end + end + end +end \ No newline at end of file diff --git a/spec/lib/pact/pact_broker/fetch_pact_uris_for_verification_spec.rb b/spec/lib/pact/pact_broker/fetch_pact_uris_for_verification_spec.rb index 3f42f8b3..764f0ad8 100644 --- a/spec/lib/pact/pact_broker/fetch_pact_uris_for_verification_spec.rb +++ b/spec/lib/pact/pact_broker/fetch_pact_uris_for_verification_spec.rb @@ -11,7 +11,7 @@ module PactBroker let(:provider) { "Foo"} let(:broker_base_url) { "http://broker.org" } let(:http_client_options) { {} } - let(:consumer_version_selectors) { [{ tag: "cmaster", latest: true}] } + let(:consumer_version_selectors) { [{ tag: "cmaster", latest: true, fallbackTag: 'blah' }] } let(:provider_version_tags) { ["pmaster"] } subject { FetchPactURIsForVerification.call(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options)} @@ -60,7 +60,7 @@ module PactBroker end it "calls the old fetch pacts code" do - expect(FetchPacts).to receive(:call).with(provider, ["cmaster"], broker_base_url, http_client_options) + expect(FetchPacts).to receive(:call).with(provider, [{ name: "cmaster", all: false, fallback: "blah" }], broker_base_url, http_client_options) subject end end diff --git a/spec/lib/pact/provider/configuration/pact_verification_from_broker_spec.rb b/spec/lib/pact/provider/configuration/pact_verification_from_broker_spec.rb index 70eb5b65..7539d792 100644 --- a/spec/lib/pact/provider/configuration/pact_verification_from_broker_spec.rb +++ b/spec/lib/pact/provider/configuration/pact_verification_from_broker_spec.rb @@ -16,6 +16,7 @@ module Configuration } end let(:tags) { ['master'] } + let(:fetch_pacts) { double('FetchPacts') } before do allow(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).and_return(fetch_pacts) @@ -82,8 +83,6 @@ module Configuration end end - let(:fetch_pacts) { double('FetchPacts') } - it "raises an error" do expect { subject }.to raise_error Pact::Error, /Please provide a pact_broker_base_url/ end @@ -97,8 +96,6 @@ module Configuration end end - let(:fetch_pacts) { double('FetchPacts') } - it "coerces the value into an array" do expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "master", latest: true}], anything, anything, anything, anything) subject @@ -112,22 +109,65 @@ module Configuration end end - let(:fetch_pacts) { double('FetchPacts') } - it "creates an instance of FetchPacts with an emtpy array for the consumer_version_tags" do expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [], anything, anything, anything, anything) subject end end - context "when no verbose flag is provided" do + context "when the old format of selector is supplied to the consumer_verison_tags" do + let(:tags) { [{ name: 'main', all: true, fallback: 'fallback' }] } + subject do PactVerificationFromBroker.build(provider_name, provider_version_tags) do pact_broker_base_url base_url + consumer_version_tags tags end end - let(:fetch_pacts) { double('FetchPacts') } + it "converts them to selectors" do + expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "main", latest: false, fallbackTag: 'fallback'}], anything, anything, anything, anything) + subject + end + end + + context "when an invalid class is used for the consumer_version_tags" do + let(:tags) { [true] } + + subject do + PactVerificationFromBroker.build(provider_name, provider_version_tags) do + pact_broker_base_url base_url + consumer_version_tags tags + end + end + + it "raises an error" do + expect { subject }.to raise_error Pact::Error, "The value supplied for consumer_version_tags must be a String or a Hash. Found TrueClass" + end + end + + context "when consumer_version_selectors are provided" do + let(:tags) { [{ tag: 'main', latest: true, fallback_tag: 'fallback' }] } + + subject do + PactVerificationFromBroker.build(provider_name, provider_version_tags) do + pact_broker_base_url base_url + consumer_version_selectors tags + end + end + + it "converts the casing of the key names" do + expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, [{ tag: "main", latest: true, fallbackTag: 'fallback'}], anything, anything, anything, anything) + subject + end + end + + context "when no verbose flag is provided" do + subject do + PactVerificationFromBroker.build(provider_name, provider_version_tags) do + pact_broker_base_url base_url + end + end it "creates an instance of FetchPactURIsForVerification with verbose: false" do expect(Pact::PactBroker::FetchPactURIsForVerification).to receive(:new).with(anything, anything, anything, anything, hash_including(verbose: false), anything)