Skip to content

Commit

Permalink
feat: add content type to return pact with extra metadata (eg tags)
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Aug 26, 2019
1 parent 2e9611a commit 7666863
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 13 deletions.
39 changes: 39 additions & 0 deletions lib/pact_broker/api/decorators/extended_pact_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'pact_broker/api/decorators/pact_decorator'

module PactBroker
module Api
module Decorators
class ExtendedPactDecorator < PactDecorator
class TagDecorator < BaseDecorator
property :name
property :latest, getter: ->(_) { true }

link "pb:latest-pact" do | opts |
{
name: "The latest pact with the tag #{represented.name}",
href: latest_tagged_pact_url(represented.pact, represented.name, opts[:base_url])
}
end
end

property :content_hash, as: :contract
collection :head_tags, exec_context: :decorator, as: :tags, embedded: true, extend: TagDecorator

# TODO rather than remove the contract keys that we added in the super class,
# it would be better to inherit from a shared super class
def to_hash(options = {})
keys_to_remove = represented.content_hash.keys
super.each_with_object({}) do | (key, value), new_hash |
new_hash[key] = value unless keys_to_remove.include?(key)
end
end

def head_tags
represented.head_tag_names.collect do | tag_name |
OpenStruct.new(name: tag_name, pact: represented)
end
end
end
end
end
end
3 changes: 0 additions & 3 deletions lib/pact_broker/api/decorators/pact_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
require 'pact_broker/api/decorators/timestamps'

module PactBroker

module Api

module Decorators

class PactDecorator < BaseDecorator

include Timestamps
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def latest_untagged_pact_url pact, base_url
"#{pactigration_base_url(base_url, pact)}/latest-untagged"
end

def latest_tagged_pact_url pact, tag_name, base_url
"#{latest_pact_url(base_url, pact)}/#{url_encode(tag_name)}"
end

def latest_pacts_url base_url
"#{base_url}/pacts/latest"
end
Expand Down
9 changes: 8 additions & 1 deletion lib/pact_broker/api/resources/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'pact_broker/api/resources/base_resource'
require 'pact_broker/api/resources/pacticipant_resource_methods'
require 'pact_broker/api/decorators/pact_decorator'
require 'pact_broker/api/decorators/extended_pact_decorator'
require 'pact_broker/json'
require 'pact_broker/pacts/pact_params'
require 'pact_broker/api/contracts/put_pact_params_contract'
Expand All @@ -26,7 +27,9 @@ class Pact < BaseResource
def content_types_provided
[["application/hal+json", :to_json],
["application/json", :to_json],
["text/html", :to_html]]
["text/html", :to_html],
["application/vnd.pactbroker.pact.v1+json", :to_extended_json]
]
end

def content_types_accepted
Expand Down Expand Up @@ -78,6 +81,10 @@ def to_json
PactBroker::Api::Decorators::PactDecorator.new(pact).to_json(user_options: decorator_context(metadata: identifier_from_path[:metadata]))
end

def to_extended_json
PactBroker::Api::Decorators::ExtendedPactDecorator.new(pact).to_json(user_options: decorator_context(metadata: identifier_from_path[:metadata]))
end

def to_html
PactBroker.configuration.html_pact_renderer.call(
pact, {
Expand Down
3 changes: 1 addition & 2 deletions lib/pact_broker/domain/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module PactBroker
module Domain
class Pact

attr_accessor :id, :provider, :consumer_version, :consumer, :created_at, :json_content, :consumer_version_number, :revision_number, :pact_version_sha, :latest_verification
attr_accessor :id, :provider, :consumer_version, :consumer, :created_at, :json_content, :consumer_version_number, :revision_number, :pact_version_sha, :latest_verification, :head_tag_names

def initialize attributes
attributes.each_pair do | key, value |
Expand Down Expand Up @@ -54,6 +54,5 @@ def pact_publication_id
id
end
end

end
end
9 changes: 8 additions & 1 deletion lib/pact_broker/pacts/all_pact_publications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,14 @@ def to_domain_without_tags
consumer_version_number: consumer_version_number,
revision_number: revision_number,
pact_version_sha: pact_version_sha,
created_at: created_at)
created_at: created_at,
head_tag_names: head_tag_names)
end

def head_tag_names
# Avoid circular dependency
require 'pact_broker/pacts/latest_tagged_pact_publications'
LatestTaggedPactPublications.where(id: id).select(:tag_name).collect{|t| t[:tag_name]}
end

