sagamore-client 3.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.
- checksums.yaml +15 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +66 -0
- data/LICENSE +21 -0
- data/README.md +252 -0
- data/Rakefile +16 -0
- data/lib/sagamore-client.rb +1 -0
- data/lib/sagamore/client.rb +263 -0
- data/lib/sagamore/client/body.rb +12 -0
- data/lib/sagamore/client/collection.rb +108 -0
- data/lib/sagamore/client/errors.rb +17 -0
- data/lib/sagamore/client/resource.rb +205 -0
- data/lib/sagamore/client/response.rb +85 -0
- data/lib/sagamore/client/uri_ext.rb +51 -0
- data/sagamore-client.gemspec +20 -0
- data/spec/sagamore/client/body_spec.rb +32 -0
- data/spec/sagamore/client/resource_spec.rb +250 -0
- data/spec/sagamore/client/response_spec.rb +100 -0
- data/spec/sagamore/client/uri_ext_spec.rb +51 -0
- data/spec/sagamore/client_spec.rb +214 -0
- data/spec/shared_client_context.rb +5 -0
- data/spec/spec_helper.rb +12 -0
- data/vendor/cache/addressable-2.2.8.gem +0 -0
- data/vendor/cache/coderay-1.0.7.gem +0 -0
- data/vendor/cache/coveralls-0.6.9.gem +0 -0
- data/vendor/cache/crack-0.3.1.gem +0 -0
- data/vendor/cache/diff-lcs-1.1.3.gem +0 -0
- data/vendor/cache/hashie-1.2.0.gem +0 -0
- data/vendor/cache/json-1.7.4.gem +0 -0
- data/vendor/cache/method_source-0.8.gem +0 -0
- data/vendor/cache/mime-types-1.25.gem +0 -0
- data/vendor/cache/multi_json-1.8.0.gem +0 -0
- data/vendor/cache/patron-0.4.18.gem +0 -0
- data/vendor/cache/pry-0.9.10.gem +0 -0
- data/vendor/cache/rake-0.9.2.2.gem +0 -0
- data/vendor/cache/rest-client-1.6.7.gem +0 -0
- data/vendor/cache/rspec-2.11.0.gem +0 -0
- data/vendor/cache/rspec-core-2.11.1.gem +0 -0
- data/vendor/cache/rspec-expectations-2.11.2.gem +0 -0
- data/vendor/cache/rspec-mocks-2.11.1.gem +0 -0
- data/vendor/cache/simplecov-0.7.1.gem +0 -0
- data/vendor/cache/simplecov-html-0.7.1.gem +0 -0
- data/vendor/cache/slop-3.3.2.gem +0 -0
- data/vendor/cache/term-ansicolor-1.2.2.gem +0 -0
- data/vendor/cache/thor-0.18.1.gem +0 -0
- data/vendor/cache/tins-0.9.0.gem +0 -0
- data/vendor/cache/webmock-1.8.8.gem +0 -0
- metadata +148 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "sagamore-client"
|
3
|
+
s.version = "3.0.1"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ["Sagamore"]
|
6
|
+
s.summary = "Sagamore client library"
|
7
|
+
|
8
|
+
s.required_rubygems_version = ">= 1.3.6"
|
9
|
+
|
10
|
+
s.add_runtime_dependency 'patron', '~> 0.4.18'
|
11
|
+
s.add_runtime_dependency 'addressable', '~> 2.2.8'
|
12
|
+
s.add_runtime_dependency 'json', '~> 1.7.4'
|
13
|
+
s.add_runtime_dependency 'hashie'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
|
17
|
+
s.require_path = 'lib'
|
18
|
+
end
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sagamore::Client::Body do
|
4
|
+
let(:hash) { {"key1" => "val1", "key2" => {"subkey1" => "subval1"}} }
|
5
|
+
let(:body) { Sagamore::Client::Body.new(hash)}
|
6
|
+
|
7
|
+
describe "[]" do
|
8
|
+
it "should support string keys" do
|
9
|
+
body["key1"].should == "val1"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should support symbol keys" do
|
13
|
+
body[:key1].should == "val1"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "nested hashes" do
|
18
|
+
it "should support nested indifferent access" do
|
19
|
+
body[:key2][:subkey1].should == "subval1"
|
20
|
+
body['key2']['subkey1'].should == "subval1"
|
21
|
+
body[:key2]['subkey1'].should == "subval1"
|
22
|
+
body['key2'][:subkey1].should == "subval1"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "to_hash" do
|
27
|
+
it "should return the original hash" do
|
28
|
+
body.to_hash.should === hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,250 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sagamore::Client::Resource do
|
4
|
+
include_context "client"
|
5
|
+
|
6
|
+
let(:resource_path) { '/some/path' }
|
7
|
+
let(:resource) { Sagamore::Client::Resource.new(client, resource_path) }
|
8
|
+
|
9
|
+
def parse_uri(uri)
|
10
|
+
Addressable::URI.parse(uri)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "[]" do
|
14
|
+
it "should return a new resource" do
|
15
|
+
resource["subpath"].should be_a Sagamore::Client::Resource
|
16
|
+
resource["subpath"].object_id.should_not == resource.object_id
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return a resource with the given subpath appended to its URI" do
|
20
|
+
resource["subpath"].uri.to_s.should == "/some/path/subpath"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return a resource with the same client instance" do
|
24
|
+
resource["subpath"].client.should === resource.client
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept a symbol as a path" do
|
28
|
+
resource[:subpath].uri.to_s.should == "/some/path/subpath"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should accept a symbol as a path" do
|
32
|
+
resource[:subpath].uri.to_s.should == "/some/path/subpath"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not URI encode the given subpath" do
|
36
|
+
resource["subpath with spaces"].uri.to_s.should == "/some/path/subpath with spaces"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
%w{query params}.each do |method|
|
41
|
+
describe method do
|
42
|
+
describe "when called with a hash" do
|
43
|
+
it "should set the query string parameters" do
|
44
|
+
resource.__send__(method, :a => 1, :b => 2).uri.to_s.should == "/some/path?a=1&b=2"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should URL encode the given keys and values" do
|
48
|
+
resource.__send__(method, "i have spaces" => "so do i: duh").uri.to_s.
|
49
|
+
should == "/some/path?i%20have%20spaces=so%20do%20i%3A%20duh"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should add bracket notation for array parameters" do
|
53
|
+
resource.__send__(method, :somearray => [1, 2, 3]).uri.to_s.should == "/some/path?somearray[]=1&somearray[]=2&somearray[]=3"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "when called without arguments" do
|
58
|
+
it "should return the current query string parameters as a hash" do
|
59
|
+
resource.__send__(method).should == {}
|
60
|
+
new_resource = resource.__send__(method, :a => 1, :b => 2)
|
61
|
+
new_resource.__send__(method).should == {"a"=>"1", "b"=>"2"}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "filter" do
|
68
|
+
describe "when given a hash" do
|
69
|
+
it "should add a _filter query string param" do
|
70
|
+
resource.filter(:a => 1, :b => 2).uri.should ==
|
71
|
+
'/some/path?_filter={"a":1,"b":2}'.to_uri
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "when called multiple times" do
|
76
|
+
it "should append args to _filter param as JSON array" do
|
77
|
+
resource.filter(:a => 1).filter(:b => 2).filter(:c => 3).uri.should ==
|
78
|
+
'/some/path?_filter=[{"a":1},{"b":2},{"c":3}]'.to_uri
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "when given a string" do
|
83
|
+
it "should add a _filter query string param" do
|
84
|
+
resource.filter('{"a":1,"b":2}').uri.should ==
|
85
|
+
'/some/path?_filter={"a":1,"b":2}'.to_uri
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "sort" do
|
91
|
+
it "should set the sort parameter based on the given values" do
|
92
|
+
resource.sort('f1', 'f2,desc').uri.query.should == 'sort[]=f1&sort[]=f2%2Cdesc'
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should replace any existing sort parameter" do
|
96
|
+
resource.sort('f1', 'f2,desc')
|
97
|
+
resource.sort('f3,asc', 'f4').uri.query.should == 'sort[]=f3%2Casc&sort[]=f4'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
%w{count each each_page}.each do |method|
|
102
|
+
describe method do
|
103
|
+
it "should call the client's #{method} method with the resource's URI" do
|
104
|
+
client.should_receive(method).with(resource.uri)
|
105
|
+
resource.__send__(method)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
%w{get head delete}.each do |method|
|
111
|
+
describe method do
|
112
|
+
it "should call the client's #{method} method with the resource's URI and a header hash" do
|
113
|
+
client.should_receive(method).with(resource.uri, false)
|
114
|
+
resource.__send__(method)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
%w{put post}.each do |method|
|
120
|
+
describe method do
|
121
|
+
it "should call the client's #{method} method with the resource's URI, the given body, and a headers hash" do
|
122
|
+
client.should_receive(method).with(resource.uri, "body", false)
|
123
|
+
resource.__send__(method, "body")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "first" do
|
129
|
+
let(:response_data) {
|
130
|
+
{
|
131
|
+
:status => 200,
|
132
|
+
:body => {:results => [{:id => "Me first!"}, {:id => "Me second!"}]}.to_json
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
it "should set the per_page query string param to 1" do
|
137
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
138
|
+
resource.first
|
139
|
+
request_stub.should have_been_requested
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should return the first element of the :results array" do
|
143
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
144
|
+
resource.first.should == {"id" => "Me first!"}
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "embed" do
|
149
|
+
it "should support a single embed" do
|
150
|
+
resource.embed(:thing1).uri.to_s.should ==
|
151
|
+
'/some/path?_include[]=thing1'
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should support multiple embeds" do
|
155
|
+
resource.embed(:thing1, :thing2, :thing3).uri.to_s.should ==
|
156
|
+
'/some/path?_include[]=thing1&_include[]=thing2&_include[]=thing3'
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should merge multiple embed calls" do
|
160
|
+
resource.embed(:thing1, :thing2).embed(:thing3, :thing4).uri.to_s.should ==
|
161
|
+
'/some/path?_include[]=thing1&_include[]=thing2&_include[]=thing3&_include[]=thing4'
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should merge multiple embed calls" do
|
165
|
+
resource.embed(:thing1, :thing2).embed(:thing3, :thing4).uri.to_s.should ==
|
166
|
+
'/some/path?_include[]=thing1&_include[]=thing2&_include[]=thing3&_include[]=thing4'
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should merge a call to embed with a manually added _include query param" do
|
170
|
+
resource.query('_include[]' => :thing1).embed(:thing2, :thing3).uri.to_s.should ==
|
171
|
+
'/some/path?_include[]=thing1&_include[]=thing2&_include[]=thing3'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "while_results" do
|
176
|
+
it "should yield each result to the block as long as the response includes results" do
|
177
|
+
results = ["r1", "r2", "r3"]
|
178
|
+
|
179
|
+
request_stub = stub_request(:get, "#{base_url}/some/path").to_return do |req|
|
180
|
+
{:body => {:results => results}.to_json}
|
181
|
+
end
|
182
|
+
|
183
|
+
yielded_results = []
|
184
|
+
|
185
|
+
# timeout in case of endless loop
|
186
|
+
Timeout::timeout(1) do
|
187
|
+
resource.while_results do |result|
|
188
|
+
yielded_results.push results.shift
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
yielded_results.should == ["r1", "r2", "r3"]
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should raise an exception if it receives an error response" do
|
196
|
+
request_stub = stub_request(:get, "#{base_url}/some/path").to_return do |req|
|
197
|
+
{:status => 400}
|
198
|
+
end
|
199
|
+
|
200
|
+
# timeout in case of endless loop
|
201
|
+
Timeout::timeout(1) do
|
202
|
+
expect do
|
203
|
+
resource.while_results do |result|
|
204
|
+
# nothing
|
205
|
+
end
|
206
|
+
end.to raise_error(Sagamore::Client::RequestFailed)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "exists?" do
|
211
|
+
let(:response) { mock(Sagamore::Client::Response) }
|
212
|
+
|
213
|
+
it "should return true if the response indicates success" do
|
214
|
+
response.stub!(:success?).and_return(true)
|
215
|
+
client.should_receive(:head).with(resource.uri, false).and_return(response)
|
216
|
+
resource.exists?.should === true
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should return false if the response status is 404" do
|
220
|
+
response.stub!(:status).and_return(404)
|
221
|
+
response.stub!(:success?).and_return(false)
|
222
|
+
client.should_receive(:head).with(resource.uri, false).and_return(response)
|
223
|
+
resource.exists?.should === false
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should raise a RequestFailed exception if the request fails but the status is not 404" do
|
227
|
+
response.stub!(:status).and_return(400)
|
228
|
+
response.stub!(:success?).and_return(false)
|
229
|
+
client.should_receive(:head).with(resource.uri, false).and_return(response)
|
230
|
+
expect { resource.exists? }.to raise_error { |e|
|
231
|
+
e.should be_a Sagamore::Client::RequestFailed
|
232
|
+
e.response.should === response
|
233
|
+
e.message.should == "Request during call to 'exists?' resulted in non-404 error."
|
234
|
+
}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "empty?" do
|
239
|
+
it "should return true if the resource has a count of zero" do
|
240
|
+
resource.stub!(:count).and_return 0
|
241
|
+
resource.empty?.should === true
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should return false if the resource has a count greater than zero" do
|
245
|
+
resource.stub!(:count).and_return 10
|
246
|
+
resource.empty?.should === false
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sagamore::Client::Response do
|
4
|
+
include_context "client"
|
5
|
+
|
6
|
+
let(:raw_body) { '{"key":"value"}' }
|
7
|
+
let(:raw_headers) { 'X-Custom-Header: Hi' }
|
8
|
+
let(:status_code) { 200 }
|
9
|
+
let(:path) { '/path' }
|
10
|
+
let(:patron_response) { Patron::Response.new(path, status_code, 0, raw_headers, raw_body) }
|
11
|
+
let(:response) { Sagamore::Client::Response.new(patron_response, client) }
|
12
|
+
|
13
|
+
describe "body" do
|
14
|
+
describe "if raw body is valid JSON" do
|
15
|
+
it "should return a Sagamore::Client::Body" do
|
16
|
+
response.body.should be_a Sagamore::Client::Body
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should wrap the parsed response body" do
|
20
|
+
response.body.to_hash.should == {"key" => "value"}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "if raw body is not valid JSON" do
|
25
|
+
let(:raw_body) { 'I am not JSON!' }
|
26
|
+
it "should raise an informative error" do
|
27
|
+
expect { response.body }.to raise_error \
|
28
|
+
Sagamore::Client::BodyError,
|
29
|
+
"Can't parse response body. (Hint: Try the raw_body method.)"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "if raw body is empty" do
|
34
|
+
let(:raw_body) { '' }
|
35
|
+
it "should raise an informative error" do
|
36
|
+
expect { response.body }.to raise_error \
|
37
|
+
Sagamore::Client::BodyError,
|
38
|
+
"Response body is empty. (Hint: If you just created a new resource, try: response.resource.get)"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "raw_body" do
|
44
|
+
it "should return the raw body JSON" do
|
45
|
+
response.raw_body.should == raw_body
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "headers" do
|
50
|
+
it "should return the response headers as a hash" do
|
51
|
+
response.headers.should == {'X-Custom-Header' => 'Hi'}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "resource" do
|
56
|
+
describe "when Location header is returned" do
|
57
|
+
let(:raw_headers) { 'Location: /new/path' }
|
58
|
+
|
59
|
+
it "should be a Sagamore::Client::Resource" do
|
60
|
+
response.resource.should be_a Sagamore::Client::Resource
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should have the Location header value as its URL" do
|
64
|
+
response.resource.uri.to_s.should == '/new/path'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "when Location header is not returned" do
|
69
|
+
let(:raw_headers) { '' }
|
70
|
+
|
71
|
+
it "should be nil" do
|
72
|
+
response.resource.should be_nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "[]" do
|
78
|
+
it "should forward [] to body" do
|
79
|
+
response.body.should_receive(:[]).with("key").and_return("value")
|
80
|
+
response["key"].should == "value"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "success?" do
|
85
|
+
%w{100 101 102 200 201 202 203 204 205 206 207 208 226 300 301 302 303 304 305 306 307 308}.each do |code|
|
86
|
+
it "should return true if the response status code is #{code}" do
|
87
|
+
response.stub!(:status).and_return(code.to_i)
|
88
|
+
response.success?.should === true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
%w{400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 425 426 428 429 431
|
93
|
+
444 449 450 499 500 501 502 503 504 505 506 507 508 509 510 511 598 599}.each do |code|
|
94
|
+
it "should return false if the response status code is #{code}" do
|
95
|
+
response.stub!(:status).and_return(code.to_i)
|
96
|
+
response.success?.should === false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Addressable::URI do
|
4
|
+
let(:uri) { Addressable::URI.parse('/relative/path') }
|
5
|
+
|
6
|
+
describe "subpath" do
|
7
|
+
it "should return a new URI with the path relative to the receiver" do
|
8
|
+
uri.subpath('other').should == Addressable::URI.parse('/relative/path/other')
|
9
|
+
uri.subpath('/other').should == Addressable::URI.parse('/relative/path/other')
|
10
|
+
uri.subpath(Addressable::URI.parse('/other')) == Addressable::URI.parse('/relative/path/other')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "merge_query_values!" do
|
15
|
+
it "should call sagamore_query_values=" do
|
16
|
+
uri.query_values = {'a' => '1'}
|
17
|
+
uri.should_receive(:sagamore_query_values=).with({'a' => '1', 'b' => '2'})
|
18
|
+
uri.merge_query_values! 'b' => '2'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should merge the given values with the existing query_values" do
|
22
|
+
uri.query_values = {'a' => '1', 'b' => '2'}
|
23
|
+
uri.merge_query_values! 'b' => '20', 'c' => '30'
|
24
|
+
uri.query_values.should == {'a' => '1', 'b' => '20', 'c' => '30'}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should set the given values if there are no existing query_values" do
|
28
|
+
uri.query_values.should be_nil
|
29
|
+
uri.merge_query_values! 'b' => '20', 'c' => '30'
|
30
|
+
uri.query_values.should == {'b' => '20', 'c' => '30'}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "sagamore_query_values=" do
|
35
|
+
it "should preserve empty bracket notation for array params" do
|
36
|
+
uri.query = 'sort[]=f1&sort[]=f2'
|
37
|
+
uri.__send__(:sagamore_query_values=, uri.query_values)
|
38
|
+
uri.to_s.should == '/relative/path?sort[]=f1&sort[]=f2'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should stringify boolean param values" do
|
42
|
+
uri.__send__(:sagamore_query_values=, {:p1 => true, :p2 => false})
|
43
|
+
uri.to_s.should == '/relative/path?p1=true&p2=false'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should support hash param values" do
|
47
|
+
uri.__send__(:sagamore_query_values=, {:a => {:b => {:c => 123}}})
|
48
|
+
uri.to_s.should == '/relative/path?a[b][c]=123'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|