pact_broker 2.72.0 → 2.76.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/.optic/.gitignore +2 -0
  4. data/.optic/api/specification.json +1 -0
  5. data/.optic/ignore +14 -0
  6. data/CHANGELOG.md +66 -0
  7. data/DEVELOPER_SETUP.md +9 -0
  8. data/Dockerfile +1 -0
  9. data/ISSUES.md +3 -3
  10. data/README.md +1 -1
  11. data/config/database.yml +1 -1
  12. data/db/migrations/20210115_add_webhook_foreign_key_indexes.rb +49 -0
  13. data/db/migrations/20210116_add_context_to_triggered_webhook.rb +11 -0
  14. data/db/migrations/migration_helper.rb +8 -0
  15. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +33 -0
  16. data/docker-compose-test.yml +4 -4
  17. data/lib/db.rb +1 -0
  18. data/lib/pact_broker/api.rb +13 -2
  19. data/lib/pact_broker/api/decorators.rb +3 -7
  20. data/lib/pact_broker/api/decorators/configuration.rb +33 -0
  21. data/lib/pact_broker/api/decorators/decorator_context_creator.rb +13 -0
  22. data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +9 -1
  23. data/lib/pact_broker/api/decorators/extended_verification_decorator.rb +8 -0
  24. data/lib/pact_broker/api/decorators/matrix_decorator.rb +9 -4
  25. data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -0
  26. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +2 -3
  27. data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -0
  28. data/lib/pact_broker/api/decorators/tag_decorator.rb +0 -3
  29. data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +3 -1
  30. data/lib/pact_broker/api/pact_broker_urls.rb +4 -4
  31. data/lib/pact_broker/api/paths.rb +5 -0
  32. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +2 -2
  33. data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
  34. data/lib/pact_broker/api/resources/can_i_deploy_badge.rb +1 -1
  35. data/lib/pact_broker/api/resources/dashboard.rb +2 -2
  36. data/lib/pact_broker/api/resources/default_base_resource.rb +37 -12
  37. data/lib/pact_broker/api/resources/error_handler.rb +1 -1
  38. data/lib/pact_broker/api/resources/error_response_body_generator.rb +41 -0
  39. data/lib/pact_broker/api/resources/group.rb +1 -1
  40. data/lib/pact_broker/api/resources/integrations.rb +1 -1
  41. data/lib/pact_broker/api/resources/label.rb +1 -1
  42. data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
  43. data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
  44. data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +2 -2
  45. data/lib/pact_broker/api/resources/matrix.rb +2 -2
  46. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
  47. data/lib/pact_broker/api/resources/metadata_resource_methods.rb +2 -1
  48. data/lib/pact_broker/api/resources/pact.rb +2 -2
  49. data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
  50. data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
  51. data/lib/pact_broker/api/resources/pact_webhooks.rb +3 -3
  52. data/lib/pact_broker/api/resources/pact_webhooks_status.rb +2 -2
  53. data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
  54. data/lib/pact_broker/api/resources/pacticipants.rb +3 -3
  55. data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
  56. data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
  57. data/lib/pact_broker/api/resources/provider_pacts.rb +1 -7
  58. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +2 -2
  59. data/lib/pact_broker/api/resources/relationships.rb +1 -1
  60. data/lib/pact_broker/api/resources/tag.rb +1 -1
  61. data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
  62. data/lib/pact_broker/api/resources/verification.rb +2 -2
  63. data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
  64. data/lib/pact_broker/api/resources/verifications.rb +1 -1
  65. data/lib/pact_broker/api/resources/version.rb +1 -1
  66. data/lib/pact_broker/api/resources/versions.rb +1 -1
  67. data/lib/pact_broker/api/resources/webhook.rb +2 -2
  68. data/lib/pact_broker/api/resources/webhook_execution.rb +4 -4
  69. data/lib/pact_broker/api/resources/webhook_execution_methods.rb +1 -3
  70. data/lib/pact_broker/api/resources/webhooks.rb +3 -3
  71. data/lib/pact_broker/app.rb +14 -3
  72. data/lib/pact_broker/application_context.rb +41 -0
  73. data/lib/pact_broker/configuration.rb +12 -4
  74. data/lib/pact_broker/doc/controllers/app.rb +3 -2
  75. data/lib/pact_broker/domain/version.rb +13 -6
  76. data/lib/pact_broker/domain/webhook_request.rb +1 -1
  77. data/lib/pact_broker/error.rb +0 -2
  78. data/lib/pact_broker/errors.rb +28 -0
  79. data/lib/pact_broker/errors/error_logger.rb +25 -0
  80. data/lib/pact_broker/metrics/service.rb +12 -1
  81. data/lib/pact_broker/pacts/metadata.rb +53 -8
  82. data/lib/pact_broker/pacts/repository.rb +10 -17
  83. data/lib/pact_broker/pacts/selector.rb +22 -0
  84. data/lib/pact_broker/pacts/selectors.rb +4 -0
  85. data/lib/pact_broker/services.rb +106 -31
  86. data/lib/pact_broker/tags/tag_with_latest_flag.rb +2 -0
  87. data/lib/pact_broker/test/http_test_data_builder.rb +83 -21
  88. data/lib/pact_broker/test/test_data_builder.rb +3 -2
  89. data/lib/pact_broker/ui/views/index/_getting-started.haml +1 -1
  90. data/lib/pact_broker/ui/views/index/show-with-tags.haml +16 -16
  91. data/lib/pact_broker/ui/views/index/show.haml +6 -6
  92. data/lib/pact_broker/ui/views/layouts/main.haml +2 -2
  93. data/lib/pact_broker/ui/views/matrix/show.haml +32 -33
  94. data/lib/pact_broker/version.rb +1 -1
  95. data/lib/pact_broker/webhooks/execution_configuration.rb +4 -0
  96. data/lib/pact_broker/webhooks/execution_configuration_creator.rb +14 -0
  97. data/lib/pact_broker/webhooks/repository.rb +3 -2
  98. data/lib/pact_broker/webhooks/service.rb +2 -1
  99. data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
  100. data/lib/rack/pact_broker/hal_browser_redirect.rb +42 -0
  101. data/lib/rack/pact_broker/set_base_url.rb +22 -0
  102. data/lib/sequel/extensions/statement_timeout.rb +22 -0
  103. data/optic.yml +5 -0
  104. data/pact_broker.gemspec +1 -1
  105. data/public/css/bootstrap-grid.css +3719 -0
  106. data/public/css/bootstrap-grid.css.map +1 -0
  107. data/public/css/bootstrap-grid.min.css +7 -0
  108. data/public/css/bootstrap-grid.min.css.map +1 -0
  109. data/public/css/bootstrap-reboot.css +331 -0
  110. data/public/css/bootstrap-reboot.css.map +1 -0
  111. data/public/css/bootstrap-reboot.min.css +8 -0
  112. data/public/css/bootstrap-reboot.min.css.map +1 -0
  113. data/public/css/bootstrap.css +8885 -5604
  114. data/public/css/bootstrap.css.map +1 -1
  115. data/public/css/bootstrap.min.css +4 -3
  116. data/public/css/bootstrap.min.css.map +1 -1
  117. data/public/images/alert.svg +1 -0
  118. data/public/images/arrow-switch.svg +1 -0
  119. data/public/images/check.svg +1 -0
  120. data/public/images/clock.svg +1 -0
  121. data/public/images/copy.svg +1 -0
  122. data/public/images/kebab-horizontal.svg +1 -0
  123. data/public/javascripts/clipboard.js +3 -3
  124. data/public/javascripts/{jquery-3.3.1.js → jquery-3.5.1.js} +1150 -642
  125. data/public/javascripts/jquery-3.5.1.min.js +2 -0
  126. data/public/javascripts/jquery-3.5.1.min.map +1 -0
  127. data/public/javascripts/matrix.js +2 -2
  128. data/public/js/bootstrap.bundle.js +7013 -0
  129. data/public/js/bootstrap.bundle.js.map +1 -0
  130. data/public/js/bootstrap.bundle.min.js +7 -0
  131. data/public/js/bootstrap.bundle.min.js.map +1 -0
  132. data/public/js/bootstrap.js +3862 -1804
  133. data/public/js/bootstrap.js.map +1 -0
  134. data/public/js/bootstrap.min.js +6 -6
  135. data/public/js/bootstrap.min.js.map +1 -0
  136. data/public/stylesheets/index.css +56 -3
  137. data/public/stylesheets/matrix.css +55 -5
  138. data/public/stylesheets/pact.css +14 -0
  139. data/regression/.gitignore +1 -0
  140. data/regression/can_i_deploy_spec.rb +42 -0
  141. data/regression/regression_helper.rb +37 -0
  142. data/regression/script/approval-all.sh +6 -0
  143. data/script/exercise-api-for-optic.sh +3 -0
  144. data/script/reproduce-issue-starting-up.rb +43 -0
  145. data/script/reproduce-issue.rb +9 -21
  146. data/spec/lib/pact_broker/api/decorators/extended_pact_decorator_spec.rb +1 -0
  147. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +20 -8
  148. data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +5 -7
  149. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +10 -6
  150. data/spec/lib/pact_broker/api/resources/can_i_deploy_badge_spec.rb +1 -1
  151. data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +59 -10
  152. data/spec/lib/pact_broker/api/resources/error_response_body_generator_spec.rb +69 -0
  153. data/spec/lib/pact_broker/db/log_quietener_spec.rb +1 -1
  154. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
  155. data/spec/lib/pact_broker/errors/error_logger_spec.rb +62 -0
  156. data/spec/lib/pact_broker/errors_spec.rb +55 -0
  157. data/spec/lib/pact_broker/pacts/metadata_spec.rb +73 -0
  158. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +2 -2
  159. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +33 -13
  160. data/spec/lib/pact_broker/pacts/selected_pact_spec.rb +23 -0
  161. data/spec/lib/pact_broker/webhooks/repository_spec.rb +5 -2
  162. data/spec/lib/pact_broker/webhooks/service_spec.rb +2 -1
  163. data/spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb +27 -0
  164. data/tasks/rspec.rake +6 -0
  165. metadata +65 -17
  166. data/public/css/bootstrap-theme.css +0 -587
  167. data/public/css/bootstrap-theme.css.map +0 -1
  168. data/public/css/bootstrap-theme.min.css +0 -6
  169. data/public/css/bootstrap-theme.min.css.map +0 -1
  170. data/public/fonts/glyphicons-halflings-regular.svg +0 -288
  171. data/public/javascripts/jquery-3.3.1.min.js +0 -2
  172. data/public/javascripts/jquery-3.3.1.min.map +0 -1
  173. data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +0 -195
