rod-rest 0.0.1.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,7 +9,7 @@ stub_class 'Rod::Rest::ProxyFactory'
9
9
  module Rod
10
10
  module Rest
11
11
  describe Client do
12
- let(:factory_class) { stub!.new([resource1],is_a(Client)) { factory }.subject }
12
+ let(:factory_class) { stub!.new([resource1],is_a(Client),is_a(Hash)) { factory }.subject }
13
13
  let(:factory) { Object.new }
14
14
  let(:metadata) { stub!.resources { [resource1] }.subject }
15
15
  let(:resource1) { resource = stub!.name { resource_name }.subject
@@ -23,9 +23,11 @@ module Rod
23
23
  let(:car_type) { resource_name }
24
24
  let(:response) { stub!.status{ 200 }.subject }
25
25
  let(:web_client) { Object.new }
26
+ let(:proxy_cache) { nil }
26
27
 
27
28
  describe "without metadata provided to the client" do
28
- let(:client) { Client.new(http_client: web_client,metadata_factory: metadata_factory, factory: factory_class) }
29
+ let(:client) { Client.new(http_client: web_client,metadata_factory: metadata_factory, factory: factory_class,
30
+ proxy_cache: proxy_cache) }
29
31
  let(:metadata_factory) { stub!.new(description: metadata_description) { metadata }.subject }
30
32
  let(:metadata_description) { "{}" }
31
33
 
@@ -39,9 +41,9 @@ module Rod
39
41
  end
40
42
 
41
43
  describe "when fetching the data via the API" do
42
- let(:json_cars_count) { { count: 3 }.to_json }
44
+ let(:cars_count_json) { { count: 3 }.to_json }
43
45
  let(:cars_response) { response = stub!.status { 200 }.subject
44
- stub(response).body { json_cars_count }
46
+ stub(response).body { cars_count_json }
45
47
  response
46
48
  }
47
49
 
@@ -56,18 +58,18 @@ module Rod
56
58
  end
57
59
 
58
60
  describe "with metadata provided to the client" do
59
- let(:client) { Client.new(http_client: web_client,metadata: metadata, factory: factory_class) }
61
+ let(:client) { Client.new(http_client: web_client,metadata: metadata, factory: factory_class, proxy_cache: proxy_cache) }
60
62
 
61
63
  let(:invalid_id) { 1000 }
62
64
  let(:invalid_index) { 2000 }
63
65
  let(:invalid_response) { stub!.status{ 404 }.subject }
64
66
 
65
67
  describe "#cars_count" do
66
- let(:json_cars_count) { { count: 3 }.to_json }
68
+ let(:cars_count_json) { { count: 3 }.to_json }
67
69
 
68
70
  before do
69
71
  stub(web_client).get("/cars") { response }
70
- stub(response).body { json_cars_count }
72
+ stub(response).body { cars_count_json }
71
73
  end
72
74
 
73
75
  it "returns the number of cars" do
@@ -75,51 +77,86 @@ module Rod
75
77
  end
76
78
  end
77
79
 
78
- describe "with two cars defined" do
80
+ describe "with three cars defined" do
79
81
  let(:mercedes_300_id) { 1 }
82
+ let(:mercedes_180_id) { 2 }
83
+ let(:audi_a4_id) { 3 }
80
84
  let(:mercedes_300_hash) { {rod_id: mercedes_300_id, type: car_type } }
81
- let(:mercedes_180_hash) { {rod_id: 2, type: car_type } }
82
- let(:mercedes_300_proxy){ Object.new }
83
- let(:mercedes_180_proxy){ Object.new }
84
- let(:factory) { factory = stub!.build(mercedes_300_hash) { mercedes_300_proxy }.subject
85
- stub(factory).build(mercedes_180_hash) { mercedes_180_proxy }
85
+ let(:mercedes_180_hash) { {rod_id: mercedes_180_id, type: car_type } }
86
+ let(:audi_a4_hash) { {rod_id: audi_a4_id, type: car_type } }
87
+ let(:mercedes_300) { mercedes = stub!.rod_id { mercedes_300_id }.subject
88
+ stub(mercedes).type { car_type }
89
+ mercedes
90
+ }
91
+ let(:mercedes_180) { Object.new }
92
+ let(:audi_a4) { Object.new }
93
+ let(:factory) { factory = stub!.build(mercedes_300_hash) { mercedes_300 }.subject
94
+ stub(factory).build(mercedes_180_hash) { mercedes_180 }
95
+ stub(factory).build(audi_a4_hash) { audi_a4 }
86
96
  factory
87
97
  }
88
98
 
89
99
  describe "#find_cars_by_name(name)" do
90
100
  let(:car_name) { "Mercedes" }
91
101
  let(:property_name) { "name" }
92
- let(:json_cars) { [mercedes_300_hash,mercedes_180_hash].to_json }
102
+ let(:cars_json) { [mercedes_300_hash,mercedes_180_hash].to_json }
93
103
  let(:indexed_properties){ [indexed_property] }
94
104
  let(:indexed_property) { stub!.name { property_name }.subject }
95
105
 
96
106
  before do
97
107
  stub(web_client).get("/cars?#{property_name}=#{car_name}") { response }
98
- stub(response).body { json_cars }
108
+ stub(response).body { cars_json }
99
109
  end
100
110
 
101
111
  it "finds the cars by their name" do
102
112
  cars = client.find_cars_by_name(car_name)
103
- expected_cars = [mercedes_300_proxy,mercedes_180_proxy]
104
- cars.size.should == expected_cars.size
105
- cars.zip(expected_cars).each do |result,expected|
106
- result.should == expected
107
- end
113
+ expected_cars = [mercedes_300,mercedes_180]
114
+ cars.should == expected_cars
115
+ end
116
+ end
117
+
118
+ describe "#find_cars(1..3)" do
119
+ let(:cars_json) { [mercedes_300_hash,mercedes_180_hash,audi_a4_hash].to_json }
120
+
121
+ before do
122
+ stub(web_client).get("/cars/#{mercedes_300_id}..#{audi_a4_id}") { response }
123
+ stub(response).body { cars_json }
124
+ end
125
+
126
+ it "returns range of cars" do
127
+ cars = client.find_cars(mercedes_300_id..audi_a4_id)
128
+ expected_cars = [mercedes_300,mercedes_180,audi_a4]
129
+ cars.should == expected_cars
130
+ end
131
+ end
132
+
133
+ describe "#find_cars(1,3)" do
134
+ let(:cars_json) { [mercedes_300_hash,audi_a4_hash].to_json }
135
+
136
+ before do
137
+ stub(web_client).get("/cars/#{mercedes_300_id},#{audi_a4_id}") { response }
138
+ stub(response).body { cars_json }
139
+ end
140
+
141
+ it "returns collection of cars" do
142
+ cars = client.find_cars(mercedes_300_id,audi_a4_id)
143
+ expected_cars = [mercedes_300,audi_a4]
144
+ cars.should == expected_cars
108
145
  end
109
146
  end
110
147
 
111
148
  describe "with car response defined" do
112
- let(:json_mercedes_300) { mercedes_300_hash.to_json }
149
+ let(:mercedes_300_json) { mercedes_300_hash.to_json }
113
150
 
114
151
  before do
115
152
  stub(web_client).get("/cars/#{mercedes_300_id}") { response }
116
153
  stub(web_client).get("/cars/#{invalid_id}") { invalid_response }
117
- stub(response).body { json_mercedes_300 }
154
+ stub(response).body { mercedes_300_json }
118
155
  end
119
156
 
120
157
  describe "#find_car(rod_id)" do
121
158
  it "finds the car by its rod_id" do
122
- client.find_car(mercedes_300_id).should == mercedes_300_proxy
159
+ client.find_car(mercedes_300_id).should == mercedes_300
123
160
  end
124
161
 
125
162
  it "raises MissingResource exception for invalid car rod_id" do
@@ -134,7 +171,7 @@ module Rod
134
171
  let(:invalid_type) { "InvalidType" }
135
172
 
136
173
  it "finds the car by its stub" do
137
- client.fetch_object(car_stub).should == mercedes_300_proxy
174
+ client.fetch_object(car_stub).should == mercedes_300
138
175
  end
139
176
 
140
177
  it "raises MissingResource execption for invalid car rod_id" do
@@ -154,13 +191,13 @@ module Rod
154
191
 
155
192
  describe "#car_drivers_count(rod_id)" do
156
193
  let(:drivers_count) { 3 }
157
- let(:json_driver_count) { { count: drivers_count }.to_json }
194
+ let(:driver_count_json) { { count: drivers_count }.to_json }
158
195
 
159
196
 
160
197
  before do
161
198
  stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}") { response }
162
199
  stub(web_client).get("/cars/#{invalid_id}/#{association_name}") { invalid_response }
163
- stub(response).body { json_driver_count }
200
+ stub(response).body { driver_count_json }
164
201
  end
165
202
 
166
203
  it "returns the number of car drivers" do
@@ -172,24 +209,33 @@ module Rod
172
209
  end
173
210
  end
174
211
 
175
- describe "with reponse defined" do
212
+ describe "with drivers" do
176
213
  let(:schumaher_index) { 0 }
214
+ let(:alonzo_index) { 2 }
177
215
  let(:schumaher_hash) { { rod_id: schumaher_id, name: "Schumaher", type: "Driver" } }
216
+ let(:kubica_hash) { { rod_id: 3, name: "Kubica", type: "Driver" } }
217
+ let(:alonzo_hash) { { rod_id: 4, name: "Alonzo", type: "Driver" } }
178
218
  let(:schumaher_json) { schumaher_hash.to_json }
179
- let(:schumaher_proxy) { Object.new }
219
+ let(:kubica_json) { kubica_hash.to_json }
220
+ let(:alonzo_json) { schumaher_hash.to_json }
221
+ let(:schumaher) { Object.new }
222
+ let(:kubica) { Object.new }
223
+ let(:alonzo) { Object.new }
180
224
  let(:schumaher_id) { 1 }
181
225
 
182
226
  before do
227
+ stub(factory).build(schumaher_hash) { schumaher }
228
+ stub(factory).build(kubica_hash) { kubica }
229
+ stub(factory).build(alonzo_hash) { alonzo }
183
230
  stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{schumaher_index}") { response }
184
231
  stub(web_client).get("/cars/#{invalid_id}/#{association_name}/#{schumaher_index}") { invalid_response }
185
232
  stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{invalid_index}") { invalid_response }
186
233
  stub(response).body { schumaher_json }
187
- stub(factory).build(schumaher_hash) { schumaher_proxy }
188
234
  end
189
235
 
190
236
  describe "#car_driver(rod_id,index)" do
191
237
  it "returns the driver" do
192
- client.car_driver(mercedes_300_id,schumaher_index).should == schumaher_proxy
238
+ client.car_driver(mercedes_300_id,schumaher_index).should == schumaher
193
239
  end
194
240
 
195
241
  it "raises MissingResource exception for invalid car rod_id" do
@@ -201,6 +247,34 @@ module Rod
201
247
  end
202
248
  end
203
249
 
250
+ describe "#car_drivers(subject,relation,0..2)" do
251
+ let(:drivers) { [schumaher,kubica,alonzo] }
252
+ let(:collection_json) { [schumaher_hash,kubica_hash,alonzo_hash].to_json }
253
+
254
+ before do
255
+ stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{schumaher_index}..#{alonzo_index}") { response }
256
+ stub(response).body { collection_json }
257
+ end
258
+
259
+ it "returns the collection of drivers" do
260
+ client.car_drivers(mercedes_300_id,schumaher_index..alonzo_index).should == drivers
261
+ end
262
+ end
263
+
264
+ describe "#car_drivers(subject,relation,0,2)" do
265
+ let(:drivers) { [schumaher,alonzo] }
266
+ let(:collection_json) { [schumaher_hash,alonzo_hash].to_json }
267
+
268
+ before do
269
+ stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{schumaher_index},#{alonzo_index}") { response }
270
+ stub(response).body { collection_json }
271
+ end
272
+
273
+ it "returns the collection of drivers" do
274
+ client.car_drivers(mercedes_300_id,schumaher_index,alonzo_index).should == drivers
275
+ end
276
+ end
277
+
204
278
  describe "#fetch_related_object(subject,relation,index)" do
205
279
  let(:association_name) { "drivers" }
206
280
  let(:invalid_association_name){ "owners" }
@@ -214,13 +288,8 @@ module Rod
214
288
  proxy
215
289
  }
