faraday 0.15.4 → 0.17.6
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 +4 -4
- data/CHANGELOG.md +232 -0
- data/README.md +15 -1
- data/Rakefile +13 -0
- data/lib/faraday/adapter/em_http.rb +9 -9
- data/lib/faraday/adapter/em_synchrony.rb +5 -5
- data/lib/faraday/adapter/excon.rb +3 -3
- data/lib/faraday/adapter/httpclient.rb +4 -4
- data/lib/faraday/adapter/net_http.rb +3 -2
- data/lib/faraday/adapter/net_http_persistent.rb +4 -4
- data/lib/faraday/adapter/patron.rb +5 -5
- data/lib/faraday/adapter/rack.rb +1 -1
- data/lib/faraday/deprecate.rb +109 -0
- data/lib/faraday/error.rb +127 -35
- data/lib/faraday/options.rb +3 -3
- data/lib/faraday/rack_builder.rb +2 -2
- data/lib/faraday/request/retry.rb +8 -5
- data/lib/faraday/request.rb +2 -0
- data/lib/faraday/response/raise_error.rb +7 -3
- data/lib/faraday/response.rb +3 -3
- data/lib/faraday/upload_io.rb +16 -6
- data/lib/faraday.rb +2 -3
- data/spec/faraday/deprecate_spec.rb +147 -0
- data/spec/faraday/error_spec.rb +102 -0
- data/spec/faraday/response/raise_error_spec.rb +106 -0
- data/spec/spec_helper.rb +105 -0
- data/test/adapters/default_test.rb +14 -0
- data/test/adapters/em_http_test.rb +30 -0
- data/test/adapters/em_synchrony_test.rb +32 -0
- data/test/adapters/excon_test.rb +30 -0
- data/test/adapters/httpclient_test.rb +34 -0
- data/test/adapters/integration.rb +263 -0
- data/test/adapters/logger_test.rb +136 -0
- data/test/adapters/net_http_persistent_test.rb +114 -0
- data/test/adapters/net_http_test.rb +79 -0
- data/test/adapters/patron_test.rb +40 -0
- data/test/adapters/rack_test.rb +38 -0
- data/test/adapters/test_middleware_test.rb +157 -0
- data/test/adapters/typhoeus_test.rb +38 -0
- data/test/authentication_middleware_test.rb +65 -0
- data/test/composite_read_io_test.rb +109 -0
- data/test/connection_test.rb +738 -0
- data/test/env_test.rb +268 -0
- data/test/helper.rb +75 -0
- data/test/live_server.rb +67 -0
- data/test/middleware/instrumentation_test.rb +88 -0
- data/test/middleware/retry_test.rb +282 -0
- data/test/middleware_stack_test.rb +260 -0
- data/test/multibyte.txt +1 -0
- data/test/options_test.rb +333 -0
- data/test/parameters_test.rb +157 -0
- data/test/request_middleware_test.rb +126 -0
- data/test/response_middleware_test.rb +72 -0
- data/test/strawberry.rb +2 -0
- data/test/utils_test.rb +98 -0
- metadata +48 -7
data/lib/faraday/error.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
|
-
|
2
|
-
class Error < StandardError; end
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
attr_reader :response, :wrapped_exception
|
3
|
+
require 'faraday/deprecate'
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# Faraday namespace.
|
6
|
+
module Faraday
|
7
|
+
# Faraday error base class.
|
8
|
+
class Error < StandardError
|
9
|
+
attr_reader :response, :wrapped_exception
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
super("the server responded with status #{ex[:status]}")
|
16
|
-
@response = ex
|
17
|
-
else
|
18
|
-
super(ex.to_s)
|
19
|
-
end
|
11
|
+
def initialize(exc, response = nil)
|
12
|
+
@wrapped_exception = nil unless defined?(@wrapped_exception)
|
13
|
+
@response = nil unless defined?(@response)
|
14
|
+
super(exc_msg_and_response!(exc, response))
|
20
15
|
end
|
21
16
|
|
22
17
|
def backtrace
|
@@ -29,38 +24,135 @@ module Faraday
|
|
29
24
|
|
30
25
|
def inspect
|
31
26
|
inner = ''
|
32
|
-
if @wrapped_exception
|
33
|
-
|
34
|
-
|
35
|
-
if @response
|
36
|
-
inner << " response=#{@response.inspect}"
|
37
|
-
end
|
38
|
-
if inner.empty?
|
39
|
-
inner << " #{super}"
|
40
|
-
end
|
27
|
+
inner += " wrapped=#{@wrapped_exception.inspect}" if @wrapped_exception
|
28
|
+
inner += " response=#{@response.inspect}" if @response
|
29
|
+
inner += " #{super}" if inner.empty?
|
41
30
|
%(#<#{self.class}#{inner}>)
|
42
31
|
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
# Pulls out potential parent exception and response hash, storing them in
|
36
|
+
# instance variables.
|
37
|
+
# exc - Either an Exception, a string message, or a response hash.
|
38
|
+
# response - Hash
|
39
|
+
# :status - Optional integer HTTP response status
|
40
|
+
# :headers - String key/value hash of HTTP response header
|
41
|
+
# values.
|
42
|
+
# :body - Optional string HTTP response body.
|
43
|
+
#
|
44
|
+
# If a subclass has to call this, then it should pass a string message
|
45
|
+
# to `super`. See NilStatusError.
|
46
|
+
def exc_msg_and_response!(exc, response = nil)
|
47
|
+
if @response.nil? && @wrapped_exception.nil?
|
48
|
+
@wrapped_exception, msg, @response = exc_msg_and_response(exc, response)
|
49
|
+
return msg
|
50
|
+
end
|
51
|
+
|
52
|
+
exc.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Pulls out potential parent exception and response hash.
|
56
|
+
def exc_msg_and_response(exc, response = nil)
|
57
|
+
return [exc, exc.message, response] if exc.respond_to?(:backtrace)
|
58
|
+
|
59
|
+
return [nil, "the server responded with status #{exc[:status]}", exc] \
|
60
|
+
if exc.respond_to?(:each_key)
|
61
|
+
|
62
|
+
[nil, exc.to_s, response]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Faraday client error class. Represents 4xx status responses.
|
67
|
+
class ClientError < Error
|
68
|
+
end
|
69
|
+
|
70
|
+
# Raised by Faraday::Response::RaiseError in case of a 400 response.
|
71
|
+
class BadRequestError < ClientError
|
43
72
|
end
|
44
73
|
|
45
|
-
|
46
|
-
class
|
47
|
-
|
74
|
+
# Raised by Faraday::Response::RaiseError in case of a 401 response.
|
75
|
+
class UnauthorizedError < ClientError
|
76
|
+
end
|
77
|
+
|
78
|
+
# Raised by Faraday::Response::RaiseError in case of a 403 response.
|
79
|
+
class ForbiddenError < ClientError
|
80
|
+
end
|
48
81
|
|
82
|
+
# Raised by Faraday::Response::RaiseError in case of a 404 response.
|
83
|
+
class ResourceNotFound < ClientError
|
84
|
+
end
|
85
|
+
|
86
|
+
# Raised by Faraday::Response::RaiseError in case of a 407 response.
|
87
|
+
class ProxyAuthError < ClientError
|
88
|
+
end
|
89
|
+
|
90
|
+
# Raised by Faraday::Response::RaiseError in case of a 409 response.
|
91
|
+
class ConflictError < ClientError
|
92
|
+
end
|
93
|
+
|
94
|
+
# Raised by Faraday::Response::RaiseError in case of a 422 response.
|
95
|
+
class UnprocessableEntityError < ClientError
|
96
|
+
end
|
97
|
+
|
98
|
+
# Faraday server error class. Represents 5xx status responses.
|
99
|
+
class ServerError < Error
|
100
|
+
end
|
101
|
+
|
102
|
+
# A unified client error for timeouts.
|
49
103
|
class TimeoutError < ClientError
|
50
|
-
def initialize(
|
51
|
-
super(
|
104
|
+
def initialize(exc = 'timeout', response = nil)
|
105
|
+
super(exc, response)
|
52
106
|
end
|
53
107
|
end
|
54
108
|
|
55
|
-
|
109
|
+
# Raised by Faraday::Response::RaiseError in case of a nil status in response.
|
110
|
+
class NilStatusError < ServerError
|
111
|
+
def initialize(exc, response = nil)
|
112
|
+
exc_msg_and_response!(exc, response)
|
113
|
+
@response = unwrap_resp!(@response)
|
114
|
+
super('http status could not be derived from the server response')
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
extend Faraday::Deprecate
|
120
|
+
|
121
|
+
def unwrap_resp(resp)
|
122
|
+
if inner = (resp.keys.size == 1 && resp[:response])
|
123
|
+
return unwrap_resp(inner)
|
124
|
+
end
|
125
|
+
|
126
|
+
resp
|
127
|
+
end
|
128
|
+
|
129
|
+
alias_method :unwrap_resp!, :unwrap_resp
|
130
|
+
deprecate('unwrap_resp', nil, '1.0')
|
56
131
|
end
|
57
132
|
|
58
|
-
|
133
|
+
# A unified error for failed connections.
|
134
|
+
class ConnectionFailed < ClientError
|
135
|
+
end
|
59
136
|
|
60
|
-
|
61
|
-
|
62
|
-
|
137
|
+
# A unified client error for SSL errors.
|
138
|
+
class SSLError < ClientError
|
139
|
+
end
|
140
|
+
|
141
|
+
# Raised by FaradayMiddleware::ResponseMiddleware
|
142
|
+
class ParsingError < ClientError
|
63
143
|
end
|
64
144
|
|
145
|
+
# Exception used to control the Retry middleware.
|
146
|
+
#
|
147
|
+
# @see Faraday::Request::Retry
|
148
|
+
class RetriableResponse < ClientError
|
149
|
+
end
|
65
150
|
|
151
|
+
[:ClientError, :ConnectionFailed, :ResourceNotFound,
|
152
|
+
:ParsingError, :TimeoutError, :SSLError, :RetriableResponse].each do |const|
|
153
|
+
Error.const_set(
|
154
|
+
const,
|
155
|
+
DeprecatedClass.proxy_class(Faraday.const_get(const))
|
156
|
+
)
|
157
|
+
end
|
66
158
|
end
|
data/lib/faraday/options.rb
CHANGED
@@ -72,7 +72,7 @@ module Faraday
|
|
72
72
|
if args.size > 0
|
73
73
|
send(key_setter, args.first)
|
74
74
|
elsif block_given?
|
75
|
-
send(key_setter,
|
75
|
+
send(key_setter, yield(key))
|
76
76
|
else
|
77
77
|
raise self.class.fetch_error_class, "key not found: #{key.inspect}"
|
78
78
|
end
|
@@ -162,8 +162,8 @@ module Faraday
|
|
162
162
|
@attribute_options ||= {}
|
163
163
|
end
|
164
164
|
|
165
|
-
def self.memoized(key)
|
166
|
-
memoized_attributes[key.to_sym] =
|
165
|
+
def self.memoized(key, &block)
|
166
|
+
memoized_attributes[key.to_sym] = block
|
167
167
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
168
168
|
def #{key}() self[:#{key}]; end
|
169
169
|
RUBY
|
data/lib/faraday/rack_builder.rb
CHANGED
@@ -49,10 +49,10 @@ module Faraday
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
def initialize(handlers = [])
|
52
|
+
def initialize(handlers = [], &block)
|
53
53
|
@handlers = handlers
|
54
54
|
if block_given?
|
55
|
-
build(&
|
55
|
+
build(&block)
|
56
56
|
elsif @handlers.empty?
|
57
57
|
# default stack, if nothing else is configured
|
58
58
|
self.request :url_encoded
|
@@ -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
|
#
|
@@ -19,8 +21,9 @@ module Faraday
|
|
19
21
|
# interval that is random between 0.1 and 0.15
|
20
22
|
#
|
21
23
|
class Request::Retry < Faraday::Middleware
|
22
|
-
|
23
|
-
|
24
|
+
DEFAULT_EXCEPTIONS = [Errno::ETIMEDOUT, 'Timeout::Error',
|
25
|
+
Faraday::TimeoutError, Faraday::RetriableResponse
|
26
|
+
].freeze
|
24
27
|
IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]
|
25
28
|
|
26
29
|
class Options < Faraday::Options.new(:max, :interval, :max_interval, :interval_randomness,
|
@@ -93,7 +96,7 @@ module Faraday
|
|
93
96
|
# exceptions - The list of exceptions to handle. Exceptions can be
|
94
97
|
# given as Class, Module, or String. (default:
|
95
98
|
# [Errno::ETIMEDOUT, 'Timeout::Error',
|
96
|
-
#
|
99
|
+
# Faraday::TimeoutError, Faraday::RetriableResponse])
|
97
100
|
# methods - A list of HTTP methods to retry without calling retry_if. Pass
|
98
101
|
# an empty Array to call retry_if for all exceptions.
|
99
102
|
# (defaults to the idempotent HTTP methods in IDEMPOTENT_METHODS)
|
@@ -126,7 +129,7 @@ module Faraday
|
|
126
129
|
begin
|
127
130
|
env[:body] = request_body # after failure env[:body] is set to the response body
|
128
131
|
@app.call(env).tap do |resp|
|
129
|
-
raise Faraday::
|
132
|
+
raise Faraday::RetriableResponse.new(nil, resp) if @options.retry_statuses.include?(resp.status)
|
130
133
|
end
|
131
134
|
rescue @errmatch => exception
|
132
135
|
if retries > 0 && retry_request?(env, exception)
|
@@ -139,7 +142,7 @@ module Faraday
|
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
142
|
-
if exception.is_a?(Faraday::
|
145
|
+
if exception.is_a?(Faraday::RetriableResponse)
|
143
146
|
exception.response
|
144
147
|
else
|
145
148
|
raise
|
data/lib/faraday/request.rb
CHANGED
@@ -12,6 +12,8 @@ module Faraday
|
|
12
12
|
class Request < Struct.new(:method, :path, :params, :headers, :body, :options)
|
13
13
|
extend MiddlewareRegistry
|
14
14
|
|
15
|
+
alias_method :http_method, :method
|
16
|
+
|
15
17
|
register_middleware File.expand_path('../request', __FILE__),
|
16
18
|
:url_encoded => [:UrlEncoded, 'url_encoded'],
|
17
19
|
:multipart => [:Multipart, 'multipart'],
|
@@ -5,12 +5,16 @@ module Faraday
|
|
5
5
|
def on_complete(env)
|
6
6
|
case env[:status]
|
7
7
|
when 404
|
8
|
-
raise Faraday::
|
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::
|
11
|
+
raise Faraday::ConnectionFailed.new(
|
12
|
+
%{407 "Proxy Authentication Required "},
|
13
|
+
response_values(env))
|
12
14
|
when ClientErrorStatuses
|
13
|
-
raise Faraday::
|
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
|
|
data/lib/faraday/response.rb
CHANGED
data/lib/faraday/upload_io.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
begin
|
2
|
-
require '
|
3
|
-
require 'parts'
|
2
|
+
require 'multipart/post'
|
4
3
|
require 'stringio'
|
5
4
|
rescue LoadError
|
6
|
-
|
7
|
-
|
5
|
+
begin
|
6
|
+
require 'composite_io'
|
7
|
+
require 'parts'
|
8
|
+
require 'stringio'
|
9
|
+
rescue LoadError
|
10
|
+
$stderr.puts "Install the multipart-post gem."
|
11
|
+
raise
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
15
|
module Faraday
|
@@ -62,6 +67,11 @@ module Faraday
|
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
65
|
-
|
66
|
-
|
70
|
+
if defined?(::Multipart::Post::UploadIO)
|
71
|
+
UploadIO = ::Multipart::Post::UploadIO
|
72
|
+
Parts = ::Multipart::Post::Parts
|
73
|
+
else
|
74
|
+
UploadIO = ::UploadIO
|
75
|
+
Parts = ::Parts
|
76
|
+
end
|
67
77
|
end
|
data/lib/faraday.rb
CHANGED
@@ -14,7 +14,7 @@ require 'forwardable'
|
|
14
14
|
# conn.get '/'
|
15
15
|
#
|
16
16
|
module Faraday
|
17
|
-
VERSION = "0.
|
17
|
+
VERSION = "0.17.6"
|
18
18
|
|
19
19
|
class << self
|
20
20
|
# Public: Gets or sets the root path that Faraday is being loaded from.
|
@@ -64,8 +64,7 @@ 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
|
67
|
+
def new(url = nil, options = nil, &block)
|
69
68
|
options = options ? default_connection_options.merge(options) : default_connection_options
|
70
69
|
Faraday::Connection.new(url, options, &block)
|
71
70
|
end
|
@@ -0,0 +1,147 @@
|
|
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
|
+
describe 'match behavior' do
|
60
|
+
class SampleDeprecatedClassA < SampleDeprecatedClass; end
|
61
|
+
class SampleDeprecatedClassB < SampleDeprecatedClass; end
|
62
|
+
|
63
|
+
class SampleDeprecatedClassAX < SampleDeprecatedClassA; end
|
64
|
+
|
65
|
+
class SampleClassA < SampleClass; end
|
66
|
+
|
67
|
+
describe 'undeprecated class' do
|
68
|
+
it 'is === to instance of deprecated class' do
|
69
|
+
expect(SampleClass === SampleDeprecatedClass.new).to be true
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'is === to instance of subclass of deprecated class' do
|
73
|
+
expect(SampleClass === SampleDeprecatedClassA.new).to be true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'is === to instance of subclass of subclass of deprecated class' do
|
77
|
+
expect(SampleClass === SampleDeprecatedClassAX.new).to be true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'subclass of undeprecated class' do
|
82
|
+
it 'is not === to instance of undeprecated class' do
|
83
|
+
expect(SampleClassA === SampleClass.new).to be false
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'is not === to instance of deprecated class' do
|
87
|
+
expect(SampleClassA === SampleDeprecatedClass.new).to be false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'deprecated class' do
|
92
|
+
it 'is === to instance of undeprecated class' do
|
93
|
+
expect(SampleDeprecatedClass === SampleClass.new).to be true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'is === to instance of subclass of undeprecated class' do
|
97
|
+
expect(SampleDeprecatedClass === SampleClassA.new).to be true
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'is === to instance of subclass of deprecated class' do
|
101
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassA.new).to be true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'is === to instance of subclass of subclass of deprecated class' do
|
105
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassAX.new).to be true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'subclass of deprecated class' do
|
110
|
+
it 'is not === to instance of subclass of undeprecated class' do
|
111
|
+
expect(SampleDeprecatedClassA === SampleClass.new).to be false
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is not === to instance of another subclass of deprecated class' do
|
115
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClassB.new).to be false
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'is === to instance of its subclass' do
|
119
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClassAX.new).to be true
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'is === to instance of deprecated class' do
|
123
|
+
expect(SampleDeprecatedClass === SampleDeprecatedClassB.new).to be true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'subclass of subclass of deprecated class' do
|
128
|
+
it 'is not === to instance of subclass of another subclass of deprecated class' do
|
129
|
+
expect(SampleDeprecatedClassAX === SampleDeprecatedClassB.new).to be false
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'is not === to instance of its superclass' do
|
133
|
+
expect(SampleDeprecatedClassA === SampleDeprecatedClass.new).to be false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def with_warn_squelching
|
139
|
+
stderr_catcher = StringIO.new
|
140
|
+
original_stderr = $stderr
|
141
|
+
$stderr = stderr_catcher
|
142
|
+
result = yield if block_given?
|
143
|
+
[stderr_catcher.tap(&:rewind).string, result]
|
144
|
+
ensure
|
145
|
+
$stderr = original_stderr
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::ClientError do
|
4
|
+
describe '.initialize' do
|
5
|
+
subject { described_class.new(exception, response) }
|
6
|
+
let(:response) { nil }
|
7
|
+
|
8
|
+
context 'with exception only' do
|
9
|
+
let(:exception) { RuntimeError.new('test') }
|
10
|
+
|
11
|
+
it { expect(subject.wrapped_exception).to eq(exception) }
|
12
|
+
it { expect(subject.response).to be_nil }
|
13
|
+
it { expect(subject.message).to eq(exception.message) }
|
14
|
+
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
15
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with response hash' do
|
19
|
+
let(:exception) { { status: 400 } }
|
20
|
+
|
21
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
22
|
+
it { expect(subject.response).to eq(exception) }
|
23
|
+
it { expect(subject.message).to eq('the server responded with status 400') }
|
24
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with string' do
|
28
|
+
let(:exception) { 'custom message' }
|
29
|
+
|
30
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
31
|
+
it { expect(subject.response).to be_nil }
|
32
|
+
it { expect(subject.message).to eq('custom message') }
|
33
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with anything else #to_s' do
|
37
|
+
let(:exception) { %w[error1 error2] }
|
38
|
+
|
39
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
40
|
+
it { expect(subject.response).to be_nil }
|
41
|
+
it { expect(subject.message).to eq('["error1", "error2"]') }
|
42
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'maintains backward-compatibility until 1.0' do
|
46
|
+
it 'does not raise an error for error-namespaced classes but prints an error message' do
|
47
|
+
error_message, error = with_warn_squelching { Faraday::Error::ClientError.new('foo') }
|
48
|
+
|
49
|
+
expect(error).to be_a Faraday::ClientError
|
50
|
+
expect(error_message).to match(
|
51
|
+
Regexp.new(
|
52
|
+
'NOTE: Faraday::Error::ClientError.new is deprecated; '\
|
53
|
+
'use Faraday::ClientError.new instead. It will be removed in or after version 1.0'
|
54
|
+
)
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not raise an error for inherited error-namespaced classes but prints an error message' do
|
59
|
+
error_message, = with_warn_squelching { Class.new(Faraday::Error::ClientError) }
|
60
|
+
|
61
|
+
expect(error_message).to match(
|
62
|
+
Regexp.new(
|
63
|
+
'NOTE: Inheriting Faraday::Error::ClientError is deprecated; '\
|
64
|
+
'use Faraday::ClientError instead. It will be removed in or after version 1.0'
|
65
|
+
)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'allows backward-compatible class to be subclassed' do
|
70
|
+
expect {
|
71
|
+
with_warn_squelching { Class.new(Faraday::Error::ClientError) }
|
72
|
+
}.not_to raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'allows rescuing of a current error with a deprecated error' do
|
76
|
+
expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'allows rescuing of a current error with a current error' do
|
80
|
+
expect { raise Faraday::ClientError, nil }.to raise_error(Faraday::ClientError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'allows rescuing of a deprecated error with a deprecated error' do
|
84
|
+
expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::Error::ClientError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'allows rescuing of a deprecated error with a current error' do
|
88
|
+
expect { raise Faraday::Error::ClientError, nil }.to raise_error(Faraday::ClientError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def with_warn_squelching
|
93
|
+
stderr_catcher = StringIO.new
|
94
|
+
original_stderr = $stderr
|
95
|
+
$stderr = stderr_catcher
|
96
|
+
result = yield if block_given?
|
97
|
+
[stderr_catcher.tap(&:rewind).string, result]
|
98
|
+
ensure
|
99
|
+
$stderr = original_stderr
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|