@@ -8,6 +8,7 @@ module PactBroker
8
8
  allow_any_instance_of(PactBroker::Api::PactBrokerUrls).to receive(:pact_version_url_with_metadata).and_return('http://pact')
9
9
  allow(PactBroker::Pacts::BuildVerifiablePactNotices).to receive(:call).and_return(notices)
10
10
  allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pact_version_short_description).and_return('short desc')
11
+ allow_any_instance_of(VerifiablePactDecorator).to receive(:build_metadata_for_pact_for_verification).and_return(metadata)
11
12
  end
12
13
 
13
14
  let(:pending_reason) { "the pending reason" }
@@ -45,13 +46,15 @@ module PactBroker
45
46
  name: "name",
46
47
  provider_name: "Bar",
47
48
  pending_provider_tags: pending_provider_tags,
48
- consumer_tags: consumer_tags)
49
+ consumer_tags: consumer_tags,
50
+ selectors: PactBroker::Pacts::Selectors.new([PactBroker::Pacts::ResolvedSelector.new({ latest: true }, double('version', number: "2", id: 1))]))
49
51
  end
50
52
  let(:pending_provider_tags) { %w[dev] }
51
53
  let(:consumer_tags) { %w[dev] }
52
54
  let(:options) { { user_options: { base_url: 'http://example.org', include_pending_status: include_pending_status } } }
