faraday 1.0.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -1
  3. data/LICENSE.md +1 -1
  4. data/README.md +35 -23
  5. data/Rakefile +6 -1
  6. data/examples/client_spec.rb +68 -14
  7. data/examples/client_test.rb +80 -15
  8. data/lib/faraday/adapter/test.rb +117 -52
  9. data/lib/faraday/adapter.rb +7 -21
  10. data/lib/faraday/adapter_registry.rb +3 -1
  11. data/lib/faraday/connection.rb +75 -133
  12. data/lib/faraday/encoders/flat_params_encoder.rb +9 -2
  13. data/lib/faraday/encoders/nested_params_encoder.rb +20 -8
  14. data/lib/faraday/error.rb +39 -6
  15. data/lib/faraday/logging/formatter.rb +28 -15
  16. data/lib/faraday/methods.rb +6 -0
  17. data/lib/faraday/middleware.rb +59 -5
  18. data/lib/faraday/middleware_registry.rb +17 -63
  19. data/lib/faraday/options/connection_options.rb +7 -6
  20. data/lib/faraday/options/env.rb +85 -62
  21. data/lib/faraday/options/proxy_options.rb +11 -3
  22. data/lib/faraday/options/request_options.rb +7 -6
  23. data/lib/faraday/options/ssl_options.rb +56 -45
  24. data/lib/faraday/options.rb +11 -14
  25. data/lib/faraday/rack_builder.rb +35 -32
  26. data/lib/faraday/request/authorization.rb +37 -36
  27. data/lib/faraday/request/instrumentation.rb +5 -1
  28. data/lib/faraday/request/json.rb +70 -0
  29. data/lib/faraday/request/url_encoded.rb +8 -2
  30. data/lib/faraday/request.rb +22 -29
  31. data/lib/faraday/response/json.rb +74 -0
  32. data/lib/faraday/response/logger.rb +8 -4
  33. data/lib/faraday/response/raise_error.rb +43 -3
  34. data/lib/faraday/response.rb +10 -23
  35. data/lib/faraday/utils/headers.rb +17 -6
  36. data/lib/faraday/utils.rb +22 -10
  37. data/lib/faraday/version.rb +5 -0
  38. data/lib/faraday.rb +49 -58
  39. data/spec/faraday/adapter/test_spec.rb +442 -0
  40. data/spec/faraday/connection_spec.rb +207 -90
  41. data/spec/faraday/error_spec.rb +45 -5
  42. data/spec/faraday/middleware_registry_spec.rb +31 -0
  43. data/spec/faraday/middleware_spec.rb +193 -6
  44. data/spec/faraday/options/env_spec.rb +8 -2
  45. data/spec/faraday/options/options_spec.rb +1 -1
  46. data/spec/faraday/options/proxy_options_spec.rb +15 -0
  47. data/spec/faraday/params_encoders/flat_spec.rb +8 -0
  48. data/spec/faraday/params_encoders/nested_spec.rb +18 -1
  49. data/spec/faraday/rack_builder_spec.rb +171 -50
  50. data/spec/faraday/request/authorization_spec.rb +54 -24
  51. data/spec/faraday/request/instrumentation_spec.rb +5 -7
  52. data/spec/faraday/request/json_spec.rb +199 -0
  53. data/spec/faraday/request/url_encoded_spec.rb +25 -2
  54. data/spec/faraday/request_spec.rb +11 -10
  55. data/spec/faraday/response/json_spec.rb +206 -0
  56. data/spec/faraday/response/logger_spec.rb +38 -0
  57. data/spec/faraday/response/raise_error_spec.rb +149 -0
  58. data/spec/faraday/response_spec.rb +3 -1
  59. data/spec/faraday/utils/headers_spec.rb +31 -4
  60. data/spec/faraday/utils_spec.rb +63 -1
  61. data/spec/faraday_spec.rb +10 -4
  62. data/spec/spec_helper.rb +6 -5
  63. data/spec/support/fake_safe_buffer.rb +1 -1
  64. data/spec/support/faraday_middleware_subclasses.rb +18 -0
  65. data/spec/support/helper_methods.rb +0 -37
  66. data/spec/support/shared_examples/adapter.rb +4 -3
  67. data/spec/support/shared_examples/request_method.rb +60 -31
  68. metadata +34 -44
  69. data/UPGRADING.md +0 -55
  70. data/lib/faraday/adapter/em_http.rb +0 -285
  71. data/lib/faraday/adapter/em_http_ssl_patch.rb +0 -62
  72. data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +0 -69
  73. data/lib/faraday/adapter/em_synchrony.rb +0 -150
  74. data/lib/faraday/adapter/excon.rb +0 -124
  75. data/lib/faraday/adapter/httpclient.rb +0 -151
  76. data/lib/faraday/adapter/net_http.rb +0 -209
  77. data/lib/faraday/adapter/net_http_persistent.rb +0 -91
  78. data/lib/faraday/adapter/patron.rb +0 -132
  79. data/lib/faraday/adapter/rack.rb +0 -75
  80. data/lib/faraday/adapter/typhoeus.rb +0 -15
  81. data/lib/faraday/autoload.rb +0 -95
  82. data/lib/faraday/dependency_loader.rb +0 -37
  83. data/lib/faraday/file_part.rb +0 -128
  84. data/lib/faraday/param_part.rb +0 -53
  85. data/lib/faraday/request/basic_authentication.rb +0 -20
  86. data/lib/faraday/request/multipart.rb +0 -99
  87. data/lib/faraday/request/retry.rb +0 -239
  88. data/lib/faraday/request/token_authentication.rb +0 -20
  89. data/spec/faraday/adapter/em_http_spec.rb +0 -47
  90. data/spec/faraday/adapter/em_synchrony_spec.rb +0 -16
  91. data/spec/faraday/adapter/excon_spec.rb +0 -49
  92. data/spec/faraday/adapter/httpclient_spec.rb +0 -73
  93. data/spec/faraday/adapter/net_http_persistent_spec.rb +0 -57
  94. data/spec/faraday/adapter/net_http_spec.rb +0 -64
  95. data/spec/faraday/adapter/patron_spec.rb +0 -18
  96. data/spec/faraday/adapter/rack_spec.rb +0 -8
  97. data/spec/faraday/adapter/typhoeus_spec.rb +0 -7
  98. data/spec/faraday/composite_read_io_spec.rb +0 -80
  99. data/spec/faraday/request/multipart_spec.rb +0 -274
  100. data/spec/faraday/request/retry_spec.rb +0 -242
  101. data/spec/faraday/response/middleware_spec.rb +0 -52
  102. data/spec/support/webmock_rack_app.rb +0 -68
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe Faraday::ClientError do
3
+ RSpec.describe Faraday::Error do
4
4
  describe '.initialize' do
