faraday 0.15.0 → 1.10.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +380 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +17 -345
  5. data/Rakefile +7 -0
  6. data/examples/client_spec.rb +97 -0
  7. data/examples/client_test.rb +118 -0
  8. data/lib/faraday/adapter/test.rb +118 -69
  9. data/lib/faraday/adapter/typhoeus.rb +4 -1
  10. data/lib/faraday/adapter.rb +72 -22
  11. data/lib/faraday/adapter_registry.rb +30 -0
  12. data/lib/faraday/autoload.rb +39 -36
  13. data/lib/faraday/connection.rb +343 -185
  14. data/lib/faraday/dependency_loader.rb +37 -0
  15. data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  16. data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
  17. data/lib/faraday/error.rb +118 -38
  18. data/lib/faraday/logging/formatter.rb +105 -0
  19. data/lib/faraday/methods.rb +6 -0
  20. data/lib/faraday/middleware.rb +19 -25
  21. data/lib/faraday/middleware_registry.rb +129 -0
  22. data/lib/faraday/options/connection_options.rb +22 -0
  23. data/lib/faraday/options/env.rb +181 -0
  24. data/lib/faraday/options/proxy_options.rb +32 -0
  25. data/lib/faraday/options/request_options.rb +22 -0
  26. data/lib/faraday/options/ssl_options.rb +59 -0
  27. data/lib/faraday/options.rb +39 -193
  28. data/lib/faraday/parameters.rb +4 -196
  29. data/lib/faraday/rack_builder.rb +77 -65
  30. data/lib/faraday/request/authorization.rb +51 -30
  31. data/lib/faraday/request/basic_authentication.rb +14 -7
  32. data/lib/faraday/request/instrumentation.rb +45 -27
  33. data/lib/faraday/request/json.rb +55 -0
  34. data/lib/faraday/request/token_authentication.rb +15 -10
  35. data/lib/faraday/request/url_encoded.rb +43 -23
  36. data/lib/faraday/request.rb +93 -32
  37. data/lib/faraday/response/json.rb +54 -0
  38. data/lib/faraday/response/logger.rb +20 -69
  39. data/lib/faraday/response/raise_error.rb +49 -14
  40. data/lib/faraday/response.rb +29 -23
  41. data/lib/faraday/utils/headers.rb +139 -0
  42. data/lib/faraday/utils/params_hash.rb +61 -0
  43. data/lib/faraday/utils.rb +38 -247
  44. data/lib/faraday/version.rb +5 -0
  45. data/lib/faraday.rb +134 -189
  46. data/spec/external_adapters/faraday_specs_setup.rb +14 -0
  47. data/spec/faraday/adapter/em_http_spec.rb +49 -0
  48. data/spec/faraday/adapter/em_synchrony_spec.rb +18 -0
  49. data/spec/faraday/adapter/excon_spec.rb +49 -0
  50. data/spec/faraday/adapter/httpclient_spec.rb +73 -0
  51. data/spec/faraday/adapter/net_http_spec.rb +64 -0
  52. data/spec/faraday/adapter/patron_spec.rb +18 -0
  53. data/spec/faraday/adapter/rack_spec.rb +8 -0
  54. data/spec/faraday/adapter/test_spec.rb +377 -0
  55. data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
  56. data/spec/faraday/adapter_registry_spec.rb +28 -0
  57. data/spec/faraday/adapter_spec.rb +55 -0
  58. data/spec/faraday/composite_read_io_spec.rb +80 -0
  59. data/spec/faraday/connection_spec.rb +736 -0
  60. data/spec/faraday/error_spec.rb +60 -0
  61. data/spec/faraday/middleware_spec.rb +52 -0
  62. data/spec/faraday/options/env_spec.rb +70 -0
  63. data/spec/faraday/options/options_spec.rb +297 -0
  64. data/spec/faraday/options/proxy_options_spec.rb +44 -0
  65. data/spec/faraday/options/request_options_spec.rb +19 -0
  66. data/spec/faraday/params_encoders/flat_spec.rb +42 -0
  67. data/spec/faraday/params_encoders/nested_spec.rb +142 -0
  68. data/spec/faraday/rack_builder_spec.rb +345 -0
  69. data/spec/faraday/request/authorization_spec.rb +96 -0
  70. data/spec/faraday/request/instrumentation_spec.rb +76 -0
  71. data/spec/faraday/request/json_spec.rb +111 -0
  72. data/spec/faraday/request/url_encoded_spec.rb +83 -0
  73. data/spec/faraday/request_spec.rb +120 -0
  74. data/spec/faraday/response/json_spec.rb +119 -0
  75. data/spec/faraday/response/logger_spec.rb +220 -0
  76. data/spec/faraday/response/middleware_spec.rb +68 -0
  77. data/spec/faraday/response/raise_error_spec.rb +169 -0
  78. data/spec/faraday/response_spec.rb +75 -0
  79. data/spec/faraday/utils/headers_spec.rb +82 -0
  80. data/spec/faraday/utils_spec.rb +56 -0
  81. data/spec/faraday_spec.rb +37 -0
  82. data/spec/spec_helper.rb +132 -0
  83. data/spec/support/disabling_stub.rb +14 -0
  84. data/spec/support/fake_safe_buffer.rb +15 -0
  85. data/spec/support/helper_methods.rb +133 -0
  86. data/spec/support/shared_examples/adapter.rb +105 -0
  87. data/spec/support/shared_examples/params_encoder.rb +18 -0
  88. data/spec/support/shared_examples/request_method.rb +262 -0
  89. data/spec/support/streaming_response_checker.rb +35 -0
  90. data/spec/support/webmock_rack_app.rb +68 -0
  91. metadata +222 -29
  92. data/lib/faraday/adapter/em_http.rb +0 -243
  93. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
  94. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
  95. data/lib/faraday/adapter/em_synchrony.rb +0 -106
  96. data/lib/faraday/adapter/excon.rb +0 -79
  97. data/lib/faraday/adapter/httpclient.rb +0 -128
  98. data/lib/faraday/adapter/net_http.rb +0 -137
  99. data/lib/faraday/adapter/net_http_persistent.rb +0 -63
  100. data/lib/faraday/adapter/patron.rb +0 -100
  101. data/lib/faraday/adapter/rack.rb +0 -58
  102. data/lib/faraday/request/multipart.rb +0 -68
  103. data/lib/faraday/request/retry.rb +0 -211
  104. data/lib/faraday/upload_io.rb +0 -67
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/utils'
4
+
5
+ RSpec.describe Faraday::NestedParamsEncoder do
6
+ it_behaves_like 'a params encoder'
7
+
8
+ it 'decodes arrays' do
9
+ query = 'a[1]=one&a[2]=two&a[3]=three'
10
+ expected = { 'a' => %w[one two three] }
11
+ expect(subject.decode(query)).to eq(expected)
12
+ end
13
+
14
+ it 'decodes hashes' do
15
+ query = 'a[b1]=one&a[b2]=two&a[b][c]=foo'
16
+ expected = { 'a' => { 'b1' => 'one', 'b2' => 'two', 'b' => { 'c' => 'foo' } } }
17
+ expect(subject.decode(query)).to eq(expected)
18
+ end
19
+
20
+ it 'decodes nested arrays rack compat' do
21
+ query = 'a[][one]=1&a[][two]=2&a[][one]=3&a[][two]=4'
22
+ expected = Rack::Utils.parse_nested_query(query)
23
+ expect(subject.decode(query)).to eq(expected)
24
+ end
25
+
26
+ it 'decodes nested array mixed types' do
27
+ query = 'a[][one]=1&a[]=2&a[]=&a[]'
28
+ expected = Rack::Utils.parse_nested_query(query)
29
+ expect(subject.decode(query)).to eq(expected)
30
+ end
31
+
32
+ it 'decodes nested ignores invalid array' do
33
+ query = '[][a]=1&b=2'
34
+ expected = { 'a' => '1', 'b' => '2' }
35
+ expect(subject.decode(query)).to eq(expected)
36
+ end
37
+
38
+ it 'decodes nested ignores repeated array notation' do
39
+ query = 'a[][][]=1'
40
+ expected = { 'a' => ['1'] }
41
+ expect(subject.decode(query)).to eq(expected)
42
+ end
43
+
44
+ it 'decodes nested ignores malformed keys' do
45
+ query = '=1&[]=2'
46
+ expected = {}
47
+ expect(subject.decode(query)).to eq(expected)
48
+ end
49
+
50
+ it 'decodes nested subkeys dont have to be in brackets' do
51
+ query = 'a[b]c[d]e=1'
52
+ expected = { 'a' => { 'b' => { 'c' => { 'd' => { 'e' => '1' } } } } }
53
+ expect(subject.decode(query)).to eq(expected)
54
+ end
55
+
56
+ it 'decodes nested final value overrides any type' do
57
+ query = 'a[b][c]=1&a[b]=2'
58
+ expected = { 'a' => { 'b' => '2' } }
59
+ expect(subject.decode(query)).to eq(expected)
60
+ end
61
+
62
+ it 'encodes rack compat' do
63
+ params = { a: [{ one: '1', two: '2' }, '3', ''] }
64
+ result = Faraday::Utils.unescape(Faraday::NestedParamsEncoder.encode(params)).split('&')
65
+ expected = Rack::Utils.build_nested_query(params).split('&')
66
+ expect(result).to match_array(expected)
67
+ end
68
+
69
+ it 'encodes empty string array value' do
70
+ expected = 'baz=&foo%5Bbar%5D='
71
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: '' }, baz: '')
72
+ expect(result).to eq(expected)
73
+ end
74
+
75
+ it 'encodes nil array value' do
76
+ expected = 'baz&foo%5Bbar%5D'
77
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: nil }, baz: nil)
78
+ expect(result).to eq(expected)
79
+ end
80
+
81
+ it 'encodes empty array value' do
82
+ expected = 'baz%5B%5D&foo%5Bbar%5D%5B%5D'
83
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: [] }, baz: [])
84
+ expect(result).to eq(expected)
85
+ end
86
+
87
+ it 'encodes boolean values' do
88
+ params = { a: true, b: false }
89
+ expect(subject.encode(params)).to eq('a=true&b=false')
90
+ end
91
+
92
+ it 'encodes boolean values in array' do
93
+ params = { a: [true, false] }
94
+ expect(subject.encode(params)).to eq('a%5B%5D=true&a%5B%5D=false')
95
+ end
96
+
97
+ it 'encodes unsorted when asked' do
98
+ params = { b: false, a: true }
99
+ expect(subject.encode(params)).to eq('a=true&b=false')
100
+ Faraday::NestedParamsEncoder.sort_params = false
101
+ expect(subject.encode(params)).to eq('b=false&a=true')
102
+ Faraday::NestedParamsEncoder.sort_params = true
103
+ end
104
+
105
+ shared_examples 'a wrong decoding' do
106
+ it do
107
+ expect { subject.decode(query) }.to raise_error(TypeError) do |e|
108
+ expect(e.message).to eq(error_message)
109
+ end
110
+ end
111
+ end
112
+
113
+ context 'when expecting hash but getting string' do
114
+ let(:query) { 'a=1&a[b]=2' }
115
+ let(:error_message) { "expected Hash (got String) for param `a'" }
116
+ it_behaves_like 'a wrong decoding'
117
+ end
118
+
119
+ context 'when expecting hash but getting array' do
120
+ let(:query) { 'a[]=1&a[b]=2' }
121
+ let(:error_message) { "expected Hash (got Array) for param `a'" }
122
+ it_behaves_like 'a wrong decoding'
123
+ end
124
+
125
+ context 'when expecting nested hash but getting non nested' do
126
+ let(:query) { 'a[b]=1&a[b][c]=2' }
127
+ let(:error_message) { "expected Hash (got String) for param `b'" }
128
+ it_behaves_like 'a wrong decoding'
129
+ end
130
+
131
+ context 'when expecting array but getting hash' do
132
+ let(:query) { 'a[b]=1&a[]=2' }
133
+ let(:error_message) { "expected Array (got Hash) for param `a'" }
134
+ it_behaves_like 'a wrong decoding'
135
+ end
136
+
137
+ context 'when expecting array but getting string' do
138
+ let(:query) { 'a=1&a[]=2' }
139
+ let(:error_message) { "expected Array (got String) for param `a'" }
140
+ it_behaves_like 'a wrong decoding'
141
+ end
142
+ end
@@ -0,0 +1,345 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::RackBuilder do
4
+ # mock handler classes
5
+ (Handler = Struct.new(:app)).class_eval do
6
+ def call(env)
7
+ env[:request_headers]['X-Middleware'] ||= ''
8
+ env[:request_headers]['X-Middleware'] += ":#{self.class.name.split('::').last}"
9
+ app.call(env)
10
+ end
11
+ end
12
+
13
+ class Apple < Handler
14
+ end
15
+ class Orange < Handler
16
+ end
17
+ class Banana < Handler
18
+ end
19
+
20
+ class Broken < Faraday::Middleware
21
+ dependency 'zomg/i_dont/exist'
22
+ end
23
+
24
+ subject { conn.builder }
25
+
26
+ context 'with default stack' do
27
+ let(:conn) { Faraday::Connection.new }
28
+
29
+ it { expect(subject[0]).to eq(Faraday::Request.lookup_middleware(:url_encoded)) }
30
+ it { expect(subject.adapter).to eq(Faraday::Adapter.lookup_middleware(Faraday.default_adapter)) }
31
+ end
32
+
33
+ context 'with custom empty block' do
34
+ let(:conn) { Faraday::Connection.new {} }
35
+
36
+ it { expect(subject[0]).to be_nil }
37
+ it { expect(subject.adapter).to eq(Faraday::Adapter.lookup_middleware(Faraday.default_adapter)) }
38
+ end
39
+
40
+ context 'with custom adapter only' do
41
+ let(:conn) do
42
+ Faraday::Connection.new do |builder|
43
+ builder.adapter :test do |stub|
44
+ stub.get('/') { |_| [200, {}, ''] }
45
+ end
46
+ end
47
+ end
48
+
49
+ it { expect(subject[0]).to be_nil }
50
+ it { expect(subject.adapter).to eq(Faraday::Adapter.lookup_middleware(:test)) }
51
+ end
52
+
53
+ context 'with custom handler and adapter' do
54
+ let(:conn) do
55
+ Faraday::Connection.new do |builder|
56
+ builder.use Apple
57
+ builder.adapter :test do |stub|
58
+ stub.get('/') { |_| [200, {}, ''] }
59
+ end
60
+ end
61
+ end
62
+
63
+ it 'locks the stack after making a request' do
64
+ expect(subject.locked?).to be_falsey
65
+ conn.get('/')
66
+ expect(subject.locked?).to be_truthy
67
+ expect { subject.use(Orange) }.to raise_error(Faraday::RackBuilder::StackLocked)
68
+ end
69
+
70
+ it 'dup stack is unlocked' do
71
+ expect(subject.locked?).to be_falsey
72
+ subject.lock!
73
+ expect(subject.locked?).to be_truthy
74
+ dup = subject.dup
75
+ expect(dup).to eq(subject)
76
+ expect(dup.locked?).to be_falsey
77
+ end
78
+
79
+ it 'allows to compare handlers' do
80
+ expect(subject.handlers.first).to eq(Faraday::RackBuilder::Handler.new(Apple))
81
+ end
82
+ end
83
+
84
+ context 'when having a single handler' do
85
+ let(:conn) { Faraday::Connection.new {} }
86
+
87
+ before { subject.use(Apple) }
88
+
89
+ it { expect(subject.handlers).to eq([Apple]) }
90
+
91
+ it 'allows rebuilding' do
92
+ subject.build do |builder|
93
+ builder.use(Orange)
94
+ end
95
+ expect(subject.handlers).to eq([Orange])
96
+ end
97
+
98
+ it 'allows use' do
99
+ subject.use(Orange)
100
+ expect(subject.handlers).to eq([Apple, Orange])
101
+ end
102
+
103
+ it 'allows insert_before' do
104
+ subject.insert_before(Apple, Orange)
105
+ expect(subject.handlers).to eq([Orange, Apple])
106
+ end
107
+
108
+ it 'allows insert_after' do
109
+ subject.insert_after(Apple, Orange)
110
+ expect(subject.handlers).to eq([Apple, Orange])
111
+ end
112
+
113
+ it 'raises an error trying to use an unregistered symbol' do
114
+ expect { subject.use(:apple) }.to raise_error(Faraday::Error) do |err|
115
+ expect(err.message).to eq(':apple is not registered on Faraday::Middleware')
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'with custom registered middleware' do
121
+ let(:conn) { Faraday::Connection.new {} }
122
+
123
+ after { Faraday::Middleware.unregister_middleware(:apple) }
124
+
125
+ it 'allows to register with constant' do
126
+ Faraday::Middleware.register_middleware(apple: Apple)
127
+ subject.use(:apple)
128
+ expect(subject.handlers).to eq([Apple])
129
+ end
130
+
131
+ it 'allows to register with symbol' do
132
+ Faraday::Middleware.register_middleware(apple: :Apple)
133
+ subject.use(:apple)
134
+ expect(subject.handlers).to eq([Apple])
135
+ end
136
+
137
+ it 'allows to register with string' do
138
+ Faraday::Middleware.register_middleware(apple: 'Apple')
139
+ subject.use(:apple)
140
+ expect(subject.handlers).to eq([Apple])
141
+ end
142
+
143
+ it 'allows to register with Proc' do
144
+ Faraday::Middleware.register_middleware(apple: -> { Apple })
145
+ subject.use(:apple)
146
+ expect(subject.handlers).to eq([Apple])
147
+ end
148
+ end
149
+
150
+ context 'when having two handlers' do
151
+ let(:conn) { Faraday::Connection.new {} }
152
+
153
+ before do
154
+ subject.use(Apple)
155
+ subject.use(Orange)
156
+ end
157
+
158
+ it 'allows insert_before' do
159
+ subject.insert_before(Orange, Banana)
160
+ expect(subject.handlers).to eq([Apple, Banana, Orange])
161
+ end
162
+
163
+ it 'allows insert_after' do
164
+ subject.insert_after(Apple, Banana)
165
+ expect(subject.handlers).to eq([Apple, Banana, Orange])
166
+ end
167
+
168
+ it 'allows to swap handlers' do
169
+ subject.swap(Apple, Banana)
170
+ expect(subject.handlers).to eq([Banana, Orange])
171
+ end
172
+
173
+ it 'allows to delete a handler' do
174
+ subject.delete(Apple)
175
+ expect(subject.handlers).to eq([Orange])
176
+ end
177
+ end
178
+
179
+ context 'when having a handler with broken dependency' do
180
+ let(:conn) do
181
+ Faraday::Connection.new do |builder|
182
+ builder.adapter :test do |stub|
183
+ stub.get('/') { |_| [200, {}, ''] }
184
+ end
185
+ end
186
+ end
187
+
188
+ before { subject.use(Broken) }
189
+
190
+ it 'raises an error while making a request' do
191
+ expect { conn.get('/') }.to raise_error(RuntimeError) do |err|
192
+ expect(err.message).to match(%r{missing dependency for Broken: .+ -- zomg/i_dont/exist})
193
+ end
194
+ end
195
+ end
196
+
197
+ context 'when middleware is added with named arguments' do
198
+ let(:conn) { Faraday::Connection.new {} }
199
+
200
+ let(:dog_middleware) do
201
+ Class.new(Faraday::Middleware) do
202
+ attr_accessor :name
203
+
204
+ def initialize(app, name:)
205
+ super(app)
206
+ @name = name
207
+ end
208
+ end
209
+ end
210
+ let(:dog) do
211
+ subject.handlers.find { |handler| handler == dog_middleware }.build
212
+ end
213
+
214
+ it 'adds a handler to construct middleware with options passed to use' do
215
+ subject.use dog_middleware, name: 'Rex'
216
+ expect { dog }.to_not output(
217
+ /warning: Using the last argument as keyword parameters is deprecated/
218
+ ).to_stderr
219
+ expect(dog.name).to eq('Rex')
220
+ end
221
+ end
222
+
223
+ context 'when a request adapter is added with named arguments' do
224
+ let(:conn) { Faraday::Connection.new {} }
225
+
226
+ let(:cat_request) do
227
+ Class.new(Faraday::Middleware) do
228
+ attr_accessor :name
229
+
230
+ def initialize(app, name:)
231
+ super(app)
232
+ @name = name
233
+ end
234
+ end
235
+ end
236
+ let(:cat) do
237
+ subject.handlers.find { |handler| handler == cat_request }.build
238
+ end
239
+
240
+ it 'adds a handler to construct request adapter with options passed to request' do
241
+ Faraday::Request.register_middleware cat_request: cat_request
242
+ subject.request :cat_request, name: 'Felix'
243
+ expect { cat }.to_not output(
244
+ /warning: Using the last argument as keyword parameters is deprecated/
245
+ ).to_stderr
246
+ expect(cat.name).to eq('Felix')
247
+ end
248
+ end
249
+
250
+ context 'when a response adapter is added with named arguments' do
251
+ let(:conn) { Faraday::Connection.new {} }
252
+
253
+ let(:fish_response) do
254
+ Class.new(Faraday::Response::Middleware) do
255
+ attr_accessor :name
256
+
257
+ def initialize(app, name:)
258
+ super(app)
259
+ @name = name
260
+ end
261
+ end
262
+ end
263
+ let(:fish) do
264
+ subject.handlers.find { |handler| handler == fish_response }.build
265
+ end
266
+
267
+ it 'adds a handler to construct response adapter with options passed to response' do
268
+ Faraday::Response.register_middleware fish_response: fish_response
269
+ subject.response :fish_response, name: 'Bubbles'
270
+ expect { fish }.to_not output(
271
+ /warning: Using the last argument as keyword parameters is deprecated/
272
+ ).to_stderr
273
+ expect(fish.name).to eq('Bubbles')
274
+ end
275
+ end
276
+
277
+ context 'when a plain adapter is added with named arguments' do
278
+ let(:conn) { Faraday::Connection.new {} }
279
+
280
+ let(:rabbit_adapter) do
281
+ Class.new(Faraday::Adapter) do
282
+ attr_accessor :name
283
+
284
+ def initialize(app, name:)
285
+ super(app)
286
+ @name = name
287
+ end
288
+ end
289
+ end
290
+ let(:rabbit) do
291
+ subject.adapter.build
292
+ end
293
+
294
+ it 'adds a handler to construct adapter with options passed to adapter' do
295
+ Faraday::Adapter.register_middleware rabbit_adapter: rabbit_adapter
296
+ subject.adapter :rabbit_adapter, name: 'Thumper'
297
+ expect { rabbit }.to_not output(
298
+ /warning: Using the last argument as keyword parameters is deprecated/
299
+ ).to_stderr
300
+ expect(rabbit.name).to eq('Thumper')
301
+ end
302
+ end
303
+
304
+ context 'when handlers are directly added or updated' do
305
+ let(:conn) { Faraday::Connection.new {} }
306
+
307
+ let(:rock_handler) do
308
+ Class.new do
309
+ attr_accessor :name
310
+
311
+ def initialize(_app, name:)
312
+ @name = name
313
+ end
314
+ end
315
+ end
316
+ let(:rock) do
317
+ subject.handlers.find { |handler| handler == rock_handler }.build
318
+ end
319
+
320
+ it 'adds a handler to construct adapter with options passed to insert' do
321
+ subject.insert 0, rock_handler, name: 'Stony'
322
+ expect { rock }.to_not output(
323
+ /warning: Using the last argument as keyword parameters is deprecated/
324
+ ).to_stderr
325
+ expect(rock.name).to eq('Stony')
326
+ end
327
+
328
+ it 'adds a handler with options passed to insert_after' do
329
+ subject.insert_after 0, rock_handler, name: 'Rocky'
330
+ expect { rock }.to_not output(
331
+ /warning: Using the last argument as keyword parameters is deprecated/
332
+ ).to_stderr
333
+ expect(rock.name).to eq('Rocky')
334
+ end
335
+
336
+ it 'adds a handler with options passed to swap' do
337
+ subject.insert 0, rock_handler, name: 'Flint'
338
+ subject.swap 0, rock_handler, name: 'Chert'
339
+ expect { rock }.to_not output(
340
+ /warning: Using the last argument as keyword parameters is deprecated/
341
+ ).to_stderr
342
+ expect(rock.name).to eq('Chert')
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Request::Authorization do
4
+ let(:conn) do
5
+ Faraday.new do |b|
6
+ b.request auth_type, *auth_config
7
+ b.adapter :test do |stub|
8
+ stub.get('/auth-echo') do |env|
9
+ [200, {}, env[:request_headers]['Authorization']]
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ shared_examples 'does not interfere with existing authentication' do
16
+ context 'and request already has an authentication header' do
17
+ let(:response) { conn.get('/auth-echo', nil, authorization: 'Token token="bar"') }
18
+
19
+ it 'does not interfere with existing authorization' do
20
+ expect(response.body).to eq('Token token="bar"')
21
+ end
22
+ end
23
+ end
24
+
25
+ let(:response) { conn.get('/auth-echo') }
26
+
27
+ describe 'basic_auth' do
28
+ let(:auth_type) { :basic_auth }
29
+
30
+ context 'when passed correct params' do
31
+ let(:auth_config) { %w[aladdin opensesame] }
32
+
33
+ it { expect(response.body).to eq('Basic YWxhZGRpbjpvcGVuc2VzYW1l') }
34
+
35
+ include_examples 'does not interfere with existing authentication'
36
+ end
37
+
38
+ context 'when passed very long values' do
39
+ let(:auth_config) { ['A' * 255, ''] }
40
+
41
+ it { expect(response.body).to eq("Basic #{'QUFB' * 85}Og==") }
42
+
43
+ include_examples 'does not interfere with existing authentication'
44
+ end
45
+ end
46
+
47
+ describe 'token_auth' do
48
+ let(:auth_type) { :token_auth }
49
+
50
+ context 'when passed correct params' do
51
+ let(:auth_config) { 'quux' }
52
+
53
+ it { expect(response.body).to eq('Token token="quux"') }
54
+
55
+ include_examples 'does not interfere with existing authentication'
56
+ end
57
+
58
+ context 'when other values are provided' do
59
+ let(:auth_config) { ['baz', { foo: 42 }] }
60
+
61
+ it { expect(response.body).to match(/^Token /) }
62
+ it { expect(response.body).to match(/token="baz"/) }
63
+ it { expect(response.body).to match(/foo="42"/) }
64
+
65
+ include_examples 'does not interfere with existing authentication'
66
+ end
67
+ end
68
+
69
+ describe 'authorization' do
70
+ let(:auth_type) { :authorization }
71
+
72
+ context 'when passed two strings' do
73
+ let(:auth_config) { ['custom', 'abc def'] }
74
+
75
+ it { expect(response.body).to eq('custom abc def') }
76
+
77
+ include_examples 'does not interfere with existing authentication'
78
+ end
79
+
80
+ context 'when passed a string and a hash' do
81
+ let(:auth_config) { ['baz', { foo: 42 }] }
82
+
83
+ it { expect(response.body).to eq('baz foo="42"') }
84
+
85
+ include_examples 'does not interfere with existing authentication'
86
+ end
87
+
88
+ context 'when passed a string and a proc' do
89
+ let(:auth_config) { ['Bearer', -> { 'custom_from_proc' }] }
90
+
91
+ it { expect(response.body).to eq('Bearer custom_from_proc') }
92
+
93
+ include_examples 'does not interfere with existing authentication'
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::Request::Instrumentation do
4
+ class FakeInstrumenter
5
+ attr_reader :instrumentations
6
+
7
+ def initialize
8
+ @instrumentations = []
9
+ end
10
+
11
+ def instrument(name, env)
12
+ @instrumentations << [name, env]
13
+ yield
14
+ end
15
+ end
16
+
17
+ let(:config) { {} }
18
+ let(:options) { Faraday::Request::Instrumentation::Options.from config }
19
+ let(:instrumenter) { FakeInstrumenter.new }
20
+ let(:conn) do
21
+ Faraday.new do |f|
22
+ f.request :instrumentation, config.merge(instrumenter: instrumenter)
23
+ f.adapter :test do |stub|
24
+ stub.get '/' do
25
+ [200, {}, 'ok']
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ it { expect(options.name).to eq('request.faraday') }
32
+ it 'defaults to ActiveSupport::Notifications' do
33
+ begin
34
+ res = options.instrumenter
35
+ rescue NameError => e
36
+ expect(e.to_s).to match('ActiveSupport')
37
+ else
38
+ expect(res).to eq(ActiveSupport::Notifications)
39
+ end
40
+ end
41
+
42
+ it 'instruments with default name' do
43
+ expect(instrumenter.instrumentations.size).to eq(0)
44
+
45
+ res = conn.get '/'
46
+ expect(res.body).to eq('ok')
47
+ expect(instrumenter.instrumentations.size).to eq(1)
48
+
49
+ name, env = instrumenter.instrumentations.first
50
+ expect(name).to eq('request.faraday')
51
+ expect(env[:url].path).to eq('/')
52
+ end
53
+
54
+ context 'with custom name' do
55
+ let(:config) { { name: 'custom' } }
56
+
57
+ it { expect(options.name).to eq('custom') }
58
+ it 'instruments with custom name' do
59
+ expect(instrumenter.instrumentations.size).to eq(0)
60
+
61
+ res = conn.get '/'
62
+ expect(res.body).to eq('ok')
63
+ expect(instrumenter.instrumentations.size).to eq(1)
64
+
65
+ name, env = instrumenter.instrumentations.first
66
+ expect(name).to eq('custom')
67
+ expect(env[:url].path).to eq('/')
68
+ end
69
+ end
70
+
71
+ context 'with custom instrumenter' do
72
+ let(:config) { { instrumenter: :custom } }
73
+
74
+ it { expect(options.instrumenter).to eq(:custom) }
75
+ end
76
+ end