Skip to content

Commit 044bab7

Browse files
committed
feat: created dashboard API
1 parent d4fc8a6 commit 044bab7

File tree

8 files changed

+280
-1
lines changed

8 files changed

+280
-1
lines changed

lib/pact_broker/api.rb

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ module PactBroker
6464
add ['matrix', 'provider', :provider_name, 'latest', :provider_tag, 'consumer', :consumer_name, 'latest', :tag, 'badge'], Api::Resources::MatrixBadge, {resource_name: "matrix_tag_badge"}
6565
add ['matrix'], Api::Resources::Matrix, {resource_name: "matrix"}
6666

67+
add ['dashboard'], Api::Resources::Dashboard, {resource_name: "dashboard"}
6768
add [], Api::Resources::Index, {resource_name: "index"}
6869
end
6970
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
require 'ostruct'
2+
require 'pact_broker/api/pact_broker_urls'
3+
4+
module PactBroker
5+
module Api
6+
module Decorators
7+
class DashboardDecorator
8+
include PactBroker::Api::PactBrokerUrls
9+
10+
def initialize(index_items)
11+
@index_items = index_items
12+
end
13+
14+
def to_json(options)
15+
to_hash(options).to_json
16+
end
17+
18+
def to_hash(options)
19+
{
20+
items: items(index_items, options[:user_options][:base_url])
21+
}
22+
end
23+
24+
private
25+
26+
attr_reader :index_items
27+
28+
def items(index_items, base_url)
29+
index_items.collect do | index_item |
30+
index_item_hash(index_item.consumer, index_item.provider, index_item.consumer_version, index_item, base_url)
31+
end
32+
end
33+
34+
def index_item_hash(consumer, provider, consumer_version, index_item, base_url)
35+
{
36+
consumer: consumer_hash(index_item, consumer, consumer_version, base_url),
37+
provider: provider_hash(index_item, provider, base_url),
38+
pact: pact_hash(index_item, base_url),
39+
latestVerificationResult: verification_hash(index_item, base_url),
40+
verificationStatus: index_item.verification_status.to_s,
41+
webhookStatus: index_item.webhook_status.to_s,
42+
latestWebhookExecution: latest_webhook_execution(index_item, base_url),
43+
_links: links(index_item, base_url)
44+
45+
}
46+
end
47+
48+
def consumer_hash(index_item, consumer, consumer_version, base_url)
49+
{
50+
name: index_item.consumer_name,
51+
version: {
52+
number: index_item.consumer_version_number,
53+
_links: {
54+
self: {
55+
href: version_url(base_url, index_item.consumer_version)
56+
}
57+
}
58+
},
59+
_links: {
60+
self: {
61+
href: pacticipant_url(base_url, index_item.consumer)
62+
}
63+
}
64+
}
65+
end
66+
67+
def provider_hash(index_item, provider, base_url)
68+
hash = {
69+
name: index_item.provider_name,
70+
version: nil,
71+
_links: {
72+
self: {
73+
href: pacticipant_url(base_url, index_item.provider)
74+
}
75+
}
76+
}
77+
78+
if index_item.latest_verification
79+
hash[:version] = { number: index_item.provider_version_number }
80+
end
81+
82+
hash
83+
end
84+
85+
def pact_hash(index_item, base_url)
86+
{
87+
createdAt: index_item.latest_pact.created_at.to_datetime.xmlschema,
88+
_links: {
89+
self: {
90+
href: pact_url(base_url, index_item.latest_pact)
91+
}
92+
}
93+
}
94+
end
95+
96+
def verification_hash(index_item, base_url)
97+
if index_item.latest_verification
98+
{
99+
success: index_item.latest_verification.success,
100+
verifiedAt: index_item.latest_verification.created_at.to_datetime.xmlschema,
101+
_links: {
102+
self: {
103+
href: verification_url(index_item.latest_verification, base_url)
104+
}
105+
}
106+
}
107+
else
108+
nil
109+
end
110+
end
111+
112+
def latest_webhook_execution(index_item, base_url)
113+
if index_item.last_webhook_execution_date
114+
{
115+
triggeredAt: index_item.last_webhook_execution_date.to_datetime.xmlschema
116+
}
117+
end
118+
end
119+
120+
def links(index_item, base_url)
121+
{
122+
'pb:webhook-status' => {
123+
title: "Status of webhooks for #{index_item.consumer_name}/#{index_item.provider_name} pact",
124+
href: webhooks_status_url(index_item.consumer, index_item.provider, base_url)
125+
}
126+
}
127+
end
128+
end
129+
end
130+
end
131+
end