5
5
  subject { described_class.new(exception, response) }
6
6
  let(:response) { nil }
@@ -12,7 +12,10 @@ RSpec.describe Faraday::ClientError do
12
12
  it { expect(subject.response).to be_nil }
13
13
  it { expect(subject.message).to eq(exception.message) }
14
14
  it { expect(subject.backtrace).to eq(exception.backtrace) }
15
- it { expect(subject.inspect).to eq('#<Faraday::ClientError wrapped=#<RuntimeError: test>>') }
15
+ it { expect(subject.inspect).to eq('#<Faraday::Error wrapped=#<RuntimeError: test>>') }
16
+ it { expect(subject.response_status).to be_nil }
17
+ it { expect(subject.response_headers).to be_nil }
18
+ it { expect(subject.response_body).to be_nil }
16
19
  end
17
20
 
18
21
  context 'with response hash' do
@@ -21,7 +24,10 @@ RSpec.describe Faraday::ClientError do
21
24
  it { expect(subject.wrapped_exception).to be_nil }
22
25
  it { expect(subject.response).to eq(exception) }
23
26
  it { expect(subject.message).to eq('the server responded with status 400') }
24
- it { expect(subject.inspect).to eq('#<Faraday::ClientError response={:status=>400}>') }
27
+ it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
28
+ it { expect(subject.response_status).to eq(400) }
29
+ it { expect(subject.response_headers).to be_nil }
30
+ it { expect(subject.response_body).to be_nil }
25
31
  end
