diff --git a/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb b/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb index bcd5baa38..67e97d219 100644 --- a/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +++ b/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb @@ -7,20 +7,11 @@ module PactBroker module Api module Decorators class VerifiablePactDecorator < BaseDecorator - - # Allows a "flat" VerifiablePact to look like it has - # a nested verification_properties object for Reform - class Reshaper < SimpleDelegator - def verification_properties - __getobj__() - end - end - def initialize(verifiable_pact) - super(Reshaper.new(verifiable_pact)) + super(verifiable_pact) end - property :verification_properties, as: :verificationProperties do + nested :verificationProperties do include PactBroker::Api::PactBrokerUrls property :pending, diff --git a/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb b/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb index 907594702..d31efc4c7 100644 --- a/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +++ b/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb @@ -2,6 +2,8 @@ require_relative 'verifiable_pact_decorator' require 'pact_broker/api/pact_broker_urls' require 'pact_broker/hash_refinements' +require 'pact_broker/pacts/selector' +require 'pact_broker/pacts/selectors' module PactBroker module Api @@ -11,7 +13,7 @@ class VerifiablePactsQueryDecorator < BaseDecorator collection :provider_version_tags, default: [] - collection :consumer_version_selectors, default: [], class: OpenStruct do + collection :consumer_version_selectors, default: PactBroker::Pacts::Selectors.new, class: PactBroker::Pacts::Selector do property :tag property :latest, setter: ->(fragment:, represented:, **) { @@ -31,7 +33,11 @@ class VerifiablePactsQueryDecorator < BaseDecorator def from_hash(hash) # This handles both the snakecase keys from the GET query and the camelcase JSON POST body - super(hash&.snakecase_keys) + result = super(hash&.snakecase_keys) + if result.consumer_version_selectors && !result.consumer_version_selectors.is_a?(PactBroker::Pacts::Selectors) + result.consumer_version_selectors = PactBroker::Pacts::Selectors.new(result.consumer_version_selectors) + end + result end end end diff --git a/lib/pact_broker/pacts/repository.rb b/lib/pact_broker/pacts/repository.rb index 43b51af35..1b042492f 100644 --- a/lib/pact_broker/pacts/repository.rb +++ b/lib/pact_broker/pacts/repository.rb @@ -207,7 +207,7 @@ def find_wip_pact_versions_for_provider provider_name, provider_tags_names = [], pre_existing_pending_tags = pending_tag_names & pre_existing_tag_names if pre_existing_pending_tags.any? - selectors = Selectors.create_for_overall_latest_of_each_tag(pact.head_tag_names) + selectors = Selectors.create_for_latest_of_each_tag(pact.head_tag_names) VerifiablePact.new(pact.to_domain, selectors, true, pre_existing_pending_tags, [], nil, true) end end.compact @@ -391,7 +391,7 @@ def find_pacts_for_which_the_latest_version_for_the_tag_is_required(provider_nam .values .collect do | pact_publications | selector_tag_names = pact_publications.collect(&:tag_name) - selectors = Selectors.create_for_overall_latest_of_each_tag(selector_tag_names) + selectors = Selectors.create_for_latest_of_each_tag(selector_tag_names) last_pact_publication = pact_publications.sort_by(&:consumer_version_order).last pact_publication = PactPublication.find(id: last_pact_publication.id) SelectedPact.new( diff --git a/lib/pact_broker/pacts/selector.rb b/lib/pact_broker/pacts/selector.rb index 867665036..3d7f21a8e 100644 --- a/lib/pact_broker/pacts/selector.rb +++ b/lib/pact_broker/pacts/selector.rb @@ -1,10 +1,22 @@ module PactBroker module Pacts class Selector < Hash - def initialize(options) + def initialize(options = {}) merge!(options) end + def tag= tag + self[:tag] = tag + end + + def latest= latest + self[:latest] = latest + end + + def latest + self[:latest] + end + def self.overall_latest Selector.new(latest: true) end @@ -56,10 +68,6 @@ def <=> other def latest? self[:latest] end - - def latest - self[:latest] - end end end end diff --git a/lib/pact_broker/pacts/selectors.rb b/lib/pact_broker/pacts/selectors.rb index c434ea15a..159eb3e11 100644 --- a/lib/pact_broker/pacts/selectors.rb +++ b/lib/pact_broker/pacts/selectors.rb @@ -3,7 +3,7 @@ module PactBroker module Pacts class Selectors < Array - def initialize selectors + def initialize selectors = [] super(selectors) end @@ -11,7 +11,7 @@ def self.create_for_all_of_each_tag(tag_names) Selectors.new(tag_names.collect{ | tag_name | Selector.all_for_tag(tag_name) }) end - def self.create_for_overall_latest_of_each_tag(tag_names) + def self.create_for_latest_of_each_tag(tag_names) Selectors.new(tag_names.collect{ | tag_name | Selector.latest_for_tag(tag_name) }) end diff --git a/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb b/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb index 1cc13f6fa..f8e7fb3b3 100644 --- a/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +++ b/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb @@ -21,6 +21,10 @@ module Decorators [{"tag" => "dev", "ignored" => "foo", "latest" => true}] end + it "parses the consumer_version_selectors to a Selectors collection" do + expect(subject.consumer_version_selectors).to be_a(PactBroker::Pacts::Selectors) + end + context "when latest is not specified" do let(:consumer_version_selectors) do [{"tag" => "dev"}] @@ -32,14 +36,14 @@ module Decorators end it "parses the latest as a boolean" do - expect(subject.consumer_version_selectors.first.latest).to be true + expect(subject.consumer_version_selectors.first).to eq PactBroker::Pacts::Selector.new(tag: "dev", latest: true) end context "when there are no consumer_version_selectors" do let(:params) { {} } it "returns an empty array" do - expect(subject.consumer_version_selectors).to eq [] + expect(subject.consumer_version_selectors).to eq PactBroker::Pacts::Selectors.new end end @@ -69,7 +73,7 @@ module Decorators end it "parses a string 'latest' to a boolean" do - expect(subject.consumer_version_selectors.first.latest).to be true + expect(subject.consumer_version_selectors.first).to eq PactBroker::Pacts::Selector.new(tag: "dev", latest: true) end end diff --git a/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb b/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb index e415033d0..044f6fe6d 100644 --- a/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +++ b/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb @@ -31,7 +31,7 @@ module Resources expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with( "Bar", ["master"], - [OpenStruct.new(tag: "dev", latest: true)], + PactBroker::Pacts::Selectors.new([PactBroker::Pacts::Selector.latest_for_tag("dev")]), { include_wip_pacts_since: DateTime.parse('2018-01-01'), include_pending_status: true @@ -77,7 +77,7 @@ module Resources expect(PactBroker::Pacts::Service).to receive(:find_for_verification).with( "Bar", ["master"], - [OpenStruct.new(tag: "dev", latest: true)], + PactBroker::Pacts::Selectors.new([PactBroker::Pacts::Selector.latest_for_tag("dev")]), { include_wip_pacts_since: DateTime.parse('2018-01-01'), include_pending_status: true diff --git a/spec/lib/pact_broker/pacts/selector_spec.rb b/spec/lib/pact_broker/pacts/selector_spec.rb new file mode 100644 index 000000000..88794c71c --- /dev/null +++ b/spec/lib/pact_broker/pacts/selector_spec.rb @@ -0,0 +1,28 @@ +require 'pact_broker/pacts/selector' + +module PactBroker + module Pacts + describe Selector do + describe "<=>" do + let(:overall_latest_1) { Selector.overall_latest } + let(:overall_latest_2) { Selector.overall_latest } + let(:latest_for_tag_prod) { Selector.latest_for_tag('prod') } + let(:latest_for_tag_dev) { Selector.latest_for_tag('dev') } + let(:all_prod) { Selector.all_for_tag('prod') } + let(:all_dev) { Selector.all_for_tag('dev') } + + let(:unsorted_selectors) do + [all_prod, all_dev, latest_for_tag_prod, overall_latest_1, overall_latest_1, latest_for_tag_dev] + end + + let(:expected_sorted_selectors) do + [overall_latest_1, overall_latest_1, latest_for_tag_dev, latest_for_tag_prod, all_dev, all_prod] + end + + it "sorts the selectors" do + expect(unsorted_selectors.sort).to eq(expected_sorted_selectors) + end + end + end + end +end diff --git a/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb b/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb index 171f763ee..160d7e782 100644 --- a/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +++ b/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb @@ -33,24 +33,24 @@ module Pacts end context "when there is 1 head consumer tags" do - let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev]) } + let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[dev]) } its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact for a consumer version tagged 'dev'" } its(:pact_description) { is_expected.to eq "Pact between Foo and Bar, consumer version 123, latest dev"} end context "when there are 2 head consumer tags" do - let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev prod]) } + let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[dev prod]) } its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criteria: latest pact for a consumer version tagged 'dev', latest pact for a consumer version tagged 'prod' (both have the same content)" } end context "when there are 3 head consumer tags" do - let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev prod feat-x]) } + let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[dev prod feat-x]) } its(:inclusion_reason) { is_expected.to include " (all have the same content)" } end context "when the pact is a WIP pact" do - let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[feat-x]) } + let(:selectors) { Selectors.create_for_latest_of_each_tag(%w[feat-x]) } let(:wip) { true } let(:pending) { true } let(:pending_provider_tags) { %w[dev] }