andrewtimberlake-flickr 1.0.5

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.
Files changed (7) hide show
  1. data/History.txt +54 -0
  2. data/LICENSE +20 -0
  3. data/README.txt +73 -0
  4. data/TODO +6 -0
  5. data/lib/flickr.rb +695 -0
  6. data/test/test_flickr.rb +1082 -0
  7. metadata +66 -0
@@ -0,0 +1,1082 @@
1
+ require 'rubygems'
2
+ require 'flickr'
3
+ require 'test/unit'
4
+ require 'mocha'
5
+
6
+ class TestFlickr < Test::Unit::TestCase
7
+
8
+ # Flickr client tests
9
+ #
10
+ # instantiation tests
11
+ def test_should_instantiate_new_flickr_client
12
+ Flickr.any_instance.stubs(:login)
13
+ flickr = Flickr.new('some_api_key', 'email@test.com', 'some_password', 'some_shared_secret')
14
+
15
+ assert_equal 'some_api_key', flickr.api_key
16
+ assert_equal 'some_shared_secret', flickr.instance_variable_get(:@shared_secret)
17
+ end
18
+
19
+ def test_should_try_to_login_using_old_api_if_email_and_password_passed
20
+ Flickr.any_instance.expects(:login).with('email@test.com', 'some_password') # checks email and password have been set
21
+ flickr = Flickr.new('some_api_key', 'email@test.com', 'some_password', 'some_shared_secret')
22
+ end
23
+
24
+ def test_should_instantiate_new_flickr_client_on_new_api
25
+ flickr = Flickr.new('api_key' => 'some_api_key', 'email' => 'email@test.com', 'password' => 'some_password', 'shared_secret' => 'some_shared_secret', 'foo' => 'bar')
26
+
27
+ assert_equal 'some_api_key', flickr.api_key
28
+ assert_equal 'some_shared_secret', flickr.instance_variable_get(:@shared_secret)
29
+ assert_nil flickr.instance_variable_get(:@foo) # should ignore other params
30
+ end
31
+
32
+ def test_should_not_try_to_login_using_old_api_when_instantiate_new_flickr_client_on_new_api
33
+ Flickr.any_instance.expects(:login).never # doesn't bother trying to login with new api -- it'll fail in any case
34
+ flickr = Flickr.new('api_key' => 'some_api_key', 'email' => 'email@test.com', 'password' => 'some_password', 'shared_secret' => 'some_shared_secret', 'foo' => 'bar')
35
+ end
36
+
37
+ # signature_from method tests
38
+ def test_should_return_signature_from_given_params
39
+ assert_equal Digest::MD5.hexdigest('shared_secret_codea_param1234xb_param5678yc_param97531t'),
40
+ authenticated_flickr_client.send(:signature_from, {:b_param => '5678y', 'c_param' => '97531t', :a_param => '1234x', :d_param => nil})
41
+ end
42
+
43
+ def test_should_return_nil_for_signature_when_no_shared_secret
44
+ assert_nil flickr_client.send(:signature_from, {:b_param => '5678y', :c_param => '97531t', :a_param => '1234x'})
45
+ end
46
+
47
+ # request_url method tests
48
+ def test_should_get_signature_for_params_when_building_url
49
+ f = authenticated_flickr_client
50
+ f.expects(:signature_from).with( 'method' => 'flickr.someMethod',
51
+ 'api_key' => 'some_api_key',
52
+ 'foo' => 'value which/needs&escaping',
53
+ 'auth_token' => 'some_auth_token').returns("foo123bar456")
54
+
55
+ url = f.send(:request_url, 'someMethod', 'foo' => 'value which/needs&escaping')
56
+ end
57
+
58
+ def test_should_build_url_from_params_with_signature
59
+ f = authenticated_flickr_client
60
+ f.stubs(:signature_from).returns("foo123bar456")
61
+
62
+ url = f.send(:request_url, 'someMethod', 'foo' => 'value which/needs&escaping')
63
+ [ "#{Flickr::HOST_URL}#{Flickr::API_PATH}",
64
+ 'api_key=some_api_key',
65
+ 'method=flickr.someMethod',
66
+ 'foo=value+which%2Fneeds%26escaping',
67
+ 'auth_token=some_auth_token',
68
+ 'api_sig=foo123bar456'].each do |kv_pair|
69
+ assert_match Regexp.new(Regexp.escape(kv_pair)), url
70
+ end
71
+ end
72
+
73
+ def test_should_build_url_from_params_when_signature_returns_nil
74
+ flickr = flickr_client
75
+ flickr.stubs(:signature_from)
76
+ assert_equal "#{Flickr::HOST_URL}#{Flickr::API_PATH}/?api_key=some_api_key&method=flickr.someMethod", flickr.send(:request_url, 'someMethod')
77
+ assert_equal "#{Flickr::HOST_URL}#{Flickr::API_PATH}/?api_key=some_api_key&method=flickr.someMethod&foo=bar", flickr.send(:request_url, 'someMethod', 'foo' => 'bar', 'foobar' => nil)
78
+ assert_equal "#{Flickr::HOST_URL}#{Flickr::API_PATH}/?api_key=some_api_key&method=flickr.someMethod&foo=101", flickr.send(:request_url, 'someMethod', 'foo' => 101)
79
+ assert_equal "#{Flickr::HOST_URL}#{Flickr::API_PATH}/?api_key=some_api_key&method=flickr.someMethod&foo=value+which%2Fneeds%26escaping", flickr.send(:request_url, 'someMethod', 'foo' => 'value which/needs&escaping')
80
+ end
81
+
82
+ # method_missing tests
83
+ def test_should_generate_flickr_method_from_unkown_method_on_flickr_client
84
+ f = flickr_client
85
+ f.expects(:request).with('some.unknown.methodForFlickr', {})
86
+ f.some_unknown_methodForFlickr
87
+ end
88
+
89
+ # request method tests
90
+ def test_should_make_successful_request
91
+ f = flickr_client
92
+ f.expects(:http_get).with('some.url').returns(successful_xml_response)
93
+ f.expects(:request_url).with('some_method', 'foo' => 'bar').returns("some.url")
94
+
95
+ f.send(:request, 'some_method', 'foo' => 'bar') # request is protected
96
+ end
97
+
98
+ def test_should_raise_exception_on_unsuccessful_request
99
+ f = flickr_client
100
+ f.expects(:http_get).returns(unsuccessful_xml_response)
101
+
102
+ assert_raise(RuntimeError) { f.send(:request, 'some_method', 'foo' => 'bar') }
103
+ end
104
+
105
+ def test_should_parse_returned_xml_in_successful_request
106
+ f = flickr_client
107
+ f.stubs(:http_get).returns(successful_xml_response)
108
+ expected_response = { "contacts" => { "perpage" => "1000",
109
+ "contact" => [{ "nsid"=>"12037949629@N01",
110
+ "username"=>"Eric",
111
+ "ignored"=>"1",
112
+ "family"=>"0",
113
+ "friend"=>"1",
114
+ "realname"=>"Eric Costello",
115
+ "iconserver"=>"1"},
116
+ { "nsid"=>"12037949631@N01",
117
+ "username"=>"neb",
118
+ "ignored"=>"0",
119
+ "family"=>"0",
120
+ "friend"=>"0",
121
+ "realname"=>"Ben Cerveny",
122
+ "iconserver"=>"1"}],
123
+ "total" => "2",
124
+ "pages"=> "1",
125
+ "page"=>"1" },
126
+ "stat"=>"ok" }
127
+
128
+ assert_equal expected_response, f.send(:request, 'some_method', 'foo' => 'bar')
129
+ end
130
+
131
+ # photos_request tests
132
+ def test_should_pass_photos_request_params_to_request
133
+ f = flickr_client
134
+ f.expects(:request).with('flickr.method', :one => 1, :two => "2").returns(dummy_photos_response)
135
+ f.photos_request( 'flickr.method', :one => 1, :two => "2")
136
+ end
137
+
138
+ def test_should_instantiate_recent_photos_with_id_and_all_params_returned_by_flickr
139
+ f = flickr_client
140
+ f.expects(:request).returns(dummy_photos_response)
141
+ Flickr::Photo.expects(:new).with("foo123",
142
+ "some_api_key", { "key1" => "value1",
143
+ "key2" => "value2"})
144
+ Flickr::Photo.expects(:new).with("bar456",
145
+ "some_api_key", { "key3" => "value3"})
146
+ photos = f.photos_request('some_method')
147
+ end
148
+
149
+ def test_should_parse_photos_response_into_flickr_photo_collection
150
+ f = flickr_client
151
+ f.expects(:request).returns(dummy_photos_response)
152
+ assert_kind_of Flickr::PhotoCollection, f.photos_request('some_method')
153
+ end
154
+
155
+ def test_should_store_pagination_info_in_photo_collection
156
+ f = flickr_client
157
+ f.expects(:request).returns(dummy_photos_response)
158
+ photos = f.photos_request('some_method')
159
+
160
+ assert_equal "3", photos.page
161
+ assert_equal "5", photos.pages
162
+ assert_equal "10", photos.perpage
163
+ assert_equal "42", photos.total
164
+ end
165
+
166
+ def test_should_return_collection_of_photos
167
+ f = flickr_client
168
+ f.expects(:request).returns(dummy_photos_response)
169
+ photos = f.photos_request('some_method')
170
+ assert_equal 2, photos.size
171
+ assert_kind_of Flickr::Photo, photos.first
172
+ assert_equal "foo123", photos.first.id
173
+ end
174
+
175
+ def test_should_work_with_single_result
176
+ f = flickr_client
177
+ f.expects(:request).returns(dummy_single_photo_response)
178
+ photos = f.photos_request('some_method')
179
+ assert_equal 1, photos.size
180
+ assert_kind_of Flickr::Photo, photos.first
181
+ assert_equal "foo123", photos.first.id
182
+ end
183
+
184
+ def test_should_work_with_empty_result
185
+ f = flickr_client
186
+ f.expects(:request).returns(dummy_zero_photo_response)
187
+ photos = f.photos_request('some_method')
188
+ assert_equal [], photos
189
+ end
190
+
191
+ def test_should_generate_login_url
192
+ f = flickr_client
193
+ f.expects(:signature_from).with('api_key' => 'some_api_key', 'perms' => 'write').returns('validsignature')
194
+ assert_equal 'http://flickr.com/services/auth/?api_key=some_api_key&perms=write&api_sig=validsignature', f.login_url('write')
195
+ end
196
+
197
+ def test_should_get_token_from_frob
198
+ f = flickr_client
199
+ f.expects(:request).with('auth.getToken',:frob => 'some_frob').returns({'auth' => {'token' => 'some_auth_token', 'user' => {}}})
200
+
201
+ auth_token = f.get_token_from('some_frob')
202
+ assert_equal 'some_auth_token', auth_token
203
+ end
204
+
205
+ def test_should_store_auth_token_in_client
206
+ f = flickr_client
207
+ f.expects(:request).returns({'auth' => {'token' => 'some_auth_token','user' => {}}})
208
+ f.get_token_from('some_frob')
209
+ assert_equal 'some_auth_token', f.auth_token
210
+ end
211
+
212
+ def test_should_store_authenticated_user_details_in_client
213
+ f = flickr_client
214
+ f.expects(:request).returns({ 'auth' => { 'token' => 'some_auth_token',
215
+ 'user' => { 'nsid' => 'foo123',
216
+ 'username' => 'some_user', 'fullname' => 'Some User'}}})
217
+ f.get_token_from('some_frob')
218
+ assert_kind_of Flickr::User, user = f.user
219
+ assert_equal 'foo123', user.id
220
+ assert_equal 'some_user', user.username
221
+ assert_equal 'Some User', user.name
222
+ assert_equal f, user.client
223
+ end
224
+
225
+ # photos method tests
226
+ def test_should_get_recent_photos_if_no_params_for_photos
227
+ f = flickr_client
228
+ f.expects(:photos_search)
229
+ f.photos
230
+ end
231
+
232
+ # photos_search method tests
233
+ def test_should_search_photos
234
+ f = authenticated_flickr_client
235
+ f.expects(:request).with('photos.search', anything).returns(dummy_photos_response)
236
+ photos = f.photos_search
237
+ assert_kind_of Flickr::Photo, photos.first
238
+ end
239
+
240
+ # users method tests
241
+ def test_should_find_user_from_email
242
+ f = flickr_client
243
+ f.expects(:request).with('people.findByEmail', anything).returns(dummy_user_response)
244
+ assert_kind_of Flickr::User, user = f.users("email@test.com")
245
+ assert_equal "12037949632@N01", user.id
246
+ assert_equal "Stewart", user.username
247
+ end
248
+
249
+ def test_should_find_user_from_username_if_fails_to_get_from_email
250
+ f = flickr_client
251
+ f.expects(:request).with('people.findByEmail', anything).raises
252
+ f.expects(:request).with('people.findByUsername', anything).returns(dummy_user_response)
253
+ assert_kind_of Flickr::User, f.users("email@test.com")
254
+ end
255
+
256
+ def test_should_pass_on_flickr_client_when_finding_user
257
+ f = flickr_client
258
+ f.stubs(:request).returns(dummy_user_response)
259
+ user = f.users("email@test.com")
260
+ assert_equal f, user.client
261
+ end
262
+
263
+ # groups method tests
264
+ def test_should_search_for_given_group
265
+ f = flickr_client
266
+ f.expects(:request).with("groups.search", {"text" => "foo"}).returns(dummy_groups_response)
267
+ f.groups("foo")
268
+ end
269
+
270
+ def test_should_search_for_given_group_with_additional_params
271
+ f = flickr_client
272
+ f.expects(:request).with("groups.search", {"text" => "foo", "per_page" => "1"}).returns(dummy_groups_response)
273
+ f.groups("foo", "per_page" => "1")
274
+ end
275
+
276
+ def test_should_instantiate_groups_from_search_response
277
+ f = flickr_client
278
+ f.stubs(:request).returns(dummy_groups_response)
279
+ assert_kind_of Array, groups = f.groups("foo")
280
+ assert_kind_of Flickr::Group, group = groups.first
281
+ assert_equal "group1", group.id
282
+ assert_equal "Group One", group.name
283
+ assert_equal "0", group.eighteenplus
284
+ assert_equal f, group.client
285
+ end
286
+
287
+ def test_should_instantiate_groups_from_search_response_with_single_group_returned
288
+ f = flickr_client
289
+ f.stubs(:request).returns(dummy_single_group_response)
290
+ assert_kind_of Array, groups = f.groups("foo")
291
+ assert_equal 1, groups.size
292
+ assert_equal "group1", groups.first.id
293
+ end
294
+
295
+ # ##### DIRECT MODE
296
+ #
297
+ # def test_test_echo
298
+ # assert_equal @f.test_echo['stat'], 'ok'
299
+ # end
300
+ # def test_test_login
301
+ # assert_equal @f.test_login['stat'], 'ok'
302
+ # end
303
+ #
304
+ #
305
+ # ##### BASICS
306
+ #
307
+ # def test_login
308
+ # assert_equal @username, @f.user.getInfo.username
309
+ # end
310
+ #
311
+ # def test_find_by_url
312
+ # assert_equal @group_id, @f.find_by_url(@group_url).getInfo.id # find group by URL
313
+ # assert_equal @user_id, @f.find_by_url(@user_url).getInfo.id # find user by URL
314
+ # end
315
+ #
316
+ # def test_licenses
317
+ # assert_kind_of Array, @f.licenses # find all licenses
318
+ # end
319
+ #
320
+
321
+ #
322
+ # Flickr#photos tests
323
+ #
324
+
325
+
326
+ # ##### Flickr::User tests
327
+ #
328
+ def test_should_instantiate_user
329
+ user = new_user
330
+ assert_equal 'foo123', user.id
331
+ assert_equal 'some_user', user.username
332
+ assert_equal 'bar', user.instance_variable_get(:@foo) # should collect all other params up and store as instance variables
333
+ end
334
+
335
+ def test_should_instantiate_new_user_with_old_api
336
+ Flickr.any_instance.stubs(:login) # stub logging in
337
+ user = Flickr::User.new('foo123',
338
+ 'some_user',
339
+ 'email@test.com', # email irrelevant since Flickr API no longer supports authentication in this way
340
+ 'password', # password irrelevant since Flickr API no longer supports authentication in this way
341
+ 'bar456')
342
+ assert_equal 'foo123', user.id
343
+ assert_equal 'some_user', user.username
344
+ assert_equal 'email@test.com', user.instance_variable_get(:@email)
345
+ assert_equal 'password', user.instance_variable_get(:@password)
346
+ assert_equal 'bar456', user.client.api_key
347
+ end
348
+
349
+ def test_should_instantiate_new_client_when_instantiating_user_if_no_client_passed_in_params
350
+ f = flickr_client
351
+ Flickr.expects(:new).returns(f)
352
+ user = new_user( 'api_key' => 'an_api_key' )
353
+ assert_equal f, user.client
354
+ end
355
+
356
+ def test_should_not_instantiate_new_client_when_instantiating_user_if_client_passed_in_params
357
+ f = flickr_client
358
+ Flickr.expects(:new).never
359
+ user = new_user( 'client' => f )
360
+ assert_equal f, user.client
361
+ end
362
+
363
+ def test_should_not_instantiate_client_if_no_api_key_passed
364
+ Flickr.expects(:new).never
365
+ user = new_user
366
+ assert_nil user.client
367
+ end
368
+
369
+ def test_should_build_url_for_users_profile_page_using_user_id
370
+ Flickr.any_instance.expects(:http_get).never
371
+ assert_equal "http://www.flickr.com/people/foo123/", new_user.url
372
+ end
373
+
374
+ def test_should_build_url_for_users_photos_page_using_user_id
375
+ Flickr.any_instance.expects(:http_get).never
376
+ assert_equal "http://www.flickr.com/photos/foo123/", new_user.photos_url
377
+ end
378
+
379
+ def test_should_get_pretty_url_for_users_profile_page
380
+ f = flickr_client
381
+ f.expects(:urls_getUserProfile).returns({"user" => {"nsid" => "bar456", "url" => "http://www.flickr.com/people/killer_bob/"}})
382
+
383
+ assert_equal "http://www.flickr.com/people/killer_bob/", new_user( 'client' => f ).pretty_url
384
+ end
385
+
386
+ def test_should_cache_pretty_url_for_users_profile_page
387
+ f = flickr_client
388
+ user = new_user( 'client' => f )
389
+ f.expects(:urls_getUserProfile).returns({"user" => {"nsid" => "bar456", "url" => "http://www.flickr.com/people/killer_bob/"}}) # expects only one call
390
+
391
+ user.pretty_url
392
+ user.pretty_url
393
+ end
394
+
395
+ def test_should_get_users_public_groups
396
+ f = flickr_client
397
+ f.expects(:request).with("people.getPublicGroups", anything).returns(dummy_groups_response)
398
+ new_user( 'client' => f ).groups
399
+ end
400
+
401
+ def test_should_instantiate_users_public_groups
402
+ f = flickr_client
403
+ f.stubs(:request).returns(dummy_groups_response)
404
+ user = new_user( 'client' => f )
405
+
406
+ groups = user.groups
407
+ assert_equal 2, groups.size
408
+ assert_kind_of Flickr::Group, group = groups.first
409
+ assert_equal "group1", group.id
410
+ assert_equal "Group One", group.name
411
+ assert_equal "0", group.eighteenplus
412
+ assert_equal f, group.client
413
+ end
414
+
415
+ def test_should_instantiate_users_public_groups_when_only_one_returned
416
+ f = flickr_client
417
+ f.stubs(:request).returns(dummy_single_group_response)
418
+ user = new_user( 'client' => f )
419
+ groups = user.groups
420
+ assert_equal 1, groups.size
421
+ end
422
+ # def test_getInfo
423
+ # @u.getInfo
424
+ # assert_equal @username, @u.username
425
+ # end
426
+ #
427
+ # def test_groups
428
+ # assert_kind_of Flickr::Group, @u.groups.first # public groups
429
+ # end
430
+ #
431
+ #
432
+ # def test_contacts
433
+ # assert_kind_of Flickr::User, @u.contacts.first # public contacts
434
+ # end
435
+ #
436
+ # def test_favorites
437
+ # assert_kind_of Flickr::Photo, @u.favorites.first # public favorites
438
+ # end
439
+ #
440
+ # def test_photosets
441
+ # assert_kind_of Flickr::Photoset, @u.photosets.first # public photosets
442
+ # end
443
+ #
444
+ # def test_tags
445
+ # assert_kind_of Array, @u.tags # tags
446
+ # end
447
+ #
448
+ # def test_contactsPhotos
449
+ # assert_kind_of Flickr::Photo, @u.contactsPhotos.first # contacts' favorites
450
+ # end
451
+
452
+ # User#photos tests
453
+
454
+ def test_should_get_users_public_photos
455
+ client = mock
456
+ client.expects(:photos_request).with('people.getPublicPhotos', {'user_id' => 'some_id'}).returns([new_photo, new_photo])
457
+ Flickr.expects(:new).at_least_once.returns(client)
458
+
459
+ user = Flickr::User.new("some_id", "some_user", nil, nil, "some_api_key")
460
+
461
+ photos = user.photos
462
+ assert_equal 2, photos.size
463
+ assert_kind_of Flickr::Photo, photos.first
464
+ end
465
+
466
+ def test_should_instantiate_favorite_photos_with_id_and_all_params_returned_by_query
467
+ client = mock
468
+ client.expects(:photos_request).with('favorites.getPublicList', {'user_id' => 'some_id'})
469
+ Flickr.expects(:new).at_least_once.returns(client)
470
+ user = Flickr::User.new("some_id", "some_user", nil, nil, "some_api_key")
471
+ user.favorites
472
+ end
473
+
474
+ def test_should_instantiate_contacts_photos_with_id_and_all_params_returned_by_query
475
+ client = mock
476
+ client.expects(:photos_request).with('photos.getContactsPublicPhotos', {'user_id' => 'some_id'})
477
+ Flickr.expects(:new).at_least_once.returns(client)
478
+ user = Flickr::User.new('some_id', "some_user", nil, nil, "some_api_key")
479
+ user.contactsPhotos
480
+ end
481
+
482
+ # ##### Flickr::Photo tests
483
+
484
+ def test_should_initialize_photo_from_id
485
+ photo = Flickr::Photo.new("foo123")
486
+ assert_equal "foo123", photo.id
487
+ end
488
+
489
+ def test_should_save_extra_params_as_instance_variables
490
+ photo = Flickr::Photo.new('foo123', 'some_api_key', { 'key1' => 'value1', 'key2' => 'value2'})
491
+ assert_equal 'value1', photo.instance_variable_get(:@key1)
492
+ assert_equal 'value2', photo.instance_variable_get(:@key2)
493
+ end
494
+
495
+ def test_should_be_able_to_access_instance_variables_through_hash_like_interface
496
+ photo = Flickr::Photo.new
497
+ photo.instance_variable_set(:@key1, 'value1')
498
+ assert_equal 'value1', photo['key1']
499
+ assert_equal 'value1', photo[:key1]
500
+ assert_nil photo[:key2]
501
+ assert_nil photo['key2']
502
+ end
503
+
504
+ def test_should_get_and_store_other_info_for_photo
505
+ Flickr.any_instance.stubs(:http_get).returns(photo_info_xml_response)
506
+ photo = Flickr::Photo.new('foo123', 'some_api_key')
507
+
508
+ assert_equal "1964 120 amazon estate", photo.title # calling #title method triggers getting of info
509
+ assert_equal "1964 120 amazon estate", photo.instance_variable_get(:@title)
510
+ assert_equal "3142", photo.instance_variable_get(:@server)
511
+ assert_equal "ae75bd3111", photo.instance_variable_get(:@secret)
512
+ assert_equal "4", photo.instance_variable_get(:@farm)
513
+ assert_equal "1204145093", photo.instance_variable_get(:@dateuploaded)
514
+ assert_equal "photo", photo.instance_variable_get(:@media)
515
+ assert_equal "0", photo.instance_variable_get(:@isfavorite)
516
+ assert_equal "0", photo.instance_variable_get(:@license)
517
+ assert_equal "0", photo.instance_variable_get(:@rotation)
518
+ assert_equal "1964 Volvo 120 amazon estate spotted in derbyshire.", photo.instance_variable_get(:@description)
519
+ assert_equal( { "w" => "50",
520
+ "x" => "10",
521
+ "y" => "10",
522
+ "authorname" => "Bees",
523
+ "author" => "12037949754@N01",
524
+ "id" => "313",
525
+ "content" => "foo",
526
+ "h" => "50" }, photo.instance_variable_get(:@notes))
527
+ assert_equal "http://www.flickr.com/photos/rootes_arrow/2296968304/", photo.instance_variable_get(:@url)
528
+ assert_equal [ { "id" => "9377979-2296968304-2228", "author" => "9383319@N05", "raw" => "volvo", "machine_tag" => "0", "content" => "volvo" },
529
+ { "id" => "9377979-2296968304-2229", "author" => "9383319@N06", "raw" => "amazon", "machine_tag" => "0", "content" => "amazon"
530
+ } ], photo.instance_variable_get(:@tags)
531
+ assert_equal "1", photo.instance_variable_get(:@comments)
532
+ assert_kind_of Flickr::User, owner = photo.instance_variable_get(:@owner)
533
+ assert_equal "Rootes_arrow_1725", owner.username
534
+ end
535
+
536
+ def test_should_get_and_other_info_for_photo_when_some_attributes_missing
537
+ Flickr.any_instance.stubs(:http_get).returns(sparse_photo_info_xml_response)
538
+ photo = Flickr::Photo.new('foo123', 'some_api_key')
539
+
540
+ assert_equal "1964 120 amazon estate", photo.title # calling #title method triggers getting of info
541
+ assert_equal "1964 120 amazon estate", photo.instance_variable_get(:@title)
542
+ assert_equal( {}, photo.instance_variable_get(:@description))
543
+ assert_nil photo.instance_variable_get(:@notes)
544
+ assert_nil photo.instance_variable_get(:@tags)
545
+ assert_equal "1", photo.instance_variable_get(:@comments)
546
+ end
547
+
548
+ def test_should_not_get_info_more_than_once
549
+ Flickr.any_instance.expects(:http_get).returns(photo_info_xml_response) # expects only one call
550
+ photo = Flickr::Photo.new('foo123', 'some_api_key')
551
+
552
+ photo.description # calling #description method triggers getting of info
553
+ photo.instance_variable_set(:@description, nil) # set description to nil
554
+ photo.description # call #description method again
555
+ end
556
+
557
+ #
558
+ # owner tests
559
+ def test_should_return_owner_when_flickr_user
560
+ user = Flickr::User.new
561
+ photo = new_photo("owner" => user)
562
+
563
+ assert_equal user, photo.owner
564
+ end
565
+
566
+ def test_should_get_info_on_owner_if_not_known
567
+ photo = new_photo("owner" => nil)
568
+ # stubbing private methods causes problems so we mock client method, which is what Photo#getInfo users to make API call
569
+ Flickr.any_instance.expects(:photos_getInfo).returns('photo' => { 'owner'=>{'nsid'=>'abc123', 'username'=>'SomeUserName', 'realname'=>"", 'location'=>''},
570
+ 'notes' => {}, 'tags' => {}, 'urls' => {'url' => {'content' => 'http://prettyurl'}}})
571
+
572
+ owner = photo.owner
573
+ assert_kind_of Flickr::User, owner
574
+ assert_equal 'abc123', owner.id
575
+ assert_equal 'SomeUserName', owner.username
576
+ end
577
+
578
+ def test_should_instantiate_flickr_user_from_owner_id_if_we_have_it
579
+ photo = Flickr::Photo.new
580
+ photo.instance_variable_set(:@owner, "some_user_id")
581
+ Flickr.any_instance.expects(:photos_getInfo).never
582
+
583
+ user = photo.owner
584
+ assert_kind_of Flickr::User, user
585
+ assert_equal "some_user_id", user.id
586
+ end
587
+
588
+ def test_should_cache_owner_when_instantiated
589
+ user = Flickr::User.new
590
+ photo = Flickr::Photo.new
591
+ photo.instance_variable_set(:@owner, "some_user_id")
592
+ Flickr::User.expects(:new).returns(user)
593
+
594
+ photo.owner
595
+ photo.owner # call twice but mock expects only one call
596
+ end
597
+
598
+ #
599
+ # image_source_uri_from_self tests
600
+ def test_should_build_image_source_uri_from_self
601
+ assert_equal "http://farm1.static.flickr.com/2/1418878_1e92283336.jpg",
602
+ new_photo.send(:image_source_uri_from_self) # no size specified
603
+ end
604
+
605
+ def test_should_build_image_source_uri_from_self_for_given_size
606
+ assert_equal "http://farm1.static.flickr.com/2/1418878_1e92283336_m.jpg",
607
+ new_photo.send(:image_source_uri_from_self, "Small") # size specified
608
+ end
609
+
610
+ def test_should_build_image_source_uri_from_self_for_default_size_when_explicitly_asked_for
611
+ assert_equal "http://farm1.static.flickr.com/2/1418878_1e92283336.jpg",
612
+ new_photo.send(:image_source_uri_from_self, "Medium") # medium size specified -- the default
613
+ end
614
+
615
+ def test_should_build_image_source_uri_from_self_for_default_size_when_unknown_size_asked_for
616
+ assert_equal "http://farm1.static.flickr.com/2/1418878_1e92283336.jpg",
617
+ new_photo.send(:image_source_uri_from_self, "Dummy") # bad size specified
618
+ end
619
+
620
+ def test_should_return_nil_for_image_source_uri_if_no_attributes
621
+ assert_nil Flickr::Photo.new.send(:image_source_uri_from_self)
622
+ end
623
+
624
+ def test_should_return_nil_for_image_source_uri_if_missing_required_attributes
625
+ assert_nil Flickr::Photo.new("1418878", nil, "farm" => "1").send(:image_source_uri_from_self)
626
+ end
627
+
628
+ def test_image_source_uri_from_self_should_normalize_size
629
+ photo = new_photo
630
+ assert_equal photo.send(:image_source_uri_from_self, 'Large'),
631
+ photo.send(:image_source_uri_from_self, :large)
632
+ end
633
+
634
+ def test_uri_for_photo_from_self_should_normalize_size
635
+ photo = new_photo
636
+ assert_equal photo.send(:uri_for_photo_from_self, 'Large'),
637
+ photo.send(:uri_for_photo_from_self, :large)
638
+ end
639
+
640
+ def test_should_get_source_uri_by_building_from_self_if_possible
641
+ photo = Flickr::Photo.new
642
+ photo.expects(:image_source_uri_from_self).with('Medium').returns(true) # return any non-false-evaluating value so that sizes method isn't called
643
+ photo.source
644
+ end
645
+
646
+ def test_should_get_source_uri_by_building_from_self_if_possible_requesting_source_for_given_size
647
+ photo = Flickr::Photo.new
648
+ photo.expects(:image_source_uri_from_self).with('Large').returns(true) # return any non-false-evaluating value so that sizes method isn't called
649
+ photo.source('Large')
650
+ end
651
+
652
+ def test_should_get_source_uri_by_calling_sizes_method_if_no_luck_building_uri
653
+ photo = Flickr::Photo.new
654
+ photo.stubs(:image_source_uri_from_self) # ...and hence returns nil
655
+ photo.expects(:sizes).with('Medium').returns({})
656
+ photo.source
657
+ end
658
+
659
+ def test_should_build_uri_for_photo_from_self
660
+ assert_equal "http://www.flickr.com/photos/abc123/1418878", new_photo.send(:uri_for_photo_from_self)
661
+ end
662
+
663
+ def test_should_build_uri_for_photo_from_self_when_owner_is_a_string
664
+ assert_equal "http://www.flickr.com/photos/789user321/1418878", new_photo('owner' => "789user321").send(:uri_for_photo_from_self)
665
+ end
666
+
667
+ def test_should_build_uri_for_photo_from_self_for_given_size
668
+ assert_equal "http://www.flickr.com/photos/abc123/1418878/sizes/s/", new_photo.send(:uri_for_photo_from_self, "Small")
669
+ end
670
+
671
+ def test_should_build_uri_for_photo_from_self_with_unknown_size
672
+ assert_equal "http://www.flickr.com/photos/abc123/1418878", new_photo.send(:uri_for_photo_from_self, "Dummy")
673
+ end
674
+
675
+ def test_should_return_nil_for_uri_for_photo_when_no_user_id
676
+ assert_nil Flickr::Photo.new("1418878", nil).send(:uri_for_photo_from_self)
677
+ end
678
+
679
+ def test_should_return_nil_for_uri_for_photo_when_no_photo_id
680
+ assert_nil Flickr::Photo.new.send(:uri_for_photo_from_self)
681
+ end
682
+
683
+ def test_should_get_uri_for_photo_flickr_page
684
+ photo = new_photo
685
+ assert_equal "http://www.flickr.com/photos/abc123/1418878", photo.url
686
+ end
687
+
688
+ def test_should_return_main_page_for_photo_flickr_page_when_medium_size_requested_as_per_previous_version
689
+ assert_equal "http://www.flickr.com/photos/abc123/1418878", new_photo.url('Medium')
690
+ end
691
+
692
+ def test_should_call_size_url_if_url_given_a_size
693
+ photo = new_photo
694
+ photo.expects(:size_url).with('Large')
695
+ photo.url('Large')
696
+ end
697
+
698
+ def test_should_get_flickr_page_uri_by_building_from_self_if_possible_requesting_source_for_given_size
699
+ photo = new_photo
700
+ photo.expects(:uri_for_photo_from_self).with('Large').returns(true) # return any non-false-evaluating value so that sizes method isn't called
701
+ photo.size_url('Large')
702
+ end
703
+
704
+ def test_should_get_flickr_page_uri_by_calling_sizes_method_if_no_luck_building_uri
705
+ photo = new_photo
706
+ photo.stubs(:uri_for_photo_from_self) # ...and hence returns nil
707
+ photo.expects(:sizes).with('Large').returns({})
708
+ photo.size_url('Large')
709
+ end
710
+
711
+ def test_should_allow_size_to_be_lowercase_or_symbol
712
+ photo = new_photo
713
+ assert_equal photo.normalize_size('Small'), 'Small'
714
+ assert_equal photo.normalize_size('small'), 'Small'
715
+ assert_equal photo.normalize_size(:small), 'Small'
716
+ assert_equal photo.normalize_size(:Small), 'Small'
717
+ assert_equal photo.normalize_size('smAlL'), 'Small'
718
+
719
+ assert_equal photo.normalize_size(""), ""
720
+ assert_nil photo.normalize_size(nil)
721
+ end
722
+
723
+ def test_size_url_should_normalize_size
724
+ photo = new_photo
725
+ assert_equal photo.size_url('Large'), photo.size_url(:large)
726
+ end
727
+
728
+ def test_url_should_normalize_size
729
+ photo = new_photo
730
+ assert_equal photo.url('Medium'), photo.url(:medium)
731
+ assert_equal photo.url('Small'), photo.url('small')
732
+ end
733
+
734
+ def test_source_should_normalize_size
735
+ photo = new_photo
736
+ assert_equal photo.source('Large'), photo.source(:large)
737
+ end
738
+
739
+ def test_sizes_should_normalize_size
740
+ sizes = {'sizes' => {'size' => [{'label' => 'Small'}, {'label' => 'Large'}]}}
741
+ photo = new_photo
742
+ photo.client.expects(:photos_getSizes).at_least_once.returns(sizes)
743
+ assert_equal photo.sizes('Large'), photo.sizes(:large)
744
+ end
745
+
746
+ # Photo#context tests
747
+ def test_should_call_photos_getContext_to_get_context_photos
748
+ Flickr.any_instance.expects(:photos_getContext).returns({'prevphoto' => {}, 'nextphoto' => {}})
749
+ new_photo.context
750
+ end
751
+
752
+ def test_should_instantiate_context_photos_with_id_and_all_params_returned_by_query
753
+ photo = new_photo
754
+ Flickr.any_instance.expects(:photos_getContext).returns({ 'prevphoto' => {'id' => '123', 'key_1' => 'value_1' },
755
+ 'nextphoto' => {'id' => '456', 'key_2' => 'value_2'}})
756
+ Flickr::Photo.expects(:new).with("123", "foo123", { "key_1" => "value_1"})
757
+ Flickr::Photo.expects(:new).with("456", "foo123", { "key_2" => "value_2"})
758
+
759
+ photo.context
760
+ end
761
+
762
+ def test_should_not_instantiate_context_photos_with_id_of_0
763
+ photo = new_photo
764
+ Flickr.any_instance.expects(:photos_getContext).returns({ 'prevphoto' => {'id' => '123', 'key_1' => 'value_1' },
765
+ 'nextphoto' => {'id' => '0', 'key_2' => 'value_2'}})
766
+ Flickr::Photo.expects(:new).with("123", anything, anything)
767
+ Flickr::Photo.expects(:new).with("0", anything, anything).never
768
+
769
+ photo.context
770
+ end
771
+
772
+ # ##### Flickr::Group tests
773
+ #
774
+ def test_should_instantiate_group_from_id
775
+ group = Flickr::Group.new("group1")
776
+ assert_equal "group1", group.id
777
+ end
778
+
779
+ # tests old api for instantiating groups
780
+ def test_should_instantiate_group_from_id_and_api_key
781
+ f = flickr_client
782
+ Flickr.expects(:new).with("some_api_key").returns(f)
783
+ group = Flickr::Group.new("group1", "some_api_key")
784
+ assert_equal f, group.client
785
+ end
786
+
787
+ # new api for instantiating groups
788
+ def test_should_instantiate_group_from_params_hash
789
+ group = Flickr::Group.new("id" => "group1", "name" => "Group One", "eighteenplus" => "1", "foo" => "bar")
790
+ assert_equal "group1", group.id
791
+ assert_equal "Group One", group.name
792
+ assert_equal "1", group.eighteenplus
793
+ assert_equal "bar", group.instance_variable_get(:@foo)
794
+ end
795
+
796
+ def test_should_use_flickr_client_passed_in_params_hash_when_instantiating_group
797
+ f = flickr_client
798
+ Flickr.expects(:new).never
799
+ group = Flickr::Group.new("id" => "group1", "name" => "Group One", "client" => f)
800
+ assert_equal f, group.client
801
+ end
802
+
803
+ def test_should_provide_id_name_eighteenplus_description_members_online_privacy_reader_methods_for_group
804
+ g = Flickr::Group.new
805
+ %w(id name eighteenplus description members online privacy).each do |m|
806
+ g.instance_variable_set("@#{m}", "foo_#{m}")
807
+ assert_equal "foo_#{m}", g.send(m)
808
+ end
809
+ end
810
+
811
+ # def test_should_initialize_photo_from_id
812
+ # photo = Flickr::Photo.new("foo123")
813
+ # assert_equal "foo123", photo.id
814
+ # end
815
+ #
816
+ # def test_should_save_extra_params_as_instance_variables
817
+ # photo = Flickr::Photo.new('foo123', 'some_api_key', { 'key1' => 'value1', 'key2' => 'value2'})
818
+ # assert_equal 'value1', photo.instance_variable_get(:@key1)
819
+ # assert_equal 'value2', photo.instance_variable_get(:@key2)
820
+ # end
821
+ #
822
+ # def test_should_be_able_to_access_instance_variables_through_hash_like_interface
823
+ # photo = Flickr::Photo.new
824
+ # photo.instance_variable_set(:@key1, 'value1')
825
+ # assert_equal 'value1', photo['key1']
826
+ # assert_equal 'value1', photo[:key1]
827
+ # assert_nil photo[:key2]
828
+ # assert_nil photo['key2']
829
+ # end
830
+
831
+ # ##### PHOTOSETS
832
+ #
833
+ # #def setup
834
+ # # super
835
+ # # @photoset = @f.photosets_create('title'=>@title, 'primary_photo_id'=>@photo_id)
836
+ # # @photoset_id = @photoset['photoset']['id']
837
+ # #end
838
+ # #def teardown
839
+ # # @f.photosets_delete('photoset_id'=>@photoset_id)
840
+ # #end
841
+ #
842
+ # def test_photosets_editMeta
843
+ # assert_equal @f.photosets_editMeta('photoset_id'=>@photoset_id, 'title'=>@title)['stat'], 'ok'
844
+ # end
845
+ #
846
+ # def test_photosets_editPhotos
847
+ # assert_equal @f.photosets_editPhotos('photoset_id'=>@photoset_id, 'primary_photo_id'=>@photo_id, 'photo_ids'=>@photo_id)['stat'], 'ok'
848
+ # end
849
+ #
850
+ # def test_photosets_getContext
851
+ # assert_equal @f.photosets_getContext('photoset_id'=>@photoset_id, 'photo_id'=>@photo_id)['stat'], 'ok'
852
+ # end
853
+ #
854
+ # def test_photosets_getContext
855
+ # assert_equal @f.photosets_getContext('photoset_id'=>@photoset_id, 'photo_id'=>@photo_id)['stat'], 'ok'
856
+ # end
857
+ #
858
+ # def test_photosets_getInfo
859
+ # assert_equal @f.photosets_getInfo('photoset_id'=>@photoset_id)['stat'], 'ok'
860
+ # end
861
+ #
862
+ # def test_photosets_getList
863
+ # assert_equal @f.photosets_getList['stat'], 'ok'
864
+ # end
865
+ #
866
+ # def test_photosets_getPhotos
867
+ # assert_equal @f.photosets_getPhotos('photoset_id'=>@photoset_id)['stat'], 'ok'
868
+ # end
869
+ #
870
+ # def test_photosets_orderSets
871
+ # assert_equal @f.photosets_orderSets('photoset_ids'=>@photoset_id)['stat'], 'ok'
872
+ # end
873
+
874
+ def test_related_tags
875
+ f = flickr_client
876
+ tags_response = {
877
+ "tags" => {
878
+ "tag" => [ "zoo", "animal" ],
879
+ "source" => "monkey",
880
+ },
881
+ "stat" => "ok",
882
+ }
883
+ f.expects(:tags_getRelated).with('tag' => 'monkey').returns(tags_response)
884
+ assert_equal f.related_tags('monkey'), %w(zoo animal)
885
+ end
886
+
887
+ # ##### Flickr::PhotoCollection tests
888
+ #
889
+ def test_should_subclass_array_as_photo_collection
890
+ assert_equal Array, Flickr::PhotoCollection.superclass
891
+ end
892
+
893
+ def test_should_make_page_a_reader_method
894
+ assert_equal "3", dummy_photo_collection.page
895
+ end
896
+
897
+ def test_should_make_pages_a_reader_method
898
+ assert_equal "5", dummy_photo_collection.pages
899
+ end
900
+
901
+ def test_should_make_perpage_a_reader_method
902
+ assert_equal "10", dummy_photo_collection.perpage
903
+ end
904
+
905
+ def test_should_make_total_a_reader_method
906
+ assert_equal "42", dummy_photo_collection.total
907
+ end
908
+
909
+ def test_should_instantiate_photo_collection_from_photos_hash
910
+ pc = Flickr::PhotoCollection.new(dummy_photos_response)
911
+ assert_kind_of Flickr::PhotoCollection, pc
912
+ assert_equal 2, pc.size
913
+ assert_kind_of Flickr::Photo, pc.first
914
+ assert_equal "foo123", pc.first["id"]
915
+ end
916
+
917
+ def test_should_instantiate_photo_collection_using_given_api_key
918
+ photo = Flickr::PhotoCollection.new(dummy_photos_response, "some_api_key").first
919
+ assert_equal "some_api_key", photo.instance_variable_get(:@api_key)
920
+ end
921
+
922
+ private
923
+ def flickr_client
924
+ Flickr.new("some_api_key")
925
+ end
926
+
927
+ def authenticated_flickr_client
928
+ f = Flickr.new('api_key' => 'some_api_key', 'shared_secret' => 'shared_secret_code')
929
+ f.instance_variable_set(:@auth_token, 'some_auth_token')
930
+ f
931
+ end
932
+
933
+ def new_user(options={})
934
+ Flickr::User.new({ 'id' => 'foo123',
935
+ 'username' => 'some_user',
936
+ 'name' => 'Some User',
937
+ 'foo' => 'bar',
938
+ 'auth_token' => 'foobar789'}.merge(options))
939
+
940
+ end
941
+ def new_photo(options={})
942
+ Flickr::Photo.new("1418878",
943
+ "foo123",
944
+ { "farm" => "1",
945
+ "server" => "2",
946
+ "secret" => "1e92283336",
947
+ "owner" => Flickr::User.new("abc123", "some_user", nil, nil, "some_api_key") }.merge(options))
948
+ end
949
+
950
+ def dummy_photo_collection
951
+ Flickr::PhotoCollection.new(dummy_photos_response)
952
+ end
953
+
954
+ def dummy_photos_response
955
+ { "photos" =>
956
+ { "photo" =>
957
+ [{ "id" => "foo123",
958
+ "key1" => "value1",
959
+ "key2" => "value2" },
960
+ { "id" => "bar456",
961
+ "key3" => "value3"}],
962
+ "page"=>"3",
963
+ "pages"=>"5",
964
+ "perpage"=>"10",
965
+ "total"=>"42" } }
966
+ end
967
+
968
+ def dummy_single_photo_response
969
+ { "photos" =>
970
+ { "photo" =>
971
+ { "id" => "foo123",
972
+ "key1" => "value1",
973
+ "key2" => "value2" } } }
974
+ end
975
+
976
+ def dummy_zero_photo_response
977
+ { "photos" => { "total" => 0 } }
978
+ end
979
+
980
+ def dummy_user_response
981
+ { "user" =>
982
+ { "nsid" => "12037949632@N01",
983
+ "username" => "Stewart" }
984
+ }
985
+ end
986
+
987
+ def dummy_groups_response
988
+ { "groups" =>
989
+ { "group" =>
990
+ [{ "nsid" => "group1",
991
+ "name" => "Group One",
992
+ "eighteenplus" => "0" },
993
+ { "nsid" => "group2",
994
+ "name" => "Group Two",
995
+ "eighteenplus" => "1"}] } }
996
+ end
997
+
998
+ def dummy_single_group_response
999
+ { "groups" =>
1000
+ { "group" =>
1001
+ { "nsid" => "group1",
1002
+ "name" => "Group One",
1003
+ "eighteenplus" => "0" } } }
1004
+ end
1005
+
1006
+ def successful_xml_response
1007
+ <<-EOF
1008
+ <?xml version="1.0" encoding="utf-8" ?>
1009
+ <rsp stat="ok">
1010
+ <contacts page="1" pages="1" perpage="1000" total="2">
1011
+ <contact nsid="12037949629@N01" username="Eric" iconserver="1"
1012
+ realname="Eric Costello"
1013
+ friend="1" family="0" ignored="1" />
1014
+ <contact nsid="12037949631@N01" username="neb" iconserver="1"
1015
+ realname="Ben Cerveny"
1016
+ friend="0" family="0" ignored="0" />
1017
+ </contacts>
1018
+ </rsp>
1019
+ EOF
1020
+ end
1021
+
1022
+ def unsuccessful_xml_response
1023
+ <<-EOF
1024
+ <?xml version="1.0" encoding="utf-8" ?>
1025
+ <rsp stat="fail">
1026
+ <err code="[error-code]" msg="[error-message]" />
1027
+ </rsp>
1028
+ EOF
1029
+ end
1030
+
1031
+ def photo_info_xml_response
1032
+ <<-EOF
1033
+ <?xml version="1.0" encoding="utf-8" ?>
1034
+ <rsp stat="ok">
1035
+ <photo id="22527834" secret="ae75bd3111" server="3142" farm="4" dateuploaded="1204145093" isfavorite="0" license="0" rotation="0" media="photo">
1036
+ <owner nsid="9383319@N05" username="Rootes_arrow_1725" realname="John" location="U.K" />
1037
+ <title>1964 120 amazon estate</title>
1038
+ <description>1964 Volvo 120 amazon estate spotted in derbyshire.</description>
1039
+ <visibility ispublic="1" isfriend="0" isfamily="0" />
1040
+ <dates posted="1204145093" taken="2007-06-10 13:18:27" takengranularity="0" lastupdate="1204166772" />
1041
+ <editability cancomment="0" canaddmeta="0" />
1042
+ <usage candownload="0" canblog="0" canprint="0" />
1043
+ <comments>1</comments>
1044
+ <notes>
1045
+ <note id="313" author="12037949754@N01" authorname="Bees" x="10" y="10" w="50" h="50">foo</note>
1046
+ </notes>
1047
+ <tags>
1048
+ <tag id="9377979-2296968304-2228" author="9383319@N05" raw="volvo" machine_tag="0">volvo</tag>
1049
+ <tag id="9377979-2296968304-2229" author="9383319@N06" raw="amazon" machine_tag="0">amazon</tag>
1050
+ </tags>
1051
+ <urls>
1052
+ <url type="photopage">http://www.flickr.com/photos/rootes_arrow/2296968304/</url>
1053
+ </urls>
1054
+ </photo>
1055
+ </rsp>
1056
+ EOF
1057
+ end
1058
+
1059
+ def sparse_photo_info_xml_response
1060
+ <<-EOF
1061
+ <?xml version="1.0" encoding="utf-8" ?>
1062
+ <rsp stat="ok">
1063
+ <photo id="22527834" secret="ae75bd3111" server="3142" farm="4" dateuploaded="1204145093" isfavorite="0" license="0" rotation="0" media="photo">
1064
+ <owner nsid="9383319@N05" username="Rootes_arrow_1725" realname="John" location="U.K" />
1065
+ <title>1964 120 amazon estate</title>
1066
+ <description/>
1067
+ <visibility ispublic="1" isfriend="0" isfamily="0" />
1068
+ <dates posted="1204145093" taken="2007-06-10 13:18:27" takengranularity="0" lastupdate="1204166772" />
1069
+ <editability cancomment="0" canaddmeta="0" />
1070
+ <usage candownload="0" canblog="0" canprint="0" />
1071
+ <comments>1</comments>
1072
+ <notes/>
1073
+ <tags/>
1074
+ <urls>
1075
+ <url type="photopage">http://www.flickr.com/photos/rootes_arrow/2296968304/</url>
1076
+ </urls>
1077
+ </photo>
1078
+ </rsp>
1079
+ EOF
1080
+ end
1081
+
1082
+ end