faraday 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c84d273b85bc4643cccee381fc7a1190305143d5dc89447fe5ac41e1db7a89e
4
- data.tar.gz: 6d9409101febc5167e3c98f33c4b5b15f0dcc68c4e3fc13198930b76dd83a39e
3
+ metadata.gz: e0b66c2e6b13140f2093c73a7b8dab39dd25690b15b1e5eadaba90a787d2fdf5
4
+ data.tar.gz: af34783d38f124632f2e4edcfd7f6bf2d763bd5d6f36ad8b6de6cac675c9858d
5
5
  SHA512:
6
- metadata.gz: a8e6280590ce1eb1b41311351e8e13b4de8f6571523f383d1651d63589db040a07eb0d0110a2d441f3fa275468b6eca6767924b8948c2e0f6cbfb2e1ef20b39a
7
- data.tar.gz: b9df5e99b07e33d19b8d2fca7ba5357e38a95fa662c960c34876f3fe43348ffe15b5fd95abc90ee0f811885dcddaac3d7f28a4f09046f6450c5202153af4f8c0
6
+ metadata.gz: dd547129c965998e13208a5a0accab40ddee955f7a001365f2a951c6a0e7d7fefc9e61c5d708188deff9e8e239c991627485e3f07e9686a87a3cd30938a8f05b
7
+ data.tar.gz: 81fdc31d08d17db983ea4a4c68951942c3673d5447096e1f51cd0f4eebac1289348b860a56e064131b65ef59e3ed6f63ce1fc004db435f7fb051460b98190b31
@@ -12,8 +12,8 @@ class Client
12
12
  @conn = conn
13
13
  end
14
14
 
15
- def sushi(jname)
16
- res = @conn.get("/#{jname}")
15
+ def sushi(jname, params: {})
16
+ res = @conn.get("/#{jname}", params)
17
17
  data = JSON.parse(res.body)
18
18
  data['name']
19
19
  end
@@ -62,4 +62,23 @@ RSpec.describe Client do
62
62
  expect { client.sushi('ebi') }.to raise_error(Faraday::ConnectionFailed)
63
63
  stubs.verify_stubbed_calls
64
64
  end
65
+
66
+ context 'When the test stub is run in strict_mode' do
67
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new(strict_mode: true) }
68
+
69
+ it 'verifies the all parameter values are identical' do
70
+ stubs.get('/ebi?abc=123') do
71
+ [
72
+ 200,
73
+ { 'Content-Type': 'application/javascript' },
74
+ '{"name": "shrimp"}'
75
+ ]
76
+ end
77
+
78
+ # uncomment to raise Stubs::NotFound
79
+ # expect(client.sushi('ebi', params: { abc: 123, foo: 'Kappa' })).to eq('shrimp')
80
+ expect(client.sushi('ebi', params: { abc: 123 })).to eq('shrimp')
81
+ stubs.verify_stubbed_calls
82
+ end
83
+ end
65
84
  end
@@ -25,6 +25,9 @@ module Faraday
25
25
  # "showing item: #{meta[:match_data][1]}"
26
26
  # ]
27
27
  # end
28
+ #
29
+ # # You can set strict_mode to exactly match the stubbed requests.
30
+ # stub.strict_mode = true
28
31
  # end
29
32
  # end
30
33
  #
@@ -47,10 +50,11 @@ module Faraday
47
50
  class NotFound < StandardError
48
51
  end
49
52
 
50
- def initialize
53
+ def initialize(strict_mode: false)
51
54
  # { get: [Stub, Stub] }
52
55
  @stack = {}
53
56
  @consumed = {}
57
+ @strict_mode = strict_mode
54
58
  yield(self) if block_given?
55
59
  end
56
60
 
@@ -115,6 +119,17 @@ module Faraday
115
119
  raise failed_stubs.join(' ') unless failed_stubs.empty?
116
120
  end
117
121
 
122
+ # Set strict_mode. If the value is true, this adapter tries to find matched requests strictly,
123
+ # which means that all of a path, parameters, and headers must be the same as an actual request.
124
+ def strict_mode=(value)
125
+ @strict_mode = value
126
+ @stack.each do |_method, stubs|
127
+ stubs.each do |stub|
128
+ stub.strict_mode = value
129
+ end
130
+ end
131
+ end
132
+
118
133
  protected
