webmock 1.18.0 → 1.19.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/CHANGELOG.md +46 -0
- data/README.md +11 -1
- data/lib/webmock/config.rb +6 -0
- data/lib/webmock/errors.rb +9 -7
- data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +23 -7
- data/lib/webmock/http_lib_adapters/excon_adapter.rb +4 -4
- data/lib/webmock/http_lib_adapters/http_gem/response.rb +3 -2
- data/lib/webmock/http_lib_adapters/http_gem/webmock.rb +1 -1
- data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +4 -4
- data/lib/webmock/matchers/hash_including_matcher.rb +1 -1
- data/lib/webmock/request_pattern.rb +11 -10
- data/lib/webmock/request_signature.rb +1 -1
- data/lib/webmock/request_stub.rb +1 -1
- data/lib/webmock/util/hash_keys_stringifier.rb +5 -3
- data/lib/webmock/util/query_mapper.rb +226 -146
- data/lib/webmock/util/uri.rb +4 -3
- data/lib/webmock/version.rb +1 -1
- data/lib/webmock/webmock.rb +12 -0
- data/spec/acceptance/em_http_request/em_http_request_spec.rb +73 -0
- data/spec/acceptance/excon/excon_spec.rb +15 -5
- data/spec/acceptance/http_gem/http_gem_spec.rb +9 -0
- data/spec/acceptance/httpclient/httpclient_spec.rb +11 -3
- data/spec/acceptance/httpclient/httpclient_spec_helper.rb +1 -1
- data/spec/acceptance/patron/patron_spec_helper.rb +1 -0
- data/spec/acceptance/shared/request_expectations.rb +18 -0
- data/spec/acceptance/shared/stubbing_requests.rb +5 -0
- data/spec/unit/errors_spec.rb +53 -15
- data/spec/unit/request_pattern_spec.rb +15 -0
- data/spec/unit/request_signature_spec.rb +3 -0
- data/spec/unit/util/hash_keys_stringifier_spec.rb +1 -1
- data/spec/unit/util/query_mapper_spec.rb +91 -17
- data/spec/unit/util/uri_spec.rb +29 -0
- data/webmock.gemspec +2 -2
- metadata +7 -15
data/lib/webmock/util/uri.rb
CHANGED
@@ -14,8 +14,8 @@ module WebMock
|
|
14
14
|
NORMALIZED_URIS = Hash.new do |hash, uri|
|
15
15
|
normalized_uri = WebMock::Util::URI.heuristic_parse(uri)
|
16
16
|
if normalized_uri.query_values
|
17
|
-
sorted_query_values = sort_query_values(WebMock::Util::QueryMapper.query_to_values(normalized_uri.query) || {})
|
18
|
-
normalized_uri.query = WebMock::Util::QueryMapper.values_to_query(sorted_query_values)
|
17
|
+
sorted_query_values = sort_query_values(WebMock::Util::QueryMapper.query_to_values(normalized_uri.query, :notation => Config.instance.query_values_notation) || {})
|
18
|
+
normalized_uri.query = WebMock::Util::QueryMapper.values_to_query(sorted_query_values, :notation => WebMock::Config.instance.query_values_notation)
|
19
19
|
end
|
20
20
|
normalized_uri = normalized_uri.normalize #normalize! is slower
|
21
21
|
normalized_uri.query = normalized_uri.query.gsub("+", "%2B") if normalized_uri.query
|
@@ -74,7 +74,8 @@ module WebMock
|
|
74
74
|
private
|
75
75
|
|
76
76
|
def self.sort_query_values(query_values)
|
77
|
-
|
77
|
+
sorted_query_values = query_values.sort
|
78
|
+
query_values.is_a?(Hash) ? Hash[*sorted_query_values.inject([]) { |values, pair| values + pair}] : sorted_query_values
|
78
79
|
end
|
79
80
|
|
80
81
|
def self.uris_with_inferred_port_and_without(uris)
|
data/lib/webmock/version.rb
CHANGED
data/lib/webmock/webmock.rb
CHANGED
@@ -75,6 +75,18 @@ module WebMock
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def self.hide_stubbing_instructions!
|
79
|
+
Config.instance.show_stubbing_instructions = false
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.show_stubbing_instructions!
|
83
|
+
Config.instance.show_stubbing_instructions = true
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.show_stubbing_instructions?
|
87
|
+
Config.instance.show_stubbing_instructions
|
88
|
+
end
|
89
|
+
|
78
90
|
def self.reset!
|
79
91
|
WebMock::RequestRegistry.instance.reset!
|
80
92
|
WebMock::StubRegistry.instance.reset!
|
@@ -267,6 +267,79 @@ unless RUBY_PLATFORM =~ /java/
|
|
267
267
|
signature.uri.should == Addressable::URI.parse(uri)
|
268
268
|
end
|
269
269
|
end
|
270
|
+
|
271
|
+
describe 'get_response_cookie' do
|
272
|
+
|
273
|
+
before(:each) do
|
274
|
+
stub_request(:get, "http://example.org/").
|
275
|
+
to_return(
|
276
|
+
:status => 200,
|
277
|
+
:body => "",
|
278
|
+
:headers => { 'Set-Cookie' => cookie_string }
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
describe 'success' do
|
283
|
+
|
284
|
+
context 'with only one cookie' do
|
285
|
+
|
286
|
+
let(:cookie_name) { 'name_of_the_cookie' }
|
287
|
+
let(:cookie_value) { 'value_of_the_cookie' }
|
288
|
+
let(:cookie_string) { "#{cookie_name}=#{cookie_value}" }
|
289
|
+
|
290
|
+
it 'successfully gets the cookie' do
|
291
|
+
EM.run {
|
292
|
+
http = EventMachine::HttpRequest.new('http://example.org').get
|
293
|
+
|
294
|
+
http.errback { fail(http.error) }
|
295
|
+
http.callback {
|
296
|
+
http.get_response_cookie(cookie_name).should == cookie_value
|
297
|
+
EM.stop
|
298
|
+
}
|
299
|
+
}
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'with several cookies' do
|
304
|
+
|
305
|
+
let(:cookie_name) { 'name_of_the_cookie' }
|
306
|
+
let(:cookie_value) { 'value_of_the_cookie' }
|
307
|
+
let(:cookie_2_name) { 'name_of_the_2nd_cookie' }
|
308
|
+
let(:cookie_2_value) { 'value_of_the_2nd_cookie' }
|
309
|
+
let(:cookie_string) { %W(#{cookie_name}=#{cookie_value} #{cookie_2_name}=#{cookie_2_value}) }
|
310
|
+
|
311
|
+
it 'successfully gets both cookies' do
|
312
|
+
EM.run {
|
313
|
+
http = EventMachine::HttpRequest.new('http://example.org').get
|
314
|
+
|
315
|
+
http.errback { fail(http.error) }
|
316
|
+
http.callback {
|
317
|
+
http.get_response_cookie(cookie_name).should == cookie_value
|
318
|
+
http.get_response_cookie(cookie_2_name).should == cookie_2_value
|
319
|
+
EM.stop
|
320
|
+
}
|
321
|
+
}
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
describe 'failure' do
|
327
|
+
|
328
|
+
let(:cookie_string) { 'a=b' }
|
329
|
+
|
330
|
+
it 'returns nil when no cookie is found' do
|
331
|
+
EM.run {
|
332
|
+
http = EventMachine::HttpRequest.new('http://example.org').get
|
333
|
+
|
334
|
+
http.errback { fail(http.error) }
|
335
|
+
http.callback {
|
336
|
+
http.get_response_cookie('not_found_cookie').should == nil
|
337
|
+
EM.stop
|
338
|
+
}
|
339
|
+
}
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
270
343
|
end
|
271
344
|
|
272
345
|
end
|
@@ -17,12 +17,12 @@ describe "Excon" do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
context "with response_block" do
|
20
|
-
it "should support excon response_block for real requests" do
|
20
|
+
it "should support excon response_block for real requests", :net_connect => true do
|
21
21
|
a = []
|
22
22
|
WebMock.allow_net_connect!
|
23
23
|
r = Excon.new('http://httpstat.us/200').get(:response_block => lambda {|e, remaining, total| a << e}, :chunk_size => 1)
|
24
24
|
a.should == ["2", "0", "0", " ", "O", "K"]
|
25
|
-
r.body.should == ""
|
25
|
+
r.body.should == "200 OK" #this should be "", but there is an issue in Excon https://github.com/excon/excon/issues/429
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should support excon response_block" do
|
@@ -30,10 +30,10 @@ describe "Excon" do
|
|
30
30
|
stub_request(:get, "http://example.com/").to_return(:body => "abc")
|
31
31
|
r = Excon.new('http://example.com').get(:response_block => lambda {|e, remaining, total| a << e}, :chunk_size => 1)
|
32
32
|
a.should == ['a', 'b', 'c']
|
33
|
-
r.body.should == ""
|
33
|
+
r.body.should == "abc" #this should be "", but there is an issue in Excon https://github.com/excon/excon/issues/429
|
34
34
|
end
|
35
35
|
|
36
|
-
it "should invoke callbacks with response body even if a real request is made" do
|
36
|
+
it "should invoke callbacks with response body even if a real request is made", :net_connect => true do
|
37
37
|
a = []
|
38
38
|
WebMock.allow_net_connect!
|
39
39
|
response = nil
|
@@ -43,7 +43,7 @@ describe "Excon" do
|
|
43
43
|
r = Excon.new('http://httpstat.us/200').get(:response_block => lambda {|e, remaining, total| a << e}, :chunk_size => 1)
|
44
44
|
response.body.should == "200 OK"
|
45
45
|
a.should == ["2", "0", "0", " ", "O", "K"]
|
46
|
-
r.body.should == ""
|
46
|
+
r.body.should == "200 OK" #this should be "", but there is an issue in Excon https://github.com/excon/excon/issues/429
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -62,4 +62,14 @@ describe "Excon" do
|
|
62
62
|
|
63
63
|
yielded_request_body.should eq(file_contents)
|
64
64
|
end
|
65
|
+
|
66
|
+
describe '.request_params_from' do
|
67
|
+
|
68
|
+
it 'rejects invalid request keys' do
|
69
|
+
request_params = WebMock::HttpLibAdapters::ExconAdapter.request_params_from(:body => :keep, :fake => :reject)
|
70
|
+
request_params.should eq(:body => :keep)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
65
75
|
end
|
@@ -47,4 +47,13 @@ describe "HTTP Gem" do
|
|
47
47
|
expect(headers).to include "Host" => "www.example.com"
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
it "restores request uri on replayed response object" do
|
52
|
+
uri = URI "http://example.com/foo"
|
53
|
+
|
54
|
+
stub_request :get, "example.com/foo"
|
55
|
+
response = HTTP.get uri
|
56
|
+
|
57
|
+
expect(response.uri).to eq uri
|
58
|
+
end
|
50
59
|
end
|
@@ -136,10 +136,11 @@ describe "HTTPClient" do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
it "client sends the Accept, User-Agent, and Date by default" do
|
139
|
+
WebMock.disable_net_connect!
|
139
140
|
stub_request(:get, "www.example.com").with do |req|
|
140
|
-
req.headers["Accept"]
|
141
|
-
req.headers["User-Agent"]
|
142
|
-
req.headers["Date"]
|
141
|
+
req.headers["Accept"] == "*/*" &&
|
142
|
+
req.headers["User-Agent"] == "#{HTTPClient::DEFAULT_AGENT_NAME} #{HTTPClient::LIB_NAME}" &&
|
143
|
+
req.headers["Date"]
|
143
144
|
end
|
144
145
|
http_request(:get, "www.example.com")
|
145
146
|
end
|
@@ -152,4 +153,11 @@ describe "HTTPClient" do
|
|
152
153
|
|
153
154
|
end
|
154
155
|
|
156
|
+
context 'httpclient response header' do
|
157
|
+
it 'receives request_method, request_uri, and request_query from the request header' do
|
158
|
+
stub_request :get, 'www.example.com'
|
159
|
+
message = HTTPClient.new.get 'www.example.com'
|
160
|
+
message.header.request_uri.to_s.should == 'www.example.com'
|
161
|
+
end
|
162
|
+
end
|
155
163
|
end
|
@@ -9,7 +9,7 @@ module HTTPClientSpecHelper
|
|
9
9
|
c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
10
10
|
c.set_basic_auth(nil, uri.user, uri.password) if uri.user
|
11
11
|
params = [method, "#{uri.omit(:userinfo, :query).normalize.to_s}",
|
12
|
-
WebMock::Util::QueryMapper.query_to_values(uri.query), options[:body], options[:headers] || {}]
|
12
|
+
WebMock::Util::QueryMapper.query_to_values(uri.query, :notation => WebMock::Config.instance.query_values_notation), options[:body], options[:headers] || {}]
|
13
13
|
if HTTPClientSpecHelper.async_mode
|
14
14
|
connection = c.request_async(*params)
|
15
15
|
connection.join
|
@@ -2,6 +2,7 @@ require 'ostruct'
|
|
2
2
|
|
3
3
|
module PatronSpecHelper
|
4
4
|
def http_request(method, uri, options = {}, &block)
|
5
|
+
method = method.to_sym
|
5
6
|
uri = Addressable::URI.heuristic_parse(uri)
|
6
7
|
sess = Patron::Session.new
|
7
8
|
sess.base_url = "#{uri.omit(:userinfo, :path, :query).normalize.to_s}".gsub(/\/$/,"")
|
@@ -159,6 +159,24 @@ shared_context "request expectations" do |*adapter_info|
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
+
context "when using flat array notation" do
|
163
|
+
before :all do
|
164
|
+
WebMock::Config.instance.query_values_notation = :flat_array
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should satisfy expectation if request includes different repeated query params in flat array notation" do
|
168
|
+
lambda {
|
169
|
+
stub_request(:get, "http://www.example.com/?a=1&a=2")
|
170
|
+
http_request(:get, "http://www.example.com/?a=1&a=2")
|
171
|
+
a_request(:get, "http://www.example.com/?a=1&a=2").should have_been_made
|
172
|
+
}.should_not raise_error
|
173
|
+
end
|
174
|
+
|
175
|
+
after :all do
|
176
|
+
WebMock::Config.instance.query_values_notation = nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
162
180
|
it "should fail if request was made more times than expected" do
|
163
181
|
lambda {
|
164
182
|
http_request(:get, "http://www.example.com/")
|
@@ -71,6 +71,11 @@ shared_examples_for "stubbing requests" do |*adapter_info|
|
|
71
71
|
http_request(:get, "http://www.example.com/").status.should == "200"
|
72
72
|
end
|
73
73
|
|
74
|
+
it "should match stubbed request when http request was made with method given as string" do
|
75
|
+
stub_request(:get, "www.example.com")
|
76
|
+
http_request('get', "http://www.example.com/").status.should == "200"
|
77
|
+
end
|
78
|
+
|
74
79
|
it "should raise error if stubbed request has different method" do
|
75
80
|
stub_request(:get, "www.example.com")
|
76
81
|
http_request(:get, "http://www.example.com/").status.should == "200"
|
data/spec/unit/errors_spec.rb
CHANGED
@@ -4,36 +4,38 @@ describe "errors" do
|
|
4
4
|
describe WebMock::NetConnectNotAllowedError do
|
5
5
|
describe "message" do
|
6
6
|
it "should have message with request signature and snippet" do
|
7
|
-
request_signature = double(:to_s => "aaa")
|
8
|
-
request_stub = double
|
9
7
|
WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
|
10
8
|
WebMock::StubRequestSnippet.stub(:new).
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
with(request_stub).and_return(stub_result)
|
10
|
+
|
11
|
+
expected = \
|
12
|
+
"Real HTTP connections are disabled. Unregistered request: #{request_signature}" \
|
13
|
+
"\n\nYou can stub this request with the following snippet:" \
|
14
|
+
"\n\n#{stub_result}" \
|
15
|
+
"\n\n============================================================"
|
15
16
|
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
16
17
|
end
|
17
18
|
|
18
19
|
it "should have message with registered stubs if available" do
|
19
|
-
request_signature = double(:to_s => "aaa")
|
20
|
-
request_stub = double
|
21
20
|
WebMock::StubRegistry.instance.stub(:request_stubs).and_return([request_stub])
|
22
21
|
WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
|
23
22
|
WebMock::StubRequestSnippet.stub(:new).
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
with(request_stub).and_return(stub_result)
|
24
|
+
|
25
|
+
expected = \
|
26
|
+
"Real HTTP connections are disabled. Unregistered request: #{request_signature}" \
|
27
|
+
"\n\nYou can stub this request with the following snippet:" \
|
28
|
+
"\n\n#{stub_result}" \
|
29
|
+
"\n\nregistered request stubs:" \
|
30
|
+
"\n\n#{stub_result}" \
|
31
|
+
"\n\n============================================================"
|
28
32
|
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
29
33
|
end
|
30
34
|
|
31
35
|
it "should not be caught by a rescue block without arguments" do
|
32
|
-
request_signature = double(:to_s => "aaa")
|
33
|
-
request_stub = double
|
34
36
|
WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
|
35
37
|
WebMock::StubRequestSnippet.stub(:new).
|
36
|
-
with(request_stub).and_return(
|
38
|
+
with(request_stub).and_return(stub_result)
|
37
39
|
|
38
40
|
exception = WebMock::NetConnectNotAllowedError.new(request_signature)
|
39
41
|
|
@@ -45,6 +47,42 @@ describe "errors" do
|
|
45
47
|
end
|
46
48
|
end.to raise_exception exception
|
47
49
|
end
|
50
|
+
|
51
|
+
context "WebMock.show_stubbing_instructions? is false" do
|
52
|
+
before do
|
53
|
+
WebMock.hide_stubbing_instructions!
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have message with request signature and snippet" do
|
57
|
+
WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
|
58
|
+
WebMock::StubRequestSnippet.stub(:new).
|
59
|
+
with(request_stub).and_return(stub_result)
|
60
|
+
|
61
|
+
expected = \
|
62
|
+
"Real HTTP connections are disabled. Unregistered request: #{request_signature}" \
|
63
|
+
"\n\n============================================================"
|
64
|
+
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should have message with registered stubs if available" do
|
68
|
+
WebMock::StubRegistry.instance.stub(:request_stubs).and_return([request_stub])
|
69
|
+
WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
|
70
|
+
WebMock::StubRequestSnippet.stub(:new).
|
71
|
+
with(request_stub).and_return(stub_result)
|
72
|
+
|
73
|
+
expected = \
|
74
|
+
"Real HTTP connections are disabled. Unregistered request: #{request_signature}" \
|
75
|
+
"\n\nregistered request stubs:" \
|
76
|
+
"\n\n#{stub_result}" \
|
77
|
+
"\n\n============================================================"
|
78
|
+
WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
|
79
|
+
end
|
80
|
+
end
|
48
81
|
end
|
82
|
+
|
83
|
+
let(:request_signature) { double(:to_s => rand(10**20).to_s) }
|
84
|
+
let(:stub_result) { double(:to_s => rand(10**20).to_s) }
|
85
|
+
let(:request_stub) { double }
|
86
|
+
|
49
87
|
end
|
50
88
|
end
|
@@ -286,6 +286,21 @@ describe WebMock::RequestPattern do
|
|
286
286
|
:query => RSpec::Mocks::ArgumentMatchers::HashIncludingMatcher.new({"a" => ["b", "d"]})).
|
287
287
|
should_not match(WebMock::RequestSignature.new(:get, "www.example.com?a[]=b&a[]=c&b=1"))
|
288
288
|
end
|
289
|
+
|
290
|
+
context "when using query values notation as flat array" do
|
291
|
+
before :all do
|
292
|
+
WebMock::Config.instance.query_values_notation = :flat_array
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should not match when repeated query params are not the same as declared as string" do
|
296
|
+
WebMock::RequestPattern.new(:get, "www.example.com", :query => "a=b&a=c").
|
297
|
+
should match(WebMock::RequestSignature.new(:get, "www.example.com?a=b&a=c"))
|
298
|
+
end
|
299
|
+
|
300
|
+
after :all do
|
301
|
+
WebMock::Config.instance.query_values_notation = nil
|
302
|
+
end
|
303
|
+
end
|
289
304
|
end
|
290
305
|
end
|
291
306
|
|
@@ -26,6 +26,9 @@ describe WebMock::RequestSignature do
|
|
26
26
|
WebMock::RequestSignature.new(:get, "www.example.com", :body => "abc").body.should == "abc"
|
27
27
|
end
|
28
28
|
|
29
|
+
it "should symbolize the method" do
|
30
|
+
WebMock::RequestSignature.new('get', "www.example.com", :body => "abc").method.should == :get
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
34
|
it "should report string describing itself" do
|
@@ -1,30 +1,104 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe WebMock::Util::QueryMapper do
|
4
|
-
|
4
|
+
subject { described_class }
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
context '#query_to_values' do
|
7
|
+
it 'should raise on invalid notation' do
|
8
|
+
query = 'a=&b=c'
|
9
|
+
expect { subject.query_to_values(query, {:notation => 'foo'}) }.to raise_error(
|
10
|
+
ArgumentError,
|
11
|
+
'Invalid notation. Must be one of: [:flat, :dot, :subscript, :flat_array].'
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should parse hash queries' do
|
16
|
+
# {"one" => {"two" => {"three" => ["four", "five"]}}}
|
17
|
+
query = 'one%5Btwo%5D%5Bthree%5D%5B%5D=four&one%5Btwo%5D%5Bthree%5D%5B%5D=five'
|
18
|
+
hsh = subject.query_to_values(query)
|
19
|
+
expect(hsh['one']['two']['three']).to eq(%w(four five))
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should parse one nil value queries' do
|
23
|
+
# {'a' => nil, 'b' => 'c'}
|
24
|
+
query = 'a=&b=c'
|
25
|
+
hsh = subject.query_to_values(query)
|
26
|
+
expect(hsh['a']).to be_empty
|
27
|
+
expect(hsh['b']).to eq('c')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should parse array queries' do
|
31
|
+
# {"one" => ["foo", "bar"]}
|
32
|
+
query = 'one%5B%5D=foo&one%5B%5D=bar'
|
33
|
+
hsh = subject.query_to_values(query)
|
34
|
+
expect(hsh['one']).to eq(%w(foo bar))
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should parse string queries' do
|
38
|
+
# {"one" => "two", "three" => "four"}
|
39
|
+
query = 'one=two&three=four'
|
40
|
+
hsh = subject.query_to_values(query)
|
41
|
+
expect(hsh).to eq({'one' => 'two', 'three' => 'four'})
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should parse nested queries' do
|
45
|
+
# [{"b"=>[{"c"=>[{"d"=>["1", {"e"=>"2"}]}]}]}]
|
46
|
+
query = 'a%5B%5D%5Bb%5D%5B%5D%5Bc%5D%5B%5D%5Bd%5D%5B%5D=1&a%5B%5D%5Bb%5D%5B%5D%5Bc%5D%5B%5D%5Bd%5D%5B%5D%5Be%5D=2'
|
47
|
+
hsh = subject.query_to_values(query)
|
48
|
+
expect(hsh['a'][0]['b'][0]['c'][0]['d'][0]).to eq('1')
|
49
|
+
expect(hsh['a'][0]['b'][0]['c'][0]['d'][1]['e']).to eq('2')
|
50
|
+
end
|
10
51
|
end
|
11
52
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
53
|
+
context '#to_query' do
|
54
|
+
it 'should transform nil value' do
|
55
|
+
expect(subject.to_query('a', nil)).to eq('a=')
|
56
|
+
end
|
57
|
+
it 'should transform string value' do
|
58
|
+
expect(subject.to_query('a', 'b')).to eq('a=b')
|
59
|
+
end
|
60
|
+
it 'should transform hash value' do
|
61
|
+
expect(subject.to_query('a', {'key' => 'value'})).to eq('a[key]=value')
|
62
|
+
end
|
63
|
+
it 'should transform array value' do
|
64
|
+
expect(subject.to_query('a', ['b', 'c'])).to eq('a[0]=b&a[1]=c')
|
65
|
+
end
|
66
|
+
it 'should transform TrueClass value' do
|
67
|
+
expect(subject.to_query('a', true)).to eq('a')
|
68
|
+
end
|
16
69
|
end
|
17
70
|
|
18
|
-
|
19
|
-
query
|
20
|
-
|
21
|
-
|
71
|
+
context '#values_to_query' do
|
72
|
+
it 'converts values to a query string' do
|
73
|
+
query = "key=value&other_key=other_value"
|
74
|
+
values = [['key','value'],['other_key','other_value']]
|
75
|
+
expect(subject.values_to_query values).to eq query
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'converts values with missing keys to a query string' do
|
79
|
+
query = "=value"
|
80
|
+
values = { '' => 'value' }
|
81
|
+
expect(subject.values_to_query values).to eq query
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'converts values with nil keys to a query string' do
|
85
|
+
query = "=value"
|
86
|
+
values = { nil => 'value' }
|
87
|
+
expect(subject.values_to_query values).to eq query
|
88
|
+
end
|
22
89
|
end
|
23
90
|
|
24
|
-
it 'converts values
|
25
|
-
query = "=
|
26
|
-
values = {
|
27
|
-
expect(
|
91
|
+
it 'converts array values, vice versa' do
|
92
|
+
query = "one%5B%5D=1&one%5B%5D=2"
|
93
|
+
values = {"one" => ["1","2"]}
|
94
|
+
expect(subject.values_to_query values).to eq query
|
95
|
+
expect(subject.query_to_values query).to eq values
|
28
96
|
end
|
29
97
|
|
98
|
+
it 'converts hash values, vice versa' do
|
99
|
+
query = "one%5Ba%5D=1&one%5Bb%5D=2"
|
100
|
+
values = {"one" => {"a" => "1", "b" => "2"}}
|
101
|
+
expect(subject.values_to_query values).to eq query
|
102
|
+
expect(subject.query_to_values query).to eq values
|
103
|
+
end
|
30
104
|
end
|