diff --git a/lib/pact_broker/matrix/repository.rb b/lib/pact_broker/matrix/repository.rb index bb8689e25..7a40ecd8d 100644 --- a/lib/pact_broker/matrix/repository.rb +++ b/lib/pact_broker/matrix/repository.rb @@ -6,9 +6,12 @@ class Repository include PactBroker::Repositories::Helpers include PactBroker::Repositories + # Return the latest matrix row (pact/verification) for each consumer_version_number/provider_version_number def find selectors, options = {} + # The group with the nil provider_version_numbers will be the results of the left outer join + # that don't have verifications, so we need to include them all. lines = find_all(selectors) - .group_by{|line| [line[:consumer_version_number], line[:provider_version_number]]} + .group_by{|line| [line[:consumer_name], line[:consumer_version_number], line[:provider_name], line[:provider_version_number]]} .values .collect{ | lines | lines.first[:provider_version_number].nil? ? lines : lines.last } .flatten @@ -34,14 +37,26 @@ def find_compatible_pacticipant_versions selectors # If the version is nil, it means all versions for that pacticipant are to be included # def find_all selectors - PactBroker::Pacts::LatestPactPublicationsByConsumerVersion + query = PactBroker::Pacts::LatestPactPublicationsByConsumerVersion .select_append(:consumer_version_number, :provider_name, :consumer_name, :provider_version_id, :provider_version_number, :success) .select_append(Sequel[:latest_pact_publications_by_consumer_versions][:created_at].as(:pact_created_at)) .select_append(Sequel[:all_verifications][:number]) .select_append(Sequel[:all_verifications][:id].as(:verification_id)) .select_append(Sequel[:execution_date].as(:verification_executed_at)) .left_outer_join(:all_verifications, pact_version_id: :pact_version_id) - .where{ + + if selectors.size == 1 + query = where_consumer_or_provider_is(selectors.first, query) + else + query = where_consumer_and_provider_within(selectors, query) + end + + query.order(:execution_date, :verification_id) + .collect(&:values) + end + + def where_consumer_and_provider_within selectors, query + query.where{ Sequel.&( Sequel.|( *selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]) } @@ -52,8 +67,15 @@ def find_all selectors ) ) } - .order(:execution_date, :verification_id) - .collect(&:values) + end + + def where_consumer_or_provider_is s, query + query.where{ + Sequel.|( + s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]), + s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name]) + ) + } end end end diff --git a/lib/pact_broker/matrix/service.rb b/lib/pact_broker/matrix/service.rb index 425208af2..6f03c32fa 100644 --- a/lib/pact_broker/matrix/service.rb +++ b/lib/pact_broker/matrix/service.rb @@ -46,8 +46,8 @@ def validate_selectors selectors end end - if selectors.size < 2 - error_messages << "Please provide 2 or more version selectors." + if selectors.size == 0 + error_messages << "Please provide 1 or more version selectors." end error_messages diff --git a/spec/lib/pact_broker/matrix/repository_spec.rb b/spec/lib/pact_broker/matrix/repository_spec.rb index a3664c880..45dd867c9 100644 --- a/spec/lib/pact_broker/matrix/repository_spec.rb +++ b/spec/lib/pact_broker/matrix/repository_spec.rb @@ -54,6 +54,109 @@ def build_selectors(hash) end end + context "when only one pacticipant/version is specified and it is a consumer" do + before do + td.create_pact_with_hierarchy("A", "1.2.3", "B") + .create_verification(provider_version: "4.5.6") + .create_provider("D") + .create_pact + .create_verification(provider_version: "6.7.8") + .create_consumer_version("5.5.5") + .create_pact + .create_verification(provider_version: "4.5.6") + end + + subject { Repository.new.find build_selectors("A" => "1.2.3") } + + it "returns a row for each verification for that version" do + expect(subject.size).to eq 2 + expect(subject.collect{|r| r[:consumer_version_number]}.sort).to eq ["1.2.3", "1.2.3"] + expect(subject.collect{|r| r[:provider_version_number]}.sort).to eq ["4.5.6", "6.7.8"] + end + end + + context "when only one pacticipant name is specified and it is a consumer" do + before do + td.create_pact_with_hierarchy("A", "1.2.3", "B") + .create_verification(provider_version: "4.5.6") + .create_provider("D") + .create_pact + .create_pact_with_hierarchy("X", "1.2.3", "Y") + end + + subject { Repository.new.find build_selectors("A" => nil) } + + it "returns a row for each verification for the pacticipant" do + expect(subject.collect{|r| r[:consumer_name]}.uniq).to eq ["A"] + provider_version_numbers = subject.collect{|r| r[:provider_version_number]} + expect(provider_version_numbers).to include nil + expect(provider_version_numbers).to include "4.5.6" + end + end + + context "when only one pacticipant/version is specified and it is a provider" do + before do + td.create_pact_with_hierarchy("A", "1.2.3", "B") + .create_verification(provider_version: "4.5.6") + .create_consumer("D") + .create_consumer_version("3.4.5") + .create_pact + .create_verification(provider_version: "4.5.6") + .create_verification(provider_version: "6.7.8", number: 2) + end + + subject { Repository.new.find build_selectors("B" => "4.5.6") } + + it "returns a row for each verification for that version" do + expect(subject.size).to eq 2 + expect(subject.collect{|r| r[:consumer_version_number]}.sort).to eq ["1.2.3", "3.4.5"] + expect(subject.collect{|r| r[:provider_version_number]}.sort).to eq ["4.5.6", "4.5.6"] + end + end + + context "when only one pacticipant name is specified and it is a provider" do + before do + td.create_pact_with_hierarchy("A", "1.2.3", "B") + .create_verification(provider_version: "4.5.6") + .create_consumer("D") + .create_consumer_version("3.4.5") + .create_pact + .create_verification(provider_version: "4.5.6") + .create_verification(provider_version: "6.7.8", number: 2) + end + + subject { Repository.new.find build_selectors("B" => nil) } + + it "returns a row for each verification for that version" do + expect(subject.size).to eq 3 + expect(subject.collect{|r| r[:consumer_version_number]}.sort).to eq ["1.2.3", "3.4.5", "3.4.5"] + expect(subject.collect{|r| r[:provider_version_number]}.sort).to eq ["4.5.6", "4.5.6", "6.7.8"] + end + end + + context "when only one pacticipant/version is specified and it is a consumer and provider" do + before do + td.create_pact_with_hierarchy("A", "1", "B") + .create_verification(provider_version: '1') + .create_verification(provider_version: '2', number: 2, success: false) + .create_verification(provider_version: '4', number: 3) + .create_provider_version("5") + .use_consumer("B") + .use_consumer_version("1") + .create_provider("C") + .create_pact + .create_verification(provider_version: '1', success: false) + end + + subject { Repository.new.find build_selectors("B" => "1") } + + it "returns rows where the pacticipant is the consumer and rows where the pacticipant is the provider" do + # A/1 and B/1 + # B/1 and C/1 + expect(subject.size).to eq 2 + end + end + context "using the success option" do before do td.create_pact_with_hierarchy("A", "1.2.3", "B") @@ -207,7 +310,7 @@ def build_selectors(hash) subject { Repository.new.find_compatible_pacticipant_versions(selectors) } it "returns all the rows" do - expect(subject.size).to eq 4 + expect(subject.size).to eq 5 end end end diff --git a/spec/lib/pact_broker/matrix/service_spec.rb b/spec/lib/pact_broker/matrix/service_spec.rb index ae1026ca7..3b5003e46 100644 --- a/spec/lib/pact_broker/matrix/service_spec.rb +++ b/spec/lib/pact_broker/matrix/service_spec.rb @@ -9,17 +9,11 @@ module Matrix subject { Service.validate_selectors(selectors) } - - context "when there is only one selector" do - before do - td.create_pacticipant("Foo") - .create_version("1") - end - - let(:selectors) { [{ pacticipant_name: "Foo", pacticipant_version_number: "1" }] } + context "when there are no selectors" do + let(:selectors) { [] } it "returns error messages" do - expect(subject.first).to eq "Please provide 2 or more version selectors." + expect(subject.first).to eq "Please provide 1 or more version selectors." end end