diff --git a/lib/pact_broker/api/decorators/matrix_decorator.rb b/lib/pact_broker/api/decorators/matrix_decorator.rb index a72be41cd..044aae964 100644 --- a/lib/pact_broker/api/decorators/matrix_decorator.rb +++ b/lib/pact_broker/api/decorators/matrix_decorator.rb @@ -7,8 +7,8 @@ module Decorators class MatrixDecorator include PactBroker::Api::PactBrokerUrls - def initialize(lines) - @lines = lines + def initialize(query_results_with_deployment_status_summary) + @query_results_with_deployment_status_summary = query_results_with_deployment_status_summary end def to_json(options) @@ -21,32 +21,27 @@ def to_hash(options) deployable: deployable, reason: reason }, - matrix: matrix(lines, options[:user_options][:base_url]) - } + matrix: matrix(options[:user_options][:base_url]) + }.tap do | hash | + hash[:summary].merge!(query_results_with_deployment_status_summary.deployment_status_summary.counts) + end + end def deployable - return nil if lines.empty? - return nil if lines.any?{ |line| line.success.nil? } - lines.any? && lines.all?{ |line| line.success } + query_results_with_deployment_status_summary.deployment_status_summary.deployable? end def reason - return "No results matched the given query" if lines.empty? - case deployable - when true then "All verification results are published and successful" - when false then "One or more verifications have failed" - else - "Missing one or more verification results" - end + query_results_with_deployment_status_summary.deployment_status_summary.reasons.join("\n") end private - attr_reader :lines + attr_reader :query_results_with_deployment_status_summary - def matrix(lines, base_url) - lines.collect do | line | + def matrix(base_url) + query_results_with_deployment_status_summary.rows.collect do | line | provider = OpenStruct.new(name: line.provider_name) consumer = OpenStruct.new(name: line.consumer_name) consumer_version = OpenStruct.new(number: line.consumer_version_number, pacticipant: consumer) diff --git a/lib/pact_broker/api/resources/relationships.rb b/lib/pact_broker/api/resources/relationships.rb index 4198d969b..2ea25600f 100644 --- a/lib/pact_broker/api/resources/relationships.rb +++ b/lib/pact_broker/api/resources/relationships.rb @@ -22,9 +22,7 @@ def to_csv def pacts pact_service.find_latest_pacts end - end end - end -end \ No newline at end of file +end diff --git a/lib/pact_broker/matrix/deployment_status_summary.rb b/lib/pact_broker/matrix/deployment_status_summary.rb new file mode 100644 index 000000000..2b60c2aaa --- /dev/null +++ b/lib/pact_broker/matrix/deployment_status_summary.rb @@ -0,0 +1,89 @@ +module PactBroker + module Matrix + class DeploymentStatusSummary + attr_reader :rows, :resolved_selectors, :integrations + + def initialize(rows, resolved_selectors, integrations) + @rows = rows + @resolved_selectors = resolved_selectors + @integrations = integrations + end + + def counts + { + success: rows.count{ |row| row.success }, + failed: rows.count { |row| row.success == false }, + unknown: integrations_without_a_row.count + rows.count { |row| row.success.nil? } + } + end + + def deployable? + return nil if rows.empty? + return nil if rows.any?{ |row| row.success.nil? } + return nil if integrations_without_a_row.any? + rows.all?{ |row| row.success } + end + + def reasons + @reasons ||= begin + reasons = [] + if rows.empty? + reasons << "No results matched the given query" + else + reasons.concat(missing_reasons) + reasons.concat(failure_messages) + reasons.concat(unverified_messages) + reasons.concat(success_messages) + end + reasons + end + end + + def unverified_messages + if rows.any?{ |row| row.success.nil? } + ["Missing one or more verification results"] + else + [] + end + end + + def failure_messages + if rows.any?{ |row| row.success == false } + ["One or more verifications have failed"] + else + [] + end + end + + def success_messages + if rows.all?{ |row| row.success } && integrations_without_a_row.empty? + ["All verification results are published and successful"] + else + [] + end + end + + def integrations_without_a_row + @integrations_without_a_row ||= begin + integrations.select do | relationship | + !rows.find do | row | + row.consumer_id == relationship.consumer_id && row.provider_id == relationship.provider_id + end + end + end + end + + def missing_reasons + integrations_without_a_row.collect do | missing_relationship| + consumer_version_desc = "#{missing_relationship.consumer_name} (#{resolved_version_for(missing_relationship.consumer_id)})" + provider_version_desc = "#{missing_relationship.provider_name} (#{resolved_version_for(missing_relationship.provider_id)})" + "There is no verified pact between #{consumer_version_desc} and #{provider_version_desc}" + end + end + + def resolved_version_for(pacticipant_id) + resolved_selectors.find{ | s| s[:pacticipant_id] == pacticipant_id }[:pacticipant_version_number] + end + end + end +end diff --git a/lib/pact_broker/matrix/integration.rb b/lib/pact_broker/matrix/integration.rb new file mode 100644 index 000000000..ccfaaa3ea --- /dev/null +++ b/lib/pact_broker/matrix/integration.rb @@ -0,0 +1,54 @@ +# +# Represents the integration relationship between a consumer and a provider +# +module PactBroker + module Matrix + class Integration + + attr_reader :consumer_name, :consumer_id, :provider_name, :provider_id + + def initialize consumer_id, consumer_name, provider_id, provider_name + @consumer_id = consumer_id + @consumer_name = consumer_name + @provider_id = provider_id + @provider_name = provider_name + end + + def self.from_hash hash + new( + hash.fetch(:consumer_id), + hash.fetch(:consumer_name), + hash.fetch(:provider_id), + hash.fetch(:provider_name) + ) + end + + def == other + consumer_id == other.consumer_id && provider_id == other.provider_id + end + + def <=> other + comparison = consumer_name <=> other.consumer_name + return comparison if comparison != 0 + provider_name <=> other.provider_name + end + + def to_hash + { + consumer_name: consumer_name, + consumer_id: consumer_id, + provider_name: provider_name, + provider_id: provider_id, + } + end + + def pacticipant_names + [consumer_name, provider_name] + end + + def to_s + "Relationship between #{consumer_name} (id=#{consumer_id}) and #{provider_name} (id=#{provider_id})" + end + end + end +end diff --git a/lib/pact_broker/matrix/parse_query.rb b/lib/pact_broker/matrix/parse_query.rb index f644d2388..39d4a0d77 100644 --- a/lib/pact_broker/matrix/parse_query.rb +++ b/lib/pact_broker/matrix/parse_query.rb @@ -29,7 +29,7 @@ def self.call query options[:limit] = params['limit'] end if params.key?('latest') && params['latest'] != '' - options[:latest] = params['latest'] + options[:latest] = params['latest'] == 'true' end if params.key?('tag') && params['tag'] != '' options[:tag] = params['tag'] diff --git a/lib/pact_broker/matrix/query_results.rb b/lib/pact_broker/matrix/query_results.rb new file mode 100644 index 000000000..ff5e28074 --- /dev/null +++ b/lib/pact_broker/matrix/query_results.rb @@ -0,0 +1,18 @@ +module PactBroker + module Matrix + class QueryResults < Array + attr_reader :selectors, :options, :resolved_selectors + + def initialize rows, selectors, options, resolved_selectors + super(rows) + @selectors = selectors + @resolved_selectors = resolved_selectors + @options = options + end + + def rows + to_a + end + end + end +end diff --git a/lib/pact_broker/matrix/query_results_with_deployment_status_summary.rb b/lib/pact_broker/matrix/query_results_with_deployment_status_summary.rb new file mode 100644 index 000000000..a27a79b9e --- /dev/null +++ b/lib/pact_broker/matrix/query_results_with_deployment_status_summary.rb @@ -0,0 +1,14 @@ +require 'pact_broker/matrix/query_results' + +module PactBroker + module Matrix + class QueryResultsWithDeploymentStatusSummary < QueryResults + attr_reader :deployment_status_summary + + def initialize rows, selectors, options, resolved_selectors, deployment_status_summary + super(rows, selectors, options, resolved_selectors) + @deployment_status_summary = deployment_status_summary + end + end + end +end diff --git a/lib/pact_broker/matrix/repository.rb b/lib/pact_broker/matrix/repository.rb index 69d7964de..ebb48118b 100644 --- a/lib/pact_broker/matrix/repository.rb +++ b/lib/pact_broker/matrix/repository.rb @@ -2,7 +2,9 @@ require 'pact_broker/matrix/row' require 'pact_broker/matrix/head_row' require 'pact_broker/error' - +require 'pact_broker/matrix/query_results' +require 'pact_broker/matrix/integration' +require 'pact_broker/matrix/query_results_with_deployment_status_summary' module PactBroker module Matrix @@ -65,7 +67,8 @@ def find_ids_for_pacticipant_names params # Return the latest matrix row (pact/verification) for each consumer_version_number/provider_version_number def find selectors, options = {} - lines = query_matrix(resolve_selectors(selectors, options), options) + resolved_selectors = resolve_selectors(selectors, options) + lines = query_matrix(resolved_selectors, options) lines = apply_latestby(options, selectors, lines) # This needs to be done after the latestby, so can't be done in the db unless @@ -74,9 +77,31 @@ def find selectors, options = {} lines = lines.select{ |l| options[:success].include?(l.success) } end - lines.sort + QueryResults.new(lines.sort, selectors, options, resolved_selectors) + end + + def find_for_consumer_and_provider pacticipant_1_name, pacticipant_2_name + selectors = [{ pacticipant_name: pacticipant_1_name }, { pacticipant_name: pacticipant_2_name }] + options = { latestby: 'cvpv' } + find(selectors, options) + end + + def find_compatible_pacticipant_versions selectors + find(selectors, latestby: 'cvpv').select{|line| line.success } + end + + def find_integrations(pacticipant_names) + selectors = pacticipant_names.collect{ | pacticipant_name | add_ids(pacticipant_name: pacticipant_name) } + Row + .select(:consumer_name, :consumer_id, :provider_name, :provider_id) + .matching_selectors(selectors) + .distinct + .all + .collect{ |row | Integration.from_hash(row.to_hash) }.uniq end + private + def apply_latestby options, selectors, lines return lines unless options[:latestby] group_by_columns = case options[:latestby] @@ -106,16 +131,6 @@ def remove_overwritten_revisions lines latest_revisions end - def find_for_consumer_and_provider pacticipant_1_name, pacticipant_2_name - selectors = [{ pacticipant_name: pacticipant_1_name }, { pacticipant_name: pacticipant_2_name }] - options = { latestby: 'cvpv' } - find(selectors, options) - end - - def find_compatible_pacticipant_versions selectors - find(selectors, latestby: 'cvpv').select{|line| line.success } - end - def query_matrix selectors, options query = view_for(options).select_all.matching_selectors(selectors) query = query.limit(options[:limit]) if options[:limit] @@ -195,7 +210,7 @@ def add_ids(selector) # eg. when checking to see if Foo version 2 can be deployed to prod, # need to look up all the 'partner' pacticipants, and determine their latest prod versions def apply_latest_and_tag_to_inferred_selectors(selectors, options) - all_pacticipant_names = all_pacticipant_names_in_specified_matrix(selectors, options) + all_pacticipant_names = all_pacticipant_names_in_specified_matrix(selectors) specified_names = selectors.collect{ |s| s[:pacticipant_name] } inferred_names = all_pacticipant_names - specified_names @@ -211,12 +226,9 @@ def apply_latest_and_tag_to_inferred_selectors(selectors, options) selectors + look_up_version_numbers(inferred_selectors, options) end - def all_pacticipant_names_in_specified_matrix(selectors, options) - query = view_for(options).select(:consumer_name, :provider_name) - query = query.matching_selectors(selectors) - query - .all - .collect{ | row | [row.consumer_name, row.provider_name] } + def all_pacticipant_names_in_specified_matrix(selectors) + find_integrations(selectors.collect{|s| s[:pacticipant_name]}) + .collect(&:pacticipant_names) .flatten .uniq end diff --git a/lib/pact_broker/matrix/service.rb b/lib/pact_broker/matrix/service.rb index df1995687..71a787ff0 100644 --- a/lib/pact_broker/matrix/service.rb +++ b/lib/pact_broker/matrix/service.rb @@ -1,5 +1,6 @@ require 'pact_broker/repositories' require 'pact_broker/matrix/row' +require 'pact_broker/matrix/deployment_status_summary' module PactBroker module Matrix @@ -17,12 +18,18 @@ def refresh_tags params, &block matrix_repository.refresh_tags(params, &block) end - def find criteria, options = {} - matrix_repository.find criteria, options + def find selectors, options = {} + query_results = matrix_repository.find selectors, options + pacticipant_names = selectors.collect{ | s| s[:pacticipant_name] } + integrations = matrix_repository.find_integrations(pacticipant_names) + deployment_status_summary = DeploymentStatusSummary.new(query_results.rows, query_results.resolved_selectors, integrations) + QueryResultsWithDeploymentStatusSummary.new(query_results.rows, query_results.selectors, query_results.options, query_results.resolved_selectors, deployment_status_summary) end def find_for_consumer_and_provider params - matrix_repository.find_for_consumer_and_provider params[:consumer_name], params[:provider_name] + selectors = [{ pacticipant_name: params[:consumer_name] }, { pacticipant_name: params[:provider_name] }] + options = { latestby: 'cvpv' } + find(selectors, options) end def find_for_consumer_and_provider_with_tags params diff --git a/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb b/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb index ce4598f4c..756a32bd8 100644 --- a/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +++ b/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb @@ -1,4 +1,6 @@ require 'pact_broker/api/decorators/matrix_decorator' +require 'pact_broker/matrix/query_results_with_deployment_status_summary' +require 'pact_broker/matrix/deployment_status_summary' module PactBroker module Api @@ -7,9 +9,9 @@ module Decorators describe "to_json" do let(:verification_date) { DateTime.new(2017, 12, 31) } let(:pact_created_at) { DateTime.new(2017, 1, 1) } - let(:line_1_success) { true } - let(:line_2_success) { true } - let(:line_1) do + let(:row_1_success) { true } + let(:row_2_success) { true } + let(:row_1) do double('PactBroker::Matrix::Row', { consumer_name: "Consumer", @@ -18,7 +20,7 @@ module Decorators pact_created_at: pact_created_at, provider_version_number: "4.5.6", provider_name: "Provider", - success: line_1_success, + success: row_1_success, verification_number: 1, verification_build_url: nil, verification_executed_at: verification_date @@ -26,7 +28,7 @@ module Decorators ) end - let(:line_2) do + let(:row_2) do double('PactBroker::Matrix::Row', { consumer_name: "Consumer", @@ -35,7 +37,7 @@ module Decorators pact_created_at: pact_created_at, provider_version_number: nil, provider_name: "Provider", - success: line_2_success, + success: row_2_success, verification_number: nil, verification_build_url: nil, verification_executed_at: verification_date @@ -99,8 +101,16 @@ module Decorators } end - let(:lines){ [line_1, line_2]} - let(:json) { MatrixDecorator.new(lines).to_json(user_options: { base_url: 'http://example.org' }) } + let(:query_results){ PactBroker::Matrix::QueryResultsWithDeploymentStatusSummary.new([row_1, row_2], selectors, options, resolved_selectors, deployment_status_summary)} + let(:selectors) { nil } + let(:options) { nil } + let(:resolved_selectors) { nil } + let(:counts) { { success: 1 } } + let(:deployment_status_summary) do + instance_double('PactBroker::Matrix::DeploymentStatusSummary', reasons: ['foo', 'bar'], deployable?: deployable, counts: counts) + end + let(:deployable) { true } + let(:json) { MatrixDecorator.new(query_results).to_json(user_options: { base_url: 'http://example.org' }) } let(:parsed_json) { JSON.parse(json, symbolize_names: true) } it "includes the consumer details" do @@ -121,13 +131,14 @@ module Decorators it "includes a summary" do expect(parsed_json[:summary][:deployable]).to eq true - expect(parsed_json[:summary][:reason]).to match /All verification results are published/ + expect(parsed_json[:summary][:reason]).to eq "foo\nbar" + expect(parsed_json[:summary][:success]).to eq 1 end context "when the pact has not been verified" do before do - allow(line_2).to receive(:success).and_return(nil) - allow(line_2).to receive(:verification_executed_at).and_return(nil) + allow(row_2).to receive(:success).and_return(nil) + allow(row_2).to receive(:verification_executed_at).and_return(nil) end let(:verification_hash) { nil } @@ -140,42 +151,6 @@ module Decorators expect(parsed_json[:matrix][1][:verificationResult]).to eq verification_hash end end - - context "when one or more successes are nil" do - let(:line_1_success) { nil } - - it "has a deployable flag of nil" do - expect(parsed_json[:summary][:deployable]).to be nil - end - - it "has an explanation" do - expect(parsed_json[:summary][:reason]).to match /Missing/ - end - end - - context "when one or more successes are false" do - let(:line_1_success) { false } - - it "has a deployable flag of false" do - expect(parsed_json[:summary][:deployable]).to be false - end - - it "has an explanation" do - expect(parsed_json[:summary][:reason]).to match /have failed/ - end - end - - context "when there are no results" do - let(:lines) { [] } - - it "has a deployable flag of false" do - expect(parsed_json[:summary][:deployable]).to be nil - end - - it "has an explanation" do - expect(parsed_json[:summary][:reason]).to match /No results/ - end - end end end end diff --git a/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb b/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb new file mode 100644 index 000000000..dea249987 --- /dev/null +++ b/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb @@ -0,0 +1,98 @@ +require 'pact_broker/matrix/deployment_status_summary' +require 'pact_broker/matrix/row' +require 'pact_broker/matrix/query_results' +require 'pact_broker/matrix/integration' + +module PactBroker + module Matrix + describe DeploymentStatusSummary do + describe ".call" do + + let(:rows) { [row_1, row_2] } + let(:row_1) do + double(Row, + consumer_name: "Foo", + consumer_id: 1, + provider_name: "Bar", + provider_id: 2, + success: row_1_success + ) + end + + let(:row_2) do + double(Row, + consumer_name: "Foo", + consumer_id: 1, + provider_name: "Baz", + provider_id: 3, + success: true + ) + end + + let(:row_1_success) { true } + + let(:integrations) do + [ + Integration.new(1, "Foo", 2, "Bar"), + Integration.new(1, "Foo", 3, "Baz") + ] + end + + let(:resolved_selectors) do + [ + { + pacticipant_id: 1, pacticipant_version_number: "ddec8101dabf4edf9125a69f9a161f0f294af43c" + }, + { + pacticipant_id: 2, pacticipant_version_number: "14131c5da3abf323ccf410b1b619edac76231243" + }, + { + pacticipant_id: 3, pacticipant_version_number: "4ee06460f10e8207ad904fa9fa6c4842e462ab59" + } + ] + end + + + subject { DeploymentStatusSummary.new(rows, resolved_selectors, integrations) } + + context "when there is a row for all integrations" do + its(:deployable?) { is_expected.to be true } + its(:reasons) { is_expected.to eq ["All verification results are published and successful"] } + its(:counts) { is_expected.to eq success: 2, failed: 0, unknown: 0 } + end + + context "when there are no rows" do + let(:rows) { [] } + + its(:deployable?) { is_expected.to be nil } + its(:reasons) { is_expected.to eq ["No results matched the given query"] } + its(:counts) { is_expected.to eq success: 0, failed: 0, unknown: 2 } + end + + context "when one or more of the success flags are nil" do + let(:row_1_success) { nil } + + its(:deployable?) { is_expected.to be nil } + its(:reasons) { is_expected.to eq ["Missing one or more verification results"] } + its(:counts) { is_expected.to eq success: 1, failed: 0, unknown: 1 } + end + + context "when one or more of the success flags are false" do + let(:row_1_success) { false } + + its(:deployable?) { is_expected.to be false } + its(:reasons) { is_expected.to eq ["One or more verifications have failed"] } + its(:counts) { is_expected.to eq success: 1, failed: 1, unknown: 0 } + end + + context "when there is a relationship missing" do + let(:rows) { [row_1] } + + its(:deployable?) { is_expected.to be nil } + its(:reasons) { is_expected.to eq ["There is no verified pact between Foo (ddec8101dabf4edf9125a69f9a161f0f294af43c) and Baz (4ee06460f10e8207ad904fa9fa6c4842e462ab59)"] } + its(:counts) { is_expected.to eq success: 1, failed: 0, unknown: 1 } + end + end + end + end +end diff --git a/spec/lib/pact_broker/matrix/parse_query_spec.rb b/spec/lib/pact_broker/matrix/parse_query_spec.rb index 0d8c4d8a6..ec08b8b8e 100644 --- a/spec/lib/pact_broker/matrix/parse_query_spec.rb +++ b/spec/lib/pact_broker/matrix/parse_query_spec.rb @@ -82,6 +82,14 @@ module Matrix end end + context "when global latest is true" do + let(:query) { "q[][pacticipant]=Foo&latest=true" } + + it "returns options with latest true" do + expect(subject.last).to eq latest: true + end + end + context "when latest is not true" do let(:query) { "q[][pacticipant]=Foo&q[][latest]=false" } diff --git a/spec/lib/pact_broker/matrix/repository_find_integrations_spec.rb b/spec/lib/pact_broker/matrix/repository_find_integrations_spec.rb new file mode 100644 index 000000000..84bfebfb7 --- /dev/null +++ b/spec/lib/pact_broker/matrix/repository_find_integrations_spec.rb @@ -0,0 +1,51 @@ +require 'pact_broker/matrix/repository' + +module PactBroker + module Matrix + describe Repository do + let(:td) { TestDataBuilder.new} + + describe "find_integrations" do + before do + td.create_pact_with_hierarchy("foo", "1", "bar") + .create_provider("baz") + .create_pact + .use_consumer("baz") + .create_consumer_version("3") + .create_provider("wiffle") + .create_pact + end + + subject { Repository.new.find_integrations(["foo"]).sort } + + context "with only one pacticipant name" do + it "returns all the integrations that the pacticipant with the given name has" do + expect(subject.first.consumer_name).to eq "foo" + expect(subject.first.provider_name).to eq "bar" + expect(subject.last.consumer_name).to eq "foo" + expect(subject.last.provider_name).to eq "baz" + expect(subject.size).to eq 2 + end + end + + context "with the names of two pacticipants that are integrated" do + subject { Repository.new.find_integrations(["foo", "bar"]).sort } + + it "returns only that integration" do + expect(subject.first.consumer_name).to eq "foo" + expect(subject.first.provider_name).to eq "bar" + expect(subject.size).to eq 1 + end + end + + context "with the names of two pacticipants that aren't integrated" do + subject { Repository.new.find_integrations(["foo", "wiffle"]).sort } + + it "returns an empty array" do + expect(subject).to eq [] + end + end + end + end + end +end diff --git a/spec/lib/pact_broker/matrix/repository_spec.rb b/spec/lib/pact_broker/matrix/repository_spec.rb index 86c67f4f6..41d75e399 100644 --- a/spec/lib/pact_broker/matrix/repository_spec.rb +++ b/spec/lib/pact_broker/matrix/repository_spec.rb @@ -998,6 +998,30 @@ def shorten_rows rows end end end + + describe "find pact_broker-client issue 33" do + before do + td + .create_consumer("foo") + .create_provider("bar") + .create_consumer_version("1.0.0") + .create_pact + .create_verification(provider_version: "10.0.0", tag_names: ["prod"]) + .create_provider("baz") + .create_consumer_version("2.0.0") + .create_pact + .create_verification(provider_version: "20.0.0", tag_names: ["prod"]) + end + + let(:selectors) { [{ pacticipant_name: "foo", pacticipant_version_number: "1.0.0" }] } + let(:options) { {latestby: "cvp", latest: true, tag: "prod"} } + + subject { shorten_rows(Repository.new.find(selectors, options)) } + + it "only returns a row for the foo pact version that has been verified by the current production version of bar" do + expect(subject).to eq ["foo1.0.0 bar10.0.0 n1"] + end + end end end end diff --git a/spec/lib/pact_broker/matrix/service_spec.rb b/spec/lib/pact_broker/matrix/service_spec.rb index a4f35421d..e8ae75061 100644 --- a/spec/lib/pact_broker/matrix/service_spec.rb +++ b/spec/lib/pact_broker/matrix/service_spec.rb @@ -5,6 +5,32 @@ module Matrix describe Service do let(:td) { TestDataBuilder.new } + describe "find integration test" do + let(:selectors) do + [ { pacticipant_name: "foo" } ] + end + + let(:options) do + { latest: true, tag: "prod" } + end + + before do + td.create_pact_with_hierarchy("foo", "1", "bar") + .create_verification(provider_version: "2", tag_names: ["prod"]) + end + + subject { Service.find(selectors, options) } + + it "returns a QueryResultsWithDeploymentStatusSummary" do + expect(subject.rows).to be_a(Array) + expect(subject.selectors).to be selectors + expect(subject.options).to be options + expect(subject.resolved_selectors).to be_a(Array) + expect(subject.resolved_selectors.count).to eq 2 + expect(subject.deployment_status_summary).to be_a(DeploymentStatusSummary) + end + end + describe "validate_selectors" do subject { Service.validate_selectors(selectors) }