Skip to content

Commit

Permalink
feat(tagged-pact-versions): add endpoint to view and delete a collect…
Browse files Browse the repository at this point in the history
…ion of pact versions by tag
  • Loading branch information
bethesque committed Sep 21, 2018
1 parent c4f23bc commit 615025e
Show file tree
Hide file tree
Showing 14 changed files with 316 additions and 15 deletions.
1 change: 1 addition & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module PactBroker

add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'versions'], Api::Resources::PactVersions, {resource_name: "pact_publications"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'versions', :consumer_version_number], Api::Resources::Pact, {resource_name: "pact_publication", deprecated: true} # Not the standard URL, but keep for backwards compatibility
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'tag', :tag], Api::Resources::TaggedPactVersions, {resource_name: "tagged_pact_publications"}

# Pacts
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number], Api::Resources::Pact, {resource_name: "pact_publication"}
Expand Down
5 changes: 0 additions & 5 deletions lib/pact_broker/api/decorators/pact_version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
require 'pact_broker/api/decorators/timestamps'

module PactBroker

module Api

module Decorators

class PactVersionDecorator < BaseDecorator

include Timestamps

property :consumer_version, as: :consumerVersion, embedded: true, decorator: EmbeddedVersionDecorator
Expand All @@ -20,7 +16,6 @@ class PactVersionDecorator < BaseDecorator
title: represented.name
}
end

end
end
end
Expand Down
46 changes: 46 additions & 0 deletions lib/pact_broker/api/decorators/tagged_pact_versions_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require_relative 'base_decorator'
require_relative 'pact_version_decorator'

module PactBroker
module Api
module Decorators
class TaggedPactVersionsDecorator < BaseDecorator

collection :entries, as: :pacts, embedded: true, :extend => PactBroker::Api::Decorators::PactVersionDecorator

link :self do | context |
{
href: context[:resource_url],
title: "All versions of the pact between #{context[:consumer_name]} and #{context[:provider_name]} with tag #{context[:tag]}"
}
end

link :'pb:consumer' do | context |
{
href: pacticipant_url(context[:base_url], OpenStruct.new(name: context[:consumer_name])),
title: "Consumer",
name: context[:consumer_name]
}
end

link :'pb:provider' do | context |
{
href: pacticipant_url(context[:base_url], OpenStruct.new(name: context[:provider_name])),
title: "Provider",
name: context[:provider_name]
}
end

