nano-sharp-sys 0.0.1

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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/faraday-2.14.3/CHANGELOG.md +574 -0
  3. data/faraday-2.14.3/LICENSE.md +20 -0
  4. data/faraday-2.14.3/README.md +67 -0
  5. data/faraday-2.14.3/Rakefile +12 -0
  6. data/faraday-2.14.3/examples/client_spec.rb +119 -0
  7. data/faraday-2.14.3/examples/client_test.rb +144 -0
  8. data/faraday-2.14.3/lib/faraday/adapter/test.rb +319 -0
  9. data/faraday-2.14.3/lib/faraday/adapter.rb +102 -0
  10. data/faraday-2.14.3/lib/faraday/adapter_registry.rb +30 -0
  11. data/faraday-2.14.3/lib/faraday/connection.rb +567 -0
  12. data/faraday-2.14.3/lib/faraday/encoders/flat_params_encoder.rb +106 -0
  13. data/faraday-2.14.3/lib/faraday/encoders/nested_params_encoder.rb +193 -0
  14. data/faraday-2.14.3/lib/faraday/error.rb +202 -0
  15. data/faraday-2.14.3/lib/faraday/logging/formatter.rb +118 -0
  16. data/faraday-2.14.3/lib/faraday/methods.rb +6 -0
  17. data/faraday-2.14.3/lib/faraday/middleware.rb +72 -0
  18. data/faraday-2.14.3/lib/faraday/middleware_registry.rb +83 -0
  19. data/faraday-2.14.3/lib/faraday/options/connection_options.rb +23 -0
  20. data/faraday-2.14.3/lib/faraday/options/env.rb +204 -0
  21. data/faraday-2.14.3/lib/faraday/options/proxy_options.rb +39 -0
  22. data/faraday-2.14.3/lib/faraday/options/request_options.rb +23 -0
  23. data/faraday-2.14.3/lib/faraday/options/ssl_options.rb +76 -0
  24. data/faraday-2.14.3/lib/faraday/options.rb +219 -0
  25. data/faraday-2.14.3/lib/faraday/parameters.rb +5 -0
  26. data/faraday-2.14.3/lib/faraday/rack_builder.rb +248 -0
  27. data/faraday-2.14.3/lib/faraday/request/authorization.rb +54 -0
  28. data/faraday-2.14.3/lib/faraday/request/instrumentation.rb +58 -0
  29. data/faraday-2.14.3/lib/faraday/request/json.rb +70 -0
  30. data/faraday-2.14.3/lib/faraday/request/url_encoded.rb +60 -0
  31. data/faraday-2.14.3/lib/faraday/request.rb +139 -0
  32. data/faraday-2.14.3/lib/faraday/response/json.rb +74 -0
  33. data/faraday-2.14.3/lib/faraday/response/logger.rb +39 -0
  34. data/faraday-2.14.3/lib/faraday/response/raise_error.rb +83 -0
  35. data/faraday-2.14.3/lib/faraday/response.rb +95 -0
  36. data/faraday-2.14.3/lib/faraday/utils/headers.rb +150 -0
  37. data/faraday-2.14.3/lib/faraday/utils/params_hash.rb +61 -0
  38. data/faraday-2.14.3/lib/faraday/utils.rb +121 -0
  39. data/faraday-2.14.3/lib/faraday/version.rb +5 -0
  40. data/faraday-2.14.3/lib/faraday.rb +158 -0
  41. data/faraday-2.14.3/spec/external_adapters/faraday_specs_setup.rb +14 -0
  42. data/faraday-2.14.3/spec/faraday/adapter/test_spec.rb +460 -0
  43. data/faraday-2.14.3/spec/faraday/adapter_registry_spec.rb +28 -0
  44. data/faraday-2.14.3/spec/faraday/adapter_spec.rb +55 -0
  45. data/faraday-2.14.3/spec/faraday/connection_spec.rb +860 -0
  46. data/faraday-2.14.3/spec/faraday/error_spec.rb +175 -0
  47. data/faraday-2.14.3/spec/faraday/middleware_registry_spec.rb +31 -0
  48. data/faraday-2.14.3/spec/faraday/middleware_spec.rb +213 -0
  49. data/faraday-2.14.3/spec/faraday/options/env_spec.rb +76 -0
  50. data/faraday-2.14.3/spec/faraday/options/options_spec.rb +297 -0
  51. data/faraday-2.14.3/spec/faraday/options/proxy_options_spec.rb +79 -0
  52. data/faraday-2.14.3/spec/faraday/options/request_options_spec.rb +19 -0
  53. data/faraday-2.14.3/spec/faraday/params_encoders/flat_spec.rb +42 -0
  54. data/faraday-2.14.3/spec/faraday/params_encoders/nested_spec.rb +179 -0
  55. data/faraday-2.14.3/spec/faraday/rack_builder_spec.rb +317 -0
  56. data/faraday-2.14.3/spec/faraday/request/authorization_spec.rb +118 -0
  57. data/faraday-2.14.3/spec/faraday/request/instrumentation_spec.rb +74 -0
  58. data/faraday-2.14.3/spec/faraday/request/json_spec.rb +199 -0
  59. data/faraday-2.14.3/spec/faraday/request/url_encoded_spec.rb +93 -0
  60. data/faraday-2.14.3/spec/faraday/request_spec.rb +119 -0
  61. data/faraday-2.14.3/spec/faraday/response/json_spec.rb +206 -0
  62. data/faraday-2.14.3/spec/faraday/response/logger_spec.rb +299 -0
  63. data/faraday-2.14.3/spec/faraday/response/raise_error_spec.rb +286 -0
  64. data/faraday-2.14.3/spec/faraday/response_spec.rb +84 -0
  65. data/faraday-2.14.3/spec/faraday/utils/headers_spec.rb +109 -0
  66. data/faraday-2.14.3/spec/faraday/utils_spec.rb +120 -0
  67. data/faraday-2.14.3/spec/faraday_spec.rb +43 -0
  68. data/faraday-2.14.3/spec/spec_helper.rb +133 -0
  69. data/faraday-2.14.3/spec/support/disabling_stub.rb +14 -0
  70. data/faraday-2.14.3/spec/support/fake_safe_buffer.rb +15 -0
  71. data/faraday-2.14.3/spec/support/faraday_middleware_subclasses.rb +18 -0
  72. data/faraday-2.14.3/spec/support/helper_methods.rb +96 -0
  73. data/faraday-2.14.3/spec/support/shared_examples/adapter.rb +105 -0
  74. data/faraday-2.14.3/spec/support/shared_examples/params_encoder.rb +18 -0
  75. data/faraday-2.14.3/spec/support/shared_examples/request_method.rb +263 -0
  76. data/faraday-2.14.3/spec/support/streaming_response_checker.rb +35 -0
  77. data/nano-sharp-sys.gemspec +12 -0
  78. metadata +117 -0
