ethon 0.15.0 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -1
- data/README.md +23 -0
- data/ethon.gemspec +6 -3
- data/lib/ethon/curls/classes.rb +12 -2
- data/lib/ethon/curls/codes.rb +3 -2
- data/lib/ethon/curls/options.rb +4 -3
- data/lib/ethon/easy/callbacks.rb +2 -1
- data/lib/ethon/easy/informations.rb +3 -0
- data/lib/ethon/easy/response_callbacks.rb +6 -1
- data/lib/ethon/version.rb +1 -1
- metadata +6 -85
- data/.github/workflows/ruby.yml +0 -41
- data/.gitignore +0 -8
- data/.rspec +0 -3
- data/Gemfile +0 -43
- data/Guardfile +0 -10
- data/Rakefile +0 -40
- data/profile/benchmarks.rb +0 -104
- data/profile/memory_leaks.rb +0 -114
- data/profile/perf_spec_helper.rb +0 -37
- data/profile/support/memory_test_helpers.rb +0 -76
- data/profile/support/os_memory_leak_tracker.rb +0 -48
- data/profile/support/ruby_object_leak_tracker.rb +0 -49
- data/spec/ethon/curl_spec.rb +0 -38
- data/spec/ethon/easy/callbacks_spec.rb +0 -59
- data/spec/ethon/easy/debug_info_spec.rb +0 -54
- data/spec/ethon/easy/features_spec.rb +0 -24
- data/spec/ethon/easy/form_spec.rb +0 -104
- data/spec/ethon/easy/header_spec.rb +0 -79
- data/spec/ethon/easy/http/custom_spec.rb +0 -177
- data/spec/ethon/easy/http/delete_spec.rb +0 -21
- data/spec/ethon/easy/http/get_spec.rb +0 -126
- data/spec/ethon/easy/http/head_spec.rb +0 -80
- data/spec/ethon/easy/http/options_spec.rb +0 -51
- data/spec/ethon/easy/http/patch_spec.rb +0 -51
- data/spec/ethon/easy/http/post_spec.rb +0 -317
- data/spec/ethon/easy/http/put_spec.rb +0 -168
- data/spec/ethon/easy/http_spec.rb +0 -64
- data/spec/ethon/easy/informations_spec.rb +0 -120
- data/spec/ethon/easy/mirror_spec.rb +0 -47
- data/spec/ethon/easy/operations_spec.rb +0 -268
- data/spec/ethon/easy/options_spec.rb +0 -193
- data/spec/ethon/easy/queryable_spec.rb +0 -235
- data/spec/ethon/easy/response_callbacks_spec.rb +0 -152
- data/spec/ethon/easy/util_spec.rb +0 -28
- data/spec/ethon/easy_spec.rb +0 -203
- data/spec/ethon/libc_spec.rb +0 -14
- data/spec/ethon/loggable_spec.rb +0 -22
- data/spec/ethon/multi/operations_spec.rb +0 -298
- data/spec/ethon/multi/options_spec.rb +0 -182
- data/spec/ethon/multi/stack_spec.rb +0 -80
- data/spec/ethon/multi_spec.rb +0 -152
- data/spec/spec_helper.rb +0 -28
- data/spec/support/localhost_server.rb +0 -95
- data/spec/support/server.rb +0 -115
@@ -1,268 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Ethon::Easy::Operations do
|
5
|
-
let(:easy) { Ethon::Easy.new }
|
6
|
-
|
7
|
-
describe "#handle" do
|
8
|
-
it "returns a pointer" do
|
9
|
-
expect(easy.handle).to be_a(FFI::Pointer)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
describe "#perform" do
|
15
|
-
let(:url) { nil }
|
16
|
-
let(:timeout) { nil }
|
17
|
-
let(:connect_timeout) { nil }
|
18
|
-
let(:follow_location) { nil }
|
19
|
-
let(:max_redirs) { nil }
|
20
|
-
let(:user_pwd) { nil }
|
21
|
-
let(:http_auth) { nil }
|
22
|
-
let(:headers) { nil }
|
23
|
-
let(:protocols) { nil }
|
24
|
-
let(:redir_protocols) { nil }
|
25
|
-
let(:username) { nil }
|
26
|
-
let(:password) { nil }
|
27
|
-
|
28
|
-
before do
|
29
|
-
Ethon.logger.level = Logger::DEBUG
|
30
|
-
easy.url = url
|
31
|
-
easy.timeout = timeout
|
32
|
-
easy.connecttimeout = connect_timeout
|
33
|
-
easy.followlocation = follow_location
|
34
|
-
easy.maxredirs = max_redirs
|
35
|
-
easy.httpauth = http_auth
|
36
|
-
easy.headers = headers
|
37
|
-
easy.protocols = protocols
|
38
|
-
easy.redir_protocols = redir_protocols
|
39
|
-
|
40
|
-
if user_pwd
|
41
|
-
easy.userpwd = user_pwd
|
42
|
-
else
|
43
|
-
easy.username = username
|
44
|
-
easy.password = password
|
45
|
-
end
|
46
|
-
|
47
|
-
easy.perform
|
48
|
-
end
|
49
|
-
|
50
|
-
it "calls Curl.easy_perform" do
|
51
|
-
expect(Ethon::Curl).to receive(:easy_perform)
|
52
|
-
easy.perform
|
53
|
-
end
|
54
|
-
|
55
|
-
it "calls Curl.easy_cleanup" do
|
56
|
-
expect_any_instance_of(FFI::AutoPointer).to receive(:free)
|
57
|
-
easy.cleanup
|
58
|
-
end
|
59
|
-
|
60
|
-
it "logs" do
|
61
|
-
expect(Ethon.logger).to receive(:debug)
|
62
|
-
easy.perform
|
63
|
-
end
|
64
|
-
|
65
|
-
it "doesn't log after completing because completing could reset" do
|
66
|
-
easy.on_complete{ expect(Ethon.logger).to receive(:debug).never }
|
67
|
-
easy.perform
|
68
|
-
end
|
69
|
-
|
70
|
-
context "when url" do
|
71
|
-
let(:url) { "http://localhost:3001/" }
|
72
|
-
|
73
|
-
it "returns ok" do
|
74
|
-
expect(easy.return_code).to eq(:ok)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "sets response body" do
|
78
|
-
expect(easy.response_body).to be
|
79
|
-
end
|
80
|
-
|
81
|
-
it "sets response headers" do
|
82
|
-
expect(easy.response_headers).to be
|
83
|
-
end
|
84
|
-
|
85
|
-
context "when request timed out" do
|
86
|
-
let(:url) { "http://localhost:3001/?delay=1" }
|
87
|
-
let(:timeout) { 1 }
|
88
|
-
|
89
|
-
it "returns operation_timedout" do
|
90
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context "when connection timed out" do
|
95
|
-
let(:url) { "http://localhost:3009" }
|
96
|
-
let(:connect_timeout) { 1 }
|
97
|
-
|
98
|
-
it "returns couldnt_connect" do
|
99
|
-
expect(easy.return_code).to eq(:couldnt_connect)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "when no follow location" do
|
104
|
-
let(:url) { "http://localhost:3001/redirect" }
|
105
|
-
let(:follow_location) { false }
|
106
|
-
|
107
|
-
it "doesn't follow" do
|
108
|
-
expect(easy.response_code).to eq(302)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context "when follow location" do
|
113
|
-
let(:url) { "http://localhost:3001/redirect" }
|
114
|
-
let(:follow_location) { true }
|
115
|
-
|
116
|
-
it "follows" do
|
117
|
-
expect(easy.response_code).to eq(200)
|
118
|
-
end
|
119
|
-
|
120
|
-
context "when infinite redirect loop" do
|
121
|
-
let(:url) { "http://localhost:3001/bad_redirect" }
|
122
|
-
let(:max_redirs) { 5 }
|
123
|
-
|
124
|
-
context "when max redirect set" do
|
125
|
-
it "follows only x times" do
|
126
|
-
expect(easy.response_code).to eq(302)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
context "when user agent" do
|
133
|
-
let(:headers) { { 'User-Agent' => 'Ethon' } }
|
134
|
-
|
135
|
-
it "sets" do
|
136
|
-
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context "when auth url" do
|
142
|
-
before { easy.url = url }
|
143
|
-
|
144
|
-
context "when basic auth" do
|
145
|
-
let(:url) { "http://localhost:3001/auth_basic/username/password" }
|
146
|
-
|
147
|
-
context "when no user_pwd" do
|
148
|
-
it "returns 401" do
|
149
|
-
expect(easy.response_code).to eq(401)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "when invalid user_pwd" do
|
154
|
-
let(:user_pwd) { "invalid:invalid" }
|
155
|
-
|
156
|
-
it "returns 401" do
|
157
|
-
expect(easy.response_code).to eq(401)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
context "when valid user_pwd" do
|
162
|
-
let(:user_pwd) { "username:password" }
|
163
|
-
|
164
|
-
it "returns 200" do
|
165
|
-
expect(easy.response_code).to eq(200)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
context "when user and password" do
|
170
|
-
let(:username) { "username" }
|
171
|
-
let(:password) { "password" }
|
172
|
-
|
173
|
-
it "returns 200" do
|
174
|
-
expect(easy.response_code).to eq(200)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context "when ntlm" do
|
180
|
-
let(:url) { "http://localhost:3001/auth_ntlm" }
|
181
|
-
let(:http_auth) { :ntlm }
|
182
|
-
|
183
|
-
context "when no user_pwd" do
|
184
|
-
it "returns 401" do
|
185
|
-
expect(easy.response_code).to eq(401)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
context "when user_pwd" do
|
190
|
-
let(:user_pwd) { "username:password" }
|
191
|
-
|
192
|
-
it "returns 200" do
|
193
|
-
expect(easy.response_code).to eq(200)
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
context "when protocols" do
|
200
|
-
context "when asking for a allowed url" do
|
201
|
-
let(:url) { "http://localhost:3001" }
|
202
|
-
let(:protocols) { :http }
|
203
|
-
|
204
|
-
it "returns ok" do
|
205
|
-
expect(easy.return_code).to be(:ok)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
context "when asking for a not allowed url" do
|
210
|
-
let(:url) { "http://localhost:3001" }
|
211
|
-
let(:protocols) { :https }
|
212
|
-
|
213
|
-
it "returns unsupported_protocol" do
|
214
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
context "when multiple protocols" do
|
220
|
-
context "when asking for a allowed url" do
|
221
|
-
let(:protocols) { [:http, :https] }
|
222
|
-
|
223
|
-
context "when http" do
|
224
|
-
let(:url) { "http://localhost:3001" }
|
225
|
-
|
226
|
-
it "returns ok for http" do
|
227
|
-
expect(easy.return_code).to be(:ok)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
context "when https" do
|
232
|
-
let(:url) { "https://localhost:3001" }
|
233
|
-
|
234
|
-
it "returns ssl_connect_error for https" do
|
235
|
-
expect(easy.return_code).to be(:ssl_connect_error)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
context "when asking for a not allowed url" do
|
241
|
-
let(:url) { "ssh://localhost" }
|
242
|
-
let(:protocols) { [:https, :http] }
|
243
|
-
|
244
|
-
it "returns unsupported_protocol" do
|
245
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
context "when redir_protocols" do
|
251
|
-
context "when redirecting to a not allowed url" do
|
252
|
-
let(:url) { "http://localhost:3001/redirect" }
|
253
|
-
let(:follow_location) { true }
|
254
|
-
let(:redir_protocols) { :https }
|
255
|
-
|
256
|
-
it "returns unsupported_protocol" do
|
257
|
-
expect(easy.return_code).to be(:unsupported_protocol)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
context "when no url" do
|
263
|
-
it "returns url_malformat" do
|
264
|
-
expect(easy.perform).to eq(:url_malformat)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
@@ -1,193 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Ethon::Easy::Options do
|
5
|
-
let(:easy) { Ethon::Easy.new }
|
6
|
-
|
7
|
-
[
|
8
|
-
:accept_encoding, :cainfo, :capath, :connecttimeout, :connecttimeout_ms, :cookie,
|
9
|
-
:cookiejar, :cookiefile, :copypostfields, :customrequest, :dns_cache_timeout,
|
10
|
-
:followlocation, :forbid_reuse, :http_version, :httpauth, :httpget, :httppost,
|
11
|
-
:infilesize, :interface, :keypasswd, :maxredirs, :nobody, :nosignal,
|
12
|
-
:postfieldsize, :postredir, :protocols, :proxy, :proxyauth, :proxyport, :proxytype,
|
13
|
-
:proxyuserpwd, :readdata, :readfunction, :redir_protocols, :ssl_verifyhost,
|
14
|
-
:ssl_verifypeer, :sslcert, :sslcerttype, :sslkey, :sslkeytype, :sslversion,
|
15
|
-
:timeout, :timeout_ms, :unrestricted_auth, :upload, :url, :useragent,
|
16
|
-
:userpwd, :verbose, :pipewait, :dns_shuffle_addresses, :path_as_is
|
17
|
-
].each do |name|
|
18
|
-
describe "#{name}=" do
|
19
|
-
it "responds_to" do
|
20
|
-
expect(easy).to respond_to("#{name}=")
|
21
|
-
end
|
22
|
-
|
23
|
-
it "sets option" do
|
24
|
-
expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks)
|
25
|
-
expect(Ethon::Curl).to receive(:set_option).with(name, anything, anything)
|
26
|
-
value = case name
|
27
|
-
when :http_version
|
28
|
-
:httpv1_0
|
29
|
-
when :httpauth
|
30
|
-
:basic
|
31
|
-
when :protocols, :redir_protocols
|
32
|
-
:http
|
33
|
-
when :postredir
|
34
|
-
:post_301
|
35
|
-
when :proxytype
|
36
|
-
:http
|
37
|
-
when :sslversion
|
38
|
-
:default
|
39
|
-
when :httppost
|
40
|
-
FFI::Pointer::NULL
|
41
|
-
else
|
42
|
-
1
|
43
|
-
end
|
44
|
-
easy.method("#{name}=").call(value)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#escape?' do
|
50
|
-
context 'by default' do
|
51
|
-
it 'returns true' do
|
52
|
-
expect(easy.escape?).to be_truthy
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'when #escape=nil' do
|
57
|
-
it 'returns true' do
|
58
|
-
easy.escape = nil
|
59
|
-
expect(easy.escape?).to be_truthy
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when #escape=true' do
|
64
|
-
it 'returns true' do
|
65
|
-
easy.escape = true
|
66
|
-
expect(easy.escape?).to be_truthy
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context 'when #escape=false' do
|
71
|
-
it 'returns true' do
|
72
|
-
easy.escape = false
|
73
|
-
expect(easy.escape?).to be_falsey
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe '#multipart?' do
|
79
|
-
context 'by default' do
|
80
|
-
it 'returns false' do
|
81
|
-
expect(easy.multipart?).to be_falsey
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'when #multipart=nil' do
|
86
|
-
it 'returns false' do
|
87
|
-
easy.multipart = nil
|
88
|
-
expect(easy.multipart?).to be_falsey
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when #multipart=true' do
|
93
|
-
it 'returns true' do
|
94
|
-
easy.multipart = true
|
95
|
-
expect(easy.multipart?).to be_truthy
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
context 'when #multipart=false' do
|
100
|
-
it 'returns false' do
|
101
|
-
easy.multipart = false
|
102
|
-
expect(easy.multipart?).to be_falsey
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "#httppost=" do
|
108
|
-
it "raises unless given a FFI::Pointer" do
|
109
|
-
expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "when requesting" do
|
114
|
-
let(:url) { "localhost:3001" }
|
115
|
-
let(:timeout) { nil }
|
116
|
-
let(:timeout_ms) { nil }
|
117
|
-
let(:connecttimeout) { nil }
|
118
|
-
let(:connecttimeout_ms) { nil }
|
119
|
-
let(:userpwd) { nil }
|
120
|
-
|
121
|
-
before do
|
122
|
-
easy.url = url
|
123
|
-
easy.timeout = timeout
|
124
|
-
easy.timeout_ms = timeout_ms
|
125
|
-
easy.connecttimeout = connecttimeout
|
126
|
-
easy.connecttimeout_ms = connecttimeout_ms
|
127
|
-
easy.userpwd = userpwd
|
128
|
-
easy.perform
|
129
|
-
end
|
130
|
-
|
131
|
-
context "when userpwd" do
|
132
|
-
context "when contains /" do
|
133
|
-
let(:url) { "localhost:3001/auth_basic/test/te%2Fst" }
|
134
|
-
let(:userpwd) { "test:te/st" }
|
135
|
-
|
136
|
-
it "works" do
|
137
|
-
expect(easy.response_code).to eq(200)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "when timeout" do
|
143
|
-
let(:timeout) { 1 }
|
144
|
-
|
145
|
-
context "when request takes longer" do
|
146
|
-
let(:url) { "localhost:3001?delay=2" }
|
147
|
-
|
148
|
-
it "times out" do
|
149
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
context "when connecttimeout" do
|
155
|
-
let(:connecttimeout) { 1 }
|
156
|
-
|
157
|
-
context "when cannot connect" do
|
158
|
-
let(:url) { "localhost:3002" }
|
159
|
-
|
160
|
-
it "times out" do
|
161
|
-
expect(easy.return_code).to eq(:couldnt_connect)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
if Ethon::Easy.supports_timeout_ms?
|
167
|
-
context "when timeout_ms" do
|
168
|
-
let(:timeout_ms) { 100 }
|
169
|
-
|
170
|
-
context "when request takes longer" do
|
171
|
-
let(:url) { "localhost:3001?delay=1" }
|
172
|
-
|
173
|
-
it "times out" do
|
174
|
-
expect(easy.return_code).to eq(:operation_timedout)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context "when connecttimeout_ms" do
|
180
|
-
let(:connecttimeout_ms) { 100 }
|
181
|
-
|
182
|
-
context "when cannot connect" do
|
183
|
-
let(:url) { "localhost:3002" }
|
184
|
-
|
185
|
-
it "times out" do
|
186
|
-
# this can either lead to a timeout or couldnt connect depending on which happens first
|
187
|
-
expect([:couldnt_connect, :operation_timedout]).to include(easy.return_code)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
@@ -1,235 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: true
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe Ethon::Easy::Queryable do
|
6
|
-
let(:hash) { {} }
|
7
|
-
let!(:easy) { Ethon::Easy.new }
|
8
|
-
let(:params) { Ethon::Easy::Params.new(easy, hash) }
|
9
|
-
|
10
|
-
describe "#to_s" do
|
11
|
-
context "when query_pairs empty" do
|
12
|
-
before { params.instance_variable_set(:@query_pairs, []) }
|
13
|
-
|
14
|
-
it "returns empty string" do
|
15
|
-
expect(params.to_s).to eq("")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
context "when query_pairs not empty" do
|
20
|
-
context "when escape" do
|
21
|
-
before do
|
22
|
-
params.escape = true
|
23
|
-
end
|
24
|
-
|
25
|
-
{
|
26
|
-
'!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28',
|
27
|
-
')' => '%29', ';' => '%3B', ':' => '%3A', '@' => '%40',
|
28
|
-
'&' => '%26', '=' => '%3D', '+' => '%2B', '$' => '%24',
|
29
|
-
',' => '%2C', '/' => '%2F', '?' => '%3F', '#' => '%23',
|
30
|
-
'[' => '%5B', ']' => '%5D',
|
31
|
-
|
32
|
-
'<' => '%3C', '>' => '%3E', '"' => '%22', '{' => '%7B',
|
33
|
-
'}' => '%7D', '|' => '%7C', '\\' => '%5C', '`' => '%60',
|
34
|
-
'^' => '%5E', '%' => '%25', ' ' => '%20', "\0" => '%00',
|
35
|
-
|
36
|
-
'まつもと' => '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8',
|
37
|
-
}.each do |value, percent|
|
38
|
-
it "turns #{value.inspect} into #{percent}" do
|
39
|
-
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
40
|
-
expect(params.to_s).to eq("a=#{percent}")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
{
|
45
|
-
'.' => '%2E', '-' => '%2D', '_' => '%5F', '~' => '%7E',
|
46
|
-
}.each do |value, percent|
|
47
|
-
it "leaves #{value.inspect} instead of turning into #{percent}" do
|
48
|
-
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
49
|
-
expect(params.to_s).to eq("a=#{value}")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context "when no escape" do
|
55
|
-
before { params.instance_variable_set(:@query_pairs, [[:a, 1], [:b, 2]]) }
|
56
|
-
|
57
|
-
it "returns concatenated query string" do
|
58
|
-
expect(params.to_s).to eq("a=1&b=2")
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when query_pairs contains a string" do
|
64
|
-
before { params.instance_variable_set(:@query_pairs, ["{a: 1}"]) }
|
65
|
-
|
66
|
-
it "returns correct string" do
|
67
|
-
expect(params.to_s).to eq("{a: 1}")
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe "#build_query_pairs" do
|
73
|
-
let(:pairs) { params.method(:build_query_pairs).call(hash) }
|
74
|
-
|
75
|
-
context "when params is empty" do
|
76
|
-
it "returns empty array" do
|
77
|
-
expect(pairs).to eq([])
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context "when params is string" do
|
82
|
-
let(:hash) { "{a: 1}" }
|
83
|
-
|
84
|
-
it "wraps it in an array" do
|
85
|
-
expect(pairs).to eq([hash])
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "when params is simple hash" do
|
90
|
-
let(:hash) { {:a => 1, :b => 2} }
|
91
|
-
|
92
|
-
it "transforms" do
|
93
|
-
expect(pairs).to include([:a, 1])
|
94
|
-
expect(pairs).to include([:b, 2])
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context "when params is a nested hash" do
|
99
|
-
let(:hash) { {:a => 1, :b => {:c => 2}} }
|
100
|
-
|
101
|
-
it "transforms" do
|
102
|
-
expect(pairs).to include([:a, 1])
|
103
|
-
expect(pairs).to include(["b[c]", 2])
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
context "when params contains an array" do
|
108
|
-
let(:hash) { {:a => 1, :b => [2, 3]} }
|
109
|
-
|
110
|
-
context "by default" do
|
111
|
-
it "transforms" do
|
112
|
-
expect(pairs).to include([:a, 1])
|
113
|
-
expect(pairs).to include(["b[0]", 2])
|
114
|
-
expect(pairs).to include(["b[1]", 3])
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context "when params_encoding is :rack" do
|
119
|
-
before { params.params_encoding = :rack }
|
120
|
-
it "transforms without indexes" do
|
121
|
-
expect(pairs).to include([:a, 1])
|
122
|
-
expect(pairs).to include(["b[]", 2])
|
123
|
-
expect(pairs).to include(["b[]", 3])
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context "when params_encoding is :none" do
|
128
|
-
before { params.params_encoding = :none }
|
129
|
-
it "does no transformation" do
|
130
|
-
expect(pairs).to include([:a, 1])
|
131
|
-
expect(pairs).to include([:b, [2, 3]])
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "when params contains something nested in an array" do
|
137
|
-
context "when string" do
|
138
|
-
let(:hash) { {:a => {:b => ["hello", "world"]}} }
|
139
|
-
|
140
|
-
it "transforms" do
|
141
|
-
expect(pairs).to eq([["a[b][0]", "hello"], ["a[b][1]", "world"]])
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
context "when hash" do
|
146
|
-
let(:hash) { {:a => {:b => [{:c =>1}, {:d => 2}]}} }
|
147
|
-
|
148
|
-
it "transforms" do
|
149
|
-
expect(pairs).to eq([["a[b][0][c]", 1], ["a[b][1][d]", 2]])
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "when file" do
|
154
|
-
let(:file) { File.open("spec/spec_helper.rb") }
|
155
|
-
let(:file_info) { params.method(:file_info).call(file) }
|
156
|
-
let(:hash) { {:a => {:b => [file]}} }
|
157
|
-
let(:mime_type) { file_info[1] }
|
158
|
-
|
159
|
-
it "transforms" do
|
160
|
-
expect(pairs).to eq([["a[b][0]", file_info]])
|
161
|
-
end
|
162
|
-
|
163
|
-
context "when MIME" do
|
164
|
-
if defined?(MIME)
|
165
|
-
context "when mime type" do
|
166
|
-
it "sets mime type to text" do
|
167
|
-
expect(mime_type).to eq("application/x-ruby")
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
context "when no mime type" do
|
173
|
-
let(:file) { Tempfile.new("fubar") }
|
174
|
-
|
175
|
-
it "sets mime type to default application/octet-stream" do
|
176
|
-
expect(mime_type).to eq("application/octet-stream")
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
context "when no MIME" do
|
182
|
-
before { hide_const("MIME") }
|
183
|
-
|
184
|
-
it "sets mime type to default application/octet-stream" do
|
185
|
-
expect(mime_type).to eq("application/octet-stream")
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
|
192
|
-
context "when params contains file" do
|
193
|
-
let(:file) { Tempfile.new("fubar") }
|
194
|
-
let(:file_info) { params.method(:file_info).call(file) }
|
195
|
-
let(:hash) { {:a => 1, :b => file} }
|
196
|
-
|
197
|
-
it "transforms" do
|
198
|
-
expect(pairs).to include([:a, 1])
|
199
|
-
expect(pairs).to include([:b, file_info])
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
context "when params key contains a null byte" do
|
204
|
-
let(:hash) { {:a => "1\0" } }
|
205
|
-
|
206
|
-
it "preserves" do
|
207
|
-
expect(pairs).to eq([[:a, "1\0"]])
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
context "when params value contains a null byte" do
|
212
|
-
let(:hash) { {"a\0" => 1 } }
|
213
|
-
|
214
|
-
it "preserves" do
|
215
|
-
expect(pairs).to eq([["a\0", 1]])
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "#empty?" do
|
221
|
-
context "when params empty" do
|
222
|
-
it "returns true" do
|
223
|
-
expect(params.empty?).to be_truthy
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
context "when params not empty" do
|
228
|
-
let(:hash) { {:a => 1} }
|
229
|
-
|
230
|
-
it "returns false" do
|
231
|
-
expect(params.empty?).to be_falsey
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|