119
134
 
120
135
  def new_stub(request_method, path, headers = {}, body = nil, &block)
@@ -128,7 +143,8 @@ module Faraday
128
143
  ]
129
144
  end
130
145
 
131
- stub = Stub.new(host, normalized_path, headers, body, block)
146
+ headers = Utils::Headers.new(headers)
147
+ stub = Stub.new(host, normalized_path, headers, body, @strict_mode, block)
132
148
  (@stack[request_method] ||= []) << stub
133
149
  end
134
150
 
@@ -143,9 +159,9 @@ module Faraday
143
159
 
144
160
  # Stub request
145
161
  # rubocop:disable Style/StructInheritance
146
- class Stub < Struct.new(:host, :path, :params, :headers, :body, :block)
162
+ class Stub < Struct.new(:host, :path, :params, :headers, :body, :strict_mode, :block)
147
163
  # rubocop:enable Style/StructInheritance
148
- def initialize(host, full, headers, body, block)
164
+ def initialize(host, full, headers, body, strict_mode, block) # rubocop:disable Metrics/ParameterLists
149
165
  path, query = full.respond_to?(:split) ? full.split('?') : full
150
166
  params =
151
167
  if query
@@ -154,7 +170,7 @@ module Faraday
154
170
  {}
155
171
  end
156
172
 
157
- super(host, path, params, headers, body, block)
173
+ super(host, path, params, headers, body, strict_mode, block)
158
174
  end
159
175
 
160
176
  def matches?(request_host, request_uri, request_headers, request_body)
@@ -184,12 +200,25 @@ module Faraday
184
200
  end
185
201
 
186
202
  def params_match?(request_params)
203
+ if strict_mode
204
+ return Set.new(params) == Set.new(request_params)
205
+ end
206
+
187
207
  params.keys.all? do |key|
188
208
  request_params[key] == params[key]
189
209
  end
190
210
  end
191
211
 
192
212
  def headers_match?(request_headers)
213
+ if strict_mode
214
+ headers_with_user_agent = headers.dup.tap do |hs|
215
+ # NOTE: Set User-Agent in case it's not set when creating Stubs.
216
+ # Users would not want to set Faraday's User-Agent explicitly.
217
+ hs[:user_agent] ||= Connection::USER_AGENT
218
+ end
219
+ return Set.new(headers_with_user_agent) == Set.new(request_headers)
220
+ end
221
+
193
222
  headers.keys.all? do |key|
194
223
  request_headers[key] == headers[key]
195
224
  end
@@ -15,6 +15,7 @@ module Faraday
15
15
  class Connection
16
16
  # A Set of allowed HTTP verbs.
17
17
  METHODS = Set.new %i[get post put delete head patch options trace]
18
+ USER_AGENT = "Faraday v#{VERSION}"
18
19
 
19
20
  # @return [Hash] URI query unencoded key/value pairs.
20
21
  attr_reader :params
@@ -89,7 +90,7 @@ module Faraday
89
90
 
90
91
  yield(self) if block_given?
91
92
 
92
- @headers[:user_agent] ||= "Faraday v#{VERSION}"
93
+ @headers[:user_agent] ||= USER_AGENT
93
94
  end
94
95
 
95
96
  def initialize_proxy(url, options)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Faraday
4
- VERSION = '1.6.0'
4
+ VERSION = '1.7.0'
5
5
  end
@@ -257,4 +257,89 @@ RSpec.describe Faraday::Adapter::Test do
257
257
  it { expect { request }.to raise_error described_class::Stubs::NotFound }
258
258
  end
259
259
  end