lib/pact_broker/api/resources/dashboard.rb

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'pact_broker/api/resources/base_resource'
2+
require 'pact_broker/api/decorators/dashboard_decorator'
23

34
module PactBroker
45
module Api
@@ -15,7 +16,13 @@ def allowed_methods
1516
end
1617

1718
def to_json
19+
PactBroker::Api::Decorators::DashboardDecorator.new(index_items).to_json(user_options: decorator_context)
20+
end
21+
22+
private
1823

24+
def index_items
25+
index_service.find_index_items
1926
end
2027
end
2128
end

lib/pact_broker/domain/index_item.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module PactBroker
55
module Domain
66
class IndexItem
77

8-
attr_reader :consumer, :provider, :latest_pact, :latest_verification, :webhooks
8+
attr_reader :consumer, :provider, :latest_pact, :latest_verification, :webhooks, :triggered_webhooks
99

1010
def initialize consumer, provider, latest_pact = nil, latest = true, latest_verification = nil, webhooks = [], triggered_webhooks = [], tags = []
1111
@consumer = consumer
@@ -54,6 +54,10 @@ def consumer_version_number
5454
@latest_pact.consumer_version_number
5555
end
5656

57+
def consumer_version
58+
@latest_pact.consumer_version
59+
end
60+
5761
def provider_version_number
5862
@latest_verification ? @latest_verification.provider_version_number : nil
5963
end

pact_broker.gemspec

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Gem::Specification.new do |gem|
4040
gem.add_runtime_dependency 'table_print', '~> 1.5'
4141

4242
gem.add_development_dependency 'pact', '~>1.14'
43+
gem.add_development_dependency 'rspec-pact-matchers', '~>0.1'
4344
gem.add_development_dependency 'bundler-audit', '~>0.4'
4445
gem.add_development_dependency 'sqlite3', '~>1.3'
4546
gem.add_development_dependency 'pry-byebug'

spec/fixtures/dashboard.json

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"items": [
3+
{
4+
"_links": {
5+
"pb:webhook-status": {
6+
"href": "webhooks_status_url",
7+
"title": "Status of webhooks for Foo/Bar pact"
8+
}
9+
},
10+
"consumer": {
11+
"_links": {
12+
"self": {
13+
"href": "consumer_url"
14+
}
15+
},
16+
"name": "Foo",
17+
"version": {
18+
"_links": {
19+
"self": {
20+
"href": "consumer_version_url"
21+
}
22+
},
23+
"number": "1"
24+
}
25+
},
26+
"latestVerificationResult": {
27+
"_links": {
28+
"self": {
29+
"href": "verification_url"
30+
}
31+
},
32+
"success": true,
33+
"verifiedAt": "2018-01-01T00:00:00+00:00"
34+
},
35+
"latestWebhookExecution": {
36+
"triggeredAt": "2018-01-01T00:00:00+00:00"
37+
},
38+
"pact": {
39+
"_links": {
40+
"self": {
41+
"href": "pact_url"
42+
}
43+
},
44+
"createdAt": "2018-01-01T00:00:00+00:00"
45+
},
46+
"provider": {
47+
"_links": {
48+
"self": {
49+
"href": "provider_url"
50+
}
51+
},
52+
"name": "Bar",
53+
"version": {
54+
"number": "2"
55+
}
56+
},
57+
"verificationStatus": "wiffle",
58+
"webhookStatus": "blah"
59+
}
60+
]
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
require 'pact_broker/api/decorators/dashboard_decorator'
2+
3+
module PactBroker
4+
module Api
5+
module Decorators
6+
describe DashboardDecorator do
7+
let(:index_item) do
8+
instance_double('PactBroker::Domain::IndexItem',
9+
consumer: consumer,
10+
provider: provider,
11+
consumer_name: consumer.name,
12+
provider_name: provider.name,
13+
latest_pact: pact,
14+
latest_verification: verification,
15+
provider_version: provider_version,
16+
consumer_version: consumer_version,
17+
last_webhook_execution_date: last_webhook_execution_date,
18+
webhook_status: 'blah',
19+
verification_status: 'wiffle',
20+
provider_version_number: provider_version.number,
21+
consumer_version_number: consumer_version.number
22+
)
23+
end
24+
let(:consumer) { instance_double('PactBroker::Domain::Pacticipant', name: 'Foo') }
25+
let(:provider) { instance_double('PactBroker::Domain::Pacticipant', name: 'Bar') }
26+
let(:pact) { instance_double('PactBroker::Domain::Pact', created_at: DateTime.new(2018)) }
27+
let(:verification) { instance_double('PactBroker::Domain::Verification', success: true, created_at: DateTime.new(2018)) }
28+
let(:consumer_version) { instance_double('PactBroker::Domain::Version', number: '1', pacticipant: consumer) }
29+
let(:provider_version) { instance_double('PactBroker::Domain::Version', number: '2', pacticipant: provider) }
30+
let(:last_webhook_execution_date) { Date.new(2018) }
31+
let(:base_url) { 'http://example.org' }
32+
let(:options) { { user_options: { base_url: base_url } } }
33+
let(:dashboard_json) { DashboardDecorator.new([index_item]).to_json(options) }
34+
35+
before do
36+
allow_any_instance_of(DashboardDecorator).to receive(:pact_url).with(base_url, pact).and_return('pact_url')
37+
allow_any_instance_of(DashboardDecorator).to receive(:verification_url).with(verification, base_url).and_return('verification_url')
38+
allow_any_instance_of(DashboardDecorator).to receive(:pacticipant_url).with(base_url, consumer).and_return('consumer_url')
39+
allow_any_instance_of(DashboardDecorator).to receive(:pacticipant_url).with(base_url, provider).and_return('provider_url')
40+
allow_any_instance_of(DashboardDecorator).to receive(:version_url).with(base_url, consumer_version).and_return('consumer_version_url')
41+
allow_any_instance_of(DashboardDecorator).to receive(:webhooks_status_url).with(consumer, provider, base_url).and_return('webhooks_status_url')
42+
end
43+
44+
let(:expected_hash) { JSON.parse(File.read('spec/fixtures/dashboard.json')) }
45+
46+
subject { JSON.parse(dashboard_json) }
47+
48+
it "creates some json" do
49+
expect(subject).to match_pact(expected_hash, {allow_unexpected_keys: false})
50+
end
51+
52+
context "when the pact has never been verified" do
53+
let(:verification) { nil }
54+
55+
it "has a null last verification and provider version" do
56+
expected_hash['items'][0]['latestVerificationResult'] = nil
57+
expected_hash['items'][0]['provider']['version'] = nil
58+
expect(subject).to match_pact(expected_hash, {allow_unexpected_keys: false})
59+
end
60+
end
61+
62+
context "when no webhooks have been executed" do
63+
let(:last_webhook_execution_date) { nil }
64+
65+
it "has a null latestWebhookExecution" do
66+
expected_hash['items'][0]['latestWebhookExecution'] = nil
67+
expect(subject).to match_pact(expected_hash, {allow_unexpected_keys: false})
68+
end
69+
end
70+
end
71+
end
72+
end
73+
end

spec/spec_helper.rb

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
require 'rack/test'
1616
require 'pact_broker/api'
1717
require 'rspec/its'
18+
require 'rspec/pact/matchers'
1819
require 'sucker_punch/testing/inline'
1920
require 'webmock/rspec'
2021

0 commit comments

Comments
 (0)