26
32
 
27
33
  context 'with string' do
@@ -30,7 +36,10 @@ RSpec.describe Faraday::ClientError do
30
36
  it { expect(subject.wrapped_exception).to be_nil }
31
37
  it { expect(subject.response).to be_nil }
32
38
  it { expect(subject.message).to eq('custom message') }
33
- it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: custom message>>') }
39
+ it { expect(subject.inspect).to eq('#<Faraday::Error #<Faraday::Error: custom message>>') }
40
+ it { expect(subject.response_status).to be_nil }
41
+ it { expect(subject.response_headers).to be_nil }
42
+ it { expect(subject.response_body).to be_nil }
34
43
  end
35
44
 
36
45
  context 'with anything else #to_s' do
@@ -39,7 +48,38 @@ RSpec.describe Faraday::ClientError do
39
48
  it { expect(subject.wrapped_exception).to be_nil }
40
49
  it { expect(subject.response).to be_nil }
41
50
  it { expect(subject.message).to eq('["error1", "error2"]') }
42
- it { expect(subject.inspect).to eq('#<Faraday::ClientError #<Faraday::ClientError: ["error1", "error2"]>>') }
51
+ it { expect(subject.inspect).to eq('#<Faraday::Error #<Faraday::Error: ["error1", "error2"]>>') }
52
+ it { expect(subject.response_status).to be_nil }
53
+ it { expect(subject.response_headers).to be_nil }
54
+ it { expect(subject.response_body).to be_nil }
55
+ end
56
+
57
+ context 'with exception string and response hash' do
58
+ let(:exception) { 'custom message' }
59
+ let(:response) { { status: 400 } }
60
+
61
+ it { expect(subject.wrapped_exception).to be_nil }
62
+ it { expect(subject.response).to eq(response) }
63
+ it { expect(subject.message).to eq('custom message') }
64
+ it { expect(subject.inspect).to eq('#<Faraday::Error response={:status=>400}>') }
65
+ it { expect(subject.response_status).to eq(400) }
66
+ it { expect(subject.response_headers).to be_nil }
67
+ it { expect(subject.response_body).to be_nil }
68
+ end
69
+
70
+ context 'with exception and response object' do
71
+ let(:exception) { RuntimeError.new('test') }
72
+ let(:body) { { test: 'test' } }
73
+ let(:headers) { { 'Content-Type' => 'application/json' } }
74
+ let(:response) { Faraday::Response.new(status: 400, response_headers: headers, response_body: body) }
75
+
76
+ it { expect(subject.wrapped_exception).to eq(exception) }
77
+ it { expect(subject.response).to eq(response) }
78
+ it { expect(subject.message).to eq(exception.message) }
79
+ it { expect(subject.backtrace).to eq(exception.backtrace) }
80
+ it { expect(subject.response_status).to eq(400) }
81
+ it { expect(subject.response_headers).to eq(headers) }
82
+ it { expect(subject.response_body).to eq(body) }
43
83
  end
44
84
  end
45
85
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Faraday::MiddlewareRegistry do
4
+ before do
5
+ stub_const('CustomMiddleware', custom_middleware_klass)
6
+ end
7
+ let(:custom_middleware_klass) { Class.new(Faraday::Middleware) }
8
+ let(:dummy) { Class.new { extend Faraday::MiddlewareRegistry } }
9
+
10
+ after { dummy.unregister_middleware(:custom) }
11
+
12
+ it 'allows to register with constant' do
13
+ dummy.register_middleware(custom: custom_middleware_klass)
14
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
15
+ end
16
+
17
+ it 'allows to register with symbol' do
18
+ dummy.register_middleware(custom: :CustomMiddleware)
19
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
20
+ end
21
+
22
+ it 'allows to register with string' do
23
+ dummy.register_middleware(custom: 'CustomMiddleware')
24
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
25
+ end
26
+
27
+ it 'allows to register with Proc' do
28
+ dummy.register_middleware(custom: -> { custom_middleware_klass })
29
+ expect(dummy.lookup_middleware(:custom)).to eq(custom_middleware_klass)
30
+ end
31
+ end
@@ -2,25 +2,212 @@
2
2
 
