activeresource_csi 2.3.5.p6

Sign up to get free protection for your applications and to get access to all the features.
data/test/base_test.rb ADDED
@@ -0,0 +1,1038 @@
1
+ require 'abstract_unit'
2
+ require "fixtures/person"
3
+ require "fixtures/customer"
4
+ require "fixtures/street_address"
5
+ require "fixtures/beast"
6
+ require "fixtures/proxy"
7
+
8
+ class BaseTest < Test::Unit::TestCase
9
+ def setup
10
+ @matz = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
11
+ @david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
12
+ @greg = { :id => 3, :name => 'Greg' }.to_xml(:root => 'person')
13
+ @addy = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address')
14
+ @default_request_headers = { 'Content-Type' => 'application/xml' }
15
+ @rick = { :name => "Rick", :age => 25 }.to_xml(:root => "person")
16
+ @people = [{ :id => 1, :name => 'Matz' }, { :id => 2, :name => 'David' }].to_xml(:root => 'people')
17
+ @people_david = [{ :id => 2, :name => 'David' }].to_xml(:root => 'people')
18
+ @addresses = [{ :id => 1, :street => '12345 Street' }].to_xml(:root => 'addresses')
19
+
20
+ # - deep nested resource -
21
+ # - Luis (Customer)
22
+ # - JK (Customer::Friend)
23
+ # - Mateo (Customer::Friend::Brother)
24
+ # - Edith (Customer::Friend::Brother::Child)
25
+ # - Martha (Customer::Friend::Brother::Child)
26
+ # - Felipe (Customer::Friend::Brother)
27
+ # - Bryan (Customer::Friend::Brother::Child)
28
+ # - Luke (Customer::Friend::Brother::Child)
29
+ # - Eduardo (Customer::Friend)
30
+ # - Sebas (Customer::Friend::Brother)
31
+ # - Andres (Customer::Friend::Brother::Child)
32
+ # - Jorge (Customer::Friend::Brother::Child)
33
+ # - Elsa (Customer::Friend::Brother)
34
+ # - Natacha (Customer::Friend::Brother::Child)
35
+ # - Milena (Customer::Friend::Brother)
36
+ #
37
+ @luis = {:id => 1, :name => 'Luis',
38
+ :friends => [{:name => 'JK',
39
+ :brothers => [{:name => 'Mateo',
40
+ :children => [{:name => 'Edith'},{:name => 'Martha'}]},
41
+ {:name => 'Felipe',
42
+ :children => [{:name => 'Bryan'},{:name => 'Luke'}]}]},
43
+ {:name => 'Eduardo',
44
+ :brothers => [{:name => 'Sebas',
45
+ :children => [{:name => 'Andres'},{:name => 'Jorge'}]},
46
+ {:name => 'Elsa',
47
+ :children => [{:name => 'Natacha'}]},
48
+ {:name => 'Milena',
49
+ :children => []}]}]}.to_xml(:root => 'customer')
50
+ # - resource with yaml array of strings; for ActiveRecords using serialize :bar, Array
51
+ @marty = <<-eof.strip
52
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
53
+ <person>
54
+ <id type=\"integer\">5</id>
55
+ <name>Marty</name>
56
+ <colors type=\"yaml\">---
57
+ - \"red\"
58
+ - \"green\"
59
+ - \"blue\"
60
+ </colors>
61
+ </person>
62
+ eof
63
+
64
+ ActiveResource::HttpMock.respond_to do |mock|
65
+ mock.get "/people/1.xml", {}, @matz
66
+ mock.get "/people/2.xml", {}, @david
67
+ mock.get "/people/5.xml", {}, @marty
68
+ mock.get "/people/Greg.xml", {}, @greg
69
+ mock.get "/people/4.xml", {'key' => 'value'}, nil, 404
70
+ mock.put "/people/1.xml", {}, nil, 204
71
+ mock.delete "/people/1.xml", {}, nil, 200
72
+ mock.delete "/people/2.xml", {}, nil, 400
73
+ mock.get "/people/99.xml", {}, nil, 404
74
+ mock.post "/people.xml", {}, @rick, 201, 'Location' => '/people/5.xml'
75
+ mock.get "/people.xml", {}, @people
76
+ mock.get "/people/1/addresses.xml", {}, @addresses
77
+ mock.get "/people/1/addresses/1.xml", {}, @addy
78
+ mock.get "/people/1/addresses/2.xml", {}, nil, 404
79
+ mock.get "/people/2/addresses/1.xml", {}, nil, 404
80
+ mock.get "/people/Greg/addresses/1.xml", {}, @addy
81
+ mock.put "/people/1/addresses/1.xml", {}, nil, 204
82
+ mock.delete "/people/1/addresses/1.xml", {}, nil, 200
83
+ mock.post "/people/1/addresses.xml", {}, nil, 201, 'Location' => '/people/1/addresses/5'
84
+ mock.get "/people//addresses.xml", {}, nil, 404
85
+ mock.get "/people//addresses/1.xml", {}, nil, 404
86
+ mock.put "/people//addresses/1.xml", {}, nil, 404
87
+ mock.delete "/people//addresses/1.xml", {}, nil, 404
88
+ mock.post "/people//addresses.xml", {}, nil, 404
89
+ mock.head "/people/1.xml", {}, nil, 200
90
+ mock.head "/people/Greg.xml", {}, nil, 200
91
+ mock.head "/people/99.xml", {}, nil, 404
92
+ mock.head "/people/1/addresses/1.xml", {}, nil, 200
93
+ mock.head "/people/1/addresses/2.xml", {}, nil, 404
94
+ mock.head "/people/2/addresses/1.xml", {}, nil, 404
95
+ mock.head "/people/Greg/addresses/1.xml", {}, nil, 200
96
+ # customer
97
+ mock.get "/customers/1.xml", {}, @luis
98
+ end
99
+
100
+ Person.user = nil
101
+ Person.password = nil
102
+ end
103
+
104
+
105
+ def test_site_accessor_accepts_uri_or_string_argument
106
+ site = URI.parse('http://localhost')
107
+
108
+ assert_nothing_raised { Person.site = 'http://localhost' }
109
+ assert_equal site, Person.site
110
+
111
+ assert_nothing_raised { Person.site = site }
112
+ assert_equal site, Person.site
113
+ end
114
+
115
+ def test_should_use_site_prefix_and_credentials
116
+ assert_equal 'http://foo:bar@beast.caboo.se', Forum.site.to_s
117
+ assert_equal 'http://foo:bar@beast.caboo.se/forums/:forum_id', Topic.site.to_s
118
+ end
119
+
120
+ def test_site_variable_can_be_reset
121
+ actor = Class.new(ActiveResource::Base)
122
+ assert_nil actor.site
123
+ actor.site = 'http://localhost:31337'
124
+ actor.site = nil
125
+ assert_nil actor.site
126
+ end
127
+
128
+ def test_proxy_accessor_accepts_uri_or_string_argument
129
+ proxy = URI.parse('http://localhost')
130
+
131
+ assert_nothing_raised { Person.proxy = 'http://localhost' }
132
+ assert_equal proxy, Person.proxy
133
+
134
+ assert_nothing_raised { Person.proxy = proxy }
135
+ assert_equal proxy, Person.proxy
136
+ end
137
+
138
+ def test_should_use_proxy_prefix_and_credentials
139
+ assert_equal 'http://user:password@proxy.local:3000', ProxyResource.proxy.to_s
140
+ end
141
+
142
+ def test_proxy_variable_can_be_reset
143
+ actor = Class.new(ActiveResource::Base)
144
+ assert_nil actor.site
145
+ actor.proxy = 'http://localhost:31337'
146
+ actor.proxy = nil
147
+ assert_nil actor.site
148
+ end
149
+
150
+ def test_should_accept_setting_user
151
+ Forum.user = 'david'
152
+ assert_equal('david', Forum.user)
153
+ assert_equal('david', Forum.connection.user)
154
+ end
155
+
156
+ def test_should_accept_setting_password
157
+ Forum.password = 'test123'
158
+ assert_equal('test123', Forum.password)
159
+ assert_equal('test123', Forum.connection.password)
160
+ end
161
+
162
+ def test_should_accept_setting_timeout
163
+ Forum.timeout = 5
164
+ assert_equal(5, Forum.timeout)
165
+ assert_equal(5, Forum.connection.timeout)
166
+ end
167
+
168
+ def test_should_accept_setting_ssl_options
169
+ expected = {:verify => 1}
170
+ Forum.ssl_options= expected
171
+ assert_equal(expected, Forum.ssl_options)
172
+ assert_equal(expected, Forum.connection.ssl_options)
173
+ end
174
+
175
+ def test_user_variable_can_be_reset
176
+ actor = Class.new(ActiveResource::Base)
177
+ actor.site = 'http://cinema'
178
+ assert_nil actor.user
179
+ actor.user = 'username'
180
+ actor.user = nil
181
+ assert_nil actor.user
182
+ assert_nil actor.connection.user
183
+ end
184
+
185
+ def test_password_variable_can_be_reset
186
+ actor = Class.new(ActiveResource::Base)
187
+ actor.site = 'http://cinema'
188
+ assert_nil actor.password
189
+ actor.password = 'username'
190
+ actor.password = nil
191
+ assert_nil actor.password
192
+ assert_nil actor.connection.password
193
+ end
194
+
195
+ def test_timeout_variable_can_be_reset
196
+ actor = Class.new(ActiveResource::Base)
197
+ actor.site = 'http://cinema'
198
+ assert_nil actor.timeout
199
+ actor.timeout = 5
200
+ actor.timeout = nil
201
+ assert_nil actor.timeout
202
+ assert_nil actor.connection.timeout
203
+ end
204
+
205
+ def test_ssl_options_hash_can_be_reset
206
+ actor = Class.new(ActiveResource::Base)
207
+ actor.site = 'https://cinema'
208
+ assert_nil actor.ssl_options
209
+ actor.ssl_options = {:foo => 5}
210
+ actor.ssl_options = nil
211
+ assert_nil actor.ssl_options
212
+ assert_nil actor.connection.ssl_options
213
+ end
214
+
215
+ def test_credentials_from_site_are_decoded
216
+ actor = Class.new(ActiveResource::Base)
217
+ actor.site = 'http://my%40email.com:%31%32%33@cinema'
218
+ assert_equal("my@email.com", actor.user)
219
+ assert_equal("123", actor.password)
220
+ end
221
+
222
+ def test_site_reader_uses_superclass_site_until_written
223
+ # Superclass is Object so returns nil.
224
+ assert_nil ActiveResource::Base.site
225
+ assert_nil Class.new(ActiveResource::Base).site
226
+
227
+ # Subclass uses superclass site.
228
+ actor = Class.new(Person)
229
+ assert_equal Person.site, actor.site
230
+
231
+ # Subclass returns frozen superclass copy.
232
+ assert !Person.site.frozen?
233
+ assert actor.site.frozen?
234
+
235
+ # Changing subclass site doesn't change superclass site.
236
+ actor.site = 'http://localhost:31337'
237
+ assert_not_equal Person.site, actor.site
238
+
239
+ # Changed subclass site is not frozen.
240
+ assert !actor.site.frozen?
241
+
242
+ # Changing superclass site doesn't overwrite subclass site.
243
+ Person.site = 'http://somewhere.else'
244
+ assert_not_equal Person.site, actor.site
245
+
246
+ # Changing superclass site after subclassing changes subclass site.
247
+ jester = Class.new(actor)
248
+ actor.site = 'http://nomad'
249
+ assert_equal actor.site, jester.site
250
+ assert jester.site.frozen?
251
+
252
+ # Subclasses are always equal to superclass site when not overridden
253
+ fruit = Class.new(ActiveResource::Base)
254
+ apple = Class.new(fruit)
255
+
256
+ fruit.site = 'http://market'
257
+ assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class'
258
+
259
+ fruit.site = 'http://supermarket'
260
+ assert_equal fruit.site, apple.site, 'subclass did not adopt changes from parent class'
261
+ end
262
+
263
+ def test_proxy_reader_uses_superclass_site_until_written
264
+ # Superclass is Object so returns nil.
265
+ assert_nil ActiveResource::Base.proxy
266
+ assert_nil Class.new(ActiveResource::Base).proxy
267
+
268
+ # Subclass uses superclass proxy.
269
+ actor = Class.new(Person)
270
+ assert_equal Person.proxy, actor.proxy
271
+
272
+ # Subclass returns frozen superclass copy.
273
+ assert !Person.proxy.frozen?
274
+ assert actor.proxy.frozen?
275
+
276
+ # Changing subclass proxy doesn't change superclass site.
277
+ actor.proxy = 'http://localhost:31337'
278
+ assert_not_equal Person.proxy, actor.proxy
279
+
280
+ # Changed subclass proxy is not frozen.
281
+ assert !actor.proxy.frozen?
282
+
283
+ # Changing superclass proxy doesn't overwrite subclass site.
284
+ Person.proxy = 'http://somewhere.else'
285
+ assert_not_equal Person.proxy, actor.proxy
286
+
287
+ # Changing superclass proxy after subclassing changes subclass site.
288
+ jester = Class.new(actor)
289
+ actor.proxy = 'http://nomad'
290
+ assert_equal actor.proxy, jester.proxy
291
+ assert jester.proxy.frozen?
292
+
293
+ # Subclasses are always equal to superclass proxy when not overridden
294
+ fruit = Class.new(ActiveResource::Base)
295
+ apple = Class.new(fruit)
296
+
297
+ fruit.proxy = 'http://market'
298
+ assert_equal fruit.proxy, apple.proxy, 'subclass did not adopt changes from parent class'
299
+
300
+ fruit.proxy = 'http://supermarket'
301
+ assert_equal fruit.proxy, apple.proxy, 'subclass did not adopt changes from parent class'
302
+ end
303
+
304
+ def test_user_reader_uses_superclass_user_until_written
305
+ # Superclass is Object so returns nil.
306
+ assert_nil ActiveResource::Base.user
307
+ assert_nil Class.new(ActiveResource::Base).user
308
+ Person.user = 'anonymous'
309
+
310
+ # Subclass uses superclass user.
311
+ actor = Class.new(Person)
312
+ assert_equal Person.user, actor.user
313
+
314
+ # Subclass returns frozen superclass copy.
315
+ assert !Person.user.frozen?
316
+ assert actor.user.frozen?
317
+
318
+ # Changing subclass user doesn't change superclass user.
319
+ actor.user = 'david'
320
+ assert_not_equal Person.user, actor.user
321
+
322
+ # Changing superclass user doesn't overwrite subclass user.
323
+ Person.user = 'john'
324
+ assert_not_equal Person.user, actor.user
325
+
326
+ # Changing superclass user after subclassing changes subclass user.
327
+ jester = Class.new(actor)
328
+ actor.user = 'john.doe'
329
+ assert_equal actor.user, jester.user
330
+
331
+ # Subclasses are always equal to superclass user when not overridden
332
+ fruit = Class.new(ActiveResource::Base)
333
+ apple = Class.new(fruit)
334
+
335
+ fruit.user = 'manager'
336
+ assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class'
337
+
338
+ fruit.user = 'client'
339
+ assert_equal fruit.user, apple.user, 'subclass did not adopt changes from parent class'
340
+ end
341
+
342
+ def test_password_reader_uses_superclass_password_until_written
343
+ # Superclass is Object so returns nil.
344
+ assert_nil ActiveResource::Base.password
345
+ assert_nil Class.new(ActiveResource::Base).password
346
+ Person.password = 'my-password'
347
+
348
+ # Subclass uses superclass password.
349
+ actor = Class.new(Person)
350
+ assert_equal Person.password, actor.password
351
+
352
+ # Subclass returns frozen superclass copy.
353
+ assert !Person.password.frozen?
354
+ assert actor.password.frozen?
355
+
356
+ # Changing subclass password doesn't change superclass password.
357
+ actor.password = 'secret'
358
+ assert_not_equal Person.password, actor.password
359
+
360
+ # Changing superclass password doesn't overwrite subclass password.
361
+ Person.password = 'super-secret'
362
+ assert_not_equal Person.password, actor.password
363
+
364
+ # Changing superclass password after subclassing changes subclass password.
365
+ jester = Class.new(actor)
366
+ actor.password = 'even-more-secret'
367
+ assert_equal actor.password, jester.password
368
+
369
+ # Subclasses are always equal to superclass password when not overridden
370
+ fruit = Class.new(ActiveResource::Base)
371
+ apple = Class.new(fruit)
372
+
373
+ fruit.password = 'mega-secret'
374
+ assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class'
375
+
376
+ fruit.password = 'ok-password'
377
+ assert_equal fruit.password, apple.password, 'subclass did not adopt changes from parent class'
378
+ end
379
+
380
+ def test_timeout_reader_uses_superclass_timeout_until_written
381
+ # Superclass is Object so returns nil.
382
+ assert_nil ActiveResource::Base.timeout
383
+ assert_nil Class.new(ActiveResource::Base).timeout
384
+ Person.timeout = 5
385
+
386
+ # Subclass uses superclass timeout.
387
+ actor = Class.new(Person)
388
+ assert_equal Person.timeout, actor.timeout
389
+
390
+ # Changing subclass timeout doesn't change superclass timeout.
391
+ actor.timeout = 10
392
+ assert_not_equal Person.timeout, actor.timeout
393
+
394
+ # Changing superclass timeout doesn't overwrite subclass timeout.
395
+ Person.timeout = 15
396
+ assert_not_equal Person.timeout, actor.timeout
397
+
398
+ # Changing superclass timeout after subclassing changes subclass timeout.
399
+ jester = Class.new(actor)
400
+ actor.timeout = 20
401
+ assert_equal actor.timeout, jester.timeout
402
+
403
+ # Subclasses are always equal to superclass timeout when not overridden.
404
+ fruit = Class.new(ActiveResource::Base)
405
+ apple = Class.new(fruit)
406
+
407
+ fruit.timeout = 25
408
+ assert_equal fruit.timeout, apple.timeout, 'subclass did not adopt changes from parent class'
409
+
410
+ fruit.timeout = 30
411
+ assert_equal fruit.timeout, apple.timeout, 'subclass did not adopt changes from parent class'
412
+ end
413
+
414
+ def test_ssl_options_reader_uses_superclass_ssl_options_until_written
415
+ # Superclass is Object so returns nil.
416
+ assert_nil ActiveResource::Base.ssl_options
417
+ assert_nil Class.new(ActiveResource::Base).ssl_options
418
+ Person.ssl_options = {:foo => 'bar'}
419
+
420
+ # Subclass uses superclass ssl_options.
421
+ actor = Class.new(Person)
422
+ assert_equal Person.ssl_options, actor.ssl_options
423
+
424
+ # Changing subclass ssl_options doesn't change superclass ssl_options.
425
+ actor.ssl_options = {:baz => ''}
426
+ assert_not_equal Person.ssl_options, actor.ssl_options
427
+
428
+ # Changing superclass ssl_options doesn't overwrite subclass ssl_options.
429
+ Person.ssl_options = {:color => 'blue'}
430
+ assert_not_equal Person.ssl_options, actor.ssl_options
431
+
432
+ # Changing superclass ssl_options after subclassing changes subclass ssl_options.
433
+ jester = Class.new(actor)
434
+ actor.ssl_options = {:color => 'red'}
435
+ assert_equal actor.ssl_options, jester.ssl_options
436
+
437
+ # Subclasses are always equal to superclass ssl_options when not overridden.
438
+ fruit = Class.new(ActiveResource::Base)
439
+ apple = Class.new(fruit)
440
+
441
+ fruit.ssl_options = {:alpha => 'betas'}
442
+ assert_equal fruit.ssl_options, apple.ssl_options, 'subclass did not adopt changes from parent class'
443
+
444
+ fruit.ssl_options = {:omega => 'moos'}
445
+ assert_equal fruit.ssl_options, apple.ssl_options, 'subclass did not adopt changes from parent class'
446
+ end
447
+
448
+ def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects
449
+ # Subclasses are always equal to superclass site when not overridden
450
+ fruit = Class.new(ActiveResource::Base)
451
+ apple = Class.new(fruit)
452
+
453
+ fruit.site = 'http://market'
454
+ assert_equal fruit.connection.site, apple.connection.site
455
+ first_connection = apple.connection.object_id
456
+
457
+ fruit.site = 'http://supermarket'
458
+ assert_equal fruit.connection.site, apple.connection.site
459
+ second_connection = apple.connection.object_id
460
+ assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
461
+ end
462
+
463
+ def test_updating_baseclass_user_wipes_descendent_cached_connection_objects
464
+ # Subclasses are always equal to superclass user when not overridden
465
+ fruit = Class.new(ActiveResource::Base)
466
+ apple = Class.new(fruit)
467
+ fruit.site = 'http://market'
468
+
469
+ fruit.user = 'david'
470
+ assert_equal fruit.connection.user, apple.connection.user
471
+ first_connection = apple.connection.object_id
472
+
473
+ fruit.user = 'john'
474
+ assert_equal fruit.connection.user, apple.connection.user
475
+ second_connection = apple.connection.object_id
476
+ assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
477
+ end
478
+
479
+ def test_updating_baseclass_password_wipes_descendent_cached_connection_objects
480
+ # Subclasses are always equal to superclass password when not overridden
481
+ fruit = Class.new(ActiveResource::Base)
482
+ apple = Class.new(fruit)
483
+ fruit.site = 'http://market'
484
+
485
+ fruit.password = 'secret'
486
+ assert_equal fruit.connection.password, apple.connection.password
487
+ first_connection = apple.connection.object_id
488
+
489
+ fruit.password = 'supersecret'
490
+ assert_equal fruit.connection.password, apple.connection.password
491
+ second_connection = apple.connection.object_id
492
+ assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
493
+ end
494
+
495
+ def test_updating_baseclass_timeout_wipes_descendent_cached_connection_objects
496
+ # Subclasses are always equal to superclass timeout when not overridden
497
+ fruit = Class.new(ActiveResource::Base)
498
+ apple = Class.new(fruit)
499
+ fruit.site = 'http://market'
500
+
501
+ fruit.timeout = 5
502
+ assert_equal fruit.connection.timeout, apple.connection.timeout
503
+ first_connection = apple.connection.object_id
504
+
505
+ fruit.timeout = 10
506
+ assert_equal fruit.connection.timeout, apple.connection.timeout
507
+ second_connection = apple.connection.object_id
508
+ assert_not_equal(first_connection, second_connection, 'Connection should be re-created')
509
+ end
510
+
511
+ def test_collection_name
512
+ assert_equal "people", Person.collection_name
513
+ end
514
+
515
+ def test_collection_path
516
+ assert_equal '/people.xml', Person.collection_path
517
+ end
518
+
519
+ def test_collection_path_with_parameters
520
+ assert_equal '/people.xml?gender=male', Person.collection_path(:gender => 'male')
521
+ assert_equal '/people.xml?gender=false', Person.collection_path(:gender => false)
522
+ assert_equal '/people.xml?gender=', Person.collection_path(:gender => nil)
523
+
524
+ assert_equal '/people.xml?gender=male', Person.collection_path('gender' => 'male')
525
+
526
+ # Use includes? because ordering of param hash is not guaranteed
527
+ assert Person.collection_path(:gender => 'male', :student => true).include?('/people.xml?')
528
+ assert Person.collection_path(:gender => 'male', :student => true).include?('gender=male')
529
+ assert Person.collection_path(:gender => 'male', :student => true).include?('student=true')
530
+
531
+ assert_equal '/people.xml?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false])
532
+
533
+ assert_equal '/people.xml?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'})
534
+ end
535
+
536
+ def test_custom_element_path
537
+ assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, :person_id => 1)
538
+ assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 1)
539
+ assert_equal '/people/Greg/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 'Greg')
540
+ end
541
+
542
+ def test_custom_element_path_with_redefined_to_param
543
+ Person.module_eval do
544
+ alias_method :original_to_param_element_path, :to_param
545
+ def to_param
546
+ name
547
+ end
548
+ end
549
+
550
+ # Class method.
551
+ assert_equal '/people/Greg.xml', Person.element_path('Greg')
552
+
553
+ # Protected Instance method.
554
+ assert_equal '/people/Greg.xml', Person.find('Greg').send(:element_path)
555
+
556
+ ensure
557
+ # revert back to original
558
+ Person.module_eval do
559
+ # save the 'new' to_param so we don't get a warning about discarding the method
560
+ alias_method :element_path_to_param, :to_param
561
+ alias_method :to_param, :original_to_param_element_path
562
+ end
563
+ end
564
+
565
+ def test_custom_element_path_with_parameters
566
+ assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :person_id => 1, :type => 'work')
567
+ assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, 'person_id' => 1, :type => 'work')
568
+ assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :type => 'work', :person_id => 1)
569
+ assert_equal '/people/1/addresses/1.xml?type%5B%5D=work&type%5B%5D=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time'])
570
+ end
571
+
572
+ def test_custom_element_path_with_prefix_and_parameters
573
+ assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, {:person_id => 1}, {:type => 'work'})
574
+ end
575
+
576
+ def test_custom_collection_path
577
+ assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
578
+ assert_equal '/people/1/addresses.xml', StreetAddress.collection_path('person_id' => 1)
579
+ end
580
+
581
+ def test_custom_collection_path_with_parameters
582
+ assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
583
+ assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path('person_id' => 1, :type => 'work')
584
+ end
585
+
586
+ def test_custom_collection_path_with_prefix_and_parameters
587
+ assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path({:person_id => 1}, {:type => 'work'})
588
+ end
589
+
590
+ def test_custom_element_name
591
+ assert_equal 'address', StreetAddress.element_name
592
+ end
593
+
594
+ def test_custom_collection_name
595
+ assert_equal 'addresses', StreetAddress.collection_name
596
+ end
597
+
598
+ def test_prefix
599
+ assert_equal "/", Person.prefix
600
+ assert_equal Set.new, Person.__send__(:prefix_parameters)
601
+ end
602
+
603
+ def test_set_prefix
604
+ SetterTrap.rollback_sets(Person) do |person_class|
605
+ person_class.prefix = "the_prefix"
606
+ assert_equal "the_prefix", person_class.prefix
607
+ end
608
+ end
609
+
610
+ def test_set_prefix_with_inline_keys
611
+ SetterTrap.rollback_sets(Person) do |person_class|
612
+ person_class.prefix = "the_prefix:the_param"
613
+ assert_equal "the_prefixthe_param_value", person_class.prefix(:the_param => "the_param_value")
614
+ end
615
+ end
616
+
617
+ def test_set_prefix_twice_should_clear_params
618
+ SetterTrap.rollback_sets(Person) do |person_class|
619
+ person_class.prefix = "the_prefix/:the_param1"
620
+ assert_equal Set.new([:the_param1]), person_class.prefix_parameters
621
+ person_class.prefix = "the_prefix/:the_param2"
622
+ assert_equal Set.new([:the_param2]), person_class.prefix_parameters
623
+ end
624
+ end
625
+
626
+ def test_set_prefix_with_default_value
627
+ SetterTrap.rollback_sets(Person) do |person_class|
628
+ person_class.set_prefix
629
+ assert_equal "/", person_class.prefix
630
+ end
631
+ end
632
+
633
+ def test_custom_prefix
634
+ assert_equal '/people//', StreetAddress.prefix
635
+ assert_equal '/people/1/', StreetAddress.prefix(:person_id => 1)
636
+ assert_equal [:person_id].to_set, StreetAddress.__send__(:prefix_parameters)
637
+ end
638
+
639
+ def test_find_by_id
640
+ matz = Person.find(1)
641
+ assert_kind_of Person, matz
642
+ assert_equal "Matz", matz.name
643
+ assert matz.name?
644
+ end
645
+
646
+ def test_respond_to
647
+ matz = Person.find(1)
648
+ assert matz.respond_to?(:name)
649
+ assert matz.respond_to?(:name=)
650
+ assert matz.respond_to?(:name?)
651
+ assert !matz.respond_to?(:super_scalable_stuff)
652
+ end
653
+
654
+ def test_find_by_id_with_custom_prefix
655
+ addy = StreetAddress.find(1, :params => { :person_id => 1 })
656
+ assert_kind_of StreetAddress, addy
657
+ assert_equal '12345 Street', addy.street
658
+ end
659
+
660
+ def test_find_all
661
+ all = Person.find(:all)
662
+ assert_equal 2, all.size
663
+ assert_kind_of Person, all.first
664
+ assert_equal "Matz", all.first.name
665
+ assert_equal "David", all.last.name
666
+ end
667
+
668
+ def test_find_first
669
+ matz = Person.find(:first)
670
+ assert_kind_of Person, matz
671
+ assert_equal "Matz", matz.name
672
+ end
673
+
674
+ def test_find_last
675
+ david = Person.find(:last)
676
+ assert_kind_of Person, david
677
+ assert_equal 'David', david.name
678
+ end
679
+
680
+ def test_custom_header
681
+ Person.headers['key'] = 'value'
682
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(4) }
683
+ ensure
684
+ Person.headers.delete('key')
685
+ end
686
+
687
+ def test_find_by_id_not_found
688
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(99) }
689
+ assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1) }
690
+ end
691
+
692
+ def test_find_all_by_from
693
+ ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
694
+
695
+ people = Person.find(:all, :from => "/companies/1/people.xml")
696
+ assert_equal 1, people.size
697
+ assert_equal "David", people.first.name
698
+ end
699
+
700
+ def test_find_all_by_from_with_options
701
+ ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
702
+
703
+ people = Person.find(:all, :from => "/companies/1/people.xml")
704
+ assert_equal 1, people.size
705
+ assert_equal "David", people.first.name
706
+ end
707
+
708
+ def test_find_all_by_symbol_from
709
+ ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, @people_david }
710
+
711
+ people = Person.find(:all, :from => :managers)
712
+ assert_equal 1, people.size
713
+ assert_equal "David", people.first.name
714
+ end
715
+
716
+ def test_find_single_by_from
717
+ ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/manager.xml", {}, @david }
718
+
719
+ david = Person.find(:one, :from => "/companies/1/manager.xml")
720
+ assert_equal "David", david.name
721
+ end
722
+
723
+ def test_find_single_by_symbol_from
724
+ ActiveResource::HttpMock.respond_to { |m| m.get "/people/leader.xml", {}, @david }
725
+
726
+ david = Person.find(:one, :from => :leader)
727
+ assert_equal "David", david.name
728
+ end
729
+
730
+ def test_save
731
+ rick = Person.new
732
+ assert_equal true, rick.save
733
+ assert_equal '5', rick.id
734
+ end
735
+
736
+ def test_id_from_response
737
+ p = Person.new
738
+ resp = {'Location' => '/foo/bar/1'}
739
+ assert_equal '1', p.__send__(:id_from_response, resp)
740
+
741
+ resp['Location'] << '.xml'
742
+ assert_equal '1', p.__send__(:id_from_response, resp)
743
+ end
744
+
745
+ def test_id_from_response_without_location
746
+ p = Person.new
747
+ resp = {}
748
+ assert_equal nil, p.__send__(:id_from_response, resp)
749
+ end
750
+
751
+ def test_create_with_custom_prefix
752
+ matzs_house = StreetAddress.new(:person_id => 1)
753
+ matzs_house.save
754
+ assert_equal '5', matzs_house.id
755
+ end
756
+
757
+ # Test that loading a resource preserves its prefix_options.
758
+ def test_load_preserves_prefix_options
759
+ address = StreetAddress.find(1, :params => { :person_id => 1 })
760
+ ryan = Person.new(:id => 1, :name => 'Ryan', :address => address)
761
+ assert_equal address.prefix_options, ryan.address.prefix_options
762
+ end
763
+
764
+ def test_reload_works_with_prefix_options
765
+ address = StreetAddress.find(1, :params => { :person_id => 1 })
766
+ assert_equal address, address.reload
767
+ end
768
+
769
+ def test_reload_with_redefined_to_param
770
+ Person.module_eval do
771
+ alias_method :original_to_param_reload, :to_param
772
+ def to_param
773
+ name
774
+ end
775
+ end
776
+
777
+ person = Person.find('Greg')
778
+ assert_equal person, person.reload
779
+
780
+ ensure
781
+ # revert back to original
782
+ Person.module_eval do
783
+ # save the 'new' to_param so we don't get a warning about discarding the method
784
+ alias_method :reload_to_param, :to_param
785
+ alias_method :to_param, :original_to_param_reload
786
+ end
787
+ end
788
+
789
+ def test_reload_works_without_prefix_options
790
+ person = Person.find(:first)
791
+ assert_equal person, person.reload
792
+ end
793
+
794
+ def test_create
795
+ rick = Person.create(:name => 'Rick')
796
+ assert rick.valid?
797
+ assert !rick.new?
798
+ assert_equal '5', rick.id
799
+
800
+ # test additional attribute returned on create
801
+ assert_equal 25, rick.age
802
+
803
+ # Test that save exceptions get bubbled up too
804
+ ActiveResource::HttpMock.respond_to do |mock|
805
+ mock.post "/people.xml", {}, nil, 409
806
+ end
807
+ assert_raise(ActiveResource::ResourceConflict) { Person.create(:name => 'Rick') }
808
+ end
809
+
810
+ def test_create_without_location
811
+ ActiveResource::HttpMock.respond_to do |mock|
812
+ mock.post "/people.xml", {}, nil, 201
813
+ end
814
+ person = Person.create(:name => 'Rick')
815
+ assert_equal nil, person.id
816
+ end
817
+
818
+ def test_clone
819
+ matz = Person.find(1)
820
+ matz_c = matz.clone
821
+ assert matz_c.new?
822
+ matz.attributes.each do |k, v|
823
+ assert_equal v, matz_c.send(k) if k != Person.primary_key
824
+ end
825
+ end
826
+
827
+ def test_nested_clone
828
+ addy = StreetAddress.find(1, :params => {:person_id => 1})
829
+ addy_c = addy.clone
830
+ assert addy_c.new?
831
+ addy.attributes.each do |k, v|
832
+ assert_equal v, addy_c.send(k) if k != StreetAddress.primary_key
833
+ end
834
+ assert_equal addy.prefix_options, addy_c.prefix_options
835
+ end
836
+
837
+ def test_complex_clone
838
+ matz = Person.find(1)
839
+ matz.address = StreetAddress.find(1, :params => {:person_id => matz.id})
840
+ matz.non_ar_hash = {:not => "an ARes instance"}
841
+ matz.non_ar_arr = ["not", "ARes"]
842
+ matz_c = matz.clone
843
+ assert matz_c.new?
844
+ assert_raise(NoMethodError) {matz_c.address}
845
+ assert_equal matz.non_ar_hash, matz_c.non_ar_hash
846
+ assert_equal matz.non_ar_arr, matz_c.non_ar_arr
847
+
848
+ # Test that actual copy, not just reference copy
849
+ matz.non_ar_hash[:not] = "changed"
850
+ assert_not_equal matz.non_ar_hash, matz_c.non_ar_hash
851
+ end
852
+
853
+ def test_update
854
+ matz = Person.find(:first)
855
+ matz.name = "David"
856
+ assert_kind_of Person, matz
857
+ assert_equal "David", matz.name
858
+ assert_equal true, matz.save
859
+ end
860
+
861
+ def test_update_with_custom_prefix_with_specific_id
862
+ addy = StreetAddress.find(1, :params => { :person_id => 1 })
863
+ addy.street = "54321 Street"
864
+ assert_kind_of StreetAddress, addy
865
+ assert_equal "54321 Street", addy.street
866
+ addy.save
867
+ end
868
+
869
+ def test_update_with_custom_prefix_without_specific_id
870
+ addy = StreetAddress.find(:first, :params => { :person_id => 1 })
871
+ addy.street = "54321 Lane"
872
+ assert_kind_of StreetAddress, addy
873
+ assert_equal "54321 Lane", addy.street
874
+ addy.save
875
+ end
876
+
877
+ def test_update_conflict
878
+ ActiveResource::HttpMock.respond_to do |mock|
879
+ mock.get "/people/2.xml", {}, @david
880
+ mock.put "/people/2.xml", @default_request_headers, nil, 409
881
+ end
882
+ assert_raise(ActiveResource::ResourceConflict) { Person.find(2).save }
883
+ end
884
+
885
+ def test_destroy
886
+ assert Person.find(1).destroy
887
+ ActiveResource::HttpMock.respond_to do |mock|
888
+ mock.get "/people/1.xml", {}, nil, 404
889
+ end
890
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
891
+ end
892
+
893
+ def test_destroy_with_custom_prefix
894
+ assert StreetAddress.find(1, :params => { :person_id => 1 }).destroy
895
+ ActiveResource::HttpMock.respond_to do |mock|
896
+ mock.get "/people/1/addresses/1.xml", {}, nil, 404
897
+ end
898
+ assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
899
+ end
900
+
901
+ def test_destroy_with_410_gone
902
+ assert Person.find(1).destroy
903
+ ActiveResource::HttpMock.respond_to do |mock|
904
+ mock.get "/people/1.xml", {}, nil, 410
905
+ end
906
+ assert_raise(ActiveResource::ResourceGone) { Person.find(1).destroy }
907
+ end
908
+
909
+ def test_delete
910
+ assert Person.delete(1)
911
+ ActiveResource::HttpMock.respond_to do |mock|
912
+ mock.get "/people/1.xml", {}, nil, 404
913
+ end
914
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(1) }
915
+ end
916
+
917
+ def test_delete_with_custom_prefix
918
+ assert StreetAddress.delete(1, :person_id => 1)
919
+ ActiveResource::HttpMock.respond_to do |mock|
920
+ mock.get "/people/1/addresses/1.xml", {}, nil, 404
921
+ end
922
+ assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
923
+ end
924
+
925
+ def test_delete_with_410_gone
926
+ assert Person.delete(1)
927
+ ActiveResource::HttpMock.respond_to do |mock|
928
+ mock.get "/people/1.xml", {}, nil, 410
929
+ end
930
+ assert_raise(ActiveResource::ResourceGone) { Person.find(1) }
931
+ end
932
+
933
+ def test_exists
934
+ # Class method.
935
+ assert !Person.exists?(nil)
936
+ assert Person.exists?(1)
937
+ assert !Person.exists?(99)
938
+
939
+ # Instance method.
940
+ assert !Person.new.exists?
941
+ assert Person.find(1).exists?
942
+ assert !Person.new(:id => 99).exists?
943
+
944
+ # Nested class method.
945
+ assert StreetAddress.exists?(1, :params => { :person_id => 1 })
946
+ assert !StreetAddress.exists?(1, :params => { :person_id => 2 })
947
+ assert !StreetAddress.exists?(2, :params => { :person_id => 1 })
948
+
949
+ # Nested instance method.
950
+ assert StreetAddress.find(1, :params => { :person_id => 1 }).exists?
951
+ assert !StreetAddress.new({:id => 1, :person_id => 2}).exists?
952
+ assert !StreetAddress.new({:id => 2, :person_id => 1}).exists?
953
+ end
954
+
955
+ def test_exists_with_redefined_to_param
956
+ Person.module_eval do
957
+ alias_method :original_to_param_exists, :to_param
958
+ def to_param
959
+ name
960
+ end
961
+ end
962
+
963
+ # Class method.
964
+ assert Person.exists?('Greg')
965
+
966
+ # Instance method.
967
+ assert Person.find('Greg').exists?
968
+
969
+ # Nested class method.
970
+ assert StreetAddress.exists?(1, :params => { :person_id => Person.find('Greg').to_param })
971
+
972
+ # Nested instance method.
973
+ assert StreetAddress.find(1, :params => { :person_id => Person.find('Greg').to_param }).exists?
974
+
975
+ ensure
976
+ # revert back to original
977
+ Person.module_eval do
978
+ # save the 'new' to_param so we don't get a warning about discarding the method
979
+ alias_method :exists_to_param, :to_param
980
+ alias_method :to_param, :original_to_param_exists
981
+ end
982
+ end
983
+
984
+ def test_exists_without_http_mock
985
+ http = Net::HTTP.new(Person.site.host, Person.site.port)
986
+ ActiveResource::Connection.any_instance.expects(:http).returns(http)
987
+ http.expects(:request).returns(ActiveResource::Response.new(""))
988
+
989
+ assert Person.exists?('not-mocked')
990
+ end
991
+
992
+ def test_exists_with_410_gone
993
+ ActiveResource::HttpMock.respond_to do |mock|
994
+ mock.head "/people/1.xml", {}, nil, 410
995
+ end
996
+
997
+ assert !Person.exists?(1)
998
+ end
999
+
1000
+ def test_to_xml
1001
+ matz = Person.find(1)
1002
+ xml = matz.encode
1003
+ assert xml.starts_with?('<?xml version="1.0" encoding="UTF-8"?>')
1004
+ assert xml.include?('<name>Matz</name>')
1005
+ assert xml.include?('<id type="integer">1</id>')
1006
+ end
1007
+
1008
+ def test_to_param_quacks_like_active_record
1009
+ new_person = Person.new
1010
+ assert_nil new_person.to_param
1011
+ matz = Person.find(1)
1012
+ assert_equal '1', matz.to_param
1013
+ end
1014
+
1015
+ def test_parse_deep_nested_resources
1016
+ luis = Customer.find(1)
1017
+ assert_kind_of Customer, luis
1018
+ luis.friends.each do |friend|
1019
+ assert_kind_of Customer::Friend, friend
1020
+ friend.brothers.each do |brother|
1021
+ assert_kind_of Customer::Friend::Brother, brother
1022
+ brother.children.each do |child|
1023
+ assert_kind_of Customer::Friend::Brother::Child, child
1024
+ end
1025
+ end
1026
+ end
1027
+ end
1028
+
1029
+ def test_load_yaml_array
1030
+ assert_nothing_raised do
1031
+ marty = Person.find(5)
1032
+ assert_equal 3, marty.colors.size
1033
+ marty.colors.each do |color|
1034
+ assert_kind_of String, color
1035
+ end
1036
+ end
1037
+ end
1038
+ end