voorhees 0.2.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.
@@ -0,0 +1,335 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe User do
4
+
5
+ before :each do
6
+ load_json
7
+ end
8
+
9
+ describe "ClassMethods" do
10
+ describe "new_from_json" do
11
+
12
+ it "Should create a new User" do
13
+ User.should_receive(:new).once.and_return(mock(:user, :null_object => true))
14
+ user_from_json
15
+ end
16
+
17
+ it "should assign the JSON to User#raw_json" do
18
+ mock_user = mock(:user, :null_object => true)
19
+ User.stub!(:new).and_return(mock_user)
20
+ mock_user.should_receive(:raw_json=).with(@json)
21
+ user_from_json
22
+ end
23
+
24
+ it "should assign the hierarchy to User#json_hierarchy" do
25
+ mock_user = mock(:user, :null_object => true)
26
+ User.stub!(:new).and_return(mock_user)
27
+ mock_user.should_receive(:json_hierarchy=).with(@hierarchy)
28
+ user_from_json
29
+ end
30
+
31
+ it "should return the new user" do
32
+ user_from_json.should be_an_instance_of(User)
33
+ end
34
+ end
35
+
36
+ describe "json_request" do
37
+
38
+ before :each do
39
+ @json_string= "{}"
40
+ @json_hash = {}
41
+
42
+ @request = mock(:request, :null_object => true)
43
+ @response = mock(:response, :null_object => true)
44
+ @objects = [mock(:object)]
45
+
46
+ Voorhees::Request.stub!(:new).and_return(@request)
47
+ @request.stub!(:perform).and_return(@response)
48
+
49
+ @response.stub!(:to_objects).and_return(@objects)
50
+ @response.stub!(:json).and_return(@json_hash)
51
+ @response.stub!(:body).and_return(@json_string)
52
+ end
53
+
54
+ def perform_request
55
+ User.json_request{}
56
+ end
57
+
58
+
59
+ it "should call Request.new with the current class if no class is passed" do
60
+ Voorhees::Request.should_receive(:new).with(User).and_return(@request)
61
+ perform_request
62
+ end
63
+
64
+ it "should call Request.new with the specified class if a class is passed" do
65
+ Voorhees::Request.should_receive(:new).with(Message).and_return(@request)
66
+ User.json_request(:class => Message) do |request|
67
+ # ...
68
+ end
69
+ end
70
+
71
+
72
+ it "should yeild a request" do
73
+ User.json_request do |r|
74
+ r.should == @request
75
+ end
76
+ end
77
+
78
+ it "should raise a LocalJumpError exception if a block is not given" do
79
+ lambda{
80
+ User.json_request
81
+ }.should raise_error(LocalJumpError)
82
+ end
83
+
84
+ it "should implicitly call Request#perform" do
85
+ @request.should_receive(:perform).once
86
+ perform_request
87
+ end
88
+
89
+ it "should return the result of Response#to_objects if :returning is not set" do
90
+ perform_request.should == @objects
91
+ end
92
+
93
+ it "should return the JSON string if :returning is set to :raw" do
94
+ User.json_request(:returning => :raw){}.should == @json_string
95
+ end
96
+
97
+ it "should return the JSON hash if :returning is set to :json" do
98
+ User.json_request(:returning => :json){}.should == @json_hash
99
+ end
100
+
101
+ it "should return the objects string if :returning is set to :objects" do
102
+ User.json_request(:returning => :objects){}.should == @objects
103
+ end
104
+
105
+ it "should return the response if :returning is set to :response" do
106
+ User.json_request(:returning => :response){}.should == @response
107
+ end
108
+
109
+ end
110
+
111
+ describe "json_service" do
112
+
113
+ before :each do
114
+ @service_name = :list
115
+ @service_attrs = {
116
+ :timeout => 100,
117
+ :required => [:monkeys]
118
+ }
119
+ end
120
+
121
+ def define_service
122
+ User.json_service @service_name, @service_attrs
123
+ end
124
+
125
+ it "should define a method with the same name as the service" do
126
+ User.should_not respond_to(@service_name)
127
+ define_service
128
+ User.should respond_to(@service_name)
129
+ end
130
+
131
+ describe "calling the defined method" do
132
+
133
+ before :each do
134
+ define_service
135
+
136
+ @request = mock(:request, :null_object => true)
137
+ @response = mock(:response, :null_object => true)
138
+ @objects = [mock(:object)]
139
+
140
+ Voorhees::Request.stub!(:new).and_return(@request)
141
+ @request.stub!(:perform).and_return(@response)
142
+ end
143
+
144
+ it "should call User#json_request" do
145
+ User.should_receive(:json_request).and_return(@response)
146
+ User.list
147
+ end
148
+
149
+ it "should pass service attributes onto the request" do
150
+ @service_attrs.each do |key, value|
151
+ @request.should_receive("#{key}=").with(value)
152
+ end
153
+ User.list
154
+ end
155
+
156
+ it "should use any hash passed in to set the request parameters" do
157
+ params = {:monkeys => true}
158
+ @request.should_receive(:parameters=).with(params)
159
+ User.list(params)
160
+ end
161
+
162
+ it "should return the result of Response#to_objects" do
163
+ @response.should_receive(:to_objects).and_return(@objects)
164
+ User.list.should == @objects
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ describe "InstanceMethods" do
171
+
172
+ describe "#raw_json" do
173
+ it "should contain the raw json" do
174
+ user_from_json.raw_json.should == @json
175
+ end
176
+ end
177
+
178
+ describe "#json_attributes" do
179
+ it "should contain symbols of the keys of the attributes available as underscored" do
180
+ user_from_json.json_attributes.sort.should == [:address, :camel_case, :email, :id, :messages, :name, :pet, :username]
181
+ end
182
+ end
183
+
184
+ describe "#json_request" do
185
+
186
+ before :each do
187
+ @request = mock(:request, :null_object => true)
188
+ @response = mock(:response, :null_object => true)
189
+
190
+ Voorhees::Request.stub!(:new).and_return(@request)
191
+ @request.stub!(:perform).and_return(@response)
192
+ end
193
+
194
+ def perform_request
195
+ user_from_json.json_request{}
196
+ end
197
+
198
+ it "should pass the request to the class method" do
199
+ User.should_receive(:json_request)
200
+ user_from_json.json_request{}
201
+ end
202
+
203
+ it "should raise a LocalJumpError exception if a block is not given" do
204
+ lambda{
205
+ user_from_json.json_request
206
+ }.should raise_error(LocalJumpError)
207
+ end
208
+
209
+ it "should implicitly call Request#perform" do
210
+ @request.should_receive(:perform).once
211
+ perform_request
212
+ end
213
+
214
+ it "should return the result of Request#perform" do
215
+ perform_request.should == @response
216
+ end
217
+
218
+ end
219
+
220
+ describe "calling assignment method with name of a json attribute" do
221
+
222
+ it "should define an assignment method" do
223
+ user = user_from_json
224
+
225
+ user.should_not respond_to(:email=)
226
+ user.email = "test"
227
+ user.should respond_to(:email=)
228
+ end
229
+
230
+ it "should assign the value" do
231
+ user = user_from_json
232
+ new_email = "a_new_address@example.com"
233
+
234
+ user.email = new_email
235
+ user.email.should == new_email
236
+ end
237
+
238
+ end
239
+
240
+ describe "calling method with the name of a json attribute" do
241
+
242
+ it "should return the correct data from #id" do
243
+ user = user_from_json
244
+ user.id.should == @json["id"]
245
+ end
246
+
247
+ it "should define a method of the same name" do
248
+ user = user_from_json
249
+
250
+ user.should_not respond_to(:email)
251
+ user.email
252
+ user.should respond_to(:email)
253
+ end
254
+
255
+ it "should return the correct data from defined methods" do
256
+ user = user_from_json
257
+
258
+ user.email # first access, now it's defined
259
+ user.email.should == @json["email"]
260
+ end
261
+
262
+ describe "which is a simple value" do
263
+ it "should return the value of the attribute" do
264
+ user_from_json.email.should == @json["email"]
265
+ end
266
+ end
267
+
268
+ describe "which is camelCase in the JSON" do
269
+ it "should return the value of the attribute" do
270
+ user_from_json.camel_case.should == @json["camelCase"]
271
+ end
272
+ end
273
+
274
+ describe "which is a collection" do
275
+ it "should return an array" do
276
+ user_from_json.messages.should be_an_instance_of(Array)
277
+ end
278
+
279
+ it "should infer the type of objects based on the collection name" do
280
+ user_from_json.messages.each do |m|
281
+ m.should be_an_instance_of(Message)
282
+ end
283
+ end
284
+ end
285
+
286
+ describe "which is a sub-object" do
287
+
288
+ it "should return as a Hash if the hierarchy is not defined" do
289
+ @hierarchy = {
290
+ }
291
+ user_from_json.pet.should be_a(Hash)
292
+ end
293
+
294
+ it "should return as the right class if the hierarchy is defined as symbol" do
295
+ @hierarchy = {
296
+ :address => :address
297
+ }
298
+ user_from_json.address.should be_a(Address)
299
+ end
300
+
301
+ it "should return as the right class if the hierarchy is defined as Class" do
302
+ @hierarchy = {
303
+ :address => Address
304
+ }
305
+ user_from_json.address.should be_a(Address)
306
+ end
307
+
308
+ it "should return as the right class for multiple depths" do
309
+ @hierarchy = {
310
+ :address => [Address, {
311
+ :coords => LatLon
312
+ }]
313
+ }
314
+ user_from_json.address.coords.should be_a(LatLon)
315
+ end
316
+
317
+ end
318
+
319
+ end
320
+
321
+ end
322
+ end
323
+
324
+ def load_json
325
+ body = ''
326
+ path = File.expand_path(File.dirname(__FILE__) + '/fixtures/user.json')
327
+ File.open(path, 'r') do |f|
328
+ body = f.read
329
+ end
330
+ @json = JSON.parse(body)
331
+ end
332
+
333
+ def user_from_json
334
+ User.new_from_json(@json, @hierarchy)
335
+ end
@@ -0,0 +1,93 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Voorhees::Response do
4
+
5
+ before :each do
6
+ User.stub!(:new_from_json).and_return(User.new)
7
+ end
8
+
9
+ describe "to_objects" do
10
+
11
+ describe "with no class set" do
12
+
13
+ before :each do
14
+ @klass = nil
15
+ build_response(:users)
16
+ end
17
+
18
+ it "should return nil" do
19
+ @response.to_objects.should be_nil
20
+ end
21
+
22
+ end
23
+
24
+ describe "with a class which does not have Voorhees::Resource mixed in" do
25
+
26
+ before :each do
27
+ @klass = NotResource
28
+ build_response(:users)
29
+ end
30
+
31
+ it "should raise a Voorhees::NotResourceError exception" do
32
+ lambda{
33
+ @response.to_objects
34
+ }.should raise_error(Voorhees::NotResourceError)
35
+ end
36
+
37
+ end
38
+
39
+ describe "with a class which has Voorhees::Resource mixed in" do
40
+
41
+ before :each do
42
+ @klass = User
43
+ end
44
+
45
+ describe "with JSON containing an array of 2 items" do
46
+
47
+ before :each do
48
+ build_response(:users)
49
+ end
50
+
51
+ it "should return an array of 2 objects of the right class" do
52
+ users = @response.to_objects
53
+ users.length.should == 2
54
+ users.each do |u|
55
+ u.should be_an_instance_of(User)
56
+ end
57
+ end
58
+
59
+ it "should create objects by sending the JSON and hierarchy to Class.new_from_json" do
60
+ User.should_receive(:new_from_json).with(@response.json[0], @hierarchy).ordered
61
+ User.should_receive(:new_from_json).with(@response.json[1], @hierarchy).ordered
62
+ @response.to_objects
63
+ end
64
+ end
65
+
66
+ describe "with JSON containing one item" do
67
+
68
+ before :each do
69
+ build_response(:user)
70
+ end
71
+
72
+ it "should return one object of the right class" do
73
+ user = @response.to_objects
74
+ user.should be_an_instance_of(User)
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def build_response(fixture)
83
+ body = ''
84
+ path = File.expand_path(File.dirname(__FILE__) + "/fixtures/#{fixture}.json")
85
+ File.open(path, 'r') do |f|
86
+ body = f.read
87
+ end
88
+
89
+ @hierarchy = {
90
+ :address => Address
91
+ }
92
+ @response = Voorhees::Response.new(body, @klass, @hierarchy)
93
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec'
2
+ require 'rubygems'
3
+ require 'json'
4
+ require 'active_support'
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ require 'voorhees'
9
+
10
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/resources')
11
+
12
+ Spec::Runner.configure do |config|
13
+
14
+ end
15
+
16
+ # allow sorting by symbol
17
+ class Symbol
18
+ def <=>(a)
19
+ self.to_s <=> a.to_s
20
+ end
21
+ end
22
+