53
55
  let(:include_pending_status) { true }
54
56
  let(:wip){ false }
57
+ let(:metadata) { double('metadata') }
55
58
  let(:json) { decorator.to_json(options) }
56
59
 
57
60
  subject { JSON.parse(json) }
@@ -61,7 +64,7 @@ module PactBroker
61
64
  end
62
65
 
63
66
  it "creates the pact version url" do
64
- expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, nil, 'http://example.org')
67
+ expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, metadata, 'http://example.org')
65
68
  subject
66
69
  end
67
70
 
@@ -84,11 +87,6 @@ module PactBroker
84
87
  it "includes the wip flag" do
85
88
  expect(subject['verificationProperties']['wip']).to be true
86
89
  end
87
-
88
- it "includes it in the metadata" do
89
- expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, { wip: true }, 'http://example.org')
90
- subject
91
- end
92
90
  end
93
91
  end
94
92
  end
@@ -36,6 +36,7 @@ module PactBroker
36
36
  pacticipant: consumer,
37
37
  number: "2/4")
38
38
  end
39
+ let(:tag) { double('tag', name: "feat/foo", version: version) }
39
40
 
40
41
  matcher :match_route_in_api do |api|
41
42
  match do |url|
@@ -106,13 +107,9 @@ module PactBroker
106
107
  end
