fleakr 0.3.0 → 0.4.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.
Files changed (51) hide show
  1. data/README.rdoc +114 -19
  2. data/Rakefile +1 -1
  3. data/lib/fleakr/api/file_parameter.rb +47 -0
  4. data/lib/fleakr/api/method_request.rb +57 -0
  5. data/lib/fleakr/api/parameter.rb +35 -0
  6. data/lib/fleakr/api/parameter_list.rb +96 -0
  7. data/lib/fleakr/api/response.rb +2 -2
  8. data/lib/fleakr/api/upload_request.rb +64 -0
  9. data/lib/fleakr/api/value_parameter.rb +36 -0
  10. data/lib/fleakr/api.rb +7 -0
  11. data/lib/fleakr/core_ext/hash.rb +22 -0
  12. data/lib/fleakr/core_ext.rb +1 -0
  13. data/lib/fleakr/objects/authentication_token.rb +43 -0
  14. data/lib/fleakr/objects/contact.rb +5 -5
  15. data/lib/fleakr/objects/error.rb +2 -2
  16. data/lib/fleakr/objects/group.rb +2 -2
  17. data/lib/fleakr/objects/image.rb +7 -7
  18. data/lib/fleakr/objects/photo.rb +69 -5
  19. data/lib/fleakr/objects/search.rb +3 -6
  20. data/lib/fleakr/objects/set.rb +11 -5
  21. data/lib/fleakr/objects/user.rb +14 -26
  22. data/lib/fleakr/objects.rb +9 -0
  23. data/lib/fleakr/support/attribute.rb +30 -12
  24. data/lib/fleakr/support/object.rb +20 -4
  25. data/lib/fleakr/support.rb +2 -0
  26. data/lib/fleakr/version.rb +1 -1
  27. data/lib/fleakr.rb +66 -7
  28. data/test/fixtures/auth.checkToken.xml +8 -0
  29. data/test/fixtures/auth.getFullToken.xml +8 -0
  30. data/test/fixtures/people.getInfo.xml +1 -1
  31. data/test/fixtures/photos.getInfo.xml +20 -0
  32. data/test/test_helper.rb +18 -3
  33. data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
  34. data/test/unit/fleakr/api/method_request_test.rb +103 -0
  35. data/test/unit/fleakr/api/parameter_list_test.rb +161 -0
  36. data/test/unit/fleakr/api/parameter_test.rb +34 -0
  37. data/test/unit/fleakr/api/upload_request_test.rb +133 -0
  38. data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
  39. data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
  40. data/test/unit/fleakr/objects/authentication_token_test.rb +47 -0
  41. data/test/unit/fleakr/objects/image_test.rb +10 -5
  42. data/test/unit/fleakr/objects/photo_test.rb +96 -36
  43. data/test/unit/fleakr/objects/search_test.rb +1 -1
  44. data/test/unit/fleakr/objects/set_test.rb +12 -1
  45. data/test/unit/fleakr/objects/user_test.rb +2 -16
  46. data/test/unit/fleakr/support/attribute_test.rb +82 -24
  47. data/test/unit/fleakr/support/object_test.rb +26 -3
  48. data/test/unit/fleakr_test.rb +65 -6
  49. metadata +28 -5
  50. data/lib/fleakr/api/request.rb +0 -58
  51. data/test/unit/fleakr/api/request_test.rb +0 -93
@@ -24,11 +24,11 @@ module Fleakr
24
24
 
25
25
  include Fleakr::Support::Object
26
26
 
27
- flickr_attribute :size, :attribute => :label
28
- flickr_attribute :width, :attribute => :width
29
- flickr_attribute :height, :attribute => :height
30
- flickr_attribute :url, :attribute => :source
31
- flickr_attribute :page, :attribute => :url
27
+ flickr_attribute :size, :from => '@label'
28
+ flickr_attribute :width
29
+ flickr_attribute :height
30
+ flickr_attribute :url, :from => '@source'
31
+ flickr_attribute :page, :from => '@url'
32
32
 
