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.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +4 -2
  4. data/CHANGELOG.md +54 -0
  5. data/DEVELOPER_DOCUMENTATION.md +11 -7
  6. data/README.md +5 -1
  7. data/UPGRADING.md +18 -0
  8. data/db/migrations/19_make_pact_version_content_sha_not_nullable.rb +9 -1
  9. data/db/migrations/25_make_pv_pacticipants_mandatory.rb +8 -0
  10. data/db/migrations/38_create_triggered_webhooks_table.rb +19 -0
  11. data/db/migrations/39_add_triggered_webhooks_fk_to_execution.rb +24 -0
  12. data/db/migrations/40_create_latest_triggered_webhooks_view.rb +24 -0
  13. data/db/migrations/41_migrate_execution_data.rb +47 -0
  14. data/db/test/backwards_compatibility/.rspec +3 -0
  15. data/db/test/backwards_compatibility/Appraisals +49 -0
  16. data/db/test/backwards_compatibility/Gemfile +11 -0
  17. data/db/test/backwards_compatibility/Rakefile +55 -0
  18. data/db/test/backwards_compatibility/config.ru +18 -0
  19. data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile +14 -0
  20. data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile.lock +210 -0
  21. data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile +14 -0
  22. data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile.lock +208 -0
  23. data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile +14 -0
  24. data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile.lock +209 -0
  25. data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile +14 -0
  26. data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile.lock +197 -0
  27. data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile +13 -0
  28. data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile.lock +196 -0
  29. data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile +13 -0
  30. data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile.lock +196 -0
  31. data/db/test/backwards_compatibility/gemfiles/head.gemfile +13 -0
  32. data/db/test/backwards_compatibility/gemfiles/head.gemfile.lock +200 -0
  33. data/db/test/backwards_compatibility/spec/fixtures/foo-bar.json +22 -0
  34. data/db/test/backwards_compatibility/spec/publish_pact_spec.rb +72 -0
  35. data/db/test/backwards_compatibility/spec/spec_helper.rb +20 -0
  36. data/db/test/backwards_compatibility/spec/support/fixture_helpers.rb +12 -0
  37. data/db/test/backwards_compatibility/spec/support/request_helpers.rb +20 -0
  38. data/example/Gemfile +2 -2
  39. data/example/pact_broker_database.sqlite3 +0 -0
  40. data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -2
  41. data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -10
  42. data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +1 -2
  43. data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +123 -0
  44. data/lib/pact_broker/api/decorators/versions_decorator.rb +17 -6
  45. data/lib/pact_broker/api/decorators/webhook_decorator.rb +8 -10
  46. data/lib/pact_broker/api/decorators/webhooks_decorator.rb +0 -1
  47. data/lib/pact_broker/api/pact_broker_urls.rb +13 -1
  48. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +47 -3
  49. data/lib/pact_broker/api/resources/badge.rb +3 -3
  50. data/lib/pact_broker/api/resources/base_resource.rb +1 -1
  51. data/lib/pact_broker/api/resources/latest_pact.rb +5 -1
  52. data/lib/pact_broker/api/resources/pact.rb +5 -1
  53. data/lib/pact_broker/api/resources/pact_webhooks_status.rb +61 -0
  54. data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +36 -0
  55. data/lib/pact_broker/api/resources/webhook.rb +31 -3
  56. data/lib/pact_broker/api/resources/webhook_execution.rb +12 -2
  57. data/lib/pact_broker/api.rb +3 -0
  58. data/lib/pact_broker/app.rb +11 -3
  59. data/lib/pact_broker/badges/service.rb +26 -5
  60. data/lib/pact_broker/configuration.rb +12 -5
  61. data/lib/pact_broker/constants.rb +1 -1
  62. data/lib/pact_broker/diagnostic/resources/heartbeat.rb +1 -2
  63. data/lib/pact_broker/doc/views/pact-webhooks.markdown +1 -1
  64. data/lib/pact_broker/doc/views/webhooks-webhooks.markdown +1 -1
  65. data/lib/pact_broker/doc/views/webhooks.markdown +1 -1
  66. data/lib/pact_broker/domain/relationship.rb +13 -4
  67. data/lib/pact_broker/domain/verification.rb +0 -4
  68. data/lib/pact_broker/domain/webhook.rb +2 -6
  69. data/lib/pact_broker/domain/webhook_execution_result.rb +1 -2
  70. data/lib/pact_broker/domain/webhook_request.rb +59 -40
  71. data/lib/pact_broker/pacticipants/service.rb +4 -3
  72. data/lib/pact_broker/pacts/repository.rb +8 -0
  73. data/lib/pact_broker/pacts/service.rb +2 -0
  74. data/lib/pact_broker/services.rb +1 -1
  75. data/lib/pact_broker/ui/view_models/relationship.rb +29 -2
  76. data/lib/pact_broker/ui/views/relationships/show.haml +7 -10
  77. data/lib/pact_broker/verifications/repository.rb +8 -1
  78. data/lib/pact_broker/version.rb +1 -1
  79. data/lib/pact_broker/webhooks/execution.rb +25 -4
  80. data/lib/pact_broker/webhooks/job.rb +55 -13
  81. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +9 -0
  82. data/lib/pact_broker/webhooks/redact_logs.rb +10 -0
  83. data/lib/pact_broker/webhooks/repository.rb +76 -8
  84. data/lib/pact_broker/webhooks/service.rb +48 -8
  85. data/lib/pact_broker/webhooks/status.rb +29 -0
  86. data/lib/pact_broker/webhooks/triggered_webhook.rb +96 -0
  87. data/lib/pact_broker/webhooks/webhook.rb +19 -8
  88. data/lib/rack/pact_broker/database_transaction.rb +9 -3
  89. data/pact_broker.gemspec +3 -3
  90. data/public/javascripts/pact.js +5 -0
  91. data/public/stylesheets/pact.css +14 -1
  92. data/public/stylesheets/relationships.css +0 -1
  93. data/script/db-spec.sh +7 -0
  94. data/script/seed.rb +13 -8
  95. data/spec/features/create_webhook_spec.rb +1 -1
  96. data/spec/features/delete_pact_spec.rb +5 -1
  97. data/spec/features/delete_webhook_spec.rb +2 -1
  98. data/spec/features/edit_webhook_spec.rb +61 -0
  99. data/spec/features/execute_webhook_spec.rb +73 -0
  100. data/spec/features/get_latest_pact_badge_spec.rb +1 -1
  101. data/spec/features/get_latest_tagged_pact_badge_spec.rb +1 -1
  102. data/spec/features/get_latest_untagged_pact_badge_spec.rb +1 -1
  103. data/spec/features/get_pact_spec.rb +1 -1
  104. data/spec/features/merge_pact_spec.rb +1 -1
  105. data/spec/features/publish_pact_spec.rb +1 -1
  106. data/spec/integration/app_spec.rb +1 -1
  107. data/spec/integration/endpoints/group.rb +1 -1
  108. data/spec/lib/pact_broker/api/decorators/latest_pact_decorator_spec.rb +2 -1
  109. data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +8 -6
  110. data/spec/lib/pact_broker/api/decorators/pact_webhooks_status_decorator_spec.rb +134 -0
  111. data/spec/lib/pact_broker/api/decorators/relationships_csv_decorator_spec.rb +1 -1
  112. data/spec/lib/pact_broker/api/decorators/representable_pact_spec.rb +1 -1
  113. data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +27 -1
  114. data/spec/lib/pact_broker/api/resources/badge_spec.rb +32 -15
  115. data/spec/lib/pact_broker/api/resources/base_resource_spec.rb +17 -0
  116. data/spec/lib/pact_broker/api/resources/latest_pact_spec.rb +5 -3
  117. data/spec/lib/pact_broker/api/resources/pact_spec.rb +9 -2
  118. data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +28 -0
  119. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +15 -5
  120. data/spec/lib/pact_broker/api/resources/webhook_spec.rb +43 -31
  121. data/spec/lib/pact_broker/app_spec.rb +12 -8
  122. data/spec/lib/pact_broker/badges/service_spec.rb +15 -1
  123. data/spec/lib/pact_broker/configuration_spec.rb +3 -2
  124. data/spec/lib/pact_broker/domain/relationship_spec.rb +24 -0
  125. data/spec/lib/pact_broker/domain/webhook_request_spec.rb +47 -31
  126. data/spec/lib/pact_broker/domain/webhook_spec.rb +4 -6
  127. data/spec/lib/pact_broker/pacticipants/service_spec.rb +16 -1
  128. data/spec/lib/pact_broker/pacts/repository_spec.rb +22 -1
  129. data/spec/lib/pact_broker/pacts/service_spec.rb +32 -1
  130. data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +44 -0
  131. data/spec/lib/pact_broker/verifications/repository_spec.rb +19 -0
  132. data/spec/lib/pact_broker/verifications/service_spec.rb +1 -1
  133. data/spec/lib/pact_broker/webhooks/job_spec.rb +80 -19
  134. data/spec/lib/pact_broker/webhooks/redact_logs_spec.rb +49 -0
  135. data/spec/lib/pact_broker/webhooks/repository_spec.rb +271 -21
  136. data/spec/lib/pact_broker/webhooks/service_spec.rb +70 -3
  137. data/spec/lib/pact_broker/webhooks/status_spec.rb +48 -0
  138. data/spec/lib/pact_broker/webhooks/triggered_webhook_spec.rb +40 -0
  139. data/spec/lib/rack/pact_broker/database_transaction_spec.rb +14 -4
  140. data/spec/migrations/23_pact_versions_spec.rb +8 -30
  141. data/spec/migrations/24_populate_pact_contents_spec.rb +3 -21
  142. data/spec/migrations/34_latest_tagged_pacts_spec.rb +1 -17
  143. data/spec/migrations/34_pact_revisions_spec.rb +7 -23
  144. data/spec/migrations/41_migrate_execution_data_spec.rb +109 -0
  145. data/spec/service_consumers/pact_helper.rb +5 -1
  146. data/spec/spec_helper.rb +15 -7
  147. data/spec/support/database_cleaner.rb +15 -2
  148. data/spec/support/migration_helpers.rb +16 -0
  149. data/spec/support/test_data_builder.rb +41 -9
  150. data/tasks/database.rb +7 -2
  151. data/tasks/db.rake +10 -0
  152. data/tasks/rspec.rake +1 -1
  153. data/vendor/hal-browser/browser.html +3 -2
  154. data/vendor/hal-browser/js/hal/resource.js +16 -2
  155. metadata +72 -13
  156. 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 'Some Consumer', '1.0', 'Some Provider'
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 "Consumer", "1.2.3", "Provider"
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(:pact) { RepresentablePact.new(TestDataBuilder.new.create_pact_with_hierarchy 'Consumer', '1.2.3', 'Provider') }
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: 'Pact',
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 "Pact"
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 "My Consumer", "1.0", "My Provider"}
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 'Consumer', '1.2.3', 'Provider' }
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 enable_badge_resources is false" do
27
+ context "when enable_public_badge_access is false and the request is not authenticated" do
14
28
  before do