@@ -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
+ ParentOptions = Faraday::Options.new(:a, :b, :c) do
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,79 @@
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 hash' do
31
+ hash = { user: 'user', password: 'pass', uri: 'http://@example.org' }
32
+ options = Faraday::ProxyOptions.from(hash)
33
+ expect(options.user).to eq('user')
34
+ expect(options.password).to eq('pass')
35
+ expect(options.uri).to be_a_kind_of(URI)
36
+ expect(options.path).to eq('')
37
+ expect(options.port).to eq(80)
38
+ expect(options.host).to eq('example.org')
39
+ expect(options.scheme).to eq('http')
40
+ expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
41
+ end
42
+
43
+ it 'works with option' do
44
+ opt_arg = { user: 'user', password: 'pass', uri: 'http://@example.org' }
45
+ option = Faraday::ConnectionOptions.from(proxy: opt_arg)
46
+ options = Faraday::ProxyOptions.from(option.proxy)
47
+ expect(options.user).to eq('user')
48
+ expect(options.password).to eq('pass')
49
+ expect(options.uri).to be_a_kind_of(URI)
50
+ expect(options.path).to eq('')
51
+ expect(options.port).to eq(80)
52
+ expect(options.host).to eq('example.org')
53
+ expect(options.scheme).to eq('http')
54
+ expect(options.inspect).to match('#<Faraday::ProxyOptions uri=')
55
+ end
56
+
57
+ it 'works with no auth' do
58
+ proxy = Faraday::ProxyOptions.from 'http://example.org'
59
+ expect(proxy.user).to be_nil
60
+ expect(proxy.password).to be_nil
61
+ end
62
+
63
+ it 'treats empty string as nil' do
64
+ proxy = nil
65
+ proxy_string = proxy.to_s # => empty string
66
+ options = Faraday::ProxyOptions.from proxy_string
67
+ expect(options).to be_a_kind_of(Faraday::ProxyOptions)
68
+ expect(options.inspect).to eq('#<Faraday::ProxyOptions (empty)>')
69
+ end
70
+ end
71
+
72
+ it 'allows hash access' do
73
+ proxy = Faraday::ProxyOptions.from 'http://a%40b:pw%20d@example.org'
74
+ expect(proxy.user).to eq('a@b')
75
+ expect(proxy[:user]).to eq('a@b')
76
+ expect(proxy.password).to eq('pw d')
77
+ expect(proxy[:password]).to eq('pw d')
78
+ end
79
+ 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
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/utils'
4
+
5
+ RSpec.describe Faraday::FlatParamsEncoder do
6
+ it_behaves_like 'a params encoder'
7
+
8
+ it 'decodes arrays' do
9
+ query = 'a=one&a=two&a=three'
10
+ expected = { 'a' => %w[one two three] }
11
+ expect(subject.decode(query)).to eq(expected)
12
+ end
13
+
14
+ it 'decodes boolean values' do
15
+ query = 'a=true&b=false'
16
+ expected = { 'a' => 'true', 'b' => 'false' }
17
+ expect(subject.decode(query)).to eq(expected)
18
+ end
19
+
20
+ it 'encodes boolean values' do
21
+ params = { a: true, b: false }
22
+ expect(subject.encode(params)).to eq('a=true&b=false')
23
+ end
24
+
25
+ it 'encodes boolean values in array' do
26
+ params = { a: [true, false] }
27
+ expect(subject.encode(params)).to eq('a=true&a=false')
28
+ end
29
+
30
+ it 'encodes empty array in hash' do
31
+ params = { a: [] }
32
+ expect(subject.encode(params)).to eq('a=')
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
42
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/utils'
4
+
5
+ RSpec.describe Faraday::NestedParamsEncoder do
6
+ it_behaves_like 'a params encoder'
7
+
8
+ around do |example|
9
+ original_param_depth_limit = described_class.param_depth_limit
10
+ example.run
11
+ ensure
12
+ described_class.param_depth_limit = original_param_depth_limit
13
+ end
14
+
15
+ it 'decodes arrays' do
16
+ query = 'a[1]=one&a[2]=two&a[3]=three'
17
+ expected = { 'a' => %w[one two three] }
18
+ expect(subject.decode(query)).to eq(expected)
19
+ end
20
+
21
+ it 'decodes hashes' do
22
+ query = 'a[b1]=one&a[b2]=two&a[b][c]=foo'
23
+ expected = { 'a' => { 'b1' => 'one', 'b2' => 'two', 'b' => { 'c' => 'foo' } } }
24
+ expect(subject.decode(query)).to eq(expected)
25
+ end
26
+
27
+ it 'decodes nested arrays rack compat' do
28
+ query = 'a[][one]=1&a[][two]=2&a[][one]=3&a[][two]=4'
29
+ expected = Rack::Utils.parse_nested_query(query)
30
+ expect(subject.decode(query)).to eq(expected)
31
+ end
32
+
33
+ it 'decodes nested array mixed types' do
34
+ query = 'a[][one]=1&a[]=2&a[]=&a[]'
35
+ expected = Rack::Utils.parse_nested_query(query)
36
+ expect(subject.decode(query)).to eq(expected)
37
+ end
38
+
39
+ it 'decodes nested ignores invalid array' do
40
+ query = '[][a]=1&b=2'
41
+ expected = { 'a' => '1', 'b' => '2' }
42
+ expect(subject.decode(query)).to eq(expected)
43
+ end
44
+
45
+ it 'decodes nested ignores repeated array notation' do
46
+ query = 'a[][][]=1'
47
+ expected = { 'a' => ['1'] }
48
+ expect(subject.decode(query)).to eq(expected)
49
+ end
50
+
51
+ it 'decodes nested ignores malformed keys' do
52
+ query = '=1&[]=2'
53
+ expected = {}
54
+ expect(subject.decode(query)).to eq(expected)
55
+ end
56
+
57
+ it 'decodes nested subkeys dont have to be in brackets' do
58
+ query = 'a[b]c[d]e=1'
59
+ expected = { 'a' => { 'b' => { 'c' => { 'd' => { 'e' => '1' } } } } }
60
+ expect(subject.decode(query)).to eq(expected)
61
+ end
62
+
63
+ it 'allows nested params within the configured depth limit' do
64
+ described_class.param_depth_limit = 3
65
+
66
+ expect(subject.decode('a[b][c]=1')).to eq({ 'a' => { 'b' => { 'c' => '1' } } })
67
+ end
68
+
69
+ it 'raises a controlled error when nested params exceed the depth limit' do
70
+ described_class.param_depth_limit = 2
71
+
72
+ expect { subject.decode('a[b][c]=1') }.to raise_error(
73
+ Faraday::Error,
74
+ 'exceeded nested parameter depth limit of 2'
75
+ )
76
+ end
77
+
78
+ it 'allows disabling the nested params depth limit' do
79
+ described_class.param_depth_limit = nil
80
+
81
+ expect(subject.decode('a[b][c][d]=1')).to eq({ 'a' => { 'b' => { 'c' => { 'd' => '1' } } } })
82
+ end
83
+
84
+ it 'decodes nested final value overrides any type' do
85
+ query = 'a[b][c]=1&a[b]=2'
86
+ expected = { 'a' => { 'b' => '2' } }
87
+ expect(subject.decode(query)).to eq(expected)
88
+ end
89
+
90
+ it 'encodes rack compat' do
91
+ params = { a: [{ one: '1', two: '2' }, '3', ''] }
92
+ result = Faraday::Utils.unescape(Faraday::NestedParamsEncoder.encode(params)).split('&')
93
+ escaped = Rack::Utils.build_nested_query(params)
94
+ expected = Rack::Utils.unescape(escaped).split('&')
95
+ expect(result).to match_array(expected)
96
+ end
97
+
98
+ it 'encodes empty string array value' do
99
+ expected = 'baz=&foo%5Bbar%5D='
100
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: '' }, baz: '')
101
+ expect(result).to eq(expected)
102
+ end
103
+
104
+ it 'encodes nil array value' do
105
+ expected = 'baz&foo%5Bbar%5D'
106
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: nil }, baz: nil)
107
+ expect(result).to eq(expected)
108
+ end
109
+
110
+ it 'encodes empty array value' do
111
+ expected = 'baz%5B%5D&foo%5Bbar%5D%5B%5D'
112
+ result = Faraday::NestedParamsEncoder.encode(foo: { bar: [] }, baz: [])
113
+ expect(result).to eq(expected)
114
+ end
115
+
116
+ it 'encodes boolean values' do
117
+ params = { a: true, b: false }
118
+ expect(subject.encode(params)).to eq('a=true&b=false')
119
+ end
120
+
121
+ it 'encodes boolean values in array' do
122
+ params = { a: [true, false] }
123
+ expect(subject.encode(params)).to eq('a%5B%5D=true&a%5B%5D=false')
124
+ end
125
+
126
+ it 'encodes unsorted when asked' do
127
+ params = { b: false, a: true }
128
+ expect(subject.encode(params)).to eq('a=true&b=false')
129
+ Faraday::NestedParamsEncoder.sort_params = false
130
+ expect(subject.encode(params)).to eq('b=false&a=true')
131
+ Faraday::NestedParamsEncoder.sort_params = true
132
+ end
133
+
134
+ it 'encodes arrays indices when asked' do
135
+ params = { a: [0, 1, 2] }
136
+ expect(subject.encode(params)).to eq('a%5B%5D=0&a%5B%5D=1&a%5B%5D=2')
137
+ Faraday::NestedParamsEncoder.array_indices = true
138
+ expect(subject.encode(params)).to eq('a%5B0%5D=0&a%5B1%5D=1&a%5B2%5D=2')
139
+ Faraday::NestedParamsEncoder.array_indices = false
140
+ end
141
+
142
+ shared_examples 'a wrong decoding' do
143
+ it do
144
+ expect { subject.decode(query) }.to raise_error(TypeError) do |e|
145
+ expect(e.message).to eq(error_message)
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'when expecting hash but getting string' do
151
+ let(:query) { 'a=1&a[b]=2' }
152
+ let(:error_message) { "expected Hash (got String) for param `a'" }
153
+ it_behaves_like 'a wrong decoding'
154
+ end
155
+
156
+ context 'when expecting hash but getting array' do
157
+ let(:query) { 'a[]=1&a[b]=2' }
158
+ let(:error_message) { "expected Hash (got Array) for param `a'" }
159
+ it_behaves_like 'a wrong decoding'
160
+ end
161
+
162
+ context 'when expecting nested hash but getting non nested' do
163
+ let(:query) { 'a[b]=1&a[b][c]=2' }
164
+ let(:error_message) { "expected Hash (got String) for param `b'" }
165
+ it_behaves_like 'a wrong decoding'
166
+ end
167
+
168
+ context 'when expecting array but getting hash' do
169
+ let(:query) { 'a[b]=1&a[]=2' }
170
+ let(:error_message) { "expected Array (got Hash) for param `a'" }
171
+ it_behaves_like 'a wrong decoding'
172
+ end
173
+
174
+ context 'when expecting array but getting string' do
175
+ let(:query) { 'a=1&a[]=2' }
176
+ let(:error_message) { "expected Array (got String) for param `a'" }
177
+ it_behaves_like 'a wrong decoding'
178
+ end
179
+ end