Skip to content

Commit 6925dcb

Browse files
committed
feat(matrix): add endpoint for consumer/provider verification matrix
1 parent d2d4545 commit 6925dcb

14 files changed

+375
-14
lines changed

lib/pact_broker/api.rb

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ module PactBroker
5959
add ['relationships'], Api::Resources::Relationships, {resource_name: "relationships"}
6060
add ['groups', :pacticipant_name], Api::Resources::Group, {resource_name: "group"}
6161

62+
# matrix
63+
add ['the-matrix', 'provider', :provider_name, 'consumer', :consumer_name], Api::Resources::Matrix, {resource_name: "matrix_consumer_provider"}
64+
6265
add [], Api::Resources::Index, {resource_name: "index"}
6366
end
6467
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
require 'ostruct'
2+
require 'pact_broker/api/pact_broker_urls'
3+
4+
module PactBroker
5+
module Api
6+
module Decorators
7+
class MatrixPactDecorator
8+
include PactBroker::Api::PactBrokerUrls
9+
10+
def initialize(lines)
11+
@lines = lines
12+
end
13+
14+
def to_json(options)
15+
to_hash(options).to_json
16+
end
17+
18+
def to_hash(options)
19+
{
20+
matrix: matrix(lines, options[:user_options][:base_url])
21+
}
22+
end
23+
24+
private
25+
26+
attr_reader :lines
27+
28+
def matrix(lines, base_url)
29+
provider = nil
30+
consumer = nil
31+
lines.collect do | line |
32+
provider ||= OpenStruct.new(name: line[:provider_name])
33+
consumer ||= OpenStruct.new(name: line[:consumer_name])
34+
consumer_version = OpenStruct.new(number: line[:consumer_version_number], pacticipant: consumer)
35+
line_hash(consumer, provider, consumer_version, line, base_url)
36+
end
37+
end
38+
39+
def line_hash(consumer, provider, consumer_version, line, base_url)
40+
{
41+
consumer: consumer_hash(line, consumer_version, base_url),
42+
provider: provider_hash(line, provider, base_url),
43+
pact: pact_hash(line, base_url),
44+
verificationResult: verification_hash(line, base_url)
45+
}
46+
end
47+
48+
def consumer_hash(line, consumer_version, base_url)
49+
{
50+
version: {
51+
number: line[:consumer_version_number],
52+
_links: {
53+
self: {
54+
href: version_url(base_url, consumer_version)
55+
}
56+
}
57+
}
58+
}
59+
end
60+
61+
def provider_hash(line, provider, base_url)
62+
if !line[:provider_version].nil?
63+
{
64+
version: {
65+
number: line[:provider_version]
66+
}
67+
}
68+
else
69+
{
70+
version: nil
71+
}
72+
end
73+
end
74+
75+
def pact_hash(line, base_url)
76+
{
77+
_links: {
78+
self: {
79+
href: pact_url_from_params(base_url, line)
80+
}
81+
}
82+
}
83+
end
84+
85+
def verification_hash(line, base_url)
86+
if !line[:success].nil?
87+
{
88+
success: line[:success],
89+
_links: {
90+
self: {
91+
href: verification_url(OpenStruct.new(line), base_url)
92+
}
93+
}
94+
}
95+
else
96+
nil
97+
end
98+
end
99+
end
100+
end
101+
end
102+
end

lib/pact_broker/api/pact_broker_urls.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def verification_url verification, base_url
8080
[ base_url, 'pacts',
8181
'provider', url_encode(verification.provider_name),
8282
'consumer', url_encode(verification.consumer_name),
83-
'pact-version', verification.pact_version.sha,
83+
'pact-version', verification.pact_version_sha,
8484
'verification-results', verification.number
8585
].join('/')
8686
end

lib/pact_broker/api/resources/index.rb

+3-5
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ def to_json
5858
href: base_url + '/webhooks',
5959
title: 'Webhooks',
6060
templated: false
61-
},'curies' =>
61+
},
62+
'curies' =>
6263
[{
6364
name: 'pb',
6465
href: base_url + '/doc/{rel}',
@@ -67,10 +68,7 @@ def to_json
6768
}
6869
}.to_json
6970
end
70-
71-
7271
end
7372
end
74-
7573
end
76-
end
74+
end
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'pact_broker/api/resources/base_resource'
2+
require 'pact_broker/api/decorators/matrix_decorator'
3+
4+
module PactBroker
5+
module Api
6+
module Resources
7+
class Matrix < BaseResource
8+
9+
def content_types_provided
10+
[["application/hal+json", :to_json]]
11+
end
12+
13+
def allowed_methods
14+
["GET"]
15+
end
16+
17+
def resource_exists?
18+
consumer && provider
19+
end
20+
21+
def to_json
22+
lines = matrix_service.find(identifier_from_path)
23+
PactBroker::Api::Decorators::MatrixPactDecorator.new(lines).to_json(user_options: { base_url: base_url })
24+
end
25+
26+
def consumer
27+
@consumer ||= find_pacticipant(identifier_from_path[:consumer_name], "consumer")
28+
end
29+
30+
def provider
31+
@provider ||= find_pacticipant(identifier_from_path[:provider_name], "provider")
32+
end
33+
34+
def find_pacticipant name, role
35+
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
36+
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
37+
end
38+
end
39+
end
40+
end
41+
end
42+
end