15
- PactBroker.configuration.enable_badge_resources = false
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 404" do
19
- expect(subject.status).to eq 404
33
+ it "returns a 401" do
34
+ expect(subject.status).to eq 401
20
35
  end
21
36
  end
22
37
 
23
- context "when enable_badge_resources is true" do
38
+ context "when enable_public_badge_access is false but the request is authenticated" do
24
39
  before do
25
- PactBroker.configuration.enable_badge_resources = true
26
- allow(PactBroker::Pacts::Service).to receive(:find_latest_pact).and_return(pact)
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
- let(:pact) { instance_double("PactBroker::Domain::Pact", consumer: consumer, provider: provider) }
33
- let(:consumer) { double('consumer') }
34
- let(:provider) { double('provider') }
35
- let(:verification) { double("verification") }
36
- let(:verification_status) { instance_double("PactBroker::Verifications::Status", to_sym: :verified) }
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) { {:provider_name=>"provider_name", :consumer_name=>"consumer_name"} }
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 "/pacts/provider/provider_name/consumer/consumer_name/latest",{}, {'HTTP_ACCEPT' => "text/html"} }
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 "find the pact" do
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
- subject { get '/webhooks/some-uuid' }
14
+ describe "GET" do
15
+ subject { get '/webhooks/some-uuid'; last_response }
15
16
 