107
108
 
108
109
  describe "webhook metadata" do
109
- let(:expected_metadata) do
110
- { consumer_version_number: "123/456", consumer_version_tags: %w[dev], wip: "true" }
111
- end
112
-
113
110
  it "builds the webhook metadata" do
114
- encoded_metadata = PactBrokerUrls.encode_metadata(PactBrokerUrls.build_metadata_for_webhook_triggered_by_pact_publication(pact))
115
- expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq (expected_metadata)
111
+ encoded_metadata = PactBrokerUrls.encode_metadata("some" => "metadata")
112
+ expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq "some" => "metadata"
116
113
  end
117
114
  end
118
115
 
@@ -168,6 +165,13 @@ module PactBroker
168
165
 
169
166
  it { is_expected.to eq "http://example.org/matrix/provider/Bar%2FBar/latest/meep/consumer/Foo%2FFoo/latest/bar/badge.svg" }
170
167
  end
168
+
169
+ describe "tag_url" do
170
+ subject { PactBrokerUrls.tag_url(base_url, tag) }
171
+
172
+ it { is_expected.to match_route_in_api(PactBroker::API) }
173
+ it { is_expected.to eq "http://example.org/pacticipants/Foo%2FFoo/versions/2%2F4/tags/feat%2Ffoo" }
174
+ end
171
175
  end
172
176
  end
173
177
  end
@@ -15,7 +15,7 @@ module PactBroker
15
15
  allow(pacticipant_service).to receive(:find_pacticipant_by_name).and_return(pacticipant)
16
16
  allow(version_service).to receive(:find_by_pacticipant_name_and_latest_tag).and_return(version)
17
17
  allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(false)
18
- allow(ErrorHandler).to receive(:generate_error_reference).and_return("abcd")
18
+ allow(PactBroker::Errors).to receive(:generate_error_reference).and_return("abcd")
19
19
  end
20
20
 
21
21
  let(:pacticipant_service) { class_double("PactBroker::Pacticipant::Service").as_stubbed_const }
@@ -1,20 +1,30 @@
1
1
  require 'pact_broker/api/resources/default_base_resource'
2
+ require 'pact_broker/application_context'
2
3
 
3
4
  module PactBroker
4
5
  module Api
5
6
  module Resources
6
7
  describe DefaultBaseResource do
7
- let(:request) { double('request', body: body, uri: uri, base_uri: URI("http://example.org/"), env: env).as_null_object }
8
+ before do
9
+ allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
10
+ end
11
+ let(:request) { double('request', body: body, uri: uri, base_uri: URI("http://example.org/"), env: env, path_info: path_info).as_null_object }
12
+ let(:path_info) { { application_context: application_context, key1: "foo%20bar", key2: :value2, key3: 1.2 }}
13
+ let(:application_context) { PactBroker::ApplicationContext.default_application_context }
8
14
  let(:response) { double('response').as_null_object }
9
15
  let(:uri) { URI('http://example.org/path?query') }
10
16
  let(:body) { double('body', to_s: body_string) }
11
17
  let(:body_string) { '' }
12
18
  let(:env) { double('env').as_null_object }
13
19
 
14
- subject { BaseResource.new(request, response) }
20
+ subject(:resource) { BaseResource.new(request, response) }
15
21
 
16
22
  its(:resource_url) { is_expected.to eq 'http://example.org/path' }
17
23
 
24
+ describe "identifier_from_path" do
25
+ its(:identifier_from_path) { is_expected.to eq key1: "foo bar", key2: :value2, key3: 1.2 }
26
+ end
27
+
18
28
  describe "params" do
19
29
  let(:body_string) { { foo: 'bar' }.to_json }
20
30
 
@@ -78,19 +88,19 @@ module PactBroker
78
88
  end
79
89
 
80
90
  describe "base_url" do
81
- context "when PactBroker.configuration.base_url is not nil" do
82
- before do
83
- allow(PactBroker.configuration).to receive(:base_url).and_return("http://foo")
84
- end
91
+ before do
92
+ allow(env).to receive(:[]).with("pactbroker.base_url").and_return("http://rack")
93
+ end
85
94
 
