heartland-retail 5.0.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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/.yardopts +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +84 -0
- data/LICENSE +21 -0
- data/README.md +272 -0
- data/Rakefile +18 -0
- data/heartland-retail.gemspec +17 -0
- data/lib/heartland-retail.rb +1 -0
- data/lib/heartland/client.rb +299 -0
- data/lib/heartland/client/body.rb +13 -0
- data/lib/heartland/client/collection.rb +121 -0
- data/lib/heartland/client/errors.rb +17 -0
- data/lib/heartland/client/resource.rb +215 -0
- data/lib/heartland/client/response.rb +84 -0
- data/lib/heartland/client/uri.rb +117 -0
- data/spec/heartland/client/body_spec.rb +31 -0
- data/spec/heartland/client/resource_spec.rb +318 -0
- data/spec/heartland/client/response_spec.rb +105 -0
- data/spec/heartland/client/uri_spec.rb +157 -0
- data/spec/heartland/client_spec.rb +361 -0
- data/spec/shared_client_context.rb +5 -0
- data/spec/spec_helper.rb +17 -0
- data/vendor/cache/addressable-2.2.8.gem +0 -0
- data/vendor/cache/codeclimate-test-reporter-1.0.8.gem +0 -0
- data/vendor/cache/coderay-1.1.0.gem +0 -0
- data/vendor/cache/coveralls-0.7.11.gem +0 -0
- data/vendor/cache/crack-0.4.2.gem +0 -0
- data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
- data/vendor/cache/docile-1.1.5.gem +0 -0
- data/vendor/cache/faraday-0.17.3.gem +0 -0
- data/vendor/cache/hashie-4.1.0.gem +0 -0
- data/vendor/cache/json-2.3.0.gem +0 -0
- data/vendor/cache/method_source-0.8.2.gem +0 -0
- data/vendor/cache/mime-types-2.4.3.gem +0 -0
- data/vendor/cache/multi_json-1.11.0.gem +0 -0
- data/vendor/cache/multipart-post-2.1.1.gem +0 -0
- data/vendor/cache/netrc-0.10.3.gem +0 -0
- data/vendor/cache/pry-0.10.1.gem +0 -0
- data/vendor/cache/rake-10.4.2.gem +0 -0
- data/vendor/cache/rest-client-1.7.3.gem +0 -0
- data/vendor/cache/rspec-3.2.0.gem +0 -0
- data/vendor/cache/rspec-core-3.2.2.gem +0 -0
- data/vendor/cache/rspec-expectations-3.2.0.gem +0 -0
- data/vendor/cache/rspec-mocks-3.2.1.gem +0 -0
- data/vendor/cache/rspec-support-3.2.2.gem +0 -0
- data/vendor/cache/safe_yaml-1.0.4.gem +0 -0
- data/vendor/cache/simplecov-0.9.2.gem +0 -0
- data/vendor/cache/simplecov-html-0.9.0.gem +0 -0
- data/vendor/cache/slop-3.6.0.gem +0 -0
- data/vendor/cache/term-ansicolor-1.3.0.gem +0 -0
- data/vendor/cache/thor-0.19.1.gem +0 -0
- data/vendor/cache/tins-1.3.5.gem +0 -0
- data/vendor/cache/webmock-1.17.4.gem +0 -0
- metadata +140 -0
@@ -0,0 +1,318 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HeartlandRetail::Client::Resource do
|
4
|
+
include_context "client"
|
5
|
+
|
6
|
+
let(:resource_path) { '/some/path' }
|
7
|
+
let(:resource) { HeartlandRetail::Client::Resource.new(client, resource_path) }
|
8
|
+
|
9
|
+
describe "[]" do
|
10
|
+
it "should return a new resource" do
|
11
|
+
expect(resource["subpath"]).to be_a HeartlandRetail::Client::Resource
|
12
|
+
expect(resource["subpath"].object_id).not_to eq(resource.object_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return a resource with the given subpath appended to its URI" do
|
16
|
+
expect(resource["subpath"].uri.to_s).to eq("#{base_url}/some/path/subpath")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return a resource with the same client instance" do
|
20
|
+
expect(resource["subpath"].client).to be === resource.client
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should accept a symbol as a path" do
|
24
|
+
expect(resource[:subpath].uri.to_s).to eq("#{base_url}/some/path/subpath")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should URI encode the given subpath" do
|
28
|
+
expect(resource["subpath with spaces"].uri.to_s).to eq(
|
29
|
+
"#{base_url}/some/path/subpath%20with%20spaces"
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
%w{query params}.each do |method|
|
35
|
+
describe method do
|
36
|
+
describe "when called with a hash" do
|
37
|
+
it "should set the query string parameters" do
|
38
|
+
expect(resource.__send__(method, :a => 1, :b => 2).uri.to_s).to eq("#{base_url}/some/path?a=1&b=2")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should URL encode the given keys and values" do
|
42
|
+
expect(resource.__send__(method, "i have spaces" => "so do i: duh").uri.to_s).to eq(
|
43
|
+
"#{base_url}/some/path?i+have+spaces=so+do+i%3A+duh"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should add bracket notation for array parameters" do
|
48
|
+
expect(resource.__send__(method, :somearray => [1, 2, 3]).uri.to_s).to eq(
|
49
|
+
"#{base_url}/some/path?somearray%5B%5D=1&somearray%5B%5D=2&somearray%5B%5D=3"
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return a new resource without modifying the existing URI" do
|
54
|
+
new_resource = resource.query(per_page: 1)
|
55
|
+
expect(new_resource.uri.to_s).to eq("#{base_url}/some/path?per_page=1")
|
56
|
+
expect(resource.uri.to_s).to eq("#{base_url}/some/path")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "when called without arguments" do
|
61
|
+
it "should return the current query string parameters as a hash" do
|
62
|
+
expect(resource.__send__(method)).to eq({})
|
63
|
+
new_resource = resource.__send__(method, :a => 1, :b => 2)
|
64
|
+
expect(new_resource.__send__(method)).to eq({"a"=>"1", "b"=>"2"})
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "filter" do
|
71
|
+
describe "when given a hash" do
|
72
|
+
it "should add a _filter query string param" do
|
73
|
+
expect(resource.filter(:a => 1, :b => 2).uri).to eq(
|
74
|
+
"#{base_url}/some/path?_filter=%7B%22a%22%3A1%2C%22b%22%3A2%7D".to_uri
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "when called multiple times" do
|
80
|
+
it "should append args to _filter param as JSON array" do
|
81
|
+
expect(resource.filter(:a => 1).filter(:b => 2).filter(:c => 3).uri).to eq(
|
82
|
+
"#{base_url}/some/path?_filter=%5B%7B%22a%22%3A1%7D%2C%7B%22b%22%3A2%7D%2C%7B%22c%22%3A3%7D%5D".to_uri
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "when given a string" do
|
88
|
+
it "should add a _filter query string param" do
|
89
|
+
expect(resource.filter('{"a":1,"b":2}').uri).to eq(
|
90
|
+
"#{base_url}/some/path?_filter=%7B%22a%22%3A1%2C%22b%22%3A2%7D".to_uri
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "when called multiple times with other methods" do
|
96
|
+
it "should append args to _filter param as JSON array" do
|
97
|
+
expect(resource.filter(:a => 1).embed(:other).only(:field).filter(:b => 2).uri).to eq(
|
98
|
+
"#{base_url}/some/path?_filter=%5B%7B%22a%22%3A1%7D%2C%7B%22b%22%3A2%7D%5D&_include%5B%5D=other&_only%5B%5D=field".to_uri
|
99
|
+
)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "sort" do
|
105
|
+
it "should set the sort parameter based on the given values" do
|
106
|
+
expect(resource.sort('f1', 'f2,desc').uri.to_s).to eq(
|
107
|
+
"#{base_url}/some/path?sort%5B%5D=f1&sort%5B%5D=f2%2Cdesc"
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should replace any existing sort parameter" do
|
112
|
+
resource.sort('f1', 'f2,desc')
|
113
|
+
expect(resource.sort('f3,asc', 'f4').uri.to_s).to eq(
|
114
|
+
"#{base_url}/some/path?sort%5B%5D=f3%2Casc&sort%5B%5D=f4"
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "only" do
|
120
|
+
it "should set the _only parameter based on the given values" do
|
121
|
+
expect(resource.only('f1', 'f2').uri.to_s).to eq(
|
122
|
+
"#{base_url}/some/path?_only%5B%5D=f1&_only%5B%5D=f2"
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should replace the existing _only parameters" do
|
127
|
+
expect(resource.only('f1').only('f2', 'f3').uri.to_s).to eq(
|
128
|
+
"#{base_url}/some/path?_only%5B%5D=f2&_only%5B%5D=f3"
|
129
|
+
)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
%w{each each_page}.each do |method|
|
134
|
+
describe method do
|
135
|
+
it "should call the client's #{method} method with the resource's URI" do
|
136
|
+
expect(client).to receive(method).with(resource.uri)
|
137
|
+
resource.__send__(method)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
%w{get head delete}.each do |method|
|
143
|
+
describe method do
|
144
|
+
it "should call the client's #{method} method with the resource's URI and a header hash" do
|
145
|
+
expect(client).to receive(method).with(resource.uri, false)
|
146
|
+
resource.__send__(method)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
%w{put post}.each do |method|
|
152
|
+
describe method do
|
153
|
+
it "should call the client's #{method} method with the resource's URI, the given body, and a headers hash" do
|
154
|
+
expect(client).to receive(method).with(resource.uri, "body", false)
|
155
|
+
resource.__send__(method, "body")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "count" do
|
161
|
+
let(:response_data) {
|
162
|
+
{
|
163
|
+
:status => 200,
|
164
|
+
:body => {total: 123}.to_json
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
it "should call the client's count method with the resource's URI" do
|
169
|
+
expect(client).to receive(:count).with(resource.uri)
|
170
|
+
resource.count
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should set the per_page query string param to 1" do
|
174
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
175
|
+
resource.count
|
176
|
+
expect(request_stub).to have_been_requested
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should return the resource count" do
|
180
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
181
|
+
expect(resource.count).to eq(123)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should not modify the original resource URI" do
|
185
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
186
|
+
resource.count
|
187
|
+
expect(resource.uri.to_s).to eq("#{base_url}/some/path")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "first" do
|
192
|
+
let(:response_data) {
|
193
|
+
{
|
194
|
+
:status => 200,
|
195
|
+
:body => {:results => [{:id => "Me first!"}, {:id => "Me second!"}]}.to_json
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
it "should set the per_page query string param to 1" do
|
200
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
201
|
+
resource.first
|
202
|
+
expect(request_stub).to have_been_requested
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should return the first element of the :results array" do
|
206
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
207
|
+
expect(resource.first).to eq({"id" => "Me first!"})
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should not modify the original resource URI" do
|
211
|
+
request_stub = stub_request(:get, "#{base_url}/some/path?page=1&per_page=1").to_return(response_data)
|
212
|
+
resource.first
|
213
|
+
expect(resource.uri.to_s).to eq("#{base_url}/some/path")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "embed" do
|
218
|
+
it "should support a single embed" do
|
219
|
+
expect(resource.embed(:thing1).uri.to_s).to eq(
|
220
|
+
"#{base_url}/some/path?_include%5B%5D=thing1"
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should support multiple embeds" do
|
225
|
+
expect(resource.embed(:thing1, :thing2, :thing3).uri.to_s).to eq(
|
226
|
+
"#{base_url}/some/path?_include%5B%5D=thing1&_include%5B%5D=thing2&_include%5B%5D=thing3"
|
227
|
+
)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should merge multiple embed calls" do
|
231
|
+
expect(resource.embed(:thing1, :thing2).embed(:thing3, :thing4).uri.to_s).to eq(
|
232
|
+
"#{base_url}/some/path?_include%5B%5D=thing1&_include%5B%5D=thing2&_include%5B%5D=thing3&_include%5B%5D=thing4"
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should merge a call to embed with a manually added _include query param" do
|
237
|
+
expect(resource.query('_include[]' => :thing1).embed(:thing2, :thing3).uri.to_s).to eq(
|
238
|
+
"#{base_url}/some/path?_include%5B%5D=thing1&_include%5B%5D=thing2&_include%5B%5D=thing3"
|
239
|
+
)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "while_results" do
|
244
|
+
it "should yield each result to the block as long as the response includes results" do
|
245
|
+
results = ["r1", "r2", "r3"]
|
246
|
+
|
247
|
+
request_stub = stub_request(:get, "#{base_url}/some/path").to_return do |req|
|
248
|
+
{:body => {:results => results}.to_json}
|
249
|
+
end
|
250
|
+
|
251
|
+
yielded_results = []
|
252
|
+
|
253
|
+
# timeout in case of endless loop
|
254
|
+
Timeout::timeout(10) do
|
255
|
+
resource.while_results do |result|
|
256
|
+
yielded_results.push results.shift
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
expect(yielded_results).to eq(["r1", "r2", "r3"])
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should raise an exception if it receives an error response" do
|
264
|
+
request_stub = stub_request(:get, "#{base_url}/some/path").to_return do |req|
|
265
|
+
{:status => 400}
|
266
|
+
end
|
267
|
+
|
268
|
+
# timeout in case of endless loop
|
269
|
+
Timeout::timeout(10) do
|
270
|
+
expect do
|
271
|
+
resource.while_results do |result|
|
272
|
+
# nothing
|
273
|
+
end
|
274
|
+
end.to raise_error(HeartlandRetail::Client::RequestFailed)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "exists?" do
|
279
|
+
let(:response) { double(HeartlandRetail::Client::Response) }
|
280
|
+
|
281
|
+
it "should return true if the response indicates success" do
|
282
|
+
allow(response).to receive(:success?).and_return(true)
|
283
|
+
expect(client).to receive(:head).with(resource.uri, false).and_return(response)
|
284
|
+
expect(resource.exists?).to be === true
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should return false if the response status is 404" do
|
288
|
+
allow(response).to receive(:status).and_return(404)
|
289
|
+
allow(response).to receive(:success?).and_return(false)
|
290
|
+
expect(client).to receive(:head).with(resource.uri, false).and_return(response)
|
291
|
+
expect(resource.exists?).to be === false
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should raise a RequestFailed exception if the request fails but the status is not 404" do
|
295
|
+
allow(response).to receive(:status).and_return(400)
|
296
|
+
allow(response).to receive(:success?).and_return(false)
|
297
|
+
expect(client).to receive(:head).with(resource.uri, false).and_return(response)
|
298
|
+
expect { resource.exists? }.to raise_error { |e|
|
299
|
+
expect(e).to be_a HeartlandRetail::Client::RequestFailed
|
300
|
+
expect(e.response).to be === response
|
301
|
+
expect(e.message).to eq("Request during call to 'exists?' resulted in non-404 error.")
|
302
|
+
}
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe "empty?" do
|
307
|
+
it "should return true if the resource has a count of zero" do
|
308
|
+
allow(resource).to receive(:count).and_return 0
|
309
|
+
expect(resource.empty?).to be === true
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should return false if the resource has a count greater than zero" do
|
313
|
+
allow(resource).to receive(:count).and_return 10
|
314
|
+
expect(resource.empty?).to be === false
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HeartlandRetail::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(:faraday_response) do
|
11
|
+
env = Faraday::Env.new(:get, raw_body, path, nil, nil, nil, nil,
|
12
|
+
nil, raw_body, raw_headers, status_code)
|
13
|
+
|
14
|
+
Faraday::Response.new(env)
|
15
|
+
end
|
16
|
+
let(:response) { HeartlandRetail::Client::Response.new(faraday_response, client) }
|
17
|
+
|
18
|
+
describe "body" do
|
19
|
+
describe "if raw body is valid JSON" do
|
20
|
+
it "should return a HeartlandRetail::Client::Body" do
|
21
|
+
expect(response.body).to be_a HeartlandRetail::Client::Body
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should wrap the parsed response body" do
|
25
|
+
expect(response.body.to_hash).to eq({"key" => "value"})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "if raw body is not valid JSON" do
|
30
|
+
let(:raw_body) { 'I am not JSON!' }
|
31
|
+
it "should raise an informative error" do
|
32
|
+
expect { response.body }.to raise_error \
|
33
|
+
HeartlandRetail::Client::BodyError,
|
34
|
+
"Can't parse response body. (Hint: Try the raw_body method.)"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "if raw body is empty" do
|
39
|
+
let(:raw_body) { '' }
|
40
|
+
it "should raise an informative error" do
|
41
|
+
expect { response.body }.to raise_error \
|
42
|
+
HeartlandRetail::Client::BodyError,
|
43
|
+
"Response body is empty. (Hint: If you just created a new resource, try: response.resource.get)"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "raw_body" do
|
49
|
+
it "should return the raw body JSON" do
|
50
|
+
expect(response.raw_body).to eq(raw_body)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "headers" do
|
55
|
+
it "should return the response headers as a hash" do
|
56
|
+
expect(response.headers).to eq({'X-Custom-Header' => 'Hi'})
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "resource" do
|
61
|
+
describe "when Location header is returned" do
|
62
|
+
let(:raw_headers) { { Location: '/new/path' } }
|
63
|
+
|
64
|
+
it "should be a HeartlandRetail::Client::Resource" do
|
65
|
+
expect(response.resource).to be_a HeartlandRetail::Client::Resource
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should have the Location header value as its URL" do
|
69
|
+
expect(response.resource.uri.to_s).to eq("#{base_url}/new/path")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "when Location header is not returned" do
|
74
|
+
let(:raw_headers) { Hash.new }
|
75
|
+
|
76
|
+
it "should be nil" do
|
77
|
+
expect(response.resource).to be_nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "[]" do
|
83
|
+
it "should forward [] to body" do
|
84
|
+
expect(response.body).to receive(:[]).with("key").and_return("value")
|
85
|
+
expect(response["key"]).to eq("value")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "success?" do
|
90
|
+
%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|
|
91
|
+
it "should return true if the response status code is #{code}" do
|
92
|
+
allow(response).to receive(:status).and_return(code.to_i)
|
93
|
+
expect(response.success?).to be === true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
%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
|
98
|
+
444 449 450 499 500 501 502 503 504 505 506 507 508 509 510 511 598 599}.each do |code|
|
99
|
+
it "should return false if the response status code is #{code}" do
|
100
|
+
allow(response).to receive(:status).and_return(code.to_i)
|
101
|
+
expect(response.success?).to be === false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HeartlandRetail::Client::URI do
|
4
|
+
let(:uri) { described_class.parse('/relative/path') }
|
5
|
+
|
6
|
+
describe "subpath" do
|
7
|
+
it "should return a new URI with the path relative to the receiver" do
|
8
|
+
expect(uri.subpath('other')).to eq(described_class.parse('/relative/path/other'))
|
9
|
+
expect(uri.subpath('/other')).to eq(described_class.parse('/relative/path/other'))
|
10
|
+
uri.subpath(described_class.parse('/other')) == described_class.parse('/relative/path/other')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "parse" do
|
15
|
+
describe "when called with a URI object" do
|
16
|
+
it "should return a cloned URI object" do
|
17
|
+
parsed_uri = described_class.parse(uri)
|
18
|
+
expect(uri.class).to eq(parsed_uri.class)
|
19
|
+
expect(uri.object_id).not_to eq(parsed_uri.object_id)
|
20
|
+
expect(parsed_uri.to_s).to eq(uri.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "when called with a URI string" do
|
25
|
+
it "should return a URI based on the given string" do
|
26
|
+
uri = described_class.parse('/some_path')
|
27
|
+
expect(uri).to be_a(described_class)
|
28
|
+
expect(uri.to_s).to eq('/some_path')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "dup" do
|
34
|
+
it "should return a duplicate URI object" do
|
35
|
+
dup_uri = uri.dup
|
36
|
+
expect(uri.class).to eq(dup_uri.class)
|
37
|
+
expect(uri.to_s).to eq(dup_uri.to_s)
|
38
|
+
expect(uri.object_id).not_to eq(dup_uri.object_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "when mutating the copy" do
|
42
|
+
it "should not affect the original" do
|
43
|
+
dup_uri = uri.dup
|
44
|
+
dup_uri.query_values = {per_page: 1}
|
45
|
+
expect(uri.to_s).to eq('/relative/path')
|
46
|
+
expect(dup_uri.to_s).to eq('/relative/path?per_page=1')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "==" do
|
52
|
+
it "should consider two URIs parsed from the same string equal" do
|
53
|
+
expect(
|
54
|
+
described_class.parse('http://example.com/some_path?a=1&b=2') ==
|
55
|
+
described_class.parse('http://example.com/some_path?a=1&b=2')
|
56
|
+
).to be(true)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should consider two URIs parsed from different strings not equal" do
|
60
|
+
expect(
|
61
|
+
described_class.parse('http://example.com/some_path?a=1&b=2') ==
|
62
|
+
described_class.parse('http://example.com/some_path?a=1&c=3')
|
63
|
+
).to be(false)
|
64
|
+
|
65
|
+
expect(
|
66
|
+
described_class.parse('http://foo.example.com') ==
|
67
|
+
described_class.parse('http://bar.example.com')
|
68
|
+
).to be(false)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "merge_query_values!" do
|
73
|
+
it "should merge the given values with the existing query_values" do
|
74
|
+
uri.query_values = {'a' => '1', 'b' => '2'}
|
75
|
+
uri.merge_query_values! 'c' => '3'
|
76
|
+
expect(uri.query_values).to eq(
|
77
|
+
{'a' => '1', 'b' => '2', 'c' => '3'}
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should overwrite the previous values when a new value is given" do
|
82
|
+
uri.query_values = {'a' => '1', 'b' => '2'}
|
83
|
+
uri.merge_query_values! 'a' => '3', 'b' => '4'
|
84
|
+
expect(uri.query_values).to eq(
|
85
|
+
{'a' => '3', 'b' => '4'}
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should overwrite the previous values if a new array is given" do
|
90
|
+
uri.query_values = {'a' => '1', 'b' => ['2', '3']}
|
91
|
+
uri.merge_query_values! 'b' => ['4', '5']
|
92
|
+
expect(uri.query_values).to eq(
|
93
|
+
{'a' => '1', 'b' => ['4', '5']}
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should set the given values if there are no existing query_values" do
|
98
|
+
expect(uri.query_values).to be_nil
|
99
|
+
uri.merge_query_values! 'a' => ['10'], 'b' => '20', 'c' => '30'
|
100
|
+
expect(uri.query_values).to eq({'a' => ['10'], 'b' => '20', 'c' => '30'})
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "query_values=" do
|
105
|
+
it "should set the string value for the specified key" do
|
106
|
+
uri.query_values = {'p1' => '1'}
|
107
|
+
expect(uri.query_values).to eq({'p1' => '1'})
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should preserve empty bracket notation for array params" do
|
111
|
+
uri.query = 'sort[]=f1&sort[]=f2'
|
112
|
+
uri.query_values = uri.query_values
|
113
|
+
expect(uri.to_s).to eq('/relative/path?sort%5B%5D=f1&sort%5B%5D=f2')
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should stringify symbol keys" do
|
117
|
+
uri.query_values = {:a => '1'}
|
118
|
+
expect(uri.query_values).to eq({'a' => '1'})
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should stringify boolean param values" do
|
122
|
+
uri.query_values = {:p1 => true, :p2 => false}
|
123
|
+
expect(uri.to_s).to eq('/relative/path?p1=true&p2=false')
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should support hash param values" do
|
127
|
+
uri.query_values = {:a => {:b => {:c => 123}}}
|
128
|
+
expect(uri.to_s).to eq(
|
129
|
+
'/relative/path?a=%7B%22b%22%3D%3E%7B%22c%22%3D%3E123%7D%7D'
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should add [] to the key for array values" do
|
134
|
+
uri.query_values = {:a => ['1', '2', '3']}
|
135
|
+
expect(uri.query).to eq('a%5B%5D=1&a%5B%5D=2&a%5B%5D=3')
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should remove duplicate values for the same key" do
|
139
|
+
uri.query_values = {:a => ['1', '1', '2']}
|
140
|
+
expect(uri.query_values).to eq({'a' => ['1', '2']})
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "query_values" do
|
145
|
+
it "should return the current query values" do
|
146
|
+
uri.query = 'sort[]=f1&sort[]=f2&per_page=all'
|
147
|
+
uri.query_values = uri.query_values
|
148
|
+
expect(uri.query_values).to eq({'sort' => ['f1', 'f2'], 'per_page' => 'all'})
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should remove [] from array keys" do
|
152
|
+
uri.query = 'sort[]=f1&sort[]=f2'
|
153
|
+
uri.query_values = uri.query_values
|
154
|
+
expect(uri.query_values).to eq({'sort' => ['f1', 'f2']})
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|