faraday 1.6.0 → 1.7.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.
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: