faraday 0.9.1 → 0.17.3

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 (74) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +212 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +203 -28
  5. data/Rakefile +6 -64
  6. data/lib/faraday/adapter/em_http.rb +17 -11
  7. data/lib/faraday/adapter/em_http_ssl_patch.rb +1 -1
  8. data/lib/faraday/adapter/em_synchrony.rb +19 -5
  9. data/lib/faraday/adapter/excon.rb +13 -11
  10. data/lib/faraday/adapter/httpclient.rb +31 -9
  11. data/lib/faraday/adapter/net_http.rb +36 -14
  12. data/lib/faraday/adapter/net_http_persistent.rb +37 -17
  13. data/lib/faraday/adapter/patron.rb +44 -21
  14. data/lib/faraday/adapter/rack.rb +1 -1
  15. data/lib/faraday/adapter/test.rb +79 -28
  16. data/lib/faraday/adapter/typhoeus.rb +4 -115
  17. data/lib/faraday/adapter.rb +10 -1
  18. data/lib/faraday/autoload.rb +1 -1
  19. data/lib/faraday/connection.rb +72 -20
  20. data/lib/faraday/deprecate.rb +107 -0
  21. data/lib/faraday/error.rb +132 -27
  22. data/lib/faraday/options.rb +45 -22
  23. data/lib/faraday/parameters.rb +56 -39
  24. data/lib/faraday/rack_builder.rb +29 -4
  25. data/lib/faraday/request/authorization.rb +1 -2
  26. data/lib/faraday/request/multipart.rb +7 -2
  27. data/lib/faraday/request/retry.rb +84 -19
  28. data/lib/faraday/request.rb +22 -0
  29. data/lib/faraday/response/logger.rb +29 -8
  30. data/lib/faraday/response/raise_error.rb +7 -3
  31. data/lib/faraday/response.rb +9 -5
  32. data/lib/faraday/utils.rb +32 -3
  33. data/lib/faraday.rb +15 -36
  34. data/spec/faraday/deprecate_spec.rb +69 -0
  35. data/spec/faraday/error_spec.rb +102 -0
  36. data/spec/faraday/response/raise_error_spec.rb +106 -0
  37. data/spec/spec_helper.rb +105 -0
  38. data/test/adapters/em_http_test.rb +10 -0
  39. data/test/adapters/em_synchrony_test.rb +22 -10
  40. data/test/adapters/excon_test.rb +10 -0
  41. data/test/adapters/httpclient_test.rb +14 -1
  42. data/test/adapters/integration.rb +17 -8
  43. data/test/adapters/logger_test.rb +65 -11
  44. data/test/adapters/net_http_persistent_test.rb +96 -2
  45. data/test/adapters/net_http_test.rb +67 -2
  46. data/test/adapters/patron_test.rb +28 -8
  47. data/test/adapters/rack_test.rb +8 -1
  48. data/test/adapters/test_middleware_test.rb +46 -3
  49. data/test/adapters/typhoeus_test.rb +19 -9
  50. data/test/composite_read_io_test.rb +16 -18
  51. data/test/connection_test.rb +294 -78
  52. data/test/env_test.rb +55 -5
  53. data/test/helper.rb +11 -17
  54. data/test/middleware/retry_test.rb +115 -10
  55. data/test/middleware_stack_test.rb +97 -10
  56. data/test/options_test.rb +97 -16
  57. data/test/parameters_test.rb +94 -1
  58. data/test/request_middleware_test.rb +24 -40
  59. data/test/response_middleware_test.rb +4 -4
  60. data/test/utils_test.rb +40 -0
  61. metadata +21 -66
  62. data/.document +0 -6
  63. data/CONTRIBUTING.md +0 -36
  64. data/Gemfile +0 -25
  65. data/faraday.gemspec +0 -34
  66. data/script/cached-bundle +0 -46
  67. data/script/console +0 -7
  68. data/script/generate_certs +0 -42
  69. data/script/package +0 -7
  70. data/script/proxy-server +0 -42
  71. data/script/release +0 -17
  72. data/script/s3-put +0 -71
  73. data/script/server +0 -36
  74. data/script/test +0 -172
@@ -1,3 +1,5 @@
1
+ require 'date'
2
+
1
3
  module Faraday
2
4
  # Catches exceptions and retries each request a limited number of times.
3
5
  #
@@ -10,7 +12,7 @@ module Faraday
10
12
  #
11
13
  # Faraday.new do |conn|
12
14
  # conn.request :retry, max: 2, interval: 0.05,
13
- # interval_randomness: 0.5, backoff_factor: 2
15
+ # interval_randomness: 0.5, backoff_factor: 2,
14
16
  # exceptions: [CustomException, 'Timeout::Error']
15
17
  # conn.adapter ...
16
18
  # end
@@ -19,15 +21,19 @@ module Faraday
19
21
  # interval that is random between 0.1 and 0.15
20
22
  #
21
23
  class Request::Retry < Faraday::Middleware
22
-
24
+ DEFAULT_EXCEPTIONS = [Errno::ETIMEDOUT, 'Timeout::Error',
25
+ Faraday::TimeoutError, Faraday::RetriableResponse
26
+ ].freeze
23
27
  IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
24
28
 
25
- class Options < Faraday::Options.new(:max, :interval, :interval_randomness, :backoff_factor,
26
- :exceptions, :methods, :retry_if)
29
+ class Options < Faraday::Options.new(:max, :interval, :max_interval, :interval_randomness,
30
+ :backoff_factor, :exceptions, :methods, :retry_if, :retry_block,
31
+ :retry_statuses)
32
+
27
33
  DEFAULT_CHECK = lambda { |env,exception| false }
28
34
 
29
35
  def self.from(value)
30
- if Fixnum === value
36
+ if Integer === value
31
37
  new(value)
32
38
  else
33
39
  super(value)
@@ -42,8 +48,12 @@ module Faraday
42
48
  (self[:interval] ||= 0).to_f
43
49
  end
44
50
 
51
+ def max_interval
52
+ (self[:max_interval] ||= Float::MAX).to_f
53
+ end
54
+
45
55
  def interval_randomness
46
- (self[:interval_randomness] ||= 0).to_i
56
+ (self[:interval_randomness] ||= 0).to_f
47
57
  end
48
58
 
49
59
  def backoff_factor
@@ -51,8 +61,7 @@ module Faraday
51
61
  end
52
62
 
53
63
  def exceptions
54
- Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error',
55
- Error::TimeoutError])
64
+ Array(self[:exceptions] ||= DEFAULT_EXCEPTIONS)
56
65
  end
57
66
 
58
67
  def methods
@@ -63,6 +72,13 @@ module Faraday
63
72
  self[:retry_if] ||= DEFAULT_CHECK
64
73
  end
65
74
 
75
+ def retry_block
76
+ self[:retry_block] ||= Proc.new {}
77
+ end
78
+
79
+ def retry_statuses
80
+ Array(self[:retry_statuses] ||= [])
81
+ end
66
82
  end
67
83
 
68
84
  # Public: Initialize middleware
@@ -73,13 +89,14 @@ module Faraday
73
89
  # interval_randomness - The maximum random interval amount expressed
74
90
  # as a float between 0 and 1 to use in addition to the
75
91
  # interval. (default: 0)
92
+ # max_interval - An upper limit for the interval (default: Float::MAX)
76
93
  # backoff_factor - The amount to multiple each successive retry's
77
94
  # interval amount by in order to provide backoff
78
95
  # (default: 1)
79
96
  # exceptions - The list of exceptions to handle. Exceptions can be
80
97
  # given as Class, Module, or String. (default:
81
- # [Errno::ETIMEDOUT, Timeout::Error,
82
- # Error::TimeoutError])
98
+ # [Errno::ETIMEDOUT, 'Timeout::Error',
99
+ # Faraday::TimeoutError, Faraday::RetriableResponse])
83
100
  # methods - A list of HTTP methods to retry without calling retry_if. Pass
84
101
  # an empty Array to call retry_if for all exceptions.
85
102
  # (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
@@ -89,17 +106,21 @@ module Faraday
89
106
  # if the exception produced is non-recoverable or if the
90
107
  # the HTTP method called is not idempotent.
91
108
  # (defaults to return false)
109
+ # retry_block - block that is executed after every retry. Request environment, middleware options,
110
+ # current number of retries and the exception is passed to the block as parameters.
92
111
  def initialize(app, options = nil)
93
112
  super(app)
94
113
  @options = Options.from(options)
95
114
  @errmatch = build_exception_matcher(@options.exceptions)
96
115
  end
97
116
 
98
- def sleep_amount(retries)
99
- retry_index = @options.max - retries
100
- current_interval = @options.interval * (@options.backoff_factor ** retry_index)
101
- random_interval = rand * @options.interval_randomness.to_f * @options.interval
102
- current_interval + random_interval
117
+ def calculate_sleep_amount(retries, env)
118
+ retry_after = calculate_retry_after(env)
119
+ retry_interval = calculate_retry_interval(retries)
120
+
121
+ return if retry_after && retry_after > @options.max_interval
122
+
123
+ retry_after && retry_after >= retry_interval ? retry_after : retry_interval
103
124
  end
104
125
 
105
126
  def call(env)
@@ -107,14 +128,25 @@ module Faraday
107
128
  request_body = env[:body]
108
129
  begin
109
130
  env[:body] = request_body # after failure env[:body] is set to the response body
110
- @app.call(env)
131
+ @app.call(env).tap do |resp|
132
+ raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
133
+ end
111
134
  rescue @errmatch => exception
112
135
  if retries > 0 && retry_request?(env, exception)
113
136
  retries -= 1
114
- sleep sleep_amount(retries + 1)
115
- retry
137
+ rewind_files(request_body)
138
+ @options.retry_block.call(env, @options, retries, exception)
139
+ if (sleep_amount = calculate_sleep_amount(retries + 1, env))
140
+ sleep sleep_amount
141
+ retry
142
+ end
143
+ end
144
+
145
+ if exception.is_a?(Faraday::RetriableResponse)
146
+ exception.response
147
+ else
148
+ raise
116
149
  end
117
- raise
118
150
  end
119
151
  end
120
152
 
@@ -144,5 +176,38 @@ module Faraday
144
176
  @options.methods.include?(env[:method]) || @options.retry_if.call(env, exception)
145
177
  end
146
178
 
179
+ def rewind_files(body)
180
+ return unless body.is_a?(Hash)
181
+ body.each do |_, value|
182
+ if value.is_a? UploadIO
183
+ value.rewind
184
+ end
185
+ end
186
+ end
187
+
188
+ # MDN spec for Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
189
+ def calculate_retry_after(env)
190
+ response_headers = env[:response_headers]
191
+ return unless response_headers
192
+
193
+ retry_after_value = env[:response_headers]["Retry-After"]
194
+
195
+ # Try to parse date from the header value
196
+ begin
197
+ datetime = DateTime.rfc2822(retry_after_value)
198
+ datetime.to_time - Time.now.utc
199
+ rescue ArgumentError
200
+ retry_after_value.to_f
201
+ end
202
+ end
203
+
204
+ def calculate_retry_interval(retries)
205
+ retry_index = @options.max - retries
206
+ current_interval = @options.interval * (@options.backoff_factor ** retry_index)
207
+ current_interval = [current_interval, @options.max_interval].min
208
+ random_interval = rand * @options.interval_randomness.to_f * @options.interval
209
+
210
+ current_interval + random_interval
211
+ end
147
212
  end
148
213
  end
@@ -52,6 +52,8 @@ module Faraday
52
52
  path.query = nil
53
53
  end
54
54
  else
55
+ anchor_index = path.index('#')
56
+ path = path.slice(0, anchor_index) unless anchor_index.nil?
55
57
  path, query = path.split('?', 2)
56
58
  end
57
59
  self.path = path
@@ -67,6 +69,26 @@ module Faraday
67
69
  headers[key] = value
68
70
  end
69
71
 
72
+ def marshal_dump
73
+ {
74
+ :method => method,
75
+ :body => body,
76
+ :headers => headers,
77
+ :path => path,
78
+ :params => params,
79
+ :options => options
80
+ }
81
+ end
82
+
83
+ def marshal_load(serialised)
84
+ self.method = serialised[:method]
85
+ self.body = serialised[:body]
86
+ self.headers = serialised[:headers]
87
+ self.path = serialised[:path]
88
+ self.params = serialised[:params]
89
+ self.options = serialised[:options]
90
+ end
91
+
70
92
  # ENV Keys
71
93
  # :method - a symbolized request method (:get, :post)
72
94
  # :body - the request body that will eventually be converted to a string.
@@ -4,30 +4,36 @@ module Faraday
4
4
  class Response::Logger < Response::Middleware
5
5
  extend Forwardable
6
6
 
7
- DEFAULT_OPTIONS = { :bodies => false }
7
+ DEFAULT_OPTIONS = { :headers => true, :bodies => false }
8
8
 
9
9
  def initialize(app, logger = nil, options = {})
10
10
  super(app)
11
11
  @logger = logger || begin
12
12
  require 'logger'
13
- ::Logger.new(STDOUT)
13
+ ::Logger.new($stdout)
14
14
  end
15
+ @filter = []
15
16
  @options = DEFAULT_OPTIONS.merge(options)
17
+ yield self if block_given?
16
18
  end
17
19
 
18
20
  def_delegators :@logger, :debug, :info, :warn, :error, :fatal
19
21
 
20
22
  def call(env)
21
- info "#{env.method} #{env.url.to_s}"
22
- debug('request') { dump_headers env.request_headers }
23
- debug('request') { dump_body(env[:body]) } if env[:body] && log_body?(:request)
23
+ info('request') { "#{env.method.upcase} #{apply_filters(env.url.to_s)}" }
24
+ debug('request') { apply_filters( dump_headers env.request_headers ) } if log_headers?(:request)
25
+ debug('request') { apply_filters( dump_body(env[:body]) ) } if env[:body] && log_body?(:request)
24
26
  super
25
27
  end
26
28
 
27
29
  def on_complete(env)
28
- info('Status') { env.status.to_s }
29
- debug('response') { dump_headers env.response_headers }
30
- debug('response') { dump_body env[:body] } if env[:body] && log_body?(:response)
30
+ info('response') { "Status #{env.status.to_s}" }
31
+ debug('response') { apply_filters( dump_headers env.response_headers ) } if log_headers?(:response)
32
+ debug('response') { apply_filters( dump_body env[:body] ) } if env[:body] && log_body?(:response)
33
+ end
34
+
35
+ def filter(filter_word, filter_replacement)
36
+ @filter.push([ filter_word, filter_replacement ])
31
37
  end
32
38
 
33
39
  private
@@ -49,11 +55,26 @@ module Faraday
49
55
  body.pretty_inspect
50
56
  end
51
57
 
58
+ def log_headers?(type)
59
+ case @options[:headers]
60
+ when Hash then @options[:headers][type]
61
+ else @options[:headers]
62
+ end
63
+ end
64
+
52
65
  def log_body?(type)
53
66
  case @options[:bodies]
54
67
  when Hash then @options[:bodies][type]
55
68
  else @options[:bodies]
56
69
  end
57
70
  end
71
+
72
+ def apply_filters(output)
73
+ @filter.each do |pattern, replacement|
74
+ output = output.to_s.gsub(pattern, replacement)
75
+ end
76
+ output
77
+ end
78
+
58
79
  end
59
80
  end
@@ -5,12 +5,16 @@ module Faraday
5
5
  def on_complete(env)
6
6
  case env[:status]
7
7
  when 404
8
- raise Faraday::Error::ResourceNotFound, response_values(env)
8
+ raise Faraday::ResourceNotFound, response_values(env)
9
9
  when 407
10
10
  # mimic the behavior that we get with proxy requests with HTTPS
11
- raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
11
+ raise Faraday::ConnectionFailed.new(
12
+ %{407 "Proxy Authentication Required "},
13
+ response_values(env))
12
14
  when ClientErrorStatuses
13
- raise Faraday::Error::ClientError, response_values(env)
15
+ raise Faraday::ClientError, response_values(env)
16
+ when nil
17
+ raise Faraday::NilStatusError, response_values(env)
14
18
  end
15
19
  end
16
20
 
@@ -37,6 +37,10 @@ module Faraday
37
37
  finished? ? env.status : nil
38
38
  end
39
39
 
40
+ def reason_phrase
41
+ finished? ? env.reason_phrase : nil
42
+ end
43
+
40
44
  def headers
41
45
  finished? ? env.response_headers : {}
42
46
  end
@@ -50,9 +54,9 @@ module Faraday
50
54
  !!env
51
55
  end
52
56
 
53
- def on_complete
54
- if not finished?
55
- @on_complete_callbacks << Proc.new
57
+ def on_complete(&block)
58
+ if !finished?
59
+ @on_complete_callbacks << block
56
60
  else
57
61
  yield(env)
58
62
  end
@@ -61,8 +65,8 @@ module Faraday
61
65
 
62
66
  def finish(env)
63
67
  raise "response already finished" if finished?
64
- @on_complete_callbacks.each { |callback| callback.call(env) }
65
- @env = Env.from(env)
68
+ @env = env.is_a?(Env) ? env : Env.from(env)
69
+ @on_complete_callbacks.each { |callback| callback.call(@env) }
66
70
  return self
67
71
  end
68
72
 
data/lib/faraday/utils.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'thread'
2
- Faraday.require_libs 'parameters'
3
2
 
