dhc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rubocop.yml +27 -0
  3. data/.github/workflows/test.yml +27 -0
  4. data/.gitignore +37 -0
  5. data/.rubocop.yml +105 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE +674 -0
  9. data/README.md +999 -0
  10. data/Rakefile +25 -0
  11. data/dhc.gemspec +40 -0
  12. data/lib/core_ext/hash/deep_transform_values.rb +48 -0
  13. data/lib/dhc.rb +77 -0
  14. data/lib/dhc/concerns/dhc/basic_methods_concern.rb +42 -0
  15. data/lib/dhc/concerns/dhc/configuration_concern.rb +20 -0
  16. data/lib/dhc/concerns/dhc/fix_invalid_encoding_concern.rb +42 -0
  17. data/lib/dhc/concerns/dhc/formats_concern.rb +25 -0
  18. data/lib/dhc/concerns/dhc/request/user_agent_concern.rb +25 -0
  19. data/lib/dhc/config.rb +47 -0
  20. data/lib/dhc/endpoint.rb +119 -0
  21. data/lib/dhc/error.rb +82 -0
  22. data/lib/dhc/errors/client_error.rb +73 -0
  23. data/lib/dhc/errors/parser_error.rb +4 -0
  24. data/lib/dhc/errors/server_error.rb +28 -0
  25. data/lib/dhc/errors/timeout.rb +4 -0
  26. data/lib/dhc/errors/unknown_error.rb +4 -0
  27. data/lib/dhc/format.rb +18 -0
  28. data/lib/dhc/formats.rb +8 -0
  29. data/lib/dhc/formats/form.rb +45 -0
  30. data/lib/dhc/formats/json.rb +55 -0
  31. data/lib/dhc/formats/multipart.rb +45 -0
  32. data/lib/dhc/formats/plain.rb +42 -0
  33. data/lib/dhc/interceptor.rb +36 -0
  34. data/lib/dhc/interceptors.rb +26 -0
  35. data/lib/dhc/interceptors/auth.rb +94 -0
  36. data/lib/dhc/interceptors/caching.rb +148 -0
  37. data/lib/dhc/interceptors/default_timeout.rb +16 -0
  38. data/lib/dhc/interceptors/logging.rb +37 -0
  39. data/lib/dhc/interceptors/monitoring.rb +92 -0
  40. data/lib/dhc/interceptors/prometheus.rb +51 -0
  41. data/lib/dhc/interceptors/retry.rb +41 -0
  42. data/lib/dhc/interceptors/rollbar.rb +36 -0
  43. data/lib/dhc/interceptors/throttle.rb +86 -0
  44. data/lib/dhc/interceptors/zipkin.rb +110 -0
  45. data/lib/dhc/railtie.rb +9 -0
  46. data/lib/dhc/request.rb +161 -0
  47. data/lib/dhc/response.rb +60 -0
  48. data/lib/dhc/response/data.rb +28 -0
  49. data/lib/dhc/response/data/base.rb +18 -0
  50. data/lib/dhc/response/data/collection.rb +16 -0
  51. data/lib/dhc/response/data/item.rb +29 -0
  52. data/lib/dhc/rspec.rb +11 -0
  53. data/lib/dhc/test/cache_helper.rb +3 -0
  54. data/lib/dhc/version.rb +5 -0
  55. data/script/ci/build.sh +19 -0
  56. data/spec/basic_methods/delete_spec.rb +34 -0
  57. data/spec/basic_methods/get_spec.rb +49 -0
  58. data/spec/basic_methods/post_spec.rb +42 -0
  59. data/spec/basic_methods/put_spec.rb +48 -0
  60. data/spec/basic_methods/request_spec.rb +19 -0
  61. data/spec/basic_methods/request_without_rails_spec.rb +29 -0
  62. data/spec/config/endpoints_spec.rb +63 -0
  63. data/spec/config/placeholders_spec.rb +32 -0
  64. data/spec/core_ext/hash/deep_transform_values_spec.rb +24 -0
  65. data/spec/dummy/README.rdoc +28 -0
  66. data/spec/dummy/Rakefile +8 -0
  67. data/spec/dummy/app/assets/config/manifest.js +3 -0
  68. data/spec/dummy/app/assets/images/.keep +0 -0
  69. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  70. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  71. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  72. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  73. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  74. data/spec/dummy/app/mailers/.keep +0 -0
  75. data/spec/dummy/app/models/.keep +0 -0
  76. data/spec/dummy/app/models/concerns/.keep +0 -0
  77. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  78. data/spec/dummy/bin/bundle +5 -0
  79. data/spec/dummy/bin/rails +6 -0
  80. data/spec/dummy/bin/rake +6 -0
  81. data/spec/dummy/config.ru +6 -0
  82. data/spec/dummy/config/application.rb +16 -0
  83. data/spec/dummy/config/boot.rb +7 -0
  84. data/spec/dummy/config/environment.rb +7 -0
  85. data/spec/dummy/config/environments/development.rb +36 -0
  86. data/spec/dummy/config/environments/production.rb +77 -0
  87. data/spec/dummy/config/environments/test.rb +41 -0
  88. data/spec/dummy/config/initializers/assets.rb +10 -0
  89. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  90. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  91. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  92. data/spec/dummy/config/initializers/inflections.rb +18 -0
  93. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  94. data/spec/dummy/config/initializers/session_store.rb +5 -0
  95. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  96. data/spec/dummy/config/locales/en.yml +23 -0
  97. data/spec/dummy/config/routes.rb +58 -0
  98. data/spec/dummy/config/secrets.yml +22 -0
  99. data/spec/dummy/lib/assets/.keep +0 -0
  100. data/spec/dummy/log/.keep +0 -0
  101. data/spec/dummy/public/404.html +67 -0
  102. data/spec/dummy/public/422.html +67 -0
  103. data/spec/dummy/public/500.html +66 -0
  104. data/spec/dummy/public/favicon.ico +0 -0
  105. data/spec/endpoint/compile_spec.rb +35 -0
  106. data/spec/endpoint/match_spec.rb +41 -0
  107. data/spec/endpoint/placeholders_spec.rb +30 -0
  108. data/spec/endpoint/remove_interpolated_params_spec.rb +17 -0
  109. data/spec/endpoint/values_as_params_spec.rb +31 -0
  110. data/spec/error/dup_spec.rb +12 -0
  111. data/spec/error/find_spec.rb +57 -0
  112. data/spec/error/response_spec.rb +17 -0
  113. data/spec/error/timeout_spec.rb +14 -0
  114. data/spec/error/to_s_spec.rb +85 -0
  115. data/spec/formats/form_spec.rb +27 -0
  116. data/spec/formats/json_spec.rb +66 -0
  117. data/spec/formats/multipart_spec.rb +26 -0
  118. data/spec/formats/plain_spec.rb +29 -0
  119. data/spec/interceptors/after_request_spec.rb +20 -0
  120. data/spec/interceptors/after_response_spec.rb +39 -0
  121. data/spec/interceptors/auth/basic_auth_spec.rb +17 -0
  122. data/spec/interceptors/auth/bearer_spec.rb +19 -0
  123. data/spec/interceptors/auth/body_spec.rb +36 -0
  124. data/spec/interceptors/auth/long_basic_auth_credentials_spec.rb +17 -0
  125. data/spec/interceptors/auth/no_instance_var_for_options_spec.rb +27 -0
  126. data/spec/interceptors/auth/reauthentication_configuration_spec.rb +61 -0
  127. data/spec/interceptors/auth/reauthentication_spec.rb +44 -0
  128. data/spec/interceptors/before_request_spec.rb +21 -0
  129. data/spec/interceptors/before_response_spec.rb +20 -0
  130. data/spec/interceptors/caching/hydra_spec.rb +26 -0
  131. data/spec/interceptors/caching/main_spec.rb +73 -0
  132. data/spec/interceptors/caching/methods_spec.rb +42 -0
  133. data/spec/interceptors/caching/multilevel_cache_spec.rb +139 -0
  134. data/spec/interceptors/caching/options_spec.rb +78 -0
  135. data/spec/interceptors/caching/parameters_spec.rb +24 -0
  136. data/spec/interceptors/caching/response_status_spec.rb +29 -0
  137. data/spec/interceptors/caching/to_cache_spec.rb +16 -0
  138. data/spec/interceptors/default_interceptors_spec.rb +15 -0
  139. data/spec/interceptors/default_timeout/main_spec.rb +34 -0
  140. data/spec/interceptors/define_spec.rb +30 -0
  141. data/spec/interceptors/dup_spec.rb +19 -0
  142. data/spec/interceptors/logging/main_spec.rb +37 -0
  143. data/spec/interceptors/monitoring/caching_spec.rb +66 -0
  144. data/spec/interceptors/monitoring/main_spec.rb +97 -0
  145. data/spec/interceptors/prometheus_spec.rb +54 -0
  146. data/spec/interceptors/response_competition_spec.rb +39 -0
  147. data/spec/interceptors/retry/main_spec.rb +73 -0
  148. data/spec/interceptors/return_response_spec.rb +38 -0
  149. data/spec/interceptors/rollbar/invalid_encoding_spec.rb +43 -0
  150. data/spec/interceptors/rollbar/main_spec.rb +57 -0
  151. data/spec/interceptors/throttle/main_spec.rb +236 -0
  152. data/spec/interceptors/throttle/reset_track_spec.rb +53 -0
  153. data/spec/interceptors/zipkin/distributed_tracing_spec.rb +135 -0
  154. data/spec/rails_helper.rb +6 -0
  155. data/spec/request/body_spec.rb +39 -0
  156. data/spec/request/encoding_spec.rb +38 -0
  157. data/spec/request/error_handling_spec.rb +88 -0
  158. data/spec/request/headers_spec.rb +12 -0
  159. data/spec/request/ignore_errors_spec.rb +73 -0
  160. data/spec/request/option_dup_spec.rb +13 -0
  161. data/spec/request/parallel_requests_spec.rb +59 -0
  162. data/spec/request/params_encoding_spec.rb +26 -0
  163. data/spec/request/request_without_rails_spec.rb +15 -0
  164. data/spec/request/url_patterns_spec.rb +54 -0
  165. data/spec/request/user_agent_spec.rb +26 -0
  166. data/spec/request/user_agent_without_rails_spec.rb +27 -0
  167. data/spec/response/body_spec.rb +16 -0
  168. data/spec/response/code_spec.rb +16 -0
  169. data/spec/response/data_accessor_spec.rb +29 -0
  170. data/spec/response/data_spec.rb +85 -0
  171. data/spec/response/effective_url_spec.rb +16 -0
  172. data/spec/response/headers_spec.rb +18 -0
  173. data/spec/response/options_spec.rb +18 -0
  174. data/spec/response/success_spec.rb +13 -0
  175. data/spec/response/time_spec.rb +21 -0
  176. data/spec/spec_helper.rb +9 -0
  177. data/spec/support/fixtures/json/feedback.json +11 -0
  178. data/spec/support/fixtures/json/feedbacks.json +164 -0
  179. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  180. data/spec/support/load_json.rb +5 -0
  181. data/spec/support/reset_config.rb +8 -0
  182. data/spec/support/zipkin_mock.rb +114 -0
  183. data/spec/timeouts/no_signal_spec.rb +13 -0
  184. data/spec/timeouts/timings_spec.rb +55 -0
  185. metadata +527 -0
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Endpoint do
6
+ context 'placeholders' do
7
+ it 'returns all placeholders alphabetically sorted' do
8
+ endpoint = DHC::Endpoint.new('{+datastore}/v2/{campaign_id}/feedbacks')
9
+ expect(
10
+ endpoint.placeholders
11
+ ).to eq %i[campaign_id datastore]
12
+ end
13
+
14
+ it 'allows basic auth token in url, like used on github' do
15
+ stub_request(:get, 'https://d123token:@api.github.com/search')
16
+ .to_return(body: {}.to_json)
17
+ expect(-> {
18
+ DHC.get('https://d123token:@api.github.com/search')
19
+ }).not_to raise_error
20
+ end
21
+
22
+ it 'allows complete basic auth (username password) in url, like used for the gemserer' do
23
+ stub_request(:get, 'https://name:password@gemserver.com')
24
+ .to_return(body: {}.to_json)
25
+ expect(-> {
26
+ DHC.get('https://name:password@gemserver.com')
27
+ }).not_to raise_error
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Endpoint do
6
+ it 'removes params used for interpolation' do
7
+ params = {
8
+ datastore: 'http://datastore',
9
+ campaign_id: 'abc',
10
+ has_reviews: true
11
+ }
12
+ endpoint = DHC::Endpoint.new('{+datastore}/v2/{campaign_id}/feedbacks')
13
+ removed = endpoint.remove_interpolated_params!(params)
14
+ expect(params).to eq(has_reviews: true)
15
+ expect(removed).to eq(datastore: 'http://datastore', campaign_id: 'abc')
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Endpoint do
6
+ context 'values_as_params' do
7
+ [
8
+ ['{+datastore}/v2/places', 'http://depay.fi:8082/v2/places', {
9
+ datastore: 'http://depay.fi:8082'
10
+ }],
11
+ ['{+datastore}/v2/places/{id}', 'http://depay.fi:8082/v2/places/ZW9OJyrbt4OZE9ueu80w-A', {
12
+ datastore: 'http://depay.fi:8082',
13
+ id: 'ZW9OJyrbt4OZE9ueu80w-A'
14
+ }],
15
+ ['{+datastore}/v2/places/{namespace}/{id}', 'http://depay.fi:8082/v2/places/switzerland/ZW9OJyrbt', {
16
+ datastore: 'http://depay.fi:8082',
17
+ namespace: 'switzerland',
18
+ id: 'ZW9OJyrbt'
19
+ }]
20
+ ].each do |example|
21
+ template = example[0]
22
+ url = example[1]
23
+ params = example[2]
24
+
25
+ it "for the template #{template} it extracts #{params.keys.join(', ')} from the url" do
26
+ extracted = DHC::Endpoint.values_as_params(template, url)
27
+ expect(extracted).to eq(params)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Error do
6
+ it 'does not dup' do
7
+ options = { errors: [described_class] }
8
+ expect(
9
+ options.deep_dup[:errors].include?(described_class)
10
+ ).to eq true
11
+ end
12
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Error do
6
+ def response(code, timedout = false)
7
+ DHC::Response.new(OpenStruct.new(code: code, 'timed_out?' => timedout), nil)
8
+ end
9
+
10
+ context 'find' do
11
+ it 'finds error class by status code' do
12
+ expect(DHC::Error.find(response('0', true))).to eq DHC::Timeout
13
+ expect(DHC::Error.find(response('400'))).to eq DHC::BadRequest
14
+ expect(DHC::Error.find(response('401'))).to eq DHC::Unauthorized
15
+ expect(DHC::Error.find(response('402'))).to eq DHC::PaymentRequired
16
+ expect(DHC::Error.find(response('403'))).to eq DHC::Forbidden
17
+ expect(DHC::Error.find(response('403'))).to eq DHC::Forbidden
18
+ expect(DHC::Error.find(response('404'))).to eq DHC::NotFound
19
+ expect(DHC::Error.find(response('405'))).to eq DHC::MethodNotAllowed
20
+ expect(DHC::Error.find(response('406'))).to eq DHC::NotAcceptable
21
+ expect(DHC::Error.find(response('407'))).to eq DHC::ProxyAuthenticationRequired
22
+ expect(DHC::Error.find(response('408'))).to eq DHC::RequestTimeout
23
+ expect(DHC::Error.find(response('409'))).to eq DHC::Conflict
24
+ expect(DHC::Error.find(response('410'))).to eq DHC::Gone
25
+ expect(DHC::Error.find(response('411'))).to eq DHC::LengthRequired
26
+ expect(DHC::Error.find(response('412'))).to eq DHC::PreconditionFailed
27
+ expect(DHC::Error.find(response('413'))).to eq DHC::RequestEntityTooLarge
28
+ expect(DHC::Error.find(response('414'))).to eq DHC::RequestUriToLong
29
+ expect(DHC::Error.find(response('415'))).to eq DHC::UnsupportedMediaType
30
+ expect(DHC::Error.find(response('416'))).to eq DHC::RequestedRangeNotSatisfiable
31
+ expect(DHC::Error.find(response('417'))).to eq DHC::ExpectationFailed
32
+ expect(DHC::Error.find(response('422'))).to eq DHC::UnprocessableEntity
33
+ expect(DHC::Error.find(response('423'))).to eq DHC::Locked
34
+ expect(DHC::Error.find(response('424'))).to eq DHC::FailedDependency
35
+ expect(DHC::Error.find(response('426'))).to eq DHC::UpgradeRequired
36
+ expect(DHC::Error.find(response('500'))).to eq DHC::InternalServerError
37
+ expect(DHC::Error.find(response('501'))).to eq DHC::NotImplemented
38
+ expect(DHC::Error.find(response('502'))).to eq DHC::BadGateway
39
+ expect(DHC::Error.find(response('503'))).to eq DHC::ServiceUnavailable
40
+ expect(DHC::Error.find(response('504'))).to eq DHC::GatewayTimeout
41
+ expect(DHC::Error.find(response('505'))).to eq DHC::HttpVersionNotSupported
42
+ expect(DHC::Error.find(response('507'))).to eq DHC::InsufficientStorage
43
+ expect(DHC::Error.find(response('510'))).to eq DHC::NotExtended
44
+ end
45
+
46
+ it 'finds error class also by extended status codes' do
47
+ expect(DHC::Error.find(response('40001'))).to eq DHC::BadRequest
48
+ expect(DHC::Error.find(response('50002'))).to eq DHC::InternalServerError
49
+ end
50
+
51
+ it 'returns UnknownError if no specific error was found' do
52
+ expect(DHC::Error.find(response('0'))).to eq DHC::UnknownError
53
+ expect(DHC::Error.find(response(''))).to eq DHC::UnknownError
54
+ expect(DHC::Error.find(response('600'))).to eq DHC::UnknownError
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Error do
6
+ context 'response' do
7
+ it 'throws timeout exception in case of a timeout' do
8
+ stub_request(:any, 'depay.fi').to_return(status: 403)
9
+ begin
10
+ DHC.get('depay.fi')
11
+ rescue => e
12
+ expect(e.response).to be_kind_of(DHC::Response)
13
+ expect(e.response.code).to eq 403
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Error do
6
+ context 'timeout' do
7
+ it 'throws timeout exception in case of a timeout' do
8
+ stub_request(:any, 'depay.fi').to_timeout
9
+ expect(lambda {
10
+ DHC.get('depay.fi')
11
+ }).to raise_error DHC::Timeout
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC::Error do
6
+ context 'to_s' do
7
+ let(:invalid) { (+"in\xc3lid").force_encoding('ASCII-8BIT') }
8
+ let(:valid) { 'vælid' }
9
+
10
+ context 'check assumptions' do
11
+ it 'joining raises an error' do
12
+ expect { [valid, invalid].join }.to raise_error Encoding::CompatibilityError
13
+ end
14
+ it 'interpolation raises an error' do
15
+ expect { "#{valid} #{invalid}" }.to raise_error Encoding::CompatibilityError
16
+ end
17
+ it 'to_json on an array raises an error' do
18
+ expect { [valid, invalid].to_json }.to raise_error Encoding::UndefinedConversionError
19
+ end
20
+
21
+ it 'to_s on a hash does not raise an error' do
22
+ expect { { valid: valid, invalid: invalid }.to_s }.not_to raise_error
23
+ end
24
+
25
+ it 'to_json on a hash does raise an error' do
26
+ expect { { valid: valid, invalid: invalid }.to_json }.to raise_error Encoding::UndefinedConversionError
27
+ end
28
+ end
29
+
30
+ it 'invalid body, valid message' do
31
+ stub_request(:get, 'http://depay.fi')
32
+ .to_return(status: 200, body: "{ text : '#{invalid}' }")
33
+ response = DHC.get('http://depay.fi')
34
+ expect { DHC::Error.new(valid, response).to_s }.not_to raise_error # Encoding::CompatibilityError
35
+ end
36
+
37
+ it 'valid body, invalid message' do
38
+ stub_request(:get, 'http://depay.fi')
39
+ .to_return(status: 200, body: "{ text : '#{valid}' }")
40
+ response = DHC.get('http://depay.fi')
41
+ expect { DHC::Error.new(invalid, response).to_s }.not_to raise_error # Encoding::CompatibilityError
42
+ end
43
+ # the other cases cannot be tested (for example what happens if the headers contain invalid data)
44
+ # because the mocking framework triggers the encoding error already
45
+
46
+ context 'some mocked response' do
47
+ let(:request) do
48
+ double('DHC::Request',
49
+ method: 'GET',
50
+ url: 'http://example.com/sessions',
51
+ headers: { 'Bearer Token' => 'aaaaaaaa-bbbb-cccc-dddd-eeee' },
52
+ options: { followlocation: true,
53
+ auth: { bearer: 'aaaaaaaa-bbbb-cccc-dddd-eeee' },
54
+ params: { limit: 20 }, url: 'http://example.com/sessions' })
55
+ end
56
+
57
+ let(:response) do
58
+ double('DHC::Response',
59
+ request: request,
60
+ code: 500,
61
+ options: { return_code: :internal_error, response_headers: '' },
62
+ body: '{"status":500,"message":"undefined"}')
63
+ end
64
+
65
+ subject { DHC::Error.new('The error message', response) }
66
+
67
+ before do
68
+ allow(request).to receive(:is_a?).with(DHC::Request).and_return(true)
69
+ allow(response).to receive(:is_a?).with(DHC::Response).and_return(true)
70
+ end
71
+
72
+ it 'produces correct debug output' do
73
+ expect(subject.to_s.split("\n")).to eq(<<-MSG.strip_heredoc.split("\n"))
74
+ GET http://example.com/sessions
75
+ Options: {:followlocation=>true, :auth=>{:bearer=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}, :params=>{:limit=>20}, :url=>"http://example.com/sessions"}
76
+ Headers: {"Bearer Token"=>"aaaaaaaa-bbbb-cccc-dddd-eeee"}
77
+ Response Code: 500 (internal_error)
78
+ Response Options: {:return_code=>:internal_error, :response_headers=>""}
79
+ {"status":500,"message":"undefined"}
80
+ The error message
81
+ MSG
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC do
6
+ include ActionDispatch::TestProcess
7
+
8
+ context 'form' do
9
+ it 'formats requests to be application/x-www-form-urlencoded' do
10
+ stub = stub_request(:post, 'http://depay.fi/')
11
+ .with(body: 'client_id=1234&client_secret=4567&grant_type=client_credentials')
12
+ .with(headers: { 'Content-Type': 'application/x-www-form-urlencoded' })
13
+ .to_return(status: 200)
14
+
15
+ DHC.form.post(
16
+ 'http://depay.fi',
17
+ body: {
18
+ client_id: '1234',
19
+ client_secret: '4567',
20
+ grant_type: 'client_credentials'
21
+ }
22
+ )
23
+
24
+ expect(stub).to have_been_requested
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC do
6
+ context 'formats' do
7
+ it 'adds Content-Type, Accept and Accept-Charset Headers to the request' do
8
+ stub_request(:get, 'http://depay.fi/')
9
+ .with(headers: {
10
+ 'Accept' => 'application/json,application/vnd.api+json',
11
+ 'Content-Type' => 'application/json; charset=utf-8',
12
+ 'Accept-Charset' => 'utf-8'
13
+ })
14
+ .to_return(body: {}.to_json)
15
+ DHC.json.get('http://depay.fi')
16
+ end
17
+
18
+ context 'header key as symbol' do
19
+ it 'raises an error when trying to set content-type header even though the format is used' do
20
+ expect(lambda {
21
+ DHC.post(
22
+ 'http://depay.fi',
23
+ headers: {
24
+ 'Content-Type': 'multipart/form-data'
25
+ }
26
+ )
27
+ }).to raise_error 'Content-Type header is not allowed for formatted requests!\nSee https://github.com/DePayFi/dhc#formats for more information.'
28
+ end
29
+
30
+ it 'raises an error when trying to set accept header even though the format is used' do
31
+ expect(lambda {
32
+ DHC.post(
33
+ 'http://depay.fi',
34
+ headers: {
35
+ 'Accept': 'multipart/form-data'
36
+ }
37
+ )
38
+ }).to raise_error 'Accept header is not allowed for formatted requests!\nSee https://github.com/DePayFi/dhc#formats for more information.'
39
+ end
40
+ end
41
+
42
+ context 'header key as string' do
43
+ it 'raises an error when trying to set content-type header even though the format is used' do
44
+ expect(lambda {
45
+ DHC.post(
46
+ 'http://depay.fi',
47
+ headers: {
48
+ 'Content-Type' => 'multipart/form-data'
49
+ }
50
+ )
51
+ }).to raise_error 'Content-Type header is not allowed for formatted requests!\nSee https://github.com/DePayFi/dhc#formats for more information.'
52
+ end
53
+
54
+ it 'raises an error when trying to set accept header even though the format is used' do
55
+ expect(lambda {
56
+ DHC.post(
57
+ 'http://depay.fi',
58
+ headers: {
59
+ 'Accept' => 'multipart/form-data'
60
+ }
61
+ )
62
+ }).to raise_error 'Accept header is not allowed for formatted requests!\nSee https://github.com/DePayFi/dhc#formats for more information.'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC do
6
+ include ActionDispatch::TestProcess
7
+
8
+ context 'multipart' do
9
+ let(:file) { Rack::Test::UploadedFile.new(Tempfile.new) }
10
+ let(:body) { { size: 2231 }.to_json }
11
+ let(:location) { 'http://depay.fi/uploads/image.jpg' }
12
+
13
+ it 'formats requests to be multipart/form-data' do
14
+ stub_request(:post, 'http://depay.fi/') do |request|
15
+ raise 'Content-Type header wrong' unless request.headers['Content-Type'] == 'multipart/form-data'
16
+ raise 'Body wrongly formatted' unless request.body.match(/file=%23%3CActionDispatch%3A%3AHttp%3A%3AUploadedFile%3A.*%3E&type=Image/)
17
+ end.to_return(status: 200, body: body, headers: { 'Location' => location })
18
+ response = DHC.multipart.post(
19
+ 'http://depay.fi',
20
+ body: { file: file, type: 'Image' }
21
+ )
22
+ expect(response.body).to eq body
23
+ expect(response.headers['Location']).to eq location
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC do
6
+ include ActionDispatch::TestProcess
7
+
8
+ context 'plain' do
9
+ let(:file) { Rack::Test::UploadedFile.new(Tempfile.new) }
10
+
11
+ it 'leaves plains requests unformatted' do
12
+ stub_request(:post, 'http://depay.fi/')
13
+ .with(body: /file=%23%3CRack%3A%3ATest%3A%3AUploadedFile%3.*%3E&type=Image/)
14
+ .to_return do |request|
15
+ expect(request.headers['Content-Type']).to be_blank
16
+
17
+ { status: 204 }
18
+ end
19
+ response = DHC.plain.post(
20
+ 'http://depay.fi',
21
+ body: { file: file, type: 'Image' }
22
+ )
23
+ expect(lambda {
24
+ response.body
25
+ response.data
26
+ }).not_to raise_error
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHC do
6
+ context 'interceptor' do
7
+ before(:each) do
8
+ class SomeInterceptor < DHC::Interceptor
9
+ def after_request; end
10
+ end
11
+ DHC.configure { |c| c.interceptors = [SomeInterceptor] }
12
+ end
13
+
14
+ it 'can perform some actions after a request was fired' do
15
+ expect_any_instance_of(SomeInterceptor).to receive(:after_request)
16
+ stub_request(:get, 'http://depay.fi')
17
+ DHC.get('http://depay.fi')
18
+ end
19
+ end
20
+ end