216
290
 
217
- before do
218
- stub(mercedes_300_proxy).rod_id { mercedes_300_id }
219
- stub(mercedes_300_proxy).type { car_type }
220
- end
221
-
222
291
  it "returns the driver" do
223
- client.fetch_related_object(mercedes_300_proxy,association_name,schumaher_index).should == schumaher_proxy
292
+ client.fetch_related_object(mercedes_300,association_name,schumaher_index).should == schumaher
224
293
  end
225
294
 
226
295
  it "raises MissingResource exception for invalid car proxy id" do
@@ -228,7 +297,7 @@ module Rod
228
297
  end
229
298
 
230
299
  it "raises MissingResource exception for invalid index" do
231
- lambda { client.fetch_related_object(mercedes_300_proxy,association_name,invalid_index)}.should raise_exception(MissingResource)
300
+ lambda { client.fetch_related_object(mercedes_300,association_name,invalid_index)}.should raise_exception(MissingResource)
232
301
  end
233
302
 
234
303
  it "raises APIError exception for invalid resource type" do
@@ -236,7 +305,37 @@ module Rod
236
305
  end
237
306
 
238
307
  it "raises APIError exception for invalid association name" do
239
- lambda { client.fetch_related_object(mercedes_300_proxy,invalid_association_name,schumaher_index)}.should raise_exception(APIError)
308
+ lambda { client.fetch_related_object(mercedes_300,invalid_association_name,schumaher_index)}.should raise_exception(APIError)
309
+ end
310
+ end
311
+
312
+ describe "#fetch_related_objects(subject,relation,0..2)" do
313
+ let(:association_name) { "drivers" }
314
+ let(:drivers) { [schumaher,kubica,alonzo] }
315
+ let(:collection_json) { [schumaher_hash,kubica_hash,alonzo_hash].to_json }
316
+
317
+ before do
318
+ stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{schumaher_index}..#{alonzo_index}") { response }
319
+ stub(response).body { collection_json }
320
+ end
321
+
322
+ it "returns drivers collection" do
323
+ client.fetch_related_objects(mercedes_300,association_name,schumaher_index..alonzo_index).should == drivers
324
+ end
325
+ end
326
+
327
+ describe "#fetch_related_objects(subject,relation,0,2)" do
328
+ let(:association_name) { "drivers" }
329
+ let(:drivers) { [schumaher,alonzo] }
330
+ let(:collection_json) { [schumaher_hash,alonzo_hash].to_json }
331
+
332
+ before do
333
+ stub(web_client).get("/cars/#{mercedes_300_id}/#{association_name}/#{schumaher_index},#{alonzo_index}") { response }
334
+ stub(response).body { collection_json }
335
+ end
336
+
337
+ it "returns drivers collection" do
338
+ client.fetch_related_objects(mercedes_300,association_name,schumaher_index,alonzo_index).should == drivers
240
339
  end
