faraday 0.17.6 → 1.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +156 -8
- data/LICENSE.md +1 -1
- data/README.md +16 -358
- data/Rakefile +1 -7
- data/examples/client_spec.rb +97 -0
- data/examples/client_test.rb +118 -0
- data/lib/faraday/adapter/test.rb +118 -69
- data/lib/faraday/adapter/typhoeus.rb +4 -1
- data/lib/faraday/adapter.rb +72 -22
- data/lib/faraday/adapter_registry.rb +30 -0
- data/lib/faraday/autoload.rb +39 -36
- data/lib/faraday/connection.rb +343 -185
- data/lib/faraday/dependency_loader.rb +39 -0
- data/lib/faraday/deprecate.rb +7 -6
- data/lib/faraday/encoders/flat_params_encoder.rb +105 -0
- data/lib/faraday/encoders/nested_params_encoder.rb +176 -0
- data/lib/faraday/error.rb +28 -40
- data/lib/faraday/logging/formatter.rb +105 -0
- data/lib/faraday/methods.rb +6 -0
- data/lib/faraday/middleware.rb +19 -25
- data/lib/faraday/middleware_registry.rb +129 -0
- data/lib/faraday/options/connection_options.rb +22 -0
- data/lib/faraday/options/env.rb +181 -0
- data/lib/faraday/options/proxy_options.rb +32 -0
- data/lib/faraday/options/request_options.rb +22 -0
- data/lib/faraday/options/ssl_options.rb +59 -0
- data/lib/faraday/options.rb +36 -191
- data/lib/faraday/parameters.rb +4 -197
- data/lib/faraday/rack_builder.rb +76 -64
- data/lib/faraday/request/authorization.rb +51 -30
- data/lib/faraday/request/basic_authentication.rb +14 -7
- data/lib/faraday/request/instrumentation.rb +45 -27
- data/lib/faraday/request/json.rb +55 -0
- data/lib/faraday/request/token_authentication.rb +15 -10
- data/lib/faraday/request/url_encoded.rb +43 -23
- data/lib/faraday/request.rb +82 -44
- data/lib/faraday/response/json.rb +54 -0
- data/lib/faraday/response/logger.rb +20 -69
- data/lib/faraday/response/raise_error.rb +49 -18
- data/lib/faraday/response.rb +26 -20
- data/lib/faraday/utils/headers.rb +139 -0
- data/lib/faraday/utils/params_hash.rb +61 -0
- data/lib/faraday/utils.rb +38 -247
- data/lib/faraday/version.rb +5 -0
- data/lib/faraday.rb +134 -188
- data/spec/external_adapters/faraday_specs_setup.rb +14 -0
- data/spec/faraday/adapter/em_http_spec.rb +49 -0
- data/spec/faraday/adapter/em_synchrony_spec.rb +18 -0
- data/spec/faraday/adapter/excon_spec.rb +49 -0
- data/spec/faraday/adapter/httpclient_spec.rb +73 -0
- data/spec/faraday/adapter/net_http_spec.rb +64 -0
- data/spec/faraday/adapter/patron_spec.rb +18 -0
- data/spec/faraday/adapter/rack_spec.rb +8 -0
- data/spec/faraday/adapter/test_spec.rb +377 -0
- data/spec/faraday/adapter/typhoeus_spec.rb +7 -0
- data/spec/faraday/adapter_registry_spec.rb +28 -0
- data/spec/faraday/adapter_spec.rb +55 -0
- data/spec/faraday/composite_read_io_spec.rb +80 -0
- data/spec/faraday/connection_spec.rb +736 -0
- data/spec/faraday/deprecate_spec.rb +17 -17
- data/spec/faraday/error_spec.rb +12 -54
- data/spec/faraday/middleware_spec.rb +52 -0
- data/spec/faraday/options/env_spec.rb +70 -0
- data/spec/faraday/options/options_spec.rb +297 -0
- data/spec/faraday/options/proxy_options_spec.rb +44 -0
- data/spec/faraday/options/request_options_spec.rb +19 -0
- data/spec/faraday/params_encoders/flat_spec.rb +42 -0
- data/spec/faraday/params_encoders/nested_spec.rb +142 -0
- data/spec/faraday/rack_builder_spec.rb +345 -0
- data/spec/faraday/request/authorization_spec.rb +96 -0
- data/spec/faraday/request/instrumentation_spec.rb +76 -0
- data/spec/faraday/request/json_spec.rb +111 -0
- data/spec/faraday/request/url_encoded_spec.rb +83 -0
- data/spec/faraday/request_spec.rb +120 -0
- data/spec/faraday/response/json_spec.rb +119 -0
- data/spec/faraday/response/logger_spec.rb +220 -0
- data/spec/faraday/response/middleware_spec.rb +68 -0
- data/spec/faraday/response/raise_error_spec.rb +78 -15
- data/spec/faraday/response_spec.rb +75 -0
- data/spec/faraday/utils/headers_spec.rb +82 -0
- data/spec/faraday/utils_spec.rb +56 -0
- data/spec/faraday_spec.rb +37 -0
- data/spec/spec_helper.rb +65 -36
- data/spec/support/disabling_stub.rb +14 -0
- data/spec/support/fake_safe_buffer.rb +15 -0
- data/spec/support/helper_methods.rb +133 -0
- data/spec/support/shared_examples/adapter.rb +105 -0
- data/spec/support/shared_examples/params_encoder.rb +18 -0
- data/spec/support/shared_examples/request_method.rb +262 -0
- data/spec/support/streaming_response_checker.rb +35 -0
- data/spec/support/webmock_rack_app.rb +68 -0
- metadata +210 -56
- data/lib/faraday/adapter/em_http.rb +0 -243
- data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -56
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -66
- data/lib/faraday/adapter/em_synchrony.rb +0 -106
- data/lib/faraday/adapter/excon.rb +0 -82
- data/lib/faraday/adapter/httpclient.rb +0 -128
- data/lib/faraday/adapter/net_http.rb +0 -153
- data/lib/faraday/adapter/net_http_persistent.rb +0 -68
- data/lib/faraday/adapter/patron.rb +0 -95
- data/lib/faraday/adapter/rack.rb +0 -58
- data/lib/faraday/request/multipart.rb +0 -68
- data/lib/faraday/request/retry.rb +0 -213
- data/lib/faraday/upload_io.rb +0 -77
- data/test/adapters/default_test.rb +0 -14
- data/test/adapters/em_http_test.rb +0 -30
- data/test/adapters/em_synchrony_test.rb +0 -32
- data/test/adapters/excon_test.rb +0 -30
- data/test/adapters/httpclient_test.rb +0 -34
- data/test/adapters/integration.rb +0 -263
- data/test/adapters/logger_test.rb +0 -136
- data/test/adapters/net_http_persistent_test.rb +0 -114
- data/test/adapters/net_http_test.rb +0 -79
- data/test/adapters/patron_test.rb +0 -40
- data/test/adapters/rack_test.rb +0 -38
- data/test/adapters/test_middleware_test.rb +0 -157
- data/test/adapters/typhoeus_test.rb +0 -38
- data/test/authentication_middleware_test.rb +0 -65
- data/test/composite_read_io_test.rb +0 -109
- data/test/connection_test.rb +0 -738
- data/test/env_test.rb +0 -268
- data/test/helper.rb +0 -75
- data/test/live_server.rb +0 -67
- data/test/middleware/instrumentation_test.rb +0 -88
- data/test/middleware/retry_test.rb +0 -282
- data/test/middleware_stack_test.rb +0 -260
- data/test/multibyte.txt +0 -1
- data/test/options_test.rb +0 -333
- data/test/parameters_test.rb +0 -157
- data/test/request_middleware_test.rb +0 -126
- data/test/response_middleware_test.rb +0 -72
- data/test/strawberry.rb +0 -2
- data/test/utils_test.rb +0 -98
@@ -35,9 +35,9 @@ RSpec.describe Faraday::DeprecatedClass do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'allows backward-compatible class to be subclassed' do
|
38
|
-
expect
|
38
|
+
expect do
|
39
39
|
with_warn_squelching { Class.new(SampleDeprecatedClass) }
|
40
|
-
|
40
|
+
end.not_to raise_error
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'allows rescuing of a current error with a deprecated error' do
|
@@ -66,71 +66,71 @@ RSpec.describe Faraday::DeprecatedClass do
|
|
66
66
|
|
67
67
|
describe 'undeprecated class' do
|
68
68
|
it 'is === to instance of deprecated class' do
|
69
|
-
expect(
|
69
|
+
expect(SampleDeprecatedClass.new.is_a?(SampleClass)).to be true
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'is === to instance of subclass of deprecated class' do
|
73
|
-
expect(
|
73
|
+
expect(SampleDeprecatedClassA.new.is_a?(SampleClass)).to be true
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'is === to instance of subclass of subclass of deprecated class' do
|
77
|
-
expect(
|
77
|
+
expect(SampleDeprecatedClassAX.new.is_a?(SampleClass)).to be true
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
describe 'subclass of undeprecated class' do
|
82
82
|
it 'is not === to instance of undeprecated class' do
|
83
|
-
expect(
|
83
|
+
expect(SampleClass.new.is_a?(SampleClassA)).to be false
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'is not === to instance of deprecated class' do
|
87
|
-
expect(
|
87
|
+
expect(SampleDeprecatedClass.new.is_a?(SampleClassA)).to be false
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
91
|
describe 'deprecated class' do
|
92
92
|
it 'is === to instance of undeprecated class' do
|
93
|
-
expect(SampleDeprecatedClass
|
93
|
+
expect(SampleDeprecatedClass.new.is_a?(SampleClass)).to be true
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'is === to instance of subclass of undeprecated class' do
|
97
|
-
expect(
|
97
|
+
expect(SampleClassA.superclass == SampleDeprecatedClass.superclass).to be true
|
98
98
|
end
|
99
99
|
|
100
100
|
it 'is === to instance of subclass of deprecated class' do
|
101
|
-
expect(
|
101
|
+
expect(SampleDeprecatedClassA.new.is_a?(SampleDeprecatedClass)).to be true
|
102
102
|
end
|
103
103
|
|
104
104
|
it 'is === to instance of subclass of subclass of deprecated class' do
|
105
|
-
expect(
|
105
|
+
expect(SampleDeprecatedClassAX.new.is_a?(SampleDeprecatedClass)).to be true
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
describe 'subclass of deprecated class' do
|
110
110
|
it 'is not === to instance of subclass of undeprecated class' do
|
111
|
-
expect(
|
111
|
+
expect(SampleClass.new.is_a?(SampleDeprecatedClassA)).to be false
|
112
112
|
end
|
113
113
|
|
114
114
|
it 'is not === to instance of another subclass of deprecated class' do
|
115
|
-
expect(
|
115
|
+
expect(SampleDeprecatedClassB.new.is_a?(SampleDeprecatedClassA)).to be false
|
116
116
|
end
|
117
117
|
|
118
118
|
it 'is === to instance of its subclass' do
|
119
|
-
expect(
|
119
|
+
expect(SampleDeprecatedClassAX.new.is_a?(SampleDeprecatedClassA)).to be true
|
120
120
|
end
|
121
121
|
|
122
122
|
it 'is === to instance of deprecated class' do
|
123
|
-
expect(
|
123
|
+
expect(SampleDeprecatedClassB.new.is_a?(SampleDeprecatedClass)).to be true
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
127
|
describe 'subclass of subclass of deprecated class' do
|
128
128
|
it 'is not === to instance of subclass of another subclass of deprecated class' do
|
129
|
-
expect(
|
129
|
+
expect(SampleDeprecatedClassB.new.is_a?(SampleDeprecatedClassAX)).to be false
|
130
130
|
end
|
131
131
|
|
132
132
|
it 'is not === to instance of its superclass' do
|
133
|
-
expect(
|
133
|
+
expect(SampleDeprecatedClass.new.is_a?(SampleDeprecatedClassA)).to be false
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
data/spec/faraday/error_spec.rb
CHANGED
@@ -13,6 +13,7 @@ RSpec.describe Faraday::ClientError do
|
|
13
13
|
it { expect(subject.message).to eq(exception.message) }
|
14
14
|
it { expect(subject.backtrace).to eq(exception.backtrace) }
|
15
15
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
|
16
|
+
it { expect(subject.response_status).to be_nil }
|
16
17
|
end
|
17
18
|
|
18
19
|
context 'with response hash' do
|
@@ -22,6 +23,7 @@ RSpec.describe Faraday::ClientError do
|
|
22
23
|
it { expect(subject.response).to eq(exception) }
|
23
24
|
it { expect(subject.message).to eq('the server responded with status 400') }
|
24
25
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
|
26
|
+
it { expect(subject.response_status).to eq(400) }
|
25
27
|
end
|
26
28
|
|
27
29
|
context 'with string' do
|
@@ -31,6 +33,7 @@ RSpec.describe Faraday::ClientError do
|
|
31
33
|
it { expect(subject.response).to be_nil }
|
32
34
|
it { expect(subject.message).to eq('custom message') }
|
33
35
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
|
36
|
+
it { expect(subject.response_status).to be_nil }
|
34
37
|
end
|
35
38
|
|
36
39
|
context 'with anything else #to_s' do
|
@@ -40,63 +43,18 @@ RSpec.describe Faraday::ClientError do
|
|
40
43
|
it { expect(subject.response).to be_nil }
|
41
44
|
it { expect(subject.message).to eq('["error1", "error2"]') }
|
42
45
|
it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
|
46
|
+
it { expect(subject.response_status).to be_nil }
|
43
47
|
end
|
44
48
|
|
45
|
-
context '
|
46
|
-
|
47
|
-
|
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
|
49
|
+
context 'with exception string and response hash' do
|
50
|
+
let(:exception) { 'custom message' }
|
51
|
+
let(:response) { { status: 400 } }
|
91
52
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
[stderr_catcher.tap(&:rewind).string, result]
|
98
|
-
ensure
|
99
|
-
$stderr = original_stderr
|
53
|
+
it { expect(subject.wrapped_exception).to be_nil }
|
54
|
+
it { expect(subject.response).to eq(response) }
|
55
|
+
it { expect(subject.message).to eq('custom message') }
|
56
|
+
it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
|
57
|
+
it { expect(subject.response_status).to eq(400) }
|
100
58
|
end
|
101
59
|
end
|
102
60
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Middleware do
|
4
|
+
subject { described_class.new(app) }
|
5
|
+
let(:app) { double }
|
6
|
+
|
7
|
+
describe 'options' do
|
8
|
+
context 'when options are passed to the middleware' do
|
9
|
+
subject { described_class.new(app, options) }
|
10
|
+
let(:options) { { field: 'value' } }
|
11
|
+
|
12
|
+
it 'accepts options when initialized' do
|
13
|
+
expect(subject.options[:field]).to eq('value')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#on_request' do
|
19
|
+
subject do
|
20
|
+
Class.new(described_class) do
|
21
|
+
def on_request(env)
|
22
|
+
# do nothing
|
23
|
+
end
|
24
|
+
end.new(app)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'is called by #call' do
|
28
|
+
expect(app).to receive(:call).and_return(app)
|
29
|
+
expect(app).to receive(:on_complete)
|
30
|
+
is_expected.to receive(:call).and_call_original
|
31
|
+
is_expected.to receive(:on_request)
|
32
|
+
subject.call(double)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#close' do
|
37
|
+
context "with app that doesn't support \#close" do
|
38
|
+
it 'should issue warning' do
|
39
|
+
is_expected.to receive(:warn)
|
40
|
+
subject.close
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with app that supports \#close" do
|
45
|
+
it 'should issue warning' do
|
46
|
+
expect(app).to receive(:close)
|
47
|
+
is_expected.to_not receive(:warn)
|
48
|
+
subject.close
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Env do
|
4
|
+
subject(:env) { described_class.new }
|
5
|
+
|
6
|
+
it 'allows to access members' do
|
7
|
+
expect(env.method).to be_nil
|
8
|
+
env.method = :get
|
9
|
+
expect(env.method).to eq(:get)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'allows to access symbol non members' do
|
13
|
+
expect(env[:custom]).to be_nil
|
14
|
+
env[:custom] = :boom
|
15
|
+
expect(env[:custom]).to eq(:boom)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'allows to access string non members' do
|
19
|
+
expect(env['custom']).to be_nil
|
20
|
+
env['custom'] = :boom
|
21
|
+
expect(env['custom']).to eq(:boom)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'ignores false when fetching' do
|
25
|
+
ssl = Faraday::SSLOptions.new
|
26
|
+
ssl.verify = false
|
27
|
+
expect(ssl.fetch(:verify, true)).to be_falsey
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'retains custom members' do
|
31
|
+
env[:foo] = 'custom 1'
|
32
|
+
env[:bar] = :custom_2
|
33
|
+
env2 = Faraday::Env.from(env)
|
34
|
+
env2[:baz] = 'custom 3'
|
35
|
+
|
36
|
+
expect(env2[:foo]).to eq('custom 1')
|
37
|
+
expect(env2[:bar]).to eq(:custom_2)
|
38
|
+
expect(env[:baz]).to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#body' do
|
42
|
+
subject(:env) { described_class.from(body: { foo: 'bar' }) }
|
43
|
+
|
44
|
+
context 'when response is not finished yet' do
|
45
|
+
it 'returns the request body' do
|
46
|
+
expect(env.body).to eq(foo: 'bar')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when response is finished' do
|
51
|
+
before do
|
52
|
+
env.status = 200
|
53
|
+
env.body = { bar: 'foo' }
|
54
|
+
env.response = Faraday::Response.new(env)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns the response body' do
|
58
|
+
expect(env.body).to eq(bar: 'foo')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'allows to access request_body' do
|
62
|
+
expect(env.request_body).to eq(foo: 'bar')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'allows to access response_body' do
|
66
|
+
expect(env.response_body).to eq(bar: 'foo')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::Options do
|
4
|
+
SubOptions = Class.new(Faraday::Options.new(:sub_a, :sub_b))
|
5
|
+
class ParentOptions < Faraday::Options.new(:a, :b, :c)
|
6
|
+
options c: SubOptions
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#merge' do
|
10
|
+
it 'merges options with hashes' do
|
11
|
+
options = ParentOptions.new(1)
|
12
|
+
expect(options.a).to eq(1)
|
13
|
+
expect(options.b).to be_nil
|
14
|
+
|
15
|
+
dup = options.merge a: 2, b: 3
|
16
|
+
expect(dup.a).to eq(2)
|
17
|
+
expect(dup.b).to eq(3)
|
18
|
+
expect(options.a).to eq(1)
|
19
|
+
expect(options.b).to be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'deeply merges two options' do
|
23
|
+
sub_opts1 = SubOptions.from(sub_a: 3)
|
24
|
+
sub_opts2 = SubOptions.from(sub_b: 4)
|
25
|
+
opt1 = ParentOptions.from(a: 1, c: sub_opts1)
|
26
|
+
opt2 = ParentOptions.from(b: 2, c: sub_opts2)
|
27
|
+
|
28
|
+
merged = opt1.merge(opt2)
|
29
|
+
|
30
|
+
expected_sub_opts = SubOptions.from(sub_a: 3, sub_b: 4)
|
31
|
+
expected = ParentOptions.from(a: 1, b: 2, c: expected_sub_opts)
|
32
|
+
expect(merged).to eq(expected)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'deeply merges options with hashes' do
|
36
|
+
sub_opts1 = SubOptions.from(sub_a: 3)
|
37
|
+
sub_opts2 = { sub_b: 4 }
|
38
|
+
opt1 = ParentOptions.from(a: 1, c: sub_opts1)
|
39
|
+
opt2 = { b: 2, c: sub_opts2 }
|
40
|
+
|
41
|
+
merged = opt1.merge(opt2)
|
42
|
+
|
43
|
+
expected_sub_opts = SubOptions.from(sub_a: 3, sub_b: 4)
|
44
|
+
expected = ParentOptions.from(a: 1, b: 2, c: expected_sub_opts)
|
45
|
+
expect(merged).to eq(expected)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'deeply merges options with nil' do
|
49
|
+
sub_opts = SubOptions.new(3, 4)
|
50
|
+
options = ParentOptions.new(1, 2, sub_opts)
|
51
|
+
expect(options.a).to eq(1)
|
52
|
+
expect(options.b).to eq(2)
|
53
|
+
expect(options.c.sub_a).to eq(3)
|
54
|
+
expect(options.c.sub_b).to eq(4)
|
55
|
+
|
56
|
+
options2 = ParentOptions.from(b: 5, c: nil)
|
57
|
+
|
58
|
+
merged = options.merge(options2)
|
59
|
+
|
60
|
+
expect(merged.b).to eq(5)
|
61
|
+
expect(merged.c).to eq(sub_opts)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'deeply merges options with options having nil sub-options' do
|
65
|
+
options = ParentOptions.from(a: 1)
|
66
|
+
|
67
|
+
sub_opts = SubOptions.new(3, 4)
|
68
|
+
options2 = ParentOptions.from(b: 2, c: sub_opts)
|
69
|
+
|
70
|
+
expect(options.a).to eq(1)
|
71
|
+
expect(options2.b).to eq(2)
|
72
|
+
expect(options2.c.sub_a).to eq(3)
|
73
|
+
expect(options2.c.sub_b).to eq(4)
|
74
|
+
|
75
|
+
merged = options.merge(options2)
|
76
|
+
|
77
|
+
expect(merged.c).to eq(sub_opts)
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#dup' do
|
81
|
+
it 'duplicate options but not sub-options' do
|
82
|
+
sub_opts = SubOptions.from(sub_a: 3)
|
83
|
+
opts = ParentOptions.from(b: 1, c: sub_opts)
|
84
|
+
|
85
|
+
duped = opts.dup
|
86
|
+
duped.b = 2
|
87
|
+
duped.c.sub_a = 4
|
88
|
+
|
89
|
+
expect(opts.b).to eq(1)
|
90
|
+
expect(opts.c.sub_a).to eq(4)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#deep_dup' do
|
95
|
+
it 'duplicate options and also suboptions' do
|
96
|
+
sub_opts = SubOptions.from(sub_a: 3)
|
97
|
+
opts = ParentOptions.from(b: 1, c: sub_opts)
|
98
|
+
|
99
|
+
duped = opts.deep_dup
|
100
|
+
duped.b = 2
|
101
|
+
duped.c.sub_a = 4
|
102
|
+
|
103
|
+
expect(opts.b).to eq(1)
|
104
|
+
expect(opts.c.sub_a).to eq(3)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#clear' do
|
109
|
+
it 'clears the options' do
|
110
|
+
options = SubOptions.new(1)
|
111
|
+
expect(options.empty?).not_to be_truthy
|
112
|
+
options.clear
|
113
|
+
expect(options.empty?).to be_truthy
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#empty?' do
|
118
|
+
it 'returns true only if all options are nil' do
|
119
|
+
options = SubOptions.new
|
120
|
+
expect(options.empty?).to be_truthy
|
121
|
+
options.sub_a = 1
|
122
|
+
expect(options.empty?).not_to be_truthy
|
123
|
+
options.delete(:sub_a)
|
124
|
+
expect(options.empty?).to be_truthy
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#each_key' do
|
129
|
+
it 'allows to iterate through keys' do
|
130
|
+
options = ParentOptions.new(1, 2, 3)
|
131
|
+
enum = options.each_key
|
132
|
+
expect(enum.next.to_sym).to eq(:a)
|
133
|
+
expect(enum.next.to_sym).to eq(:b)
|
134
|
+
expect(enum.next.to_sym).to eq(:c)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#key?' do
|
139
|
+
it 'returns true if the key exists and is not nil' do
|
140
|
+
options = SubOptions.new
|
141
|
+
expect(options.key?(:sub_a)).not_to be_truthy
|
142
|
+
options.sub_a = 1
|
143
|
+
expect(options.key?(:sub_a)).to be_truthy
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#each_value' do
|
148
|
+
it 'allows to iterate through values' do
|
149
|
+
options = ParentOptions.new(1, 2, 3)
|
150
|
+
enum = options.each_value
|
151
|
+
expect(enum.next).to eq(1)
|
152
|
+
expect(enum.next).to eq(2)
|
153
|
+
expect(enum.next).to eq(3)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe '#value?' do
|
158
|
+
it 'returns true if any key has that value' do
|
159
|
+
options = SubOptions.new
|
160
|
+
expect(options.value?(1)).not_to be_truthy
|
161
|
+
options.sub_a = 1
|
162
|
+
expect(options.value?(1)).to be_truthy
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#update' do
|
167
|
+
it 'updates options from hashes' do
|
168
|
+
options = ParentOptions.new(1)
|
169
|
+
expect(options.a).to eq(1)
|
170
|
+
expect(options.b).to be_nil
|
171
|
+
|
172
|
+
updated = options.update a: 2, b: 3
|
173
|
+
expect(options.a).to eq(2)
|
174
|
+
expect(options.b).to eq(3)
|
175
|
+
expect(updated).to eq(options)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe '#delete' do
|
180
|
+
it 'allows to remove value for key' do
|
181
|
+
options = ParentOptions.new(1)
|
182
|
+
expect(options.a).to eq(1)
|
183
|
+
expect(options.delete(:a)).to eq(1)
|
184
|
+
expect(options.a).to be_nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe '#from' do
|
189
|
+
it { expect { ParentOptions.from invalid: 1 }.to raise_error(NoMethodError) }
|
190
|
+
|
191
|
+
it 'works with options' do
|
192
|
+
options = ParentOptions.new(1)
|
193
|
+
|
194
|
+
value = ParentOptions.from(options)
|
195
|
+
expect(value.a).to eq(1)
|
196
|
+
expect(value.b).to be_nil
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'works with options with sub object' do
|
200
|
+
sub = SubOptions.new(1)
|
201
|
+
options = ParentOptions.from a: 1, c: sub
|
202
|
+
expect(options).to be_a_kind_of(ParentOptions)
|
203
|
+
expect(options.a).to eq(1)
|
204
|
+
expect(options.b).to be_nil
|
205
|
+
expect(options.c).to be_a_kind_of(SubOptions)
|
206
|
+
expect(options.c.sub_a).to eq(1)
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'works with hash' do
|
210
|
+
options = ParentOptions.from a: 1
|
211
|
+
expect(options).to be_a_kind_of(ParentOptions)
|
212
|
+
expect(options.a).to eq(1)
|
213
|
+
expect(options.b).to be_nil
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'works with hash with sub object' do
|
217
|
+
options = ParentOptions.from a: 1, c: { sub_a: 1 }
|
218
|
+
expect(options).to be_a_kind_of(ParentOptions)
|
219
|
+
expect(options.a).to eq(1)
|
220
|
+
expect(options.b).to be_nil
|
221
|
+
expect(options.c).to be_a_kind_of(SubOptions)
|
222
|
+
expect(options.c.sub_a).to eq(1)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'works with deep hash' do
|
226
|
+
hash = { b: 1 }
|
227
|
+
options = ParentOptions.from a: hash
|
228
|
+
expect(options.a[:b]).to eq(1)
|
229
|
+
|
230
|
+
hash[:b] = 2
|
231
|
+
expect(options.a[:b]).to eq(1)
|
232
|
+
|
233
|
+
options.a[:b] = 3
|
234
|
+
expect(hash[:b]).to eq(2)
|
235
|
+
expect(options.a[:b]).to eq(3)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'works with nil' do
|
239
|
+
options = ParentOptions.from(nil)
|
240
|
+
expect(options).to be_a_kind_of(ParentOptions)
|
241
|
+
expect(options.a).to be_nil
|
242
|
+
expect(options.b).to be_nil
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'respects inheritance' do
|
246
|
+
subclass = Class.new(ParentOptions)
|
247
|
+
options = subclass.from(c: { sub_a: 'hello' })
|
248
|
+
expect(options.c).to be_a_kind_of(SubOptions)
|
249
|
+
expect(options.c.sub_a).to eq('hello')
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe '#memoized' do
|
254
|
+
subject(:options_class) { Class.new(ParentOptions) }
|
255
|
+
it 'requires block' do
|
256
|
+
expect { options_class.memoized(:a) }.to raise_error(ArgumentError)
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'accepts block' do
|
260
|
+
options_class.memoized(:a) { :foo }
|
261
|
+
expect(options_class.new.a).to eql(:foo)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe '#fetch' do
|
266
|
+
subject { SubOptions.new }
|
267
|
+
|
268
|
+
context 'when the fetched key has no value' do
|
269
|
+
it 'uses falsey default' do
|
270
|
+
expect(subject.fetch(:sub_a, false) { |_| :blah }).to be_falsey
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'accepts block' do
|
274
|
+
expect(subject.fetch(:sub_a) { |k| "yo #{k.inspect}" }).to eq('yo :sub_a')
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'needs a default if key is missing' do
|
278
|
+
expect { subject.fetch(:sub_a) }.to raise_error(Faraday::Options.fetch_error_class)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'when the fetched key has a value' do
|
283
|
+
before do
|
284
|
+
subject.sub_a = 1
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'grabs value' do
|
288
|
+
expect(subject.fetch(:sub_a, false) { |_| :blah }).to eq(1)
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'works with key' do
|
292
|
+
expect(subject.fetch(:sub_a)).to eq(1)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::ProxyOptions do
|
4
|
+
describe '#from' do
|
5
|
+
it 'works with string' do
|
6
|
+
options = Faraday::ProxyOptions.from 'http://user:pass@example.org'
|
7
|
+
expect(options.user).to eq('user')
|
8
|
+
expect(options.password).to eq('pass')
|
9
|
+
expect(options.uri).to be_a_kind_of(URI)
|
10
|
+
expect(options.path).to eq('')
|
11
|
+
expect(options.port).to eq(80)
|
12
|
+
expect(options.host).to eq('example.org')
|
13
|
+
expect(options.scheme).to eq('http')
|
14
|
+
expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'defaults to http' do
|
18
|
+
options = Faraday::ProxyOptions.from 'example.org'
|
19
|
+
expect(options.port).to eq(80)
|
20
|
+
expect(options.host).to eq('example.org')
|
21
|
+
expect(options.scheme).to eq('http')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'works with nil' do
|
25
|
+
options = Faraday::ProxyOptions.from nil
|
26
|
+
expect(options).to be_a_kind_of(Faraday::ProxyOptions)
|
27
|
+
expect(options.inspect).to eq('#<Faraday::ProxyOptions (empty)>')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'works with no auth' do
|
31
|
+
proxy = Faraday::ProxyOptions.from 'http://example.org'
|
32
|
+
expect(proxy.user).to be_nil
|
33
|
+
expect(proxy.password).to be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'allows hash access' do
|
38
|
+
proxy = Faraday::ProxyOptions.from 'http://a%40b:pw%20d@example.org'
|
39
|
+
expect(proxy.user).to eq('a@b')
|
40
|
+
expect(proxy[:user]).to eq('a@b')
|
41
|
+
expect(proxy.password).to eq('pw d')
|
42
|
+
expect(proxy[:password]).to eq('pw d')
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Faraday::RequestOptions do
|
4
|
+
subject(:options) { Faraday::RequestOptions.new }
|
5
|
+
|
6
|
+
it 'allows to set the request proxy' do
|
7
|
+
expect(options.proxy).to be_nil
|
8
|
+
|
9
|
+
expect { options[:proxy] = { booya: 1 } }.to raise_error(NoMethodError)
|
10
|
+
|
11
|
+
options[:proxy] = { user: 'user' }
|
12
|
+
expect(options.proxy).to be_a_kind_of(Faraday::ProxyOptions)
|
13
|
+
expect(options.proxy.user).to eq('user')
|
14
|
+
|
15
|
+
options.proxy = nil
|
16
|
+
expect(options.proxy).to be_nil
|
17
|
+
expect(options.inspect).to eq('#<Faraday::RequestOptions (empty)>')
|
18
|
+
end
|
19
|
+
end
|