Skip to content

Commit

Permalink
feat(matrix): add endpoint for consumer/provider verification matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Oct 6, 2017
1 parent d2d4545 commit 6925dcb
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 14 deletions.
3 changes: 3 additions & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ module PactBroker
add ['relationships'], Api::Resources::Relationships, {resource_name: "relationships"}
add ['groups', :pacticipant_name], Api::Resources::Group, {resource_name: "group"}

# matrix
add ['the-matrix', 'provider', :provider_name, 'consumer', :consumer_name], Api::Resources::Matrix, {resource_name: "matrix_consumer_provider"}

add [], Api::Resources::Index, {resource_name: "index"}
end
end
Expand Down
102 changes: 102 additions & 0 deletions lib/pact_broker/api/decorators/matrix_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
require 'ostruct'
require 'pact_broker/api/pact_broker_urls'

module PactBroker
module Api
module Decorators
class MatrixPactDecorator
include PactBroker::Api::PactBrokerUrls

def initialize(lines)
@lines = lines
end

def to_json(options)
to_hash(options).to_json
end

def to_hash(options)
{
matrix: matrix(lines, options[:user_options][:base_url])
}
end

private

attr_reader :lines

def matrix(lines, base_url)
provider = nil
consumer = nil
lines.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)
line_hash(consumer, provider, consumer_version, line, base_url)
end
end

def line_hash(consumer, provider, consumer_version, line, base_url)
{
consumer: consumer_hash(line, consumer_version, base_url),
provider: provider_hash(line, provider, base_url),
pact: pact_hash(line, base_url),
verificationResult: verification_hash(line, base_url)
}
end

def consumer_hash(line, consumer_version, base_url)
{
version: {
number: line[:consumer_version_number],
_links: {
self: {
href: version_url(base_url, consumer_version)
}
}
}
}
end

def provider_hash(line, provider, base_url)
if !line[:provider_version].nil?
{
version: {
number: line[:provider_version]
}
}
else
{
version: nil
}
end
end

def pact_hash(line, base_url)
{
_links: {
self: {
href: pact_url_from_params(base_url, line)
}
}
}
end

def verification_hash(line, base_url)
if !line[:success].nil?
{
success: line[:success],
_links: {
self: {
href: verification_url(OpenStruct.new(line), base_url)
}
}
}
else
nil
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def verification_url verification, base_url
[ base_url, 'pacts',
'provider', url_encode(verification.provider_name),
'consumer', url_encode(verification.consumer_name),
'pact-version', verification.pact_version.sha,
'pact-version', verification.pact_version_sha,
'verification-results', verification.number
].join('/')
end
Expand Down
8 changes: 3 additions & 5 deletions lib/pact_broker/api/resources/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def to_json
href: base_url + '/webhooks',
title: 'Webhooks',
templated: false
},'curies' =>
},
'curies' =>
[{
name: 'pb',
href: base_url + '/doc/{rel}',
Expand All @@ -67,10 +68,7 @@ def to_json
}
}.to_json
end


end
end

end
end
end
42 changes: 42 additions & 0 deletions lib/pact_broker/api/resources/matrix.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'pact_broker/api/resources/base_resource'
require 'pact_broker/api/decorators/matrix_decorator'

module PactBroker
module Api
module Resources
class Matrix < BaseResource

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

def allowed_methods
["GET"]
end

def resource_exists?
consumer && provider
end

def to_json
lines = matrix_service.find(identifier_from_path)
PactBroker::Api::Decorators::MatrixPactDecorator.new(lines).to_json(user_options: { base_url: base_url })
end

def consumer
@consumer ||= find_pacticipant(identifier_from_path[:consumer_name], "consumer")
end

def provider
@provider ||= find_pacticipant(identifier_from_path[:provider_name], "provider")
end

def find_pacticipant name, role
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
end
end
end
end
end
end
19 changes: 19 additions & 0 deletions lib/pact_broker/matrix/repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'pact_broker/repositories/helpers'

module PactBroker
module Matrix
class Repository
include PactBroker::Repositories::Helpers

def find consumer_name, provider_name
PactBroker::Pacts::LatestPactPublicationsByConsumerVersion
.left_outer_join(:latest_verifications, pact_version_id: :pact_version_id)
.consumer(consumer_name)
.provider(provider_name)
.reverse(:consumer_version_order)
.all
.collect(&:values)
end
end
end
end
15 changes: 15 additions & 0 deletions lib/pact_broker/matrix/service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'pact_broker/repositories'

module PactBroker
module Matrix
module Service
extend self

extend PactBroker::Repositories

def find params
matrix_repository.find params[:consumer_name], params[:provider_name]
end
end
end
end
5 changes: 5 additions & 0 deletions lib/pact_broker/repositories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ def verification_repository
Verifications::Repository.new
end

def matrix_repository
require 'pact_broker/matrix/repository'
Matrix::Repository.new
end

extend self
end
end
5 changes: 5 additions & 0 deletions lib/pact_broker/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,10 @@ def badge_service
require 'pact_broker/badges/service'
Badges::Service
end

def matrix_service
require 'pact_broker/matrix/service'
Matrix::Service
end
end
end
25 changes: 25 additions & 0 deletions spec/features/get_matrix_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'spec/support/test_data_builder'

describe "Get matrix" do
before do
TestDataBuilder.new
.create_pact_with_hierarchy('Consumer', '1.0.0', 'Provider')
.create_verification(provider_version: '4.5.6')
end

let(:path) { "/the-matrix/provider/Provider/consumer/Consumer" }
let(:last_response_body) { JSON.parse(subject.body, symbolize_names: true) }

subject { get path; last_response }

it "returns a 200 HAL JSON response" do
expect(subject).to be_a_hal_json_success_response
end

it "returns the JSON representation of the matrix" do
expect(last_response_body[:matrix][0][:consumer]).to be_instance_of(Hash)
expect(last_response_body[:matrix][0][:provider]).to be_instance_of(Hash)
expect(last_response_body[:matrix][0][:pact]).to be_instance_of(Hash)
expect(last_response_body[:matrix][0][:verificationResult]).to be_instance_of(Hash)
end
end
121 changes: 121 additions & 0 deletions spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require 'pact_broker/api/decorators/matrix_decorator'

module PactBroker
module Api
module Decorators
describe MatrixPactDecorator do
describe "to_json" do
let(:line_1) do
{
consumer_name: "Consumer",
consumer_version_number: "1.0.0",
pact_version_sha: "1234",
provider_version: "4.5.6",
provider_name: "Provider",
success: true,
number: 1,
build_url: nil,
execution_date: DateTime.now
}
end

let(:line_2) do
{
consumer_name: "Consumer",
consumer_version_number: "1.0.0",
pact_version_sha: "1234",
provider_version: nil,
provider_name: "Provider",
success: nil,
number: nil,
build_url: nil,
execution_date: nil
}
end

let(:consumer_hash) do
{
version: {
number: '1.0.0',
_links: {
self: {
href: 'http://example.org/pacticipants/Consumer/versions/1.0.0'
}
}
}
}
end

let(:provider_hash) do
{
version: {
number: '4.5.6'
}
}
end

let(:verification_hash) do
{
success: true,
_links: {
self: {
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/1"
}
}
}
end

let(:pact_hash) do
{
_links: {
self: {
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/version/1.0.0"
}
}
}
end

let(:lines){ [line_1, line_2]}
let(:json) { MatrixPactDecorator.new(lines).to_json(user_options: { base_url: 'http://example.org' }) }
let(:parsed_json) { JSON.parse(json, symbolize_names: true) }

it "includes the consumer details" do
expect(parsed_json[:matrix][0][:consumer]).to eq consumer_hash
end

it "includes the provider details" do
expect(parsed_json[:matrix][0][:provider]).to eq provider_hash
end

it "includes the verification details" do
expect(parsed_json[:matrix][0][:verificationResult]).to eq verification_hash
end

it "includes the pact details" do
expect(parsed_json[:matrix][0][:pact]).to eq pact_hash
end

context "when the pact has not been verified" do
let(:provider_hash) do
{
version: nil
}
end

let(:verification_hash) do
nil
end

it "has empty provider details" do
expect(parsed_json[:matrix][1][:provider]).to eq provider_hash
end

it "has a nil verificationResult" do
expect(parsed_json[:matrix][1][:verificationResult]).to eq verification_hash
end
end
end
end
end
end
end
Loading

0 comments on commit 6925dcb

Please sign in to comment.