16
- context "when the webhook does not exist" do
17
- let(:webhook) { nil }
17
+ context "when the webhook does not exist" do
18
+ let(:webhook) { nil }
18
19
 
19
- it "returns a 404" do
20
- subject
21
- expect(last_response).to be_a_404_response
20
+ it "returns a 404" do
21
+ expect(subject).to be_a_404_response
22
+ end
22
23
  end
23
- end
24
24
 
25
- context "when the webhook exists" do
25
+ context "when the webhook exists" do
26
26
 
27
- let(:webhook) { double("webhook") }
28
- let(:decorator) { double(Decorators::WebhookDecorator, to_json: json)}
29
- let(:json) { {some: 'json'}.to_json }
27
+ let(:webhook) { double("webhook") }
28
+ let(:decorator) { double(Decorators::WebhookDecorator, to_json: json)}
29
+ let(:json) { {some: 'json'}.to_json }
30
30
 
31
- before do
32
- allow(Decorators::WebhookDecorator).to receive(:new).and_return(decorator)
33
- end
31
+ before do
32
+ allow(Decorators::WebhookDecorator).to receive(:new).and_return(decorator)
33
+ end
34
34
 
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
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
- it "returns a 200 JSON response" do
41
- subject
42
- expect(last_response).to be_a_hal_json_success_response
43
- end
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
- 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
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
- it "includes the JSON representation in the response body" do
52
- subject
53
- expect(last_response.body).to eq json
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
- class TestApp < PactBroker::App
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