33
33
  find_all :by_photo_id, :call => 'photos.getSizes', :path => 'sizes/size'
34
34
 
@@ -41,8 +41,8 @@ module Fleakr
41
41
  # directory, the file will be created with the original filename from Flickr.
42
42
  # If the target is a file, it will be saved with the specified name. In the
43
43
  # case that the target file already exists, this method will overwrite it.
44
- def save_to(target)
45
- destination = File.directory?(target) ? "#{target}/#{self.filename}" : "#{target}"
44
+ def save_to(target, prefix = nil)
45
+ destination = File.directory?(target) ? "#{target}/#{prefix}#{self.filename}" : "#{target}"
46
46
  File.open(destination, 'w') {|f| f << Net::HTTP.get(URI.parse(self.url)) }
47
47
  end
48
48
 
@@ -7,6 +7,10 @@ module Fleakr
7
7
  #
8
8
  # [id] The ID for this photo
9
9
  # [title] The title of this photo
10
+ # [description] The description of this photo
11
+ # [secret] This photo's secret (used for sharing photo without permissions checking)
12
+ # [comment_count] Count of the comments attached to this photo
13
+ # [url] This photo's page on Flickr
10
14
  # [square] The tiny square representation of this photo
11
15
  # [thumbnail] The thumbnail for this photo
12
16
  # [small] The small representation of this photo
@@ -25,18 +29,78 @@ module Fleakr
25
29
 
26
30
  include Fleakr::Support::Object
27
31
 
28
- flickr_attribute :title, :attribute => 'title'
29
- flickr_attribute :id, :attribute => 'id'
30
- flickr_attribute :farm_id, :attribute => 'farm'
31
- flickr_attribute :server_id, :attribute => 'server'
32
- flickr_attribute :secret, :attribute => 'secret'
32
+ flickr_attribute :id, :from => ['@id', 'photoid']
33
+ flickr_attribute :title
34
+ flickr_attribute :description
35
+ flickr_attribute :farm_id, :from => '@farm'
36
+ flickr_attribute :server_id, :from => '@server'
37
+ flickr_attribute :secret
38
+ flickr_attribute :posted
39
+ flickr_attribute :taken
40
+ flickr_attribute :updated, :from => '@lastupdate'
41
+ flickr_attribute :comment_count, :from => 'comments'
42
+ flickr_attribute :url
43
+
44
+ # TODO:
45
+ # * owner (user)
46
+ # * visibility
47
+ # * editability
48
+ # * usage
49
+ # * notes
50
+ # * tags
33
51
 
34
52
  find_all :by_photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
35
53
  find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
36
54
  find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
37
55
 
56
+ find_one :by_id, :using => :photo_id, :call => 'photos.getInfo', :authenticate? => true
57
+
58
+ lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
59
+
38
60
  has_many :images
39
61
 
62
+ # Upload the photo specified by <tt>filename</tt> to the user's Flickr account. This
63
+ # call requires authentication.
64
+ #
65
+ def self.upload(filename)
66
+ response = Fleakr::Api::UploadRequest.with_response!(filename)
67
+ photo = Photo.new(response.body)
68
+ Photo.find_by_id(photo.id, :authenticate? => true)
69
+ end
70
+
71
+ # Replace the current photo's image with the one specified by filename. This
72
+ # call requires authentication.
73
+ #
74
+ def replace_with(filename)
75
+ response = Fleakr::Api::UploadRequest.with_response!(filename, :photo_id => self.id, :type => :update)
76
+ self.populate_from(response.body)
77
+ self
78
+ end
79
+
80
+ # TODO: Refactor this to remove duplication w/ User#load_info - possibly in the lazily_load class method
81
+ def load_info # :nodoc:
82
+ response = Fleakr::Api::MethodRequest.with_response!('photos.getInfo', :photo_id => self.id)
83
+ self.populate_from(response.body)
84
+ end
85
+
86
+ # When was this photo posted?
87
+ #
88
+ def posted_at
89
+ Time.at(posted.to_i)
90
+ end
91
+
92
+ # When was this photo taken?
93
+ #
94
+ def taken_at
95
+ Time.parse(taken)
96
+ end
97
+
98
+ # When was this photo last updated? This includes addition of tags and other metadata.
99
+ #
100
+ def updated_at
101
+ Time.at(updated.to_i)
102
+ end
103
+
40
104
  # Create methods to access image sizes by name