links :'pb:pact-versions' do | context |
represented.collect do | pact |
{
:href => pact_url(context[:base_url], pact),
:title => "Pact version",
:name => pact.version_and_updated_date
}
end
end
end
end
end
end
6 changes: 6 additions & 0 deletions lib/pact_broker/api/resources/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ def links
title: 'Latest pact versions',
templated: false
},
'pb:tagged-pact-versions' =>
{
href: base_url + '/pacts/provider/{provider}/consumer/{consumer}/tag/{tag}',
title: 'All versions of a pact for a given consumer, provider and consumer version tag',
templated: false
},
'pb:pacticipants' =>
{
href: base_url + '/pacticipants',
Expand Down
38 changes: 38 additions & 0 deletions lib/pact_broker/api/resources/tagged_pact_versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'pact_broker/api/resources/base_resource'
require 'pact_broker/configuration'
require 'pact_broker/api/decorators/tagged_pact_versions_decorator'

module PactBroker
module Api
module Resources
class TaggedPactVersions < BaseResource

def content_types_provided
[["application/hal+json", :to_json]]
end

def allowed_methods
["GET", "DELETE", "OPTIONS"]
end

def resource_exists?
pacticipant_service.find_pacticipant_by_name(consumer_name) &&
pacticipant_service.find_pacticipant_by_name(provider_name)
end

def to_json
PactBroker::Api::Decorators::TaggedPactVersionsDecorator.new(pacts).to_json(user_options: decorator_context(identifier_from_path))
end

def delete_resource
pact_service.delete_all_pact_versions_between consumer_name, and: provider_name, tag: identifier_from_path[:tag]
true
end

def pacts
pact_service.find_all_pact_versions_between consumer_name, and: provider_name, tag: identifier_from_path[:tag]
end
end
end
end
end
7 changes: 7 additions & 0 deletions lib/pact_broker/doc/views/index/tagged-pact-versions.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Tagged pact versions

Allowed methods: `GET`, `DELETE`

Lists all the pact versions with the specified consumer, provider and consumer version tag.

Send a `DELETE` request to the resource to batch delete all the versions.
21 changes: 17 additions & 4 deletions lib/pact_broker/pacts/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ def delete_by_version_id version_id
end

def find_all_pact_versions_between consumer_name, options
provider_name = options.fetch(:and)
LatestPactPublicationsByConsumerVersion
find_all_database_versions_between(consumer_name, options)
.eager(:tags)
.consumer(consumer_name)
.provider(provider_name)
.reverse_order(:consumer_version_order)
.collect(&:to_domain)
end

def delete_all_pact_versions_between consumer_name, options
ids = find_all_database_versions_between(consumer_name, options).select_for_subquery(:id)
PactPublication.where(id: ids).delete
end

def find_latest_pact_versions_for_provider provider_name, tag = nil
if tag
LatestTaggedPactPublications.provider(provider_name).order_ignore_case(:consumer_name).where(tag_name: tag).collect(&:to_domain)
Expand Down Expand Up @@ -255,6 +257,17 @@ def create_pact_version consumer_id, provider_id, sha, json_content
pact_version = PactVersion.new(consumer_id: consumer_id, provider_id: provider_id, sha: sha, content: json_content)
pact_version.save
end

def find_all_database_versions_between(consumer_name, options)
provider_name = options.fetch(:and)

query = LatestPactPublicationsByConsumerVersion
.consumer(consumer_name)
.provider(provider_name)

query = query.tag(options[:tag]) if options[:tag]
query
end
end
end
end
4 changes: 4 additions & 0 deletions lib/pact_broker/pacts/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ def find_all_pact_versions_between consumer, options
pact_repository.find_all_pact_versions_between consumer, options
end

def delete_all_pact_versions_between consumer, options
pact_repository.delete_all_pact_versions_between consumer, options
end

def find_latest_pact_versions_for_provider provider_name, options = {}
pact_repository.find_latest_pact_versions_for_provider provider_name, options[:tag]
end
Expand Down
22 changes: 22 additions & 0 deletions spec/features/get_tagged_pact_versions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
describe "retrieving tagged pact versions" do

let(:path) { "/pacts/provider/Provider/consumer/Consumer/tag/prod"}

subject { get path; last_response }
let(:json_response_body) { JSON.parse(subject.body, symbolize_names: true) }

before do
TestDataBuilder.new
.create_consumer("Consumer")
.create_provider("Provider")
.create_consumer_version("1.2.3")
.create_consumer_version_tag("prod")
.create_pact
.create_consumer_version("4.5.6")
.create_pact
end

it "returns the latest tagged pact version" do
expect(json_response_body[:_links][:self][:href]).to end_with("1.2.3")
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
require 'pact_broker/api/decorators/pact_version_decorator'

module PactBroker

module Api

module Decorators

describe PactVersionDecorator do

let(:json_content) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'pact_broker/api/decorators/tagged_pact_versions_decorator'

def register_fixture name
yield
end


module PactBroker
module Api
module Decorators
describe TaggedPactVersionsDecorator do

let(:user_options) do
register_fixture(:tagged_pact_versions_decorator_args) do
{
consumer_name: "Foo",
provider_name: "Bar"
}
end
end

let(:pact_versions) { [pact_version] }
let(:pact_version) do
instance_double("PactBroker::Domain::Pact")
end

let(:decorator) { TaggedPactVersionsDecorator.new(pact_versions) }
let(:json) { decorator.to_json(user_options: user_options) }
subject { JSON.parse(json) }

xit "" do
subject(subject['_links']['pb:consumer']).to eq({})
end

end
end
end
end
86 changes: 86 additions & 0 deletions spec/lib/pact_broker/api/resources/tagged_pact_versions_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
require 'pact_broker/api/resources/tagged_pact_versions'

module PactBroker
module Api
module Resources
describe TaggedPactVersions do
include_context "stubbed services"

before do
allow(pacticipant_service).to receive(:find_pacticipant_by_name).with("Foo").and_return(consumer)
allow(pacticipant_service).to receive(:find_pacticipant_by_name).with("Bar").and_return(provider)
end

let(:path) { "/pacts/provider/Bar/consumer/Foo/tag/prod" }
let(:consumer) { double('Bar') }
let(:provider) { double('Foo') }

context "GET" do
before do
allow(PactBroker::Api::Decorators::TaggedPactVersionsDecorator).to receive(:new).and_return(decorator)
allow(pact_service).to receive(:find_all_pact_versions_between).and_return(pact_versions)
end

let(:decorator) { instance_double(PactBroker::Api::Decorators::TaggedPactVersionsDecorator, to_json: 'json') }
let(:pact_versions) { double('pacts') }

subject { get(path) }

let(:user_options) do
{
base_url: "http://example.org",
resource_url: "http://example.org/pacts/provider/Bar/consumer/Foo/tag/prod",
consumer_name: "Foo",
provider_name: "Bar",
tag: "prod"
}
end

it "finds all the pacts with the given consumer/provider/tag" do
expect(pact_service).to receive(:find_all_pact_versions_between).with("Foo", and: "Bar", tag: "prod")
subject
end

it "returns a 200 OK hal+json response" do
expect(subject).to be_a_hal_json_success_response
end

it "creates a JSON representation of the pact versions" do
expect(PactBroker::Api::Decorators::TaggedPactVersionsDecorator).to receive(:new).with(pact_versions)
expect(decorator).to receive(:to_json).with(user_options: hash_including(user_options))
subject
end

it "returns the JSON representation of the pact versions" do
expect(subject.body).to eq 'json'
end

context "with the consumer or provider do not exist" do
let(:consumer) { nil }

it "returns a 404" do
expect(subject).to be_a_404_response
end
end
end

context "DELETE" do
before do
allow(pact_service).to receive(:delete_all_pact_versions_between)
end

subject { delete(path) }

it "deletes all the pacts with the given consumer/provider/tag" do
expect(pact_service).to receive(:delete_all_pact_versions_between).with("Foo", and: "Bar", tag: "prod")
subject
end

it "returns a 204" do
expect(subject.status).to eq 204
end
end
end
end
end
end
Loading

0 comments on commit 615025e

Please sign in to comment.