webmock 1.18.0 → 1.19.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.
- 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
|