3
3
  RSpec.describe Faraday::Middleware do
4
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 '#on_error' do
37
+ subject do
38
+ Class.new(described_class) do
39
+ def on_error(error)
40
+ # do nothing
41
+ end
42
+ end.new(app)
43
+ end
44
+
45
+ it 'is called by #call' do
46
+ expect(app).to receive(:call).and_raise(Faraday::ConnectionFailed)
47
+ is_expected.to receive(:call).and_call_original
48
+ is_expected.to receive(:on_error)
49
+
50
+ expect { subject.call(double) }.to raise_error(Faraday::ConnectionFailed)
51
+ end
52
+ end
5
53
 
6
54
  describe '#close' do
7
55
  context "with app that doesn't support \#close" do
8
- let(:app) { double }
9
-
10
56
  it 'should issue warning' do
11
- expect(subject).to receive(:warn)
57
+ is_expected.to receive(:warn)
12
58
  subject.close
13
59
  end
14
60
  end
15
61
 
16
62
  context "with app that supports \#close" do
17
- let(:app) { double }
18
-
19
63
  it 'should issue warning' do
20
64
  expect(app).to receive(:close)
21
- expect(subject).to_not receive(:warn)
65
+ is_expected.to_not receive(:warn)
22
66
  subject.close
23
67
  end
24
68
  end
25
69
  end