260
+
261
+ describe 'strict_mode' do
262
+ let(:stubs) do
263
+ described_class::Stubs.new(strict_mode: true) do |stubs|
264
+ stubs.get('/strict?a=12&b=xy', 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello') { [200, {}, 'a'] }
265
+ stubs.get('/with_user_agent?a=12&b=xy', authorization: 'Bearer m_ck', 'User-Agent' => 'My Agent') { [200, {}, 'a'] }
266
+ end
267
+ end
268
+
269
+ context 'when params and headers are exactly set' do
270
+ subject(:request) { connection.get('/strict', { a: '12', b: 'xy' }, { authorization: 'Bearer m_ck', x_c: 'hello' }) }
271
+
272
+ it { expect(request.status).to eq 200 }
273
+ end
274
+
275
+ context 'when params and headers are exactly set with a custom user agent' do
276
+ subject(:request) { connection.get('/with_user_agent', { a: '12', b: 'xy' }, { authorization: 'Bearer m_ck', 'User-Agent' => 'My Agent' }) }
277
+
278
+ it { expect(request.status).to eq 200 }
279
+ end
280
+
281
+ shared_examples 'raise NotFound when params do not satisfy the strict check' do |params|
282
+ subject(:request) { connection.get('/strict', params, { 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello' }) }
283
+
284
+ context "with #{params.inspect}" do
285
+ it { expect { request }.to raise_error described_class::Stubs::NotFound }
286
+ end
287
+ end
288
+
289
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12' }
290
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { b: 'xy' }
291
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '123', b: 'xy' }
292
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12', b: 'xyz' }
293
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { a: '12', b: 'xy', c: 'hello' }
294
+ it_behaves_like 'raise NotFound when params do not satisfy the strict check', { additional: 'special', a: '12', b: 'xy', c: 'hello' }
295
+
296
+ shared_examples 'raise NotFound when headers do not satisfy the strict check' do |path, headers|
297
+ subject(:request) { connection.get(path, { a: 12, b: 'xy' }, headers) }
298
+
299
+ context "with #{headers.inspect}" do
300
+ it { expect { request }.to raise_error described_class::Stubs::NotFound }
301
+ end
302
+ end
303
+
304
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck' }
305
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { 'X-C' => 'hello' }
306
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'Hi' }
307
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Basic m_ck', 'x-c': 'hello' }
308
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', x_special: 'special' }
309
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck' }
310
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'Unknown' }
311
+ it_behaves_like 'raise NotFound when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent', x_special: 'special' }
312
+
313
+ context 'when strict_mode is disabled' do
314
+ before do
315
+ stubs.strict_mode = false
316
+ end
317
+
318
+ shared_examples 'does not raise NotFound even when params do not satisfy the strict check' do |params|
319
+ subject(:request) { connection.get('/strict', params, { 'Authorization' => 'Bearer m_ck', 'X-C' => 'hello' }) }
320
+
321
+ context "with #{params.inspect}" do
322
+ it { expect(request.status).to eq 200 }
323
+ end
324
+ end
325
+
326
+ it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { a: '12', b: 'xy' }
327
+ it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { a: '12', b: 'xy', c: 'hello' }
328
+ it_behaves_like 'does not raise NotFound even when params do not satisfy the strict check', { additional: 'special', a: '12', b: 'xy', c: 'hello' }
329
+
330
+ shared_examples 'does not raise NotFound even when headers do not satisfy the strict check' do |path, headers|
331
+ subject(:request) { connection.get(path, { a: 12, b: 'xy' }, headers) }
332
+
333
+ context "with #{headers.inspect}" do
334
+ it { expect(request.status).to eq 200 }
335
+ end
336
+ end
337
+
338
+ it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello' }
339
+ it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', x_special: 'special' }
340
+ it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/strict', { authorization: 'Bearer m_ck', 'x-c': 'hello', user_agent: 'Special Agent' }
341
+ it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent' }
342
+ it_behaves_like 'does not raise NotFound even when headers do not satisfy the strict check', '/with_user_agent', { authorization: 'Bearer m_ck', user_agent: 'My Agent', x_special: 'special' }
343
+ end
344
+ end
260
345
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "@technoweenie"
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-01 00:00:00.000000000 Z
13
+ date: 2021-08-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: faraday-em_http
@@ -260,7 +260,7 @@ licenses:
260
260
  - MIT
261
261
  metadata:
262
262
  homepage_uri: https://lostisland.github.io/faraday
263
- changelog_uri: https://github.com/lostisland/faraday/releases/tag/v1.6.0
263
+ changelog_uri: https://github.com/lostisland/faraday/releases/tag/v1.7.0
264
264
  source_code_uri: https://github.com/lostisland/faraday
265
265
  bug_tracker_uri: https://github.com/lostisland/faraday/issues
266
266
  post_install_message: