pact_broker 2.4.2 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +4 -2
- data/CHANGELOG.md +54 -0
- data/DEVELOPER_DOCUMENTATION.md +11 -7
- data/README.md +5 -1
- data/UPGRADING.md +18 -0
- data/db/migrations/19_make_pact_version_content_sha_not_nullable.rb +9 -1
- data/db/migrations/25_make_pv_pacticipants_mandatory.rb +8 -0
- data/db/migrations/38_create_triggered_webhooks_table.rb +19 -0
- data/db/migrations/39_add_triggered_webhooks_fk_to_execution.rb +24 -0
- data/db/migrations/40_create_latest_triggered_webhooks_view.rb +24 -0
- data/db/migrations/41_migrate_execution_data.rb +47 -0
- data/db/test/backwards_compatibility/.rspec +3 -0
- data/db/test/backwards_compatibility/Appraisals +49 -0
- data/db/test/backwards_compatibility/Gemfile +11 -0
- data/db/test/backwards_compatibility/Rakefile +55 -0
- data/db/test/backwards_compatibility/config.ru +18 -0
- data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile.lock +210 -0
- data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile.lock +208 -0
- data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile.lock +209 -0
- data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile.lock +197 -0
- data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile.lock +196 -0
- data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile.lock +196 -0
- data/db/test/backwards_compatibility/gemfiles/head.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/head.gemfile.lock +200 -0
- data/db/test/backwards_compatibility/spec/fixtures/foo-bar.json +22 -0
- data/db/test/backwards_compatibility/spec/publish_pact_spec.rb +72 -0
- data/db/test/backwards_compatibility/spec/spec_helper.rb +20 -0
- data/db/test/backwards_compatibility/spec/support/fixture_helpers.rb +12 -0
- data/db/test/backwards_compatibility/spec/support/request_helpers.rb +20 -0
- data/example/Gemfile +2 -2
- data/example/pact_broker_database.sqlite3 +0 -0
- data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -2
- data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -10
- data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +1 -2
- data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +123 -0
- data/lib/pact_broker/api/decorators/versions_decorator.rb +17 -6
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +8 -10
- data/lib/pact_broker/api/decorators/webhooks_decorator.rb +0 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +13 -1
- data/lib/pact_broker/api/renderers/html_pact_renderer.rb +47 -3
- data/lib/pact_broker/api/resources/badge.rb +3 -3
- data/lib/pact_broker/api/resources/base_resource.rb +1 -1
- data/lib/pact_broker/api/resources/latest_pact.rb +5 -1
- data/lib/pact_broker/api/resources/pact.rb +5 -1
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +61 -0
- data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +36 -0
- data/lib/pact_broker/api/resources/webhook.rb +31 -3
- data/lib/pact_broker/api/resources/webhook_execution.rb +12 -2
- data/lib/pact_broker/api.rb +3 -0
- data/lib/pact_broker/app.rb +11 -3
- data/lib/pact_broker/badges/service.rb +26 -5
- data/lib/pact_broker/configuration.rb +12 -5
- data/lib/pact_broker/constants.rb +1 -1
- data/lib/pact_broker/diagnostic/resources/heartbeat.rb +1 -2
- data/lib/pact_broker/doc/views/pact-webhooks.markdown +1 -1
- data/lib/pact_broker/doc/views/webhooks-webhooks.markdown +1 -1
- data/lib/pact_broker/doc/views/webhooks.markdown +1 -1
- data/lib/pact_broker/domain/relationship.rb +13 -4
- data/lib/pact_broker/domain/verification.rb +0 -4
- data/lib/pact_broker/domain/webhook.rb +2 -6
- data/lib/pact_broker/domain/webhook_execution_result.rb +1 -2
- data/lib/pact_broker/domain/webhook_request.rb +59 -40
- data/lib/pact_broker/pacticipants/service.rb +4 -3
- data/lib/pact_broker/pacts/repository.rb +8 -0
- data/lib/pact_broker/pacts/service.rb +2 -0
- data/lib/pact_broker/services.rb +1 -1
- data/lib/pact_broker/ui/view_models/relationship.rb +29 -2
- data/lib/pact_broker/ui/views/relationships/show.haml +7 -10
- data/lib/pact_broker/verifications/repository.rb +8 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/execution.rb +25 -4
- data/lib/pact_broker/webhooks/job.rb +55 -13
- data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +9 -0
- data/lib/pact_broker/webhooks/redact_logs.rb +10 -0
- data/lib/pact_broker/webhooks/repository.rb +76 -8
- data/lib/pact_broker/webhooks/service.rb +48 -8
- data/lib/pact_broker/webhooks/status.rb +29 -0
- data/lib/pact_broker/webhooks/triggered_webhook.rb +96 -0
- data/lib/pact_broker/webhooks/webhook.rb +19 -8
- data/lib/rack/pact_broker/database_transaction.rb +9 -3
- data/pact_broker.gemspec +3 -3
- data/public/javascripts/pact.js +5 -0
- data/public/stylesheets/pact.css +14 -1
- data/public/stylesheets/relationships.css +0 -1
- data/script/db-spec.sh +7 -0
- data/script/seed.rb +13 -8
- data/spec/features/create_webhook_spec.rb +1 -1
- data/spec/features/delete_pact_spec.rb +5 -1
- data/spec/features/delete_webhook_spec.rb +2 -1
- data/spec/features/edit_webhook_spec.rb +61 -0
- data/spec/features/execute_webhook_spec.rb +73 -0
- data/spec/features/get_latest_pact_badge_spec.rb +1 -1
- data/spec/features/get_latest_tagged_pact_badge_spec.rb +1 -1
- data/spec/features/get_latest_untagged_pact_badge_spec.rb +1 -1
- data/spec/features/get_pact_spec.rb +1 -1
- data/spec/features/merge_pact_spec.rb +1 -1
- data/spec/features/publish_pact_spec.rb +1 -1
- data/spec/integration/app_spec.rb +1 -1
- data/spec/integration/endpoints/group.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/latest_pact_decorator_spec.rb +2 -1
- data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +8 -6
- data/spec/lib/pact_broker/api/decorators/pact_webhooks_status_decorator_spec.rb +134 -0
- data/spec/lib/pact_broker/api/decorators/relationships_csv_decorator_spec.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/representable_pact_spec.rb +1 -1
- data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +27 -1
- data/spec/lib/pact_broker/api/resources/badge_spec.rb +32 -15
- data/spec/lib/pact_broker/api/resources/base_resource_spec.rb +17 -0
- data/spec/lib/pact_broker/api/resources/latest_pact_spec.rb +5 -3
- data/spec/lib/pact_broker/api/resources/pact_spec.rb +9 -2
- data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +28 -0
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +15 -5
- data/spec/lib/pact_broker/api/resources/webhook_spec.rb +43 -31
- data/spec/lib/pact_broker/app_spec.rb +12 -8
- data/spec/lib/pact_broker/badges/service_spec.rb +15 -1
- data/spec/lib/pact_broker/configuration_spec.rb +3 -2
- data/spec/lib/pact_broker/domain/relationship_spec.rb +24 -0
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +47 -31
- data/spec/lib/pact_broker/domain/webhook_spec.rb +4 -6
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +16 -1
- data/spec/lib/pact_broker/pacts/repository_spec.rb +22 -1
- data/spec/lib/pact_broker/pacts/service_spec.rb +32 -1
- data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +44 -0
- data/spec/lib/pact_broker/verifications/repository_spec.rb +19 -0
- data/spec/lib/pact_broker/verifications/service_spec.rb +1 -1
- data/spec/lib/pact_broker/webhooks/job_spec.rb +80 -19
- data/spec/lib/pact_broker/webhooks/redact_logs_spec.rb +49 -0
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +271 -21
- data/spec/lib/pact_broker/webhooks/service_spec.rb +70 -3
- data/spec/lib/pact_broker/webhooks/status_spec.rb +48 -0
- data/spec/lib/pact_broker/webhooks/triggered_webhook_spec.rb +40 -0
- data/spec/lib/rack/pact_broker/database_transaction_spec.rb +14 -4
- data/spec/migrations/23_pact_versions_spec.rb +8 -30
- data/spec/migrations/24_populate_pact_contents_spec.rb +3 -21
- data/spec/migrations/34_latest_tagged_pacts_spec.rb +1 -17
- data/spec/migrations/34_pact_revisions_spec.rb +7 -23
- data/spec/migrations/41_migrate_execution_data_spec.rb +109 -0
- data/spec/service_consumers/pact_helper.rb +5 -1
- data/spec/spec_helper.rb +15 -7
- data/spec/support/database_cleaner.rb +15 -2
- data/spec/support/migration_helpers.rb +16 -0
- data/spec/support/test_data_builder.rb +41 -9
- data/tasks/database.rb +7 -2
- data/tasks/db.rake +10 -0
- data/tasks/rspec.rake +1 -1
- data/vendor/hal-browser/browser.html +3 -2
- data/vendor/hal-browser/js/hal/resource.js +16 -2
- metadata +72 -13
- data/script/record_verification.sh +0 -4
@@ -7,7 +7,7 @@ module PactBroker
|
|
7
7
|
describe App do
|
8
8
|
|
9
9
|
before do
|
10
|
-
TestDataBuilder.new.create_pact_with_hierarchy
|
10
|
+
TestDataBuilder.new.create_pact_with_hierarchy('Some Consumer', '1.0', 'Some Provider').and_return(:pact)
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:hal_browser_enabled) { true }
|
@@ -6,7 +6,7 @@ describe "/groups/{pacticipant-name}" do
|
|
6
6
|
|
7
7
|
describe "GET" do
|
8
8
|
before do
|
9
|
-
TestDataBuilder.new.create_pact_with_hierarchy
|
9
|
+
TestDataBuilder.new.create_pact_with_hierarchy("Consumer", "1.2.3", "Provider").and_return(:pact)
|
10
10
|
get "/groups/Consumer"
|
11
11
|
end
|
12
12
|
|
@@ -9,7 +9,8 @@ module PactBroker
|
|
9
9
|
|
10
10
|
describe LatestPactDecorator do
|
11
11
|
|
12
|
-
let(:
|
12
|
+
let(:pact_domain) { TestDataBuilder.new.create_pact_with_hierarchy('Consumer', '1.2.3', 'Provider').and_return(:pact) }
|
13
|
+
let(:pact) { RepresentablePact.new(pact_domain) }
|
13
14
|
let(:base_url) { 'http://example.org' }
|
14
15
|
|
15
16
|
subject { JSON.parse LatestPactDecorator.new(pact).to_json(user_options: { base_url: base_url }), symbolize_names: true}
|
@@ -53,14 +53,12 @@ module PactBroker
|
|
53
53
|
|
54
54
|
it "includes a link to the diff with the previous distinct version" do
|
55
55
|
expect(subject[:_links][:'pb:diff-previous-distinct']).to eq({href: 'http://example.org/pacts/provider/A%20Provider/consumer/A%20Consumer/version/1234/diff/previous-distinct',
|
56
|
-
title: 'Diff'
|
57
|
-
name: 'Diff with previous distinct version of this pact'})
|
56
|
+
title: 'Diff with previous distinct version of this pact'})
|
58
57
|
end
|
59
58
|
|
60
59
|
it "includes a link to the previous distinct pact version" do
|
61
60
|
expect(subject[:_links][:'pb:previous-distinct']).to eq({href: 'http://example.org/pacts/provider/A%20Provider/consumer/A%20Consumer/version/1234/previous-distinct',
|
62
|
-
title: '
|
63
|
-
name: 'Previous distinct version of this pact'})
|
61
|
+
title: 'Previous distinct version of this pact'})
|
64
62
|
end
|
65
63
|
|
66
64
|
it "includes a link to tag this version" do
|
@@ -80,11 +78,15 @@ module PactBroker
|
|
80
78
|
end
|
81
79
|
|
82
80
|
it "includes a link to the latest pact" do
|
83
|
-
expect(subject[:_links][:'pb:latest-pact-version'][:title]).to eq "
|
84
|
-
expect(subject[:_links][:'pb:latest-pact-version'][:name]).to eq "Latest version of this pact"
|
81
|
+
expect(subject[:_links][:'pb:latest-pact-version'][:title]).to eq "Latest version of this pact"
|
85
82
|
expect(subject[:_links][:'pb:latest-pact-version'][:href]).to eq "http://example.org/pacts/provider/A%20Provider/consumer/A%20Consumer/latest"
|
86
83
|
end
|
87
84
|
|
85
|
+
it "includes a link to all pact versions" do
|
86
|
+
expect(subject[:_links][:'pb:all-pact-versions'][:title]).to eq "All versions of this pact"
|
87
|
+
expect(subject[:_links][:'pb:all-pact-versions'][:href]).to eq "http://example.org/pacts/provider/A%20Provider/consumer/A%20Consumer/versions"
|
88
|
+
end
|
89
|
+
|
88
90
|
it "includes a link to the pact version" do
|
89
91
|
expect(subject[:_links][:'pb:consumer-version'][:title]).to eq "Consumer version"
|
90
92
|
expect(subject[:_links][:'pb:consumer-version'][:name]).to eq "1234"
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'pact_broker/api/decorators/pact_webhooks_status_decorator'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Decorators
|
6
|
+
describe PactWebhooksStatusDecorator do
|
7
|
+
|
8
|
+
let(:user_options) do
|
9
|
+
{consumer: 'Foo', provider: 'Bar', resource_url: 'http://example.org/foo', base_url: 'http://example.org'}
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:triggered_webhook) do
|
13
|
+
double('PactBroker::Webhooks::TriggeredWebhook',
|
14
|
+
trigger_type: PactBroker::Webhooks::TriggeredWebhook::TRIGGER_TYPE_PUBLICATION,
|
15
|
+
status: status,
|
16
|
+
failure?: failure,
|
17
|
+
retrying?: retrying,
|
18
|
+
trigger_uuid: '1234',
|
19
|
+
webhook_uuid: '4321',
|
20
|
+
request_description: "GET http://foo",
|
21
|
+
pact_publication: pact,
|
22
|
+
number_of_attempts_made: 1,
|
23
|
+
number_of_attempts_remaining: 2,
|
24
|
+
created_at: DateTime.new(2017),
|
25
|
+
updated_at: DateTime.new(2017)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:pact) do
|
30
|
+
double('pact',
|
31
|
+
provider: double(name: 'provider'),
|
32
|
+
consumer: double(name: 'consumer'),
|
33
|
+
consumer_version_number: '1',
|
34
|
+
name: 'foo '
|
35
|
+
)
|
36
|
+
end
|
37
|
+
let(:failure) { false }
|
38
|
+
let(:retrying) { false }
|
39
|
+
let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_SUCCESS }
|
40
|
+
let(:logs_url) { "http://example.org/webhooks/4321/trigger/1234/logs" }
|
41
|
+
let(:triggered_webhooks) { [triggered_webhook] }
|
42
|
+
|
43
|
+
let(:json) do
|
44
|
+
PactWebhooksStatusDecorator.new(triggered_webhooks).to_json(user_options: user_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
subject { JSON.parse json, symbolize_names: true }
|
48
|
+
|
49
|
+
it "includes a list of triggered webhooks" do
|
50
|
+
expect(subject[:_embedded][:triggeredWebhooks]).to be_instance_of(Array)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "includes a link to the logs" do
|
54
|
+
expect(subject[:_embedded][:triggeredWebhooks][0][:_links][:logs][:href]).to eq logs_url
|
55
|
+
end
|
56
|
+
|
57
|
+
it "includes a link to the webhook" do
|
58
|
+
expect(subject[:_embedded][:triggeredWebhooks][0][:_links][:'pb:webhook'][:href]).to eq "http://example.org/webhooks/4321"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "includes the triggered webhooks properties" do
|
62
|
+
expect(subject[:_embedded][:triggeredWebhooks].first).to include(
|
63
|
+
status: 'success',
|
64
|
+
triggerType: 'pact_publication',
|
65
|
+
attemptsMade: 1,
|
66
|
+
attemptsRemaining: 2
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "includes a link to the consumer" do
|
71
|
+
expect(subject[:_links][:'pb:consumer']).to_not be nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "includes a link to the provider" do
|
75
|
+
expect(subject[:_links][:'pb:provider']).to_not be nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "includes a link to the pact" do
|
79
|
+
expect(subject[:_links][:'pb:pact-version']).to_not be nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it "includes a summary of the triggered webhook statuses" do
|
83
|
+
expect(subject[:summary]).to eq({successful: 1, failed: 0})
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when there is a failure" do
|
87
|
+
let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_FAILURE }
|
88
|
+
let(:failure) { true }
|
89
|
+
|
90
|
+
it "includes a link to the error logs" do
|
91
|
+
expect(subject[:_links][:'pb:error-logs'][0][:href]).to eq logs_url
|
92
|
+
end
|
93
|
+
|
94
|
+
it "has a failed count of 1" do
|
95
|
+
expect(subject[:summary]).to eq({successful: 0, failed: 1})
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when there is a retry" do
|
100
|
+
let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_RETRYING }
|
101
|
+
let(:retrying) { true }
|
102
|
+
|
103
|
+
it "includes a link to the error logs" do
|
104
|
+
expect(subject[:_links][:'pb:error-logs'][0][:href]).to eq logs_url
|
105
|
+
end
|
106
|
+
|
107
|
+
it "has a retrying count of 1" do
|
108
|
+
expect(subject[:summary]).to eq({successful: 0, failed: 0, retrying: 1})
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when there is a not_run triggered webhook" do
|
113
|
+
let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_NOT_RUN }
|
114
|
+
|
115
|
+
it "does not include a link to the error logs" do
|
116
|
+
expect(subject[:_links][:'pb:error-logs']).to be_empty
|
117
|
+
end
|
118
|
+
|
119
|
+
it "has a notRun count of 1" do
|
120
|
+
expect(subject[:summary]).to eq({successful: 0, failed: 0, notRun: 1})
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when there are no triggered webhooks" do
|
125
|
+
let(:triggered_webhooks) { [] }
|
126
|
+
|
127
|
+
it "doesn't blow up" do
|
128
|
+
subject
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -9,7 +9,7 @@ module PactBroker
|
|
9
9
|
|
10
10
|
describe RelationshipsCsvDecorator do
|
11
11
|
|
12
|
-
let(:pact) { TestDataBuilder.new.create_pact_with_hierarchy
|
12
|
+
let(:pact) { TestDataBuilder.new.create_pact_with_hierarchy("My Consumer", "1.0", "My Provider").and_return(:pact) }
|
13
13
|
let(:pacts) { [pact]}
|
14
14
|
|
15
15
|
|
@@ -4,7 +4,7 @@ require 'pact_broker/api/decorators/representable_pact'
|
|
4
4
|
|
5
5
|
module PactBroker::Api::Decorators
|
6
6
|
describe RepresentablePact do
|
7
|
-
let(:pact) { TestDataBuilder.new.create_pact_with_hierarchy
|
7
|
+
let(:pact) { TestDataBuilder.new.create_pact_with_hierarchy('Consumer', '1.2.3', 'Provider').and_return(:pact) }
|
8
8
|
|
9
9
|
subject { RepresentablePact.new(pact) }
|
10
10
|
|
@@ -9,6 +9,7 @@ module PactBroker
|
|
9
9
|
before do
|
10
10
|
ENV['BACKUP_TZ'] = ENV['TZ']
|
11
11
|
ENV['TZ'] = "Australia/Melbourne"
|
12
|
+
PactBroker.configuration.enable_public_badge_access = true
|
12
13
|
end
|
13
14
|
|
14
15
|
after do
|
@@ -21,12 +22,18 @@ module PactBroker
|
|
21
22
|
let(:json_content) { load_fixture('renderer_pact.json') }
|
22
23
|
let(:pact) { double('pact', json_content: json_content, consumer_version_number: '1.2.3', consumer: consumer, provider: provider, consumer_version_tag_names: ['prod', 'master'], created_at: created_at)}
|
23
24
|
let(:pact_url) { '/pact/url' }
|
25
|
+
let(:options) do
|
26
|
+
{
|
27
|
+
base_url: 'http://base',
|
28
|
+
badge_url: 'http://badge'
|
29
|
+
}
|
30
|
+
end
|
24
31
|
|
25
32
|
before do
|
26
33
|
allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).with('', pact).and_return(pact_url)
|
27
34
|
end
|
28
35
|
|
29
|
-
subject { HtmlPactRenderer.call pact }
|
36
|
+
subject { HtmlPactRenderer.call pact, options }
|
30
37
|
|
31
38
|
describe ".call" do
|
32
39
|
it "renders the pact as HTML" do
|
@@ -44,6 +51,25 @@ module PactBroker
|
|
44
51
|
expect(subject).to match /prod, master/
|
45
52
|
end
|
46
53
|
|
54
|
+
it "renders the badge image" do
|
55
|
+
expect(subject).to include "<img src='http://badge'/>"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "renders a text area with the badge markdown" do
|
59
|
+
expect(subject).to include "<textarea"
|
60
|
+
expect(subject).to include "[![Consumer/Provider Pact Status](http://badge)](http://base)"
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when enable_public_badge_access is false" do
|
64
|
+
before do
|
65
|
+
PactBroker.configuration.enable_public_badge_access = false
|
66
|
+
end
|
67
|
+
|
68
|
+
it "renders a message instructing the user to turn public access on" do
|
69
|
+
expect(subject).to include "set `enable_public_badge_access` to true in the configuration"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
47
73
|
context "when the content is not a valid pact, but is still JSON" do
|
48
74
|
before do
|
49
75
|
allow(pact).to receive(:content_hash).and_return(content_hash)
|
@@ -8,32 +8,49 @@ module PactBroker
|
|
8
8
|
let(:path) { "/pacts/provider/provider/consumer/consumer/latest/badge" }
|
9
9
|
let(:params) { {} }
|
10
10
|
|
11
|
+
before do
|
12
|
+
allow(PactBroker::Pacts::Service).to receive(:find_latest_pact).and_return(pact)
|
13
|
+
allow(PactBroker::Verifications::Service).to receive(:find_latest_verification_for).and_return(verification)
|
14
|
+
allow(PactBroker::Badges::Service).to receive(:pact_verification_badge).and_return("badge")
|
15
|
+
allow(PactBroker::Verifications::Status).to receive(:new).and_return(verification_status)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:pact) { instance_double("PactBroker::Domain::Pact", consumer: consumer, provider: provider) }
|
19
|
+
let(:consumer) { double('consumer') }
|
20
|
+
let(:provider) { double('provider') }
|
21
|
+
let(:verification) { double("verification") }
|
22
|
+
let(:verification_status) { instance_double("PactBroker::Verifications::Status", to_sym: :verified) }
|
23
|
+
|
24
|
+
|
11
25
|
subject { get path, params, {'HTTP_ACCEPT' => 'image/svg+xml'}; last_response }
|
12
26
|
|
13
|
-
context "when
|
27
|
+
context "when enable_public_badge_access is false and the request is not authenticated" do
|
14
28
|
before do
|
15
|
-
PactBroker.configuration.
|
29
|
+
PactBroker.configuration.enable_public_badge_access = false
|
30
|
+
allow_any_instance_of(Badge).to receive(:authenticated?).and_return(false)
|
16
31
|
end
|
17
32
|
|
18
|
-
it "returns a
|
19
|
-
expect(subject.status).to eq
|
33
|
+
it "returns a 401" do
|
34
|
+
expect(subject.status).to eq 401
|
20
35
|
end
|
21
36
|
end
|
22
37
|
|
23
|
-
context "when
|
38
|
+
context "when enable_public_badge_access is false but the request is authenticated" do
|
24
39
|
before do
|
25
|
-
PactBroker.configuration.
|
26
|
-
|
27
|
-
allow(PactBroker::Verifications::Service).to receive(:find_latest_verification_for).and_return(verification)
|
28
|
-
allow(PactBroker::Badges::Service).to receive(:pact_verification_badge).and_return("badge")
|
29
|
-
allow(PactBroker::Verifications::Status).to receive(:new).and_return(verification_status)
|
40
|
+
PactBroker.configuration.enable_public_badge_access = false
|
41
|
+
allow_any_instance_of(Badge).to receive(:authenticated?).and_return(true)
|
30
42
|
end
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
44
|
+
it "returns a 200" do
|
45
|
+
expect(subject.status).to eq 200
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when enable_public_badge_access is true" do
|
50
|
+
|
51
|
+
before do
|
52
|
+
PactBroker.configuration.enable_public_badge_access = true
|
53
|
+
end
|
37
54
|
|
38
55
|
it "retrieves the latest pact" do
|
39
56
|
expect(PactBroker::Pacts::Service).to receive(:find_latest_pact)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'pact_broker/api/resources/base_resource'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
describe BaseResource do
|
7
|
+
let(:request) { double('request', uri: uri) }
|
8
|
+
let(:response) { double('response') }
|
9
|
+
let(:uri) { URI('http://example.org/path?query') }
|
10
|
+
|
11
|
+
subject { BaseResource.new(request, response) }
|
12
|
+
|
13
|
+
its(:resource_url) { is_expected.to eq 'http://example.org/path' }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -16,17 +16,19 @@ module PactBroker::Api
|
|
16
16
|
|
17
17
|
context "Accept: text/html" do
|
18
18
|
|
19
|
+
let(:path) { "/pacts/provider/provider_name/consumer/consumer_name/latest" }
|
19
20
|
let(:json_content) { 'json_content' }
|
20
21
|
let(:pact) { double("pact", json_content: json_content)}
|
21
22
|
let(:html) { 'html' }
|
22
|
-
let(:pact_id_params) { {:
|
23
|
+
let(:pact_id_params) { {provider_name: "provider_name", consumer_name: "consumer_name"} }
|
24
|
+
let(:html_options) { { base_url: 'http://example.org', badge_url: "http://example.org#{path}/badge.svg" } }
|
23
25
|
|
24
26
|
before do
|
25
27
|
allow(PactBroker::Pacts::Service).to receive(:find_latest_pact).and_return(pact)
|
26
28
|
allow(PactBroker.configuration.html_pact_renderer).to receive(:call).and_return(html)
|
27
29
|
end
|
28
30
|
|
29
|
-
subject { get
|
31
|
+
subject { get path ,{}, {'HTTP_ACCEPT' => "text/html"} }
|
30
32
|
|
31
33
|
it "find the pact" do
|
32
34
|
expect(PactBroker::Pacts::Service).to receive(:find_latest_pact).with(hash_including(pact_id_params))
|
@@ -34,7 +36,7 @@ module PactBroker::Api
|
|
34
36
|
end
|
35
37
|
|
36
38
|
it "uses the configured HTML renderer" do
|
37
|
-
expect(PactBroker.configuration.html_pact_renderer).to receive(:call).with(pact)
|
39
|
+
expect(PactBroker.configuration.html_pact_renderer).to receive(:call).with(pact, html_options)
|
38
40
|
subject
|
39
41
|
end
|
40
42
|
|
@@ -24,21 +24,28 @@ module PactBroker::Api
|
|
24
24
|
let(:pact) { double("pact", json_content: json_content)}
|
25
25
|
let(:html) { 'html' }
|
26
26
|
let(:pact_id_params) { {provider_name: "provider_name", consumer_name: "consumer_name", consumer_version_number: "1.2.3"} }
|
27
|
+
let(:html_options) { { base_url: 'http://example.org', badge_url: 'http://badge' } }
|
27
28
|
|
28
29
|
before do
|
30
|
+
allow_any_instance_of(Pact).to receive(:badge_url_for_latest_pact).and_return('http://badge')
|
29
31
|
allow(PactBroker::Pacts::Service).to receive(:find_pact).and_return(pact)
|
30
32
|
allow(PactBroker.configuration.html_pact_renderer).to receive(:call).and_return(html)
|
31
33
|
end
|
32
34
|
|
33
35
|
subject { get "/pacts/provider/provider_name/consumer/consumer_name/versions/1.2.3",{}, {'HTTP_ACCEPT' => "text/html"} }
|
34
36
|
|
35
|
-
it "
|
37
|
+
it "finds the pact" do
|
36
38
|
expect(PactBroker::Pacts::Service).to receive(:find_pact).with(hash_including(pact_id_params))
|
37
39
|
subject
|
38
40
|
end
|
39
41
|
|
42
|
+
it "determines the badge url for the HTML page" do
|
43
|
+
expect_any_instance_of(Pact).to receive(:badge_url_for_latest_pact).with(pact, 'http://example.org')
|
44
|
+
subject
|
45
|
+
end
|
46
|
+
|
40
47
|
it "uses the configured HTML renderer" do
|
41
|
-
expect(PactBroker.configuration.html_pact_renderer).to receive(:call).with(pact)
|
48
|
+
expect(PactBroker.configuration.html_pact_renderer).to receive(:call).with(pact, html_options)
|
42
49
|
subject
|
43
50
|
end
|
44
51
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pact_broker/api/resources/triggered_webhook_logs'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
describe TriggeredWebhookLogs do
|
7
|
+
|
8
|
+
let(:td) { TestDataBuilder.new }
|
9
|
+
|
10
|
+
before do
|
11
|
+
td.create_pact_with_hierarchy
|
12
|
+
.create_webhook(uuid: "5432")
|
13
|
+
.create_triggered_webhook(trigger_uuid: "1234")
|
14
|
+
.create_webhook_execution(logs: "foo")
|
15
|
+
.create_webhook_execution(logs: "bar")
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:path) { "/webhooks/5432/trigger/1234/logs" }
|
19
|
+
|
20
|
+
subject { get path; last_response }
|
21
|
+
|
22
|
+
it "returns the concatenated webhook execution logs" do
|
23
|
+
expect(subject.body).to eq "foo\nbar"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -28,12 +28,26 @@ module PactBroker
|
|
28
28
|
let(:success) { true }
|
29
29
|
let(:execution_result) { double('execution_result', success?: success, to_json: json)}
|
30
30
|
let(:json) { {some: 'json'}.to_json }
|
31
|
-
let(:webhook) { double("webhook") }
|
31
|
+
let(:webhook) { double("webhook", consumer_name: consumer_name, provider_name: provider_name) }
|
32
32
|
let(:decorator) { instance_double(PactBroker::Api::Decorators::WebhookExecutionResultDecorator, to_json: json)}
|
33
|
+
let(:pact) { instance_double("PactBroker::Domain::Pact") }
|
34
|
+
let(:consumer_name) { "foo" }
|
35
|
+
let(:provider_name) { "bar" }
|
33
36
|
|
34
37
|
before do
|
35
38
|
allow(PactBroker::Webhooks::Service).to receive(:execute_webhook_now).and_return(execution_result)
|
36
39
|
allow(PactBroker::Api::Decorators::WebhookExecutionResultDecorator).to receive(:new).and_return(decorator)
|
40
|
+
allow(PactBroker::Pacts::Service).to receive(:find_latest_pact).and_return(pact)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "finds the latest pact for the webhook" do
|
44
|
+
expect(PactBroker::Pacts::Service).to receive(:find_latest_pact).with(consumer_name: consumer_name, provider_name: provider_name)
|
45
|
+
subject
|
46
|
+
end
|
47
|
+
|
48
|
+
it "executes the webhook" do
|
49
|
+
expect(PactBroker::Webhooks::Service).to receive(:execute_webhook_now).with(webhook, pact)
|
50
|
+
subject
|
37
51
|
end
|
38
52
|
|
39
53
|
context "when execution is successful" do
|
@@ -65,13 +79,9 @@ module PactBroker
|
|
65
79
|
expect(last_response.body).to eq json
|
66
80
|
end
|
67
81
|
end
|
68
|
-
|
69
82
|
end
|
70
|
-
|
71
83
|
end
|
72
|
-
|
73
84
|
end
|
74
85
|
end
|
75
86
|
end
|
76
|
-
|
77
87
|
end
|
@@ -11,50 +11,62 @@ module PactBroker::Api
|
|
11
11
|
allow(PactBroker::Webhooks::Service).to receive(:find_by_uuid).and_return(webhook)
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
describe "GET" do
|
15
|
+
subject { get '/webhooks/some-uuid'; last_response }
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
context "when the webhook does not exist" do
|
18
|
+
let(:webhook) { nil }
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
it "returns a 404" do
|
21
|
+
expect(subject).to be_a_404_response
|
22
|
+
end
|
22
23
|
end
|
23
|
-
end
|
24
24
|
|
25
|
-
|
25
|
+
context "when the webhook exists" do
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
let(:webhook) { double("webhook") }
|
28
|
+
let(:decorator) { double(Decorators::WebhookDecorator, to_json: json)}
|
29
|
+
let(:json) { {some: 'json'}.to_json }
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
before do
|
32
|
+
allow(Decorators::WebhookDecorator).to receive(:new).and_return(decorator)
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
it "finds the webhook by UUID" do
|
36
|
+
expect(PactBroker::Webhooks::Service).to receive(:find_by_uuid).with('some-uuid')
|
37
|
+
subject
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
it "returns a 200 JSON response" do
|
41
|
+
subject
|
42
|
+
expect(last_response).to be_a_hal_json_success_response
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
it "generates a JSON representation of the webhook" do
|
46
|
+
expect(Decorators::WebhookDecorator).to receive(:new).with(webhook)
|
47
|
+
expect(decorator).to receive(:to_json).with(user_options: { base_url: 'http://example.org'})
|
48
|
+
subject
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
it "includes the JSON representation in the response body" do
|
52
|
+
subject
|
53
|
+
expect(last_response.body).to eq json
|
54
|
+
end
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
58
|
+
describe "PUT" do
|
59
|
+
context "when the webhook does not exist" do
|
60
|
+
let(:webhook) { nil }
|
61
|
+
let(:webhook_json) { load_fixture('webhook_valid.json') }
|
62
|
+
|
63
|
+
subject { put '/webhooks/some-uuid', webhook_json, {'CONTENT_TYPE' => 'application/json'}; last_response }
|
64
|
+
|
65
|
+
it "returns a 404" do
|
66
|
+
expect(subject).to be_a_404_response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
57
70
|
end
|
58
71
|
end
|
59
|
-
|
60
72
|
end
|
@@ -3,16 +3,14 @@ require 'pact_broker/app'
|
|
3
3
|
module PactBroker
|
4
4
|
describe App do
|
5
5
|
|
6
|
-
|
6
|
+
before do
|
7
|
+
allow(PactBroker::DB).to receive(:run_migrations)
|
8
|
+
end
|
7
9
|
|
10
|
+
class TestApp < PactBroker::App
|
8
11
|
def configure_database_connection
|
9
|
-
# do nothing
|
10
|
-
end
|
11
|
-
|
12
|
-
def migrate_database
|
13
|
-
# do nothing
|
12
|
+
# do nothing so we don't screw up our test connection
|
14
13
|
end
|
15
|
-
|
16
14
|
end
|
17
15
|
|
18
16
|
let(:app) do
|
@@ -21,6 +19,13 @@ module PactBroker
|
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
22
|
+
describe "on start up" do
|
23
|
+
it "fails any retrying triggered webhooks left over when the app shut down" do
|
24
|
+
expect(PactBroker::Webhooks::Service).to receive(:fail_retrying_triggered_webhooks)
|
25
|
+
app
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
24
29
|
it "adds the X-Pact-Broker-Version header" do
|
25
30
|
get "/"
|
26
31
|
expect(last_response.headers['X-Pact-Broker-Version']).to match /\d/
|
@@ -208,6 +213,5 @@ module PactBroker
|
|
208
213
|
expect { subject }.to_not change { PactBroker::Domain::Pacticipant.count }
|
209
214
|
end
|
210
215
|
end
|
211
|
-
|
212
216
|
end
|
213
217
|
end
|