70
+
71
+ describe '::default_options' do
72
+ let(:subclass_no_options) { FaradayMiddlewareSubclasses::SubclassNoOptions }
73
+ let(:subclass_one_option) { FaradayMiddlewareSubclasses::SubclassOneOption }
74
+ let(:subclass_two_options) { FaradayMiddlewareSubclasses::SubclassTwoOptions }
75
+
76
+ def build_conn(resp_middleware)
77
+ Faraday.new do |c|
78
+ c.adapter :test do |stub|
79
+ stub.get('/success') { [200, {}, 'ok'] }
80
+ end
81
+ c.response resp_middleware
82
+ end
83
+ end
84
+
85
+ RSpec.shared_context 'reset @default_options' do
86
+ before(:each) do
87
+ FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
88
+ FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
89
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
90
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
91
+ end
92
+ end
93
+
94
+ after(:all) do
95
+ FaradayMiddlewareSubclasses::SubclassNoOptions.instance_variable_set(:@default_options, nil)
96
+ FaradayMiddlewareSubclasses::SubclassOneOption.instance_variable_set(:@default_options, nil)
97
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.instance_variable_set(:@default_options, nil)
98
+ Faraday::Middleware.instance_variable_set(:@default_options, nil)
99
+ end
100
+
101
+ context 'with subclass DEFAULT_OPTIONS defined' do
102
+ include_context 'reset @default_options'
103
+
104
+ context 'and without application options configured' do
105
+ let(:resp1) { build_conn(:one_option).get('/success') }
106
+
107
+ it 'has only subclass defaults' do
108
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
109
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
110
+ expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
111
+ expect(subclass_two_options.default_options).to eq(subclass_two_options::DEFAULT_OPTIONS)
112
+ end
113
+
114
+ it { expect(resp1.body).to eq('ok') }
115
+ end
116
+
117
+ context "and with one application's options changed" do
118
+ let(:resp2) { build_conn(:two_options).get('/success') }
119
+
120
+ before(:each) do
121
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
122
+ end
123
+
124
+ it 'only updates default options of target subclass' do
125
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
126
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
127
+ expect(subclass_one_option.default_options).to eq(subclass_one_option::DEFAULT_OPTIONS)
128
+ expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
129
+ end
130
+
131
+ it { expect(resp2.body).to eq('ok') }
132
+ end
133
+
134
+ context "and with two applications' options changed" do
135
+ let(:resp1) { build_conn(:one_option).get('/success') }
136
+ let(:resp2) { build_conn(:two_options).get('/success') }
137
+
138
+ before(:each) do
139
+ FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
140
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
141
+ end
142
+
143
+ it 'updates subclasses and parent independent of each other' do
144
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
145
+ expect(subclass_no_options.default_options).to eq(subclass_no_options::DEFAULT_OPTIONS)
146
+ expect(subclass_one_option.default_options).to eq({ some_other_option: true })
147
+ expect(subclass_two_options.default_options).to eq({ some_option: false, some_other_option: false })
148
+ end
149
+
150
+ it { expect(resp1.body).to eq('ok') }
151
+ it { expect(resp2.body).to eq('ok') }
152
+ end
153
+ end
154
+
155
+ context 'with FARADAY::MIDDLEWARE DEFAULT_OPTIONS and with Subclass DEFAULT_OPTIONS' do
156
+ before(:each) do
157
+ stub_const('Faraday::Middleware::DEFAULT_OPTIONS', { its_magic: false })
158
+ end
159
+
160
+ # Must stub Faraday::Middleware::DEFAULT_OPTIONS before resetting default options
161
+ include_context 'reset @default_options'
162
+
163
+ context 'and without application options configured' do
164
+ let(:resp1) { build_conn(:one_option).get('/success') }
165
+
166
+ it 'has only subclass defaults' do
167
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
168
+ expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
169
+ expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: false })
170
+ expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: true, some_other_option: false })
171
+ end
172
+
173
+ it { expect(resp1.body).to eq('ok') }
174
+ end
175
+
176
+ context "and with two applications' options changed" do
177
+ let(:resp1) { build_conn(:one_option).get('/success') }
178
+ let(:resp2) { build_conn(:two_options).get('/success') }
179
+
180
+ before(:each) do
181
+ FaradayMiddlewareSubclasses::SubclassOneOption.default_options = { some_other_option: true }
182
+ FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options = { some_option: false }
183
+ end
184
+
185
+ it 'updates subclasses and parent independent of each other' do
186
+ expect(Faraday::Middleware.default_options).to eq(Faraday::Middleware::DEFAULT_OPTIONS)
187
+ expect(FaradayMiddlewareSubclasses::SubclassNoOptions.default_options).to eq({ its_magic: false })
188
+ expect(FaradayMiddlewareSubclasses::SubclassOneOption.default_options).to eq({ its_magic: false, some_other_option: true })
189
+ expect(FaradayMiddlewareSubclasses::SubclassTwoOptions.default_options).to eq({ its_magic: false, some_option: false, some_other_option: false })
190
+ end
191
+
192
+ it { expect(resp1.body).to eq('ok') }
193
+ it { expect(resp2.body).to eq('ok') }
194
+ end
195
+ end
196
+
197
+ describe 'default_options input validation' do
198
+ include_context 'reset @default_options'
199
+
200
+ it 'raises error if Faraday::Middleware option does not exist' do
201
+ expect { Faraday::Middleware.default_options = { something_special: true } }.to raise_error(Faraday::InitializationError) do |e|
202
+ expect(e.message).to eq('Invalid options provided. Keys not found in Faraday::Middleware::DEFAULT_OPTIONS: something_special')
203
+ end
204
+ end
205
+
206
+ it 'raises error if subclass option does not exist' do
207
+ expect { subclass_one_option.default_options = { this_is_a_typo: true } }.to raise_error(Faraday::InitializationError) do |e|
208
+ expect(e.message).to eq('Invalid options provided. Keys not found in FaradayMiddlewareSubclasses::SubclassOneOption::DEFAULT_OPTIONS: this_is_a_typo')
209
+ end
210
+ end
211
+ end
212
+ end
26
213
  end
@@ -27,14 +27,20 @@ RSpec.describe Faraday::Env do
27
27
  expect(ssl.fetch(:verify, true)).to be_falsey
28
28
  end
29
29
 
30
+ it 'handle verify_hostname when fetching' do
31
+ ssl = Faraday::SSLOptions.new
32
+ ssl.verify_hostname = true
33
+ expect(ssl.fetch(:verify_hostname, false)).to be_truthy
34
+ end
35
+
30
36
  it 'retains custom members' do
31
37
  env[:foo] = 'custom 1'
32
- env[:bar] = :custom_2
38
+ env[:bar] = :custom2
33
39
  env2 = Faraday::Env.from(env)
34
40
  env2[:baz] = 'custom 3'
35
41
 
36
42
  expect(env2[:foo]).to eq('custom 1')