86
- it "returns the configured base URL" do
87
- expect(subject.base_url).to eq "http://foo"
95
+ context "when pactbroker.base_url is set on the env" do
96
+ it "uses that" do
97
+ expect(subject.base_url).to eq "http://rack"
88
98
  end
89
99
  end
90
100
 
91
- context "when PactBroker.configuration.base_url is nil" do
101
+ context "when the rack env value is not set" do
92
102
  before do
93
- allow(PactBroker.configuration).to receive(:base_url).and_return(nil)
103
+ allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
94
104
  end
95
105
 
96
106
  it "returns the base URL from the request" do
@@ -133,6 +143,39 @@ module PactBroker
133
143
  end
134
144
  end
135
145
  end
146
+
147
+ describe "forbidden?" do
148
+ context "with the resource_authorizer configured" do
149
+ let(:application_context) { PactBroker::ApplicationContext.default_application_context(resource_authorizer: resource_authorizer) }
150
+ let(:resource_authorizer) { double('resource_authorizer', call: allowed) }
151
+ let(:allowed) { true }
152
+
153
+ it "calls the resource authorizer" do
154
+ expect(resource_authorizer).to receive(:call).with(resource)
155
+ resource.forbidden?
156
+ end
157
+
158
+ context "when the authorizer returns true" do
159
+ it "returns false" do
160
+ expect(resource.forbidden?).to eq false
161
+ end
162
+ end
163
+
164
+ context "when the authorizer returns false" do
165
+ let(:allowed) { false }
166
+
167
+ it "returns true" do
168
+ expect(resource.forbidden?).to eq true
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ context "with no resource_authorizer configured" do
175
+ it "returns false" do
176
+ expect(resource.forbidden?).to eq false
177
+ end
178
+ end
136
179
  end
137
180
 
138
181
  ALL_RESOURCES = ObjectSpace.each_object(::Class)
@@ -144,22 +187,28 @@ module PactBroker
144
187
  before do
145
188
  # stub out all path info params for pf
146
189
  allow(path_info).to receive(:[]).and_return('1')
190
+ allow(path_info).to receive(:[]).with(:application_context).and_return(application_context)
147
191
  end
192
+ let(:application_context) { PactBroker::ApplicationContext.default_application_context(before_resource: before_resource, after_resource: after_resource) }
148
193
  let(:request) { double('request', uri: URI("http://example.org"), path_info: path_info).as_null_object }
149
194
  let(:path_info) { {} }
150
195
  let(:response) { double('response').as_null_object }
151
196
  let(:resource) { resource_class.new(request, response) }
197
+ let(:before_resource) { double('before_resource', call: nil) }
198
+ let(:after_resource) { double('after_resource', call: nil) }
152
199
 
153
200
  it "includes OPTIONS in the list of allowed_methods" do
154
201
  expect(resource.allowed_methods).to include "OPTIONS"
155
202
  end
156
203
 
157
204
  it "calls super in its constructor" do
205
+ expect(application_context.before_resource).to receive(:call)
158
206
  expect(PactBroker.configuration.before_resource).to receive(:call)
159
207
  resource
160
208
  end
161
209
 
162
210
  it "calls super in finish_request" do
211
+ expect(application_context.after_resource).to receive(:call)
163
212
  expect(PactBroker.configuration.after_resource).to receive(:call)
164
213
  resource.finish_request
165
214
  end
