webmock 1.18.0 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +4 -1
  2. data/CHANGELOG.md +46 -0
  3. data/README.md +11 -1
  4. data/lib/webmock/config.rb +6 -0
  5. data/lib/webmock/errors.rb +9 -7
  6. data/lib/webmock/http_lib_adapters/em_http_request/em_http_request_1_x.rb +23 -7
  7. data/lib/webmock/http_lib_adapters/excon_adapter.rb +4 -4
  8. data/lib/webmock/http_lib_adapters/http_gem/response.rb +3 -2
  9. data/lib/webmock/http_lib_adapters/http_gem/webmock.rb +1 -1
  10. data/lib/webmock/http_lib_adapters/httpclient_adapter.rb +4 -4
  11. data/lib/webmock/matchers/hash_including_matcher.rb +1 -1
  12. data/lib/webmock/request_pattern.rb +11 -10
  13. data/lib/webmock/request_signature.rb +1 -1
  14. data/lib/webmock/request_stub.rb +1 -1
  15. data/lib/webmock/util/hash_keys_stringifier.rb +5 -3
  16. data/lib/webmock/util/query_mapper.rb +226 -146
  17. data/lib/webmock/util/uri.rb +4 -3
  18. data/lib/webmock/version.rb +1 -1
  19. data/lib/webmock/webmock.rb +12 -0
  20. data/spec/acceptance/em_http_request/em_http_request_spec.rb +73 -0
  21. data/spec/acceptance/excon/excon_spec.rb +15 -5
  22. data/spec/acceptance/http_gem/http_gem_spec.rb +9 -0
  23. data/spec/acceptance/httpclient/httpclient_spec.rb +11 -3
  24. data/spec/acceptance/httpclient/httpclient_spec_helper.rb +1 -1
  25. data/spec/acceptance/patron/patron_spec_helper.rb +1 -0
  26. data/spec/acceptance/shared/request_expectations.rb +18 -0
  27. data/spec/acceptance/shared/stubbing_requests.rb +5 -0
  28. data/spec/unit/errors_spec.rb +53 -15
  29. data/spec/unit/request_pattern_spec.rb +15 -0
  30. data/spec/unit/request_signature_spec.rb +3 -0
  31. data/spec/unit/util/hash_keys_stringifier_spec.rb +1 -1
  32. data/spec/unit/util/query_mapper_spec.rb +91 -17
  33. data/spec/unit/util/uri_spec.rb +29 -0
  34. data/webmock.gemspec +2 -2
  35. metadata +7 -15
@@ -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
- Hash[*query_values.sort.inject([]) { |values, pair| values + pair}]
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)
@@ -1,3 +1,3 @@
1
1
  module WebMock
2
- VERSION = '1.18.0' unless defined?(::WebMock::VERSION)
2
+ VERSION = '1.19.0' unless defined?(::WebMock::VERSION)
3
3
  end
@@ -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"].should == "*/*"
141
- req.headers["User-Agent"].should == "#{HTTPClient::DEFAULT_AGENT_NAME} #{HTTPClient::LIB_NAME}"
142
- req.headers["Date"].should_not be_nil
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"
@@ -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
- with(request_stub).and_return(double(:to_s => "bbb"))
12
- expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
13
- "\n\nYou can stub this request with the following snippet:\n\n" +
14
- "bbb\n\n============================================================"
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
- with(request_stub).and_return(double(:to_s => "bbb"))
25
- expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
26
- "\n\nYou can stub this request with the following snippet:\n\n" +
27
- "bbb\n\nregistered request stubs:\n\nbbb\n\n============================================================"
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(double(:to_s => "bbb"))
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
@@ -21,7 +21,7 @@ describe WebMock::Util::HashKeysStringifier do
21
21
  ]
22
22
  }
23
23
  }
24
- WebMock::Util::HashKeysStringifier.stringify_keys!(hash).should == stringified
24
+ WebMock::Util::HashKeysStringifier.stringify_keys!(hash, :deep => true).should == stringified
25
25
  end
26
26
 
27
27
  end
@@ -1,30 +1,104 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe WebMock::Util::QueryMapper do
4
- let(:query_mapper) { described_class }
4
+ subject { described_class }
5
5
 
6
- it "converts query to values" do
7
- query = "key=value&other_key=other_value"
8
- values = { 'key' => 'value', 'other_key' => 'other_value' }
9
- expect(query_mapper.query_to_values query).to eq values
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
- it 'converts values to a query string' do
13
- query = "key=value&other_key=other_value"
14
- values = [['key','value'],['other_key','other_value']]
15
- expect(query_mapper.values_to_query values).to eq query
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
- it 'converts values with missing keys to a query string' do
19
- query = "=value"
20
- values = { '' => 'value' }
21
- expect(query_mapper.values_to_query values).to eq query
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 with nil keys to a query string' do
25
- query = "=value"
26
- values = { nil => 'value' }
27
- expect(query_mapper.values_to_query values).to eq query
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