37
- expect(env2[:bar]).to eq(:custom_2)
43
+ expect(env2[:bar]).to eq(:custom2)
38
44
  expect(env[:baz]).to be_nil
39
45
  end
40
46
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  RSpec.describe Faraday::Options do
4
4
  SubOptions = Class.new(Faraday::Options.new(:sub_a, :sub_b))
5
- class ParentOptions < Faraday::Options.new(:a, :b, :c)
5
+ ParentOptions = Faraday::Options.new(:a, :b, :c) do
6
6
  options c: SubOptions
7
7
  end
8
8
 
@@ -14,6 +14,13 @@ RSpec.describe Faraday::ProxyOptions do
14
14
  expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
15
15
  end
16
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
+
17
24
  it 'works with nil' do
18
25
  options = Faraday::ProxyOptions.from nil
19
26
  expect(options).to be_a_kind_of(Faraday::ProxyOptions)
@@ -25,6 +32,14 @@ RSpec.describe Faraday::ProxyOptions do
25
32
  expect(proxy.user).to be_nil
26
33
  expect(proxy.password).to be_nil
27
34
  end
35
+
36
+ it 'treats empty string as nil' do
37
+ proxy = nil
38
+ proxy_string = proxy.to_s # => empty string
39
+ options = Faraday::ProxyOptions.from proxy_string
40
+ expect(options).to be_a_kind_of(Faraday::ProxyOptions)
41
+ expect(options.inspect).to eq('#<Faraday::ProxyOptions (empty)>')
42
+ end
28
43
  end
29
44
 
30
45
  it 'allows hash access' do
@@ -31,4 +31,12 @@ RSpec.describe Faraday::FlatParamsEncoder do
31
31
  params = { a: [] }
32
32
  expect(subject.encode(params)).to eq('a=')
33
33
  end
34
+
35
+ it 'encodes unsorted when asked' do
36
+ params = { b: false, a: true }
37
+ expect(subject.encode(params)).to eq('a=true&b=false')
38
+ Faraday::FlatParamsEncoder.sort_params = false
39
+ expect(subject.encode(params)).to eq('b=false&a=true')
40
+ Faraday::FlatParamsEncoder.sort_params = true
41
+ end
34
42
  end
@@ -62,7 +62,8 @@ RSpec.describe Faraday::NestedParamsEncoder do
62
62
  it 'encodes rack compat' do
63
63
  params = { a: [{ one: '1', two: '2' }, '3', ''] }
64
64
  result = Faraday::Utils.unescape(Faraday::NestedParamsEncoder.encode(params)).split('&')
65
- expected = Rack::Utils.build_nested_query(params).split('&')
65
+ escaped = Rack::Utils.build_nested_query(params)
66
+ expected = Rack::Utils.unescape(escaped).split('&')
66
67
  expect(result).to match_array(expected)
67
68
  end
68
69
 
@@ -94,6 +95,22 @@ RSpec.describe Faraday::NestedParamsEncoder do
94
95
  expect(subject.encode(params)).to eq('a%5B%5D=true&a%5B%5D=false')
95
96
  end
96
97
 
98
+ it 'encodes unsorted when asked' do
99
+ params = { b: false, a: true }
100
+ expect(subject.encode(params)).to eq('a=true&b=false')
101
+ Faraday::NestedParamsEncoder.sort_params = false
102
+ expect(subject.encode(params)).to eq('b=false&a=true')
103
+ Faraday::NestedParamsEncoder.sort_params = true
104
+ end
105
+
106
+ it 'encodes arrays indices when asked' do
107
+ params = { a: [0, 1, 2] }
108
+ expect(subject.encode(params)).to eq('a%5B%5D=0&a%5B%5D=1&a%5B%5D=2')
109
+ Faraday::NestedParamsEncoder.array_indices = true
110
+ expect(subject.encode(params)).to eq('a%5B0%5D=0&a%5B1%5D=1&a%5B2%5D=2')
111
+ Faraday::NestedParamsEncoder.array_indices = false
112
+ end
113
+
97
114
  shared_examples 'a wrong decoding' do
98
115
  it do
99
116
  expect { subject.decode(query) }.to raise_error(TypeError) do |e|