faraday 1.0.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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|