def to_domain_with_content
Expand Down
9 changes: 7 additions & 2 deletions lib/pact_broker/pacts/pact_publication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ def before_create
self.revision_number ||= 1
end

def latest_tag_names
def head_tag_names
LatestTaggedPactPublications.where(id: id).select(:tag_name).collect{|t| t[:tag_name]}
end

def consumer_version_tags
consumer_version.tags
end

def latest_verification
pact_version.latest_verification
end
Expand All @@ -50,7 +54,8 @@ def to_domain
json_content: pact_version.content,
pact_version_sha: pact_version.sha,
latest_verification: latest_verification,
created_at: created_at
created_at: created_at,
head_tag_names: head_tag_names
)
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require 'pact_broker/api/decorators/extended_pact_decorator'

module PactBroker
module Api
module Decorators
describe ExtendedPactDecorator do
before do
allow(decorator).to receive(:templated_diff_url).and_return('templated-diff-url')
allow(decorator).to receive(:verification_publication_url).and_return('verification-publication-url')
end
let(:content_hash) {
{
'consumer' => {'name' => 'Consumer'},
'provider' => {'name' => 'Provider'},
'interactions' => [],
'metadata' => {}
}
}

let(:base_url) { 'http://example.org' }
let(:created_at) { Time.new(2014, 3, 4) }
let(:pact) { double('pact',
content_hash: content_hash,
created_at: created_at,
consumer: consumer,
provider: provider,
consumer_version: consumer_version,
consumer_version_number: '1234',
pact_version_sha: '9999',
revision_number: 2,
name: 'A Pact',
head_tag_names: head_tag_names
)}
let(:head_tag_names) { ['prod'] }
let(:consumer) { instance_double(PactBroker::Domain::Pacticipant, name: 'A Consumer')}
let(:provider) { instance_double(PactBroker::Domain::Pacticipant, name: 'A Provider')}
let(:consumer_version) { instance_double(PactBroker::Domain::Version, number: '1234', pacticipant: consumer)}
let(:metadata) { "abcd" }
let(:decorator) { ExtendedPactDecorator.new(pact) }
let(:json) { decorator.to_json(user_options: { base_url: base_url, metadata: metadata }) }
subject { JSON.parse(json, symbolize_names: true) }

it "includes an array of tags" do
expect(subject[:_embedded][:tags].first).to include name: 'prod', latest: true
# Can't seem to stub the verification_publication_url method on the TagDecorator
expect(subject[:_embedded][:tags].first[:_links][:'pb:latest-pact'][:href]).to eq "http://example.org/pacts/provider/A%20Provider/consumer/A%20Consumer/latest/prod"
end

it "includes the pact contents under the contract key" do
expect(subject[:contract]).to eq JSON.parse(content_hash.to_json, symbolize_names: true)
end

it "does not include the contract contents in the root" do
expect(subject).to_not have_key(:interactions)
end
end
end
end
end
1 change: 0 additions & 1 deletion spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module PactBroker
module Api
module Decorators
describe PactDecorator do

before do
allow(decorator).to receive(:templated_diff_url).and_return('templated-diff-url')
allow(decorator).to receive(:verification_publication_url).and_return('verification-publication-url')
Expand Down
24 changes: 21 additions & 3 deletions spec/lib/pact_broker/pacts/pact_publication_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,25 @@ module Pacts
end
end

describe "#latest_tag_names" do
describe "#consumer_version_tags" do
before do
td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
.create_consumer_version_tag("no")
.create_consumer_version("3.4.5")
.create_consumer_version_tag("yes")
.create_pact
.create_consumer_version("5.6.7")
.create_consumer_version_tag("no")
end

let(:pact_publication) { PactPublication.find(id: td.pact.id) }

it "" do
expect(pact_publication.consumer_version_tags.collect(&:name)).to eq ["yes"]
end
end

describe "#head_tag_names" do
before do
td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
.create_consumer_version_tag("no")
Expand All @@ -80,13 +98,13 @@ module Pacts

context "when the pact is the latest for a tag" do
it "returns the relevant tag names" do
expect(pact_publication.latest_tag_names).to eq ["yes"]
expect(pact_publication.head_tag_names).to eq ["yes"]
end
end

context "when the pact is not the latest for a tag" do
it "returns the relevant tag names" do
expect(pact_publication.latest_tag_names).to eq ["yes"]
expect(pact_publication.head_tag_names).to eq ["yes"]
end
end
end
Expand Down

0 comments on commit 7666863

Please sign in to comment.