241
340
  end
242
341
  end
@@ -11,6 +11,34 @@ module Rod
11
11
  let(:size) { 0 }
12
12
  let(:client) { Object.new }
13
13
 
14
+ describe "#inspect" do
15
+ let(:car_type) { "Car" }
16
+ before do
17
+ stub(mercedes_proxy).type { car_type }
18
+ end
19
+
20
+ it "reports the type of the proxy object" do
21
+ collection.inspect.should match(/#{car_type}/)
22
+ end
23
+
24
+ it "reports the name of the association" do
25
+ collection.inspect.should match(/#{association_name}/)
26
+ end
27
+
28
+ it "reports size of the collection" do
29
+ collection.inspect.should match(/#{size}/)
30
+ end
31
+ end
32
+
33
+ describe "#to_s" do
34
+ it "reports the size of the collection" do
35
+ collection.to_s.should match(/#{size}/)
36
+ end
37
+ end
38
+
39
+ describe "#to_s" do
40
+ end
41
+
14
42
  describe "#empty?" do
15
43
  describe "with 0 elements" do
16
44
  it "is empty" do
@@ -60,6 +88,29 @@ module Rod
60
88
  it "returns nil in case of out of bounds driver" do
61
89
  collection[5].should == nil
62
90
  end
91
+
92
+ it "caches retrieved objects" do
93
+ collection[1]
94
+ collection[1]
95
+ expect(client).to have_received.fetch_related_object(mercedes_proxy,association_name,1) { kubica }.once
96
+ end
97
+ end
98
+
99
+ describe "#[lower..upper]" do
100
+ before do
101
+ stub(client).fetch_related_objects(mercedes_proxy,association_name,0..2) { [schumaher,kubica,alonzo] }
102
+ end
103
+
104
+ it "returns drivers by index range" do
105
+ collection[0..2].should == [schumaher,kubica,alonzo]
106
+ end
107
+
108
+ it "caches retrieved objects" do
109
+ collection[0..2]
110
+ collection[1]
111
+ collection[1]
112
+ expect(client).to have_received.fetch_related_objects(mercedes_proxy,association_name,0..2).once
113
+ end
63
114
  end
64
115
 
65
116
  describe "#first" do
@@ -84,9 +135,7 @@ module Rod
84
135
 
85
136
  describe "#each" do
86
137
  before do
87
- stub(client).fetch_related_object(mercedes_proxy,association_name,0) { schumaher }
88
- stub(client).fetch_related_object(mercedes_proxy,association_name,1) { kubica }
89
- stub(client).fetch_related_object(mercedes_proxy,association_name,2) { alonzo }
138
+ stub(client).fetch_related_objects(mercedes_proxy,association_name,0..2) { [schumaher,kubica,alonzo] }
90
139
  end
91
140
 
92
141
  it "iterates over the drivers" do
@@ -32,6 +32,30 @@ module Rod
32
32
  metadata.resources.first
33
33
  expect(resource_metadata_factory).to have_received.new(resource_name,resource_description)
34
34
  end
35
+
36
+ describe "#inspect" do
37
+ let(:data_description) { "data description" }
38
+
39
+ before do
40
+ stub(description).inspect { data_description }
41
+ end
42
+
43
+ it "returns the description of the data" do
44
+ metadata.inspect.should match(/#{data_description}/)
45
+ end
46
+ end
47
+
48
+ describe "#to_s" do
49
+ let(:data_description) { "data description" }
50
+
51
+ before do
52
+ stub(description).to_s { data_description }
53
+ end
54
+
55
+ it "returns the description of the data" do
56
+ metadata.to_s.should match(/#{data_description}/)
57
+ end
58
+ end
35
59
  end
36
60
  end
37
61
  end
@@ -6,6 +6,8 @@ module Rod
6
6
  module Rest
7
7
  describe PropertyMetadata do
8
8
  let(:property_metadata) { PropertyMetadata.new(name,options) }
9
+ let(:name) { :age }
10
+ let(:options) { { type: :integer } }
9
11
 
10
12
  describe "constructor" do
11
13
  it "forbids to create property without name" do
@@ -14,9 +16,6 @@ module Rod
14
16
  end
15
17
 
16
18
  describe "#name" do
17
- let(:options) { { type: :integer } }
18
- let(:name) { :age }
19
-
20
19
  it "converts its name to string" do
21
20
  property_metadata.name.should be_a(String)
22
21
  end
@@ -27,9 +26,6 @@ module Rod
27
26
  end
28
27
 
29
28
  describe "#symbolic_name" do
30
- let(:options) { { type: :string } }
31
- let(:name) { :name }
32
-
33
29
  it "converts its symbolic name to string" do
34
30
  property_metadata.symbolic_name.should be_a(Symbol)
35
31
  end
@@ -58,6 +54,35 @@ module Rod
58
54
  end
59
55
  end
60
56
  end
57
+
58
+ describe "#inspect" do
59
+ let(:options) { { type: :string, index: index } }
60
+ let(:index) { nil }
61
+
62
+ it "reports the name of the property" do
63
+ property_metadata.inspect.should match(/#{name}/)
64
+ end
65
+
66
+ context "without index" do
67
+ it "doesn't report that it is indexed" do
68
+ property_metadata.inspect.should_not match(/indexed/)
69
+ end
70
+ end
71
+
72
+ context "with index" do
73
+ let(:index) { :hash }
74
+
75
+ it "reports that it is indexed" do
76
+ property_metadata.inspect.should match(/indexed/)
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#to_s" do
82
+ it "reports the name of the property" do
83
+ property_metadata.to_s.should match(/#{name}/)
84
+ end
85
+ end
61
86
  end
62
87
  end
63
88
  end