@@ -0,0 +1,69 @@
1
+ require 'pact_broker/api/resources/error_response_body_generator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Resources
6
+ describe ErrorResponseBodyGenerator do
7
+ describe ".call" do
8
+ before do
9
+ allow(error).to receive(:backtrace).and_return(["backtrace"])
10
+ end
11
+ let(:error) { StandardError.new('test error') }
12
+ let(:error_reference) { "bYWfnyWPlf" }
13
+
14
+ subject { JSON.parse(ErrorResponseBodyGenerator.call(error, error_reference)) }
15
+
16
+ it "includes an error reference" do
17
+ expect(subject['error']).to include 'reference' => "bYWfnyWPlf"
18
+ end
19
+
20
+ context "when show_backtrace_in_error_response? is true" do
21
+ before do
22
+ allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(true)
23
+ end
24
+
25
+ context "when the error is a PactBroker::Error or subclass" do
26
+ let(:error) { Class.new(PactBroker::Error).new('test error') }
27
+
28
+ it "uses the error message as the message" do
29
+ expect(subject['error']).to include 'message' => "test error"
30
+ end
31
+
32
+ it "includes the backtrace in the error response" do
33
+ expect(subject['error']).to include ('backtrace')
34
+ end
35
+ end
36
+ end
37
+
38
+ context "when show_backtrace_in_error_response? is false" do
39
+ before do
40
+ allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(false)
41
+ end
42
+
43
+ context "when the error is a PactBroker::Error or subclass" do
44
+ let(:error) { Class.new(PactBroker::Error).new('test error') }
45
+
46
+ it "uses the error message as the message" do
47
+ expect(subject['error']).to include 'message' => "test error"
48
+ end
49
+
50
+ it "does not include the backtrace in the error response" do
51
+ expect(subject['error']).to_not include ('backtrace')
52
+ end
53
+ end
54
+
55
+ context "when the error is not a PactBroker::Error or subclass" do
56
+ it "uses a hardcoded error message" do
57
+ expect(subject['error']['message']).to match /An error/
58
+ end
59
+
60
+ it "does not include the backtrace in the error response" do
61
+ expect(subject['error']).to_not include ('backtrace')
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -42,7 +42,7 @@ module PactBroker
42
42
  expect(logs.string).to include "ERROR -- :"
43
43
  end
44
44
 
45
- it "does not appends a friendly message so people will correctly panic" do
45
+ it "does not append a friendly message so people will correctly panic" do
46
46
  expect(logs.string).to_not include "Don't panic."
47
47
  end
48
48
  end
@@ -4,13 +4,13 @@ module PactBroker
4
4
  module Doc
5
5
  module Controllers
6
6
  describe App do
7
-
8
7
  describe "GET relation" do
9
8
 
10
9
  let(:app) { PactBroker::Doc::Controllers::App }
10
+ let(:rack_env) { {} }
11
11
 
12
12
  context "when the resource exists" do
13
- subject { get "/webhooks" }
13
+ subject { get "/webhooks", nil, rack_env }
14
14
 
15
15
  it "returns a 200 status" do
16
16
  subject
@@ -34,9 +34,7 @@ module PactBroker
34
34
  end
35
35
 
36
36
  context "with the base_url set" do
37
- before do
38
- allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org/pact-broker')
39
- end
37
+ let(:rack_env) { { "pactbroker.base_url" => "http://example.org/pact-broker"} }
40
38
 
41
39
  it "returns absolute links" do
42
40
  expect(subject.body).to include "href='http://example.org/pact-broker/css"