4
3
  module Faraday
5
4
  module Utils
@@ -11,12 +10,28 @@ module Faraday
11
10
  new(value)
12
11
  end
13
12
 
13
+ def self.allocate
14
+ new_self = super
15
+ new_self.initialize_names
16
+ new_self
17
+ end
18
+
14
19
  def initialize(hash = nil)
15
20
  super()
16
21
  @names = {}
17
22
  self.update(hash || {})
18
23
  end
19
24
 
25
+ def initialize_names
26
+ @names = {}
27
+ end
28
+
29
+ # on dup/clone, we need to duplicate @names hash
30
+ def initialize_copy(other)
31
+ super
32
+ @names = other.names.dup
33
+ end
34
+
20
35
  # need to synchronize concurrent writes to the shared KeyMap
21
36
  keymap_mutex = Mutex.new
22
37
 
@@ -81,6 +96,7 @@ module Faraday
81
96
 
82
97
  def replace(other)
83
98
  clear
99
+ @names.clear
84
100
  self.update other
85
101
  self
86
102
  end
@@ -89,9 +105,16 @@ module Faraday
89
105
 
90
106
  def parse(header_string)
91
107
  return unless header_string && !header_string.empty?
92
- header_string.split(/\r\n/).
108
+
109
+ headers = header_string.split(/\r\n/)
110
+
111
+ # Find the last set of response headers.
112
+ start_index = headers.rindex { |x| x.match(/^HTTP\//) } || 0
113
+ last_response = headers.slice(start_index, headers.size)
114
+
115
+ last_response.
93
116
  tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
94
- map { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
117
+ map { |h| h.split(/:\s*/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
95
118
  each { |key, value|
96
119
  # join multiple values with a comma
97
120
  if self[key]
@@ -101,6 +124,12 @@ module Faraday
101
124
  end
102
125
  }
103
126
  end
127
+
128
+ protected
129
+
130
+ def names
131
+ @names
132
+ end
104
133
  end
105
134
 
106
135
  # hash with stringified keys
data/lib/faraday.rb CHANGED
@@ -14,7 +14,7 @@ require 'forwardable'
14
14
  # conn.get '/'
15
15
  #
16
16
  module Faraday
17
- VERSION = "0.9.1"
17
+ VERSION = "0.17.3"
18
18
 
19
19
  class << self
20
20
  # Public: Gets or sets the root path that Faraday is being loaded from.
@@ -34,8 +34,8 @@ module Faraday
34
34
  # Faraday.get "https://faraday.com"
35
35
  attr_writer :default_connection
36
36
 
37
- # Public: Sets the default options used when calling Faraday#new.
38
- attr_writer :default_connection_options
37
+ # Public: Tells faraday to ignore the environment proxy (http_proxy).
38
+ attr_accessor :ignore_env_proxy
39
39
 
40
40
  # Public: Initializes a new Faraday::Connection.
41
41
  #
@@ -64,9 +64,8 @@ module Faraday
64
64
  # :params => {:page => 1}
65
65
  #
66
66
  # Returns a Faraday::Connection.
67
- def new(url = nil, options = nil)
68
- block = block_given? ? Proc.new : nil
69
- options = options ? default_connection_options.merge(options) : default_connection_options.dup
67
+ def new(url = nil, options = nil, &block)
68
+ options = options ? default_connection_options.merge(options) : default_connection_options
70
69
  Faraday::Connection.new(url, options, &block)
71
70
  end
72
71
 
@@ -92,6 +91,10 @@ module Faraday
92
91
 
93
92
  alias require_lib require_libs
94
93
 
94
+ def respond_to?(symbol, include_private = false)
95
+ default_connection.respond_to?(symbol, include_private) || super
96
+ end
97
+
95
98
  private
96
99
  # Internal: Proxies method calls on the Faraday constant to
97
100
  # #default_connection.
@@ -100,6 +103,7 @@ module Faraday
100
103
  end
101
104
  end
102
105
 
106
+ self.ignore_env_proxy = false
103
107
  self.root_path = File.expand_path "..", __FILE__
104
108
  self.lib_path = File.expand_path "../faraday", __FILE__
105
109
  self.default_adapter = :net_http
@@ -108,7 +112,7 @@ module Faraday
108
112
  #
109
113
  # Returns a Faraday::Connection, configured with the #default_adapter.
110
114
  def self.default_connection
111
- @default_connection ||= Connection.new
115
+ @default_connection ||= Connection.new(default_connection_options)
112
116
  end
113
117
 
114
118
  # Gets the default connection options used when calling Faraday#new.
@@ -118,13 +122,10 @@ module Faraday
118
122
  @default_connection_options ||= ConnectionOptions.new
119
123
  end
120
124
 
121
- if (!defined?(RUBY_ENGINE) || "ruby" == RUBY_ENGINE) && RUBY_VERSION < '1.9'
122
- begin
123
- require 'system_timer'
124
- Timer = SystemTimer
125
- rescue LoadError
126
- warn "Faraday: you may want to install system_timer for reliable timeouts"
127
- end
125
+ # Public: Sets the default options used when calling Faraday#new.
126
+ def self.default_connection_options=(options)
127
+ @default_connection = nil
128
+ @default_connection_options = ConnectionOptions.from(options)
128
129
  end
129
130
 
130
131
  unless const_defined? :Timer
@@ -244,25 +245,3 @@ module Faraday
244
245
  require_lib 'autoload'
245
246
  end
246
247
  end
247
-
248
- # not pulling in active-support JUST for this method. And I love this method.
249
- class Object
250
- # The primary purpose of this method is to "tap into" a method chain,
251
- # in order to perform operations on intermediate results within the chain.
252
- #
253
- # Examples
254
- #
255
- # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
256
- # tap { |x| puts "array: #{x.inspect}" }.
257
- # select { |x| x%2 == 0 }.
258
- # tap { |x| puts "evens: #{x.inspect}" }.
259
- # map { |x| x*x }.
260
- # tap { |x| puts "squares: #{x.inspect}" }
261
- #
262
- # Yields self.
263
- # Returns self.
264
- def tap
265
- yield(self)
266
- self
267
- end unless Object.respond_to?(:tap)
268
- end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::DeprecatedClass do
4
+ class SampleClass < StandardError
5
+ attr_accessor :foo
6
+
7
+ def initialize(foo = nil)
8
+ @foo = foo || :foo
9
+ end
10
+ end
11
+
12
+ SampleDeprecatedClass = Faraday::DeprecatedClass.proxy_class(SampleClass)
13
+
14
+ it 'does not raise error for deprecated classes but prints an error message' do
15
+ error_message, foobar = with_warn_squelching { SampleDeprecatedClass.new(:foo_bar) }
16
+ expect(foobar).to be_a(SampleClass)
17
+ expect(foobar.foo).to eq(:foo_bar)
18
+ expect(error_message).to match(
19
+ Regexp.new(
20
+ 'NOTE: SampleDeprecatedClass.new is deprecated; '\
21
+ 'use SampleClass.new instead. It will be removed in or after version 1.0'
22
+ )
23
+ )
24
+ end
25
+
26
+ it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
27
+ error_message, = with_warn_squelching { Class.new(SampleDeprecatedClass) }
28
+
29
+ expect(error_message).to match(
30
+ Regexp.new(
31
+ 'NOTE: Inheriting SampleDeprecatedClass is deprecated; '\
32
+ 'use SampleClass instead. It will be removed in or after version 1.0'
33
+ )
34
+ )
35
+ end
36
+
37
+ it 'allows backward-compatible class to be subclassed' do
38
+ expect {
39
+ with_warn_squelching { Class.new(SampleDeprecatedClass) }
40
+ }.not_to raise_error
41
+ end
42
+
43
+ it 'allows rescuing of a current error with a deprecated error' do
44
+ expect { raise SampleClass, nil }.to raise_error(SampleDeprecatedClass)
45
+ end
46
+
47
+ it 'allows rescuing of a current error with a current error' do
48
+ expect { raise SampleClass, nil }.to raise_error(SampleClass)
49
+ end
50
+
51
+ it 'allows rescuing of a deprecated error with a deprecated error' do
52
+ expect { raise SampleDeprecatedClass, nil }.to raise_error(SampleDeprecatedClass)
53
+ end
54
+
55
+ it 'allows rescuing of a deprecated error with a current error' do
56
+ expect { raise SampleDeprecatedClass, nil }.to raise_error(SampleClass)
57
+ end
58
+
59
+
60
+ def with_warn_squelching
61
+ stderr_catcher = StringIO.new
62
+ original_stderr = $stderr
63
+ $stderr = stderr_catcher
64
+ result = yield if block_given?
65
+ [stderr_catcher.tap(&:rewind).string, result]
66
+ ensure
67
+ $stderr = original_stderr
68
+ end
69
+ end