lib/pact_broker/matrix/repository.rb

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require 'pact_broker/repositories/helpers'
2+
3+
module PactBroker
4+
module Matrix
5+
class Repository
6+
include PactBroker::Repositories::Helpers
7+
8+
def find consumer_name, provider_name
9+
PactBroker::Pacts::LatestPactPublicationsByConsumerVersion
10+
.left_outer_join(:latest_verifications, pact_version_id: :pact_version_id)
11+
.consumer(consumer_name)
12+
.provider(provider_name)
13+
.reverse(:consumer_version_order)
14+
.all
15+
.collect(&:values)
16+
end
17+
end
18+
end
19+
end

lib/pact_broker/matrix/service.rb

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require 'pact_broker/repositories'
2+
3+
module PactBroker
4+
module Matrix
5+
module Service
6+
extend self
7+
8+
extend PactBroker::Repositories
9+
10+
def find params
11+
matrix_repository.find params[:consumer_name], params[:provider_name]
12+
end
13+
end
14+
end
15+
end

lib/pact_broker/repositories.rb

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def verification_repository
3737
Verifications::Repository.new
3838
end
3939

40+
def matrix_repository
41+
require 'pact_broker/matrix/repository'
42+
Matrix::Repository.new
43+
end
44+
4045
extend self
4146
end
4247
end

lib/pact_broker/services.rb

+5
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,10 @@ def badge_service
4646
require 'pact_broker/badges/service'
4747
Badges::Service
4848
end
49+
50+
def matrix_service
51+
require 'pact_broker/matrix/service'
52+
Matrix::Service
53+
end
4954
end
5055
end

spec/features/get_matrix_spec.rb

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'spec/support/test_data_builder'
2+
3+
describe "Get matrix" do
4+
before do
5+
TestDataBuilder.new
6+
.create_pact_with_hierarchy('Consumer', '1.0.0', 'Provider')
7+
.create_verification(provider_version: '4.5.6')
8+
end
9+
10+
let(:path) { "/the-matrix/provider/Provider/consumer/Consumer" }
11+
let(:last_response_body) { JSON.parse(subject.body, symbolize_names: true) }
12+
13+
subject { get path; last_response }
14+
15+
it "returns a 200 HAL JSON response" do
16+
expect(subject).to be_a_hal_json_success_response
17+
end
18+
19+
it "returns the JSON representation of the matrix" do
20+
expect(last_response_body[:matrix][0][:consumer]).to be_instance_of(Hash)
21+
expect(last_response_body[:matrix][0][:provider]).to be_instance_of(Hash)
22+
expect(last_response_body[:matrix][0][:pact]).to be_instance_of(Hash)
23+
expect(last_response_body[:matrix][0][:verificationResult]).to be_instance_of(Hash)
24+
end
25+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
require 'pact_broker/api/decorators/matrix_decorator'
2+
3+
module PactBroker
4+
module Api
5+
module Decorators
6+
describe MatrixPactDecorator do
7+
describe "to_json" do
8+
let(:line_1) do
9+
{
10+
consumer_name: "Consumer",
11+
consumer_version_number: "1.0.0",
12+
pact_version_sha: "1234",
13+
provider_version: "4.5.6",
14+
provider_name: "Provider",
15+
success: true,
16+
number: 1,
17+
build_url: nil,
18+
execution_date: DateTime.now
19+
}
20+
end
21+
22+
let(:line_2) do
23+
{
24+
consumer_name: "Consumer",
25+
consumer_version_number: "1.0.0",
26+
pact_version_sha: "1234",
27+
provider_version: nil,
28+
provider_name: "Provider",
29+
success: nil,
30+
number: nil,
31+
build_url: nil,
32+
execution_date: nil
33+
}
34+
end
35+
36+
let(:consumer_hash) do
37+
{
38+
version: {
39+
number: '1.0.0',
40+
_links: {
41+
self: {
42+
href: 'http://example.org/pacticipants/Consumer/versions/1.0.0'
43+
}
44+
}
45+
}
46+
}
47+
end
48+
49+
let(:provider_hash) do
50+
{
51+
version: {
52+
number: '4.5.6'
53+
}
54+
}
55+
end
56+
57+
let(:verification_hash) do
58+
{
59+
success: true,
60+
_links: {
61+
self: {
62+
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/1"
63+
}
64+
}
65+
}
66+
end
67+
68+
let(:pact_hash) do
69+
{
70+
_links: {
71+
self: {
72+
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/version/1.0.0"
73+
}
74+
}
75+
}
76+
end
77+
78+
let(:lines){ [line_1, line_2]}
79+
let(:json) { MatrixPactDecorator.new(lines).to_json(user_options: { base_url: 'http://example.org' }) }
80+
let(:parsed_json) { JSON.parse(json, symbolize_names: true) }
81+
82+
it "includes the consumer details" do
83+
expect(parsed_json[:matrix][0][:consumer]).to eq consumer_hash
84+
end
85+
86+
it "includes the provider details" do
87+
expect(parsed_json[:matrix][0][:provider]).to eq provider_hash
88+
end
89+
90+
it "includes the verification details" do
91+
expect(parsed_json[:matrix][0][:verificationResult]).to eq verification_hash
92+
end
93+
94+
it "includes the pact details" do
95+
expect(parsed_json[:matrix][0][:pact]).to eq pact_hash
96+
end
97+
98+
context "when the pact has not been verified" do
99+
let(:provider_hash) do
100+
{
101+
version: nil
102+
}
103+
end
104+
105+
let(:verification_hash) do
106+
nil
107+
end
108+
109+
it "has empty provider details" do
110+
expect(parsed_json[:matrix][1][:provider]).to eq provider_hash
111+
end
112+
113+
it "has a nil verificationResult" do
114+
expect(parsed_json[:matrix][1][:verificationResult]).to eq verification_hash
115+
end
116+
end
117+
end
118+
end
119+
end
120+
end
121+
end

0 commit comments

Comments
 (0)