@@ -0,0 +1,62 @@
1
+ require 'pact_broker/errors/error_logger'
2
+
3
+ module PactBroker
4
+ module Errors
5
+ describe ErrorLogger do
6
+ before do
7
+ allow(ErrorLogger).to receive(:logger).and_return(logger)
8
+ allow(error).to receive(:backtrace).and_return(["backtrace"])
9
+ allow(PactBroker::Errors).to receive(:reportable_error?).and_return(reportable)
10
+ end
11
+
12
+ let(:logger) { double('logger').as_null_object }
13
+ let(:error) { StandardError.new('test error') }
14
+ let(:env) { double('env') }
15
+ let(:error_reference) { "bYWfnyWPlf" }
16
+ let(:reportable) { true }
17
+
18
+ subject { ErrorLogger.call(error, error_reference, env) }
19
+
20
+ context "when the error class is in the warning_error_classes list" do
21
+ let(:error) { Sequel::ForeignKeyConstraintViolation.new }
22
+
23
+ it "logs at warn so as not to wake everyone up in the middle of the night" do
24
+ expect(logger).to receive(:warn).with(/bYWfnyWPlf/, error)
25
+ subject
26
+ end
27
+ end
28
+
29
+ context "when the error cause class is in the warning_error_classes list" do
30
+ class TestCauseError < StandardError; end
31
+
32
+ before do
33
+ allow(PactBroker.configuration).to receive(:warning_error_classes).and_return([TestCauseError])
34
+ allow(error).to receive(:cause).and_return(TestCauseError.new)
35
+ end
36
+
37
+ let(:error) { StandardError.new("message") }
38
+
39
+ it "logs at warn so as not to wake everyone up in the middle of the night" do
40
+ expect(logger).to receive(:warn).with(/bYWfnyWPlf/, error)
41
+ subject
42
+ end
43
+ end
44
+
45
+ context "when the error is reportable" do
46
+ it "logs at error" do
47
+ expect(ErrorLogger).to receive(:log_error).with(error, /bYWfnyWPlf/)
48
+ subject
49
+ end
50
+ end
51
+
52
+ context "when the error is not reportable and not a warning level" do
53
+ let(:reportable) { false }
54
+
55
+ it "logs at info" do
56
+ expect(logger).to receive(:info).with(/bYWfnyWPlf/, error)
57
+ subject
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,55 @@
1
+ require 'pact_broker/errors'
2
+ require 'pact_broker/configuration'
3
+
4
+ module PactBroker
5
+ module Errors
6
+ describe ".report" do
7
+ before do
8
+ PactBroker.configuration.add_api_error_reporter do | error, options |
9
+ thing.call(error, options)
10
+ end
11
+
12
+ PactBroker.configuration.add_api_error_reporter do | error, options |
13
+ thing.another_call(error, options)
14
+ end
15
+ end
16
+
17
+ let(:error) { StandardError.new('test error') }
18
+ let(:thing) { double('thing', call: nil, another_call: nil) }
19
+ let(:request) { double('request', env: env ) }
20
+ let(:error_reference) { "bYWfnyWPlf" }
21
+ let(:expected_options) { { env: env, error_reference: "bYWfnyWPlf" } }
22
+ let(:env) { double('env') }
23
+
24
+ subject { PactBroker::Errors.report(error, error_reference, request) }
25
+
26
+
27
+ it "invokes the api error reporters" do
28
+ expect(thing).to receive(:call).with(error, expected_options)
29
+ expect(thing).to receive(:another_call).with(error, expected_options)
30
+ subject
31
+ end
32
+
33
+ context "when the error reporter raises an error itself" do
34
+ class TestError < StandardError; end
35
+
36
+ let(:logger) { double('logger').as_null_object }
37
+
38
+ before do
39
+ expect(thing).to receive(:call).and_raise(TestError.new)
40
+ allow(PactBroker::Errors).to receive(:logger).and_return(logger)
41
+ end
42
+
43
+ it "logs the error" do
44
+ expect(logger).to receive(:error).at_least(1).times
45
+ subject
46
+ end
47
+
48
+ it "does not propagate the error" do
49
+ expect(thing).to receive(:another_call)
50
+ subject
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,73 @@
1
+ require 'pact_broker/pacts/metadata'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ module Metadata
6
+ describe "#build_metadata_for_pact_for_verification" do
7
+ let(:selectors) do
8
+ Selectors.new([ResolvedSelector.new({ latest: true, consumer: "consumer", tag: "tag" }, consumer_version)])
9
+ end
10
+ let(:consumer_version) { double('version', number: "2") }
11
+ let(:verifiable_pact) { double('PactBroker::Pacts::VerifiablePact', wip: wip, selectors: selectors) }
12
+ let(:wip) { false }
13
+
14
+ subject { Metadata.build_metadata_for_pact_for_verification(verifiable_pact) }
15
+
16
+ it "builds the metadata with the resolved selectors" do
17
+ expect(subject).to eq({
18
+ "s" => [
19
+ {
20
+ "l" => true,
21
+ "t" => "tag",
22
+ "cvn" => "2"
23
+ }
24
+ ]
25
+ })
26
+ end
27
+
28
+ context "when wip is true" do
29
+ let(:wip) { true }
30
+
31
+ it { is_expected.to eq "w" => true }
32
+
33
+ end
34
+ end
35
+
36
+ describe "parse_metadata" do
37
+ let(:incoming_metadata) do
38
+ {
39
+ "cvn" => "2",
40
+ "cvt" => ["tag"],
41
+ "w" => true,
42
+ "s" => [
43
+ {
44
+ "l" => true,
45
+ "t" => "tag",
46
+ "cvn" => "2"
47
+ }
48
+ ]
49
+ }
50
+ end
51
+
52
+ let(:parsed_metadata) do
53
+ {
54
+ :consumer_version_number => "2",
55
+ :consumer_version_tags => ["tag"],
56
+ :wip => true,
57
+ :consumer_version_selectors => [
58
+ {
59
+ :latest => true,
60
+ :tag => "tag",
61
+ :consumer_version_number => "2"
62
+ }
63
+ ]
64
+ }
65
+ end
66
+
67
+ it "expands the key names" do
68
+ expect(Metadata.parse_metadata(incoming_metadata)).to eq parsed_metadata
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end