41
105
  SIZES.each do |size|
42
106
  define_method(size) do
@@ -9,13 +9,10 @@ module Fleakr
9
9
 
10
10
  # Retrieve search results from the API
11
11
  def results
12
- if @results.nil?
13
- response = Fleakr::Api::Request.with_response!('photos.search', parameters)
14
- @results = (response.body/'rsp/photos/photo').map do |flickr_photo|
15
- Photo.new(flickr_photo)
16
- end
12
+ @results ||= begin
13
+ response = Fleakr::Api::MethodRequest.with_response!('photos.search', parameters)
14
+ (response.body/'rsp/photos/photo').map {|p| Photo.new(p) }
17
15
  end
18
- @results
19
16
  end
20
17
 
21
18
  private
@@ -8,6 +8,7 @@ module Fleakr
8
8
  # [id] The ID for this photoset
9
9
  # [title] The title of this photoset
10
10
  # [description] The description of this set
11
+ # [count] Count of photos in this set
11
12
  #
12
13
  # == Associations
13
14
  #
@@ -19,26 +20,31 @@ module Fleakr
19
20
 
20
21
  has_many :photos, :using => :photoset_id
21
22
 
22
- flickr_attribute :id, :attribute => 'id'
23
+ flickr_attribute :id
23
24
  flickr_attribute :title
24
25
  flickr_attribute :description
26
+ flickr_attribute :count, :from => '@photos'
25
27
 
26
28
  find_all :by_user_id, :call => 'photosets.getList', :path => 'photosets/photoset'
27
29
 
28
- # Save all photos in this set to the specified directory using the specified size. Allowed
30
+ # Save all photos in this set to the specified directory for the specified size. Allowed
29
31
  # Sizes include <tt>:square</tt>, <tt>:small</tt>, <tt>:thumbnail</tt>, <tt>:medium</tt>,
30
- # <tt>:large</tt>, and <tt>:original</tt>. When saving the set, this # method will create
32
+ # <tt>:large</tt>, and <tt>:original</tt>. When saving the set, this method will create
31
33
  # a subdirectory based on the set's title.
32
34
  #
33
35
  def save_to(path, size)
34
36
  target = "#{path}/#{self.title}"
35
37
  FileUtils.mkdir(target) unless File.exist?(target)
36
38
 
37
- self.photos.each do |photo|
39
+ self.photos.each_with_index do |photo, index|
38
40
  image = photo.send(size)
39
- image.save_to(target) unless image.nil?
41
+ image.save_to(target, file_prefix(index)) unless image.nil?
40
42
  end
41
43
  end
44
+
45
+ def file_prefix(index) # :nodoc:
46
+ sprintf("%0#{self.count.length}d_", (index + 1))
47
+ end
42
48
 
43
49
  end
44
50
  end
@@ -11,6 +11,7 @@ module Fleakr
11
11
  # [id] The ID for this user (also referred to as the NSID in the API docs)
12
12
  # [username] This user's username
13
13
  # [name] This user's full name (if entered)
14
+ # [location] This user's location (if entered)
14
15
  # [photos_url] The direct URL to this user's photostream
15
16
  # [profile_url] The direct URL to this user's profile
16
17
  # [photos_count] The number of photos that this user has uploaded
@@ -42,37 +43,24 @@ module Fleakr
42
43
 
43
44
  include Fleakr::Support::Object
44
45
 
45
- def self.lazily_load(*attributes)
46
- options = attributes.extract_options!
47
-
48
- attributes.each do |attribute|
49
- class_eval <<-CODE
50
- def #{attribute}_with_loading
51
- self.send(:#{options[:with]}) if @#{attribute}.nil?
52
- #{attribute}_without_loading
53
- end
54
- alias_method_chain :#{attribute}, :loading
55
- CODE
56
- end
57
- end
58
-
59
- flickr_attribute :id, :xpath => 'rsp/user', :attribute => 'nsid'
60
- flickr_attribute :username, :xpath => 'rsp/user/username'
61
- flickr_attribute :name, :xpath => 'rsp/person/realname'
62
- flickr_attribute :photos_url, :xpath => 'rsp/person/photosurl'
63
- flickr_attribute :profile_url, :xpath => 'rsp/person/profileurl'
64
- flickr_attribute :photos_count, :xpath => 'rsp/person/photos/count'
65
- flickr_attribute :icon_server, :xpath => 'rsp/person', :attribute => 'iconserver'
66
- flickr_attribute :icon_farm, :xpath => 'rsp/person', :attribute => 'iconfarm'
67
- flickr_attribute :pro, :xpath => 'rsp/person', :attribute => 'ispro'
68
- flickr_attribute :admin, :xpath => 'rsp/person', :attribute => 'isadmin'
46
+ flickr_attribute :id, :from => 'user@nsid'
47
+ flickr_attribute :username
48
+ flickr_attribute :name, :from => 'person/realname'
49
+ flickr_attribute :location
50
+ flickr_attribute :photos_url, :from => 'person/photosurl'
51
+ flickr_attribute :profile_url, :from => 'person/profileurl'
52
+ flickr_attribute :photos_count, :from => 'person/photos/count'
53
+ flickr_attribute :icon_server, :from => 'person@iconserver'
54
+ flickr_attribute :icon_farm, :from => 'person@iconfarm'
55
+ flickr_attribute :pro, :from => 'person@ispro'
56
+ flickr_attribute :admin, :from => 'person@isadmin'
69
57
 
70
58
  has_many :sets, :groups, :photos, :contacts
71
59
 
72
60
  find_one :by_username, :call => 'people.findByUsername'
73
61
  find_one :by_email, :using => :find_email, :call => 'people.findByEmail'
74
62
 
75
- lazily_load :name, :photos_url, :profile_url, :photos_count, :with => :load_info
63
+ lazily_load :name, :photos_url, :profile_url, :photos_count, :location, :with => :load_info
76
64
  lazily_load :icon_server, :icon_farm, :pro, :admin, :with => :load_info
77
65
 
78
66
  scoped_search
@@ -97,7 +85,7 @@ module Fleakr
97
85
  end
98
86
 
99
87
  def load_info # :nodoc:
100
- response = Fleakr::Api::Request.with_response!('people.getInfo', :user_id => self.id)
88
+ response = Fleakr::Api::MethodRequest.with_response!('people.getInfo', :user_id => self.id)
101
89
  self.populate_from(response.body)
102
90
  end
103
91
 
@@ -0,0 +1,9 @@
1
+ require 'fleakr/objects/authentication_token'
2
+ require 'fleakr/objects/contact'
3
+ require 'fleakr/objects/error'
4
+ require 'fleakr/objects/group'
5
+ require 'fleakr/objects/image'
6
+ require 'fleakr/objects/photo'
7
+ require 'fleakr/objects/search'
8
+ require 'fleakr/objects/set'
9
+ require 'fleakr/objects/user'
@@ -2,25 +2,43 @@ module Fleakr
2
2
  module Support # :nodoc:all
3
3
  class Attribute
4
4
 
5
- attr_reader :name, :xpath, :attribute
5
+ # TODO: Refactor the location / attribute logic into a Source class
6
6
 
7
- def initialize(name, options = {})
7
+ attr_reader :name, :sources
8
+
9
+ def initialize(name, sources = nil)
8
10
  @name = name.to_sym
9
- @attribute = options[:attribute]
11
+
12
+ @sources = Array(sources)
13
+ @sources << @name.to_s if @sources.empty?
14
+ end
15
+
16
+ def split(source)
17
+ location, attribute = source.split('@')
18
+ location = self.name.to_s if location.blank?
19
+
20
+ [location, attribute]
21
+ end
22
+
23
+ def node_for(document, source)
24
+ document.at(location(source)) || document.search("//[@#{attribute(source)}]").first
25
+ end
10
26
 
11
- @xpath = options[:xpath]
12
- @xpath ||= @name.to_s unless @attribute
27
+ def attribute(source)
28
+ location, attribute = source.split('@')
29
+ attribute || location
30
+ end
31
+
32
+ def location(source)
33
+ split(source).first
13
34
  end
14
35
 
15
36
  def value_from(document)
16
- node = document
17
-
18
- begin
19
- node = document.at(self.xpath) if self.xpath
20
- self.attribute.nil? ? node.inner_text : node[self.attribute]
21
- rescue NoMethodError
22
- nil
37
+ values = sources.map do |source|
38
+ node = node_for(document, source)
39
+ (node.attributes[attribute(source)] || node.inner_text) unless node.nil?
23
40
  end
41
+ values.compact.first
24
42
  end
25
43
 
26
44
  end
@@ -9,7 +9,7 @@ module Fleakr
9
9
  end
10
10
 
11
11
  def flickr_attribute(name, options = {})
12
- self.attributes << Attribute.new(name, options)
12
+ self.attributes << Attribute.new(name, options[:from])
13
13
  class_eval "attr_accessor :#{name}"
14
14
  end
15
15
 
@@ -34,7 +34,7 @@ module Fleakr
34
34
 
35
35
  class_eval <<-CODE
36
36
  def self.find_all_#{condition}(value)
37
- response = Fleakr::Api::Request.with_response!('#{options[:call]}', :#{attribute} => value)
37
+ response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', :#{attribute} => value)
38
38
  (response.body/'rsp/#{options[:path]}').map {|e| #{target_class}.new(e) }
39
39
  end
40
40
  CODE
@@ -44,8 +44,10 @@ module Fleakr
44
44
  attribute = options[:using].nil? ? condition.to_s.sub(/^by_/, '') : options[:using]
45
45
 
46
46
  class_eval <<-CODE
47
- def self.find_#{condition}(value)
48
- response = Fleakr::Api::Request.with_response!('#{options[:call]}', :#{attribute} => value)
47
+ def self.find_#{condition}(value, options = {})
48
+ options.merge!(:#{attribute} => value)
49
+
50
+ response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', options)
49
51
  #{self.name}.new(response.body)
50
52
  end
51
53
  CODE
@@ -60,6 +62,20 @@ module Fleakr
60
62
  end
61
63
  CODE
62
64
  end
65
+
66
+ def lazily_load(*attributes)
67
+ options = attributes.extract_options!
68
+
69
+ attributes.each do |attribute|
70
+ class_eval <<-CODE
71
+ def #{attribute}_with_loading
72
+ self.send(:#{options[:with]}) if @#{attribute}.nil?
73
+ #{attribute}_without_loading
74
+ end
75
+ alias_method_chain :#{attribute}, :loading
76
+ CODE
77
+ end
78
+ end
63
79
 
64
80
  end
65
81
 
@@ -0,0 +1,2 @@
1
+ require 'fleakr/support/attribute'
2
+ require 'fleakr/support/object'
@@ -2,7 +2,7 @@ module Fleakr
2
2
  module Version # :nodoc:
3
3
 
4
4
  MAJOR = 0
5
- MINOR = 3
5
+ MINOR = 4
6
6
  TINY = 0
7
7
 
8
8
  def self.to_s
data/lib/fleakr.rb CHANGED
@@ -6,13 +6,16 @@ require 'net/http'
6
6
  require 'rubygems'
7
7
  require 'hpricot'
8
8
  require 'activesupport'
9
+ require 'md5'
9
10
 
10
- %w(support api objects).each do |path|
11
- full_path = File.expand_path(File.dirname(__FILE__)) + "/fleakr/#{path}"
12
- Dir["#{full_path}/*.rb"].each {|f| require f }
13
- end
11
+ require 'fleakr/api'
12
+ require 'fleakr/core_ext'
13
+ require 'fleakr/support'
14
+ require 'fleakr/objects'
14
15
 
15
- # = Fleakr: A teeny tiny gem to interface with Flickr
16
+ # = Fleakr: A small, yet powerful, gem to interface with Flickr photostreams
17
+ #
18
+ # == Quick Start
16
19
  #
17
20
  # Getting started is easy, just make sure you have a valid API key from Flickr and you can
18
21
  # then start making any non-authenticated request to pull back data for yours and others'
@@ -36,10 +39,42 @@ end
36
39
  # user.groups
37
40
  #
38
41
  # To see what other associations and attributes are available, see the Fleakr::Objects::User class
42
+ #
43
+ # == Authentication
44
+ #
45
+ # If you want to do something more than just retrieve public photos (like upload your own),
46
+ # you'll need to generate an authentication token to use across requests and sessions.
47
+ #
48
+ # Assuming you've already applied for a key, go back and make sure you have the right settings
49
+ # to get your auth token. Click on the 'Edit key details' link and ensure that:
50
+ #
51
+ # 1. Your application description and notes are up-to-date
52
+ # 1. The value for 'Authentication Type' is set to 'Mobile Application'
53
+ # 1. The value for 'Mobile Permissions' is set to either 'write' or 'delete'
54
+ #
55
+ # Once this is set, you'll see your Authentication URL on the key details page (it will look
56
+ # something like http://www.flickr.com/auth-534525246245). Paste this URL into your browser and
57
+ # confirm access to get your mini-token. Now you're ready to make authenticated requests:
58
+ #
59
+ # require 'rubygems'
60
+ # require 'fleakr'
61
+ #
62
+ # Fleakr.api_key = 'ABC123'
63
+ # Fleakr.shared_secret = 'sekrit' # Available with your key details on the Flickr site
64
+ # Fleakr.mini_token = '362-133-214'
65
+ #
66
+ # Fleakr.upload('/path/to/my/photo.jpg')
67
+ # Fleakr.token.value # => "34132412341235-12341234ef34"
68
+ #
69
+ # Once you use the mini-token once, it is no longer available. To use the generated auth_token
70
+ # for future requests, just set Fleakr.auth_token to the generated value.
39
71
  #
40
72
  module Fleakr
41
73
 
42
- mattr_accessor :api_key
74
+ # Generic catch-all exception for any API errors
75
+ class ApiError < StandardError; end
76
+
77
+ mattr_accessor :api_key, :shared_secret, :mini_token, :auth_token
43
78
 
44
79
  # Find a user based on some unique user data. This method will try to find
45
80
  # the user based on username and will fall back to email if that fails. Example:
@@ -51,7 +86,7 @@ module Fleakr
51
86
  def self.user(user_data)
52
87
  begin
53
88
  Objects::User.find_by_username(user_data)
54
- rescue Api::Request::ApiError
89
+ rescue ApiError
55
90
  Objects::User.find_by_email(user_data)
56
91
  end
57
92
  end
@@ -71,4 +106,28 @@ module Fleakr
71
106
  Objects::Search.new(params).results
72
107
  end
73
108
 
109
+ # Upload one or more files to your Flickr account (requires authentication). Simply provide
110
+ # a filename or a pattern to upload one or more files:
111
+ #
112
+ # Fleakr.upload('/path/to/my/mug.jpg')
113
+ # Fleakr.upload('/User/Pictures/Party/*.jpg')
114
+ #
115
+ def self.upload(glob)
116
+ Dir[glob].each {|file| Fleakr::Objects::Photo.upload(file) }
117
+ end
118
+
119
+ # Get the authentication token needed for authenticated requests. Will either use
120
+ # a valid auth_token (if available) or a mini-token to generate the auth_token.
121
+ #
122
+ def self.token
123
+ @token ||= begin
124
+ if !Fleakr.auth_token.nil?
125
+ Fleakr::Objects::AuthenticationToken.from_auth_token(Fleakr.auth_token)
126
+ else
127
+ Fleakr::Objects::AuthenticationToken.from_mini_token(Fleakr.mini_token)
128
+ end
129
+ end
130
+ end
131
+
132
+
74
133
  end
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <rsp stat="ok">
3
+ <auth>
4
+ <token>abc-123</token>
5
+ <perms>delete</perms>
6
+ <user nsid="31066442@N69" fullname="Sir Froot Pants" username="frootpantz"></user>
7
+ </auth>
8
+ </rsp>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <rsp stat="ok">
3
+ <auth>
4
+ <token>abc-123</token>
5
+ <perms>delete</perms>
6
+ <user nsid="31066442@N69" fullname="Sir Froot Pants" username="frootpantz"></user>
7
+ </auth>
8
+ </rsp>
@@ -4,7 +4,7 @@
4
4
  <username>frootpantz</username>
5
5
  <realname>Sir Froot Pantz</realname>
6
6
  <mbox_sha1sum>e52ed1e5b91c763694995460e9796fc2adc02019</mbox_sha1sum>
7
- <location />
7
+ <location>The Moon</location>
8
8
  <photosurl>http://www.flickr.com/photos/frootpantz/</photosurl>
9
9
  <profileurl>http://www.flickr.com/people/frootpantz/</profileurl>
10
10
  <mobileurl>http://m.flickr.com/photostream.gne?id=34225</mobileurl>
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <rsp stat="ok">
3
+ <photo id="1" secret="secret" server="3085" farm="4" dateuploaded="1230274722" isfavorite="0" license="0" rotation="0" originalsecret="sekrit" originalformat="jpg" media="photo">
4
+ <owner nsid="31066442@N69" username="frootpantz" realname="" location="" />
5
+ <title>Tree</title>
6
+ <description>A Tree</description>
7
+ <visibility ispublic="1" isfriend="0" isfamily="0" />
8
+ <dates posted="1230274722" taken="2008-12-25 18:26:55" takengranularity="0" lastupdate="1230276652" />
9
+
10
+ <editability cancomment="0" canaddmeta="0" />
11
+ <usage candownload="1" canblog="0" canprint="0" />
12
+ <comments>0</comments>
13
+ <notes />
14
+ <tags />
15
+ <urls>
16
+ <url type="photopage">http://www.flickr.com/photos/yes/1</url>
17
+ </urls>
18
+
19
+ </photo>
20
+ </rsp>
data/test/test_helper.rb CHANGED
@@ -9,6 +9,19 @@ require File.dirname(__FILE__) + '/../lib/fleakr'
9
9
 
10
10
  class Test::Unit::TestCase
11
11
 
12
+ def self.should_autoload_when_accessing(*attributes)
13
+ options = attributes.extract_options!
14
+ attributes.each do |accessor_name|
15
+ it "should load the additional user information when accessing the :#{accessor_name} attribute" do
16
+ klass = self.class.name.sub(/Test$/, '').constantize
17
+
18
+ object = klass.new
19
+ object.expects(options[:with]).with()
20
+ object.send(accessor_name)
21
+ end
22
+ end
23
+ end
24
+
12
25
  def self.should_have_a_value_for(attribute_test)
13
26
  it "should have a value for :#{attribute_test.keys.first}" do
14
27
  @object.send(attribute_test.keys.first).should == attribute_test.values.first
@@ -64,12 +77,14 @@ class Test::Unit::TestCase
64
77
  klass = "Fleakr::Objects::#{class_name}".constantize
65
78
  object_type = class_name.downcase
66
79
 
80
+ condition_value = '1'
81
+
67
82
  options[:with] = options[:by] if options[:with].nil?
83
+ params = {options[:with] => condition_value}
68
84
 
69
85
  it "should be able to find a #{thing} by #{options[:by]}" do
70
- condition_value = '1'
71
86
  stub = stub()
72
- response = mock_request_cycle :for => options[:call], :with => {options[:with] => condition_value}
87
+ response = mock_request_cycle :for => options[:call], :with => params
73
88
 
74
89
  klass.expects(:new).with(response.body).returns(stub)
75
90
  klass.send("find_by_#{options[:by]}".to_sym, condition_value).should == stub
@@ -108,7 +123,7 @@ class Test::Unit::TestCase
108
123
 
109
124
  def mock_request_cycle(options)
110
125
  response = stub(:body => Hpricot.XML(read_fixture(options[:for])))
111
- Fleakr::Api::Request.expects(:with_response!).with(options[:for], options[:with]).returns(response)
126
+ Fleakr::Api::MethodRequest.expects(:with_response!).with(options[:for], options[:with]).returns(response)
112
127
 
113
128
  response
114
129
  end
@@ -0,0 +1,63 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class FileParameterTest < Test::Unit::TestCase
5
+
6
+ describe "An instance of the FileParameter class" do
7
+
8
+ before do
9
+ @temp_dir = File.expand_path(create_temp_directory)
10
+ @filename = "#{@temp_dir}/image.jpg"
11
+ end
12
+
13
+ after do
14
+ FileUtils.rm_rf(@temp_dir)
15
+ end
16
+
17
+ it "should know not to include itself in the parameter signature" do
18
+ parameter = FileParameter.new('photo', @filename)
19
+ parameter.include_in_signature?.should be(false)
20
+ end
21
+
22
+ {'jpg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif'}.each do |ext, mime_type|
23
+ it "should know the correct MIME type for an extension of #{ext}" do
24
+ parameter = FileParameter.new('photo', "#{@temp_dir}/image.#{ext}")
25
+ parameter.mime_type.should == mime_type
26
+ end
27
+ end
28
+
29
+ it "should retrieve the contents of the file when accessing the value" do
30
+ File.expects(:read).with(@filename).returns('bopbip')
31
+
32
+ parameter = FileParameter.new('photo', @filename)
33
+ parameter.value.should == 'bopbip'
34
+ end
35
+
36
+ it "should cache the file contents after retrieving them" do
37
+ File.expects(:read).with(@filename).once.returns('bopbip')
38
+
39
+ parameter = FileParameter.new('photo', @filename)
40
+ 2.times { parameter.value }
41
+ end
42
+
43
+ it "should know how to generate a form representation of itself" do
44
+ filename = 'image.jpg'
45
+ mime_type = 'image/jpeg'
46
+
47
+ parameter = FileParameter.new('photo', filename)
48
+ parameter.stubs(:mime_type).with().returns(mime_type)
49
+ parameter.stubs(:value).with().returns('data')
50
+
51
+ expected =
52
+ "Content-Disposition: form-data; name=\"photo\"; filename=\"#{filename}\"\r\n" +
53
+ "Content-Type: image/jpeg\r\n" +
54
+ "\r\n" +
55
+ "data\r\n"
56
+
57
+ parameter.to_form.should == expected
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end