latompa-fleakr 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/README.rdoc +350 -0
  2. data/Rakefile +41 -0
  3. data/lib/fleakr/api/file_parameter.rb +47 -0
  4. data/lib/fleakr/api/method_request.rb +66 -0
  5. data/lib/fleakr/api/option.rb +175 -0
  6. data/lib/fleakr/api/parameter.rb +35 -0
  7. data/lib/fleakr/api/parameter_list.rb +97 -0
  8. data/lib/fleakr/api/response.rb +35 -0
  9. data/lib/fleakr/api/upload_request.rb +75 -0
  10. data/lib/fleakr/api/value_parameter.rb +36 -0
  11. data/lib/fleakr/api.rb +8 -0
  12. data/lib/fleakr/core_ext/false_class.rb +7 -0
  13. data/lib/fleakr/core_ext/hash.rb +22 -0
  14. data/lib/fleakr/core_ext/true_class.rb +7 -0
  15. data/lib/fleakr/core_ext.rb +3 -0
  16. data/lib/fleakr/objects/authentication_token.rb +60 -0
  17. data/lib/fleakr/objects/comment.rb +49 -0
  18. data/lib/fleakr/objects/contact.rb +37 -0
  19. data/lib/fleakr/objects/error.rb +22 -0
  20. data/lib/fleakr/objects/group.rb +36 -0
  21. data/lib/fleakr/objects/image.rb +50 -0
  22. data/lib/fleakr/objects/photo.rb +148 -0
  23. data/lib/fleakr/objects/photo_context.rb +49 -0
  24. data/lib/fleakr/objects/search.rb +30 -0
  25. data/lib/fleakr/objects/set.rb +50 -0
  26. data/lib/fleakr/objects/tag.rb +56 -0
  27. data/lib/fleakr/objects/user.rb +95 -0
  28. data/lib/fleakr/objects.rb +12 -0
  29. data/lib/fleakr/support/attribute.rb +46 -0
  30. data/lib/fleakr/support/object.rb +110 -0
  31. data/lib/fleakr/support.rb +2 -0
  32. data/lib/fleakr/version.rb +13 -0
  33. data/lib/fleakr.rb +171 -0
  34. data/test/fixtures/auth.checkToken.xml +8 -0
  35. data/test/fixtures/auth.getFullToken.xml +8 -0
  36. data/test/fixtures/auth.getToken.xml +8 -0
  37. data/test/fixtures/contacts.getPublicList.xml +7 -0
  38. data/test/fixtures/groups.pools.getPhotos.xml +7 -0
  39. data/test/fixtures/people.findByEmail.xml +6 -0
  40. data/test/fixtures/people.findByUsername.xml +6 -0
  41. data/test/fixtures/people.getInfo.xml +18 -0
  42. data/test/fixtures/people.getPublicGroups.xml +7 -0
  43. data/test/fixtures/people.getPublicPhotos.xml +7 -0
  44. data/test/fixtures/photos.comments.getList.xml +7 -0
  45. data/test/fixtures/photos.getContext.xml +6 -0
  46. data/test/fixtures/photos.getInfo.xml +20 -0
  47. data/test/fixtures/photos.getSizes.xml +10 -0
  48. data/test/fixtures/photos.search.xml +7 -0
  49. data/test/fixtures/photosets.comments.getList.xml +7 -0
  50. data/test/fixtures/photosets.getList.xml +13 -0
  51. data/test/fixtures/photosets.getPhotos.xml +7 -0
  52. data/test/fixtures/tags.getListPhoto.xml +9 -0
  53. data/test/fixtures/tags.getListUser.xml +10 -0
  54. data/test/fixtures/tags.getRelated.xml +9 -0
  55. data/test/test_helper.rb +141 -0
  56. data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
  57. data/test/unit/fleakr/api/method_request_test.rb +94 -0
  58. data/test/unit/fleakr/api/option_test.rb +179 -0
  59. data/test/unit/fleakr/api/parameter_list_test.rb +176 -0
  60. data/test/unit/fleakr/api/parameter_test.rb +34 -0
  61. data/test/unit/fleakr/api/response_test.rb +49 -0
  62. data/test/unit/fleakr/api/upload_request_test.rb +149 -0
  63. data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
  64. data/test/unit/fleakr/core_ext/false_class_test.rb +13 -0
  65. data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
  66. data/test/unit/fleakr/core_ext/true_class_test.rb +13 -0
  67. data/test/unit/fleakr/objects/authentication_token_test.rb +61 -0
  68. data/test/unit/fleakr/objects/comment_test.rb +66 -0
  69. data/test/unit/fleakr/objects/contact_test.rb +70 -0
  70. data/test/unit/fleakr/objects/error_test.rb +21 -0
  71. data/test/unit/fleakr/objects/group_test.rb +46 -0
  72. data/test/unit/fleakr/objects/image_test.rb +81 -0
  73. data/test/unit/fleakr/objects/photo_context_test.rb +80 -0
  74. data/test/unit/fleakr/objects/photo_test.rb +247 -0
  75. data/test/unit/fleakr/objects/search_test.rb +74 -0
  76. data/test/unit/fleakr/objects/set_test.rb +82 -0
  77. data/test/unit/fleakr/objects/tag_test.rb +98 -0
  78. data/test/unit/fleakr/objects/user_test.rb +91 -0
  79. data/test/unit/fleakr/support/attribute_test.rb +126 -0
  80. data/test/unit/fleakr/support/object_test.rb +129 -0
  81. data/test/unit/fleakr_test.rb +171 -0
  82. metadata +175 -0
@@ -0,0 +1,94 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class MethodRequestTest < Test::Unit::TestCase
5
+
6
+ context "An instance of MethodRequest" do
7
+
8
+ context "with API credentials" do
9
+
10
+ setup do
11
+ @api_key = 'f00b4r'
12
+ Fleakr.stubs(:api_key).with().returns(@api_key)
13
+ Fleakr.stubs(:shared_secret).with().returns('sekrit')
14
+ end
15
+
16
+ should "know the full query parameters" do
17
+ request = MethodRequest.new('flickr.people.findByUsername', :username => 'foobar')
18
+
19
+ request.parameters[:api_key].value.should == @api_key
20
+ request.parameters[:method].value.should == 'flickr.people.findByUsername'
21
+ request.parameters[:username].value.should == 'foobar'
22
+ end
23
+
24
+ should "translate a shorthand API call" do
25
+ request = MethodRequest.new('people.findByUsername')
26
+ request.parameters[:method].value.should == 'flickr.people.findByUsername'
27
+ end
28
+
29
+ should "know the endpoint with full parameters" do
30
+ query_parameters = 'foo=bar'
31
+
32
+ request = MethodRequest.new('people.getInfo')
33
+ request.parameters.stubs(:to_query).returns(query_parameters)
34
+
35
+ uri_mock = mock()
36
+ uri_mock.expects(:query=).with(query_parameters)
37
+ URI.expects(:parse).with("http://api.flickr.com/services/rest/").returns(uri_mock)
38
+
39
+ request.__send__(:endpoint_uri).should == uri_mock
40
+ end
41
+
42
+ should "be able to make a request" do
43
+ endpoint_uri = stub()
44
+
45
+ request = MethodRequest.new('people.findByUsername')
46
+ request.stubs(:endpoint_uri).with().returns(endpoint_uri)
47
+
48
+ Net::HTTP.expects(:get).with(endpoint_uri).returns('<xml>')
49
+
50
+ request.send
51
+ end
52
+
53
+ should "create a response from the request" do
54
+ response_xml = '<xml>'
55
+ response_stub = stub()
56
+
57
+ Net::HTTP.stubs(:get).returns(response_xml)
58
+ Response.expects(:new).with(response_xml).returns(response_stub)
59
+
60
+ request = MethodRequest.new('people.findByUsername')
61
+ request.stubs(:endpoint_uri)
62
+
63
+ request.send.should == response_stub
64
+ end
65
+
66
+ should "be able to make a full request and response cycle" do
67
+ method = 'flickr.people.findByUsername'
68
+ params = {:username => 'foobar'}
69
+
70
+ response = stub(:error? => false)
71
+
72
+ MethodRequest.expects(:new).with(method, params).returns(stub(:send => response))
73
+
74
+ MethodRequest.with_response!(method, params).should == response
75
+ end
76
+
77
+ should "raise an exception when the full request / response cycle has errors" do
78
+ method = 'flickr.people.findByUsername'
79
+ params = {:username => 'foobar'}
80
+
81
+ response = stub(:error? => true, :error => stub(:code => '1', :message => 'User not found'))
82
+
83
+ MethodRequest.expects(:new).with(method, params).returns(stub(:send => response))
84
+
85
+ lambda do
86
+ MethodRequest.with_response!('flickr.people.findByUsername', :username => 'foobar')
87
+ end.should raise_error(Fleakr::ApiError)
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,179 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+
5
+ class OptionTest < Test::Unit::TestCase
6
+
7
+ def self.should_know_the_class_for(type, options)
8
+ should "know the class for the :#{type} type" do
9
+ Option.class_for(type).should == options[:is]
10
+ end
11
+ end
12
+
13
+ context "The Option class" do
14
+ should_know_the_class_for :title, :is => Fleakr::Api::SimpleOption
15
+ should_know_the_class_for :description, :is => Fleakr::Api::SimpleOption
16
+ should_know_the_class_for :tags, :is => Fleakr::Api::TagOption
17
+ should_know_the_class_for :viewable_by, :is => Fleakr::Api::ViewOption
18
+ should_know_the_class_for :level, :is => Fleakr::Api::LevelOption
19
+ should_know_the_class_for :type, :is => Fleakr::Api::TypeOption
20
+ should_know_the_class_for :hide?, :is => Fleakr::Api::HiddenOption
21
+
22
+ should "be able to create an option for a type" do
23
+ option = stub()
24
+
25
+ Option.expects(:class_for).with(:title).returns(Fleakr::Api::SimpleOption)
26
+ Fleakr::Api::SimpleOption.expects(:new).with(:title, 'blip').returns(option)
27
+
28
+ Option.for(:title, 'blip').should == option
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ class SimpleOptionTest < Test::Unit::TestCase
35
+
36
+ context "An instance of the SimpleOption class" do
37
+ should "have a type" do
38
+ so = SimpleOption.new(:title, 'blip')
39
+ so.type.should == :title
40
+ end
41
+
42
+ should "have a value" do
43
+ so = SimpleOption.new(:title, 'blip')
44
+ so.value.should == 'blip'
45
+ end
46
+
47
+ should "be able to generate a hash representation of itself" do
48
+ so = SimpleOption.new(:title, 'blip')
49
+ so.to_hash.should == {:title => 'blip'}
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ class TagOptionTest < Test::Unit::TestCase
56
+
57
+ context "An instance of the TagOption class" do
58
+
59
+ should "normalize the input value to an array" do
60
+ to = TagOption.new(:tags, 'blip')
61
+ to.value.should == ['blip']
62
+ end
63
+
64
+ should "be able to generate a hash representation of itself with tags joined on spaces" do
65
+ to = TagOption.new(:tags, %w(bop bip))
66
+ to.to_hash.should == {:tags => '"bop" "bip"'}
67
+ end
68
+
69
+ should "quote tag values with spaces" do
70
+ to = TagOption.new(:tags, ['tag', 'one with spaces'])
71
+ to.to_hash.should == {:tags => '"tag" "one with spaces"'}
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ class ViewOptionTest < Test::Unit::TestCase
78
+
79
+ context "An instance of the ViewOption class" do
80
+ should "be able to generate a hash representation for viewing by :everyone" do
81
+ vo = ViewOption.new(:viewable_by, :everyone)
82
+ vo.to_hash.should == {:is_public => 1, :is_family => 0, :is_friend => 0}
83
+ end
84
+
85
+ should "be able to generate a hash representation for viewing by :family" do
86
+ vo = ViewOption.new(:viewable_by, :family)
87
+ vo.to_hash.should == {:is_public => 0, :is_family => 1, :is_friend => 0}
88
+ end
89
+
90
+ should "be able to generate a hash representation for viewing by :friends" do
91
+ vo = ViewOption.new(:viewable_by, :friends)
92
+ vo.to_hash.should == {:is_public => 0, :is_family => 0, :is_friend => 1}
93
+ end
94
+
95
+ should "know the visibility is public if value is set to :everyone" do
96
+ vo = ViewOption.new(:viewable_by, :everyone)
97
+ vo.public?.should be(true)
98
+ end
99
+
100
+ should "know the visibility is not public if :everyone is not the only value" do
101
+ vo = ViewOption.new(:viewable_by, [:everyone, :family])
102
+ vo.public?.should be(false)
103
+ end
104
+
105
+ should "know that its visible to friends and family if specified as such" do
106
+ vo = ViewOption.new(:viewable_by, [:friends, :family])
107
+ vo.friends?.should be(true)
108
+ vo.family?.should be(true)
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+
115
+ class LevelOptionTest < Test::Unit::TestCase
116
+
117
+ context "An instance of the LevelOption class" do
118
+
119
+ should "be able to generate a hash representation for the :safe level" do
120
+ lo = LevelOption.new(:level, :safe)
121
+ lo.to_hash.should == {:safety_level => 1}
122
+ end
123
+
124
+ should "be able to generate a hash representation for the :moderate level" do
125
+ lo = LevelOption.new(:level, :moderate)
126
+ lo.to_hash.should == {:safety_level => 2}
127
+ end
128
+
129
+ should "be able to generate a hash representation for the :restricted level" do
130
+ lo = LevelOption.new(:level, :restricted)
131
+ lo.to_hash.should == {:safety_level => 3}
132
+ end
133
+
134
+ end
135
+
136
+ end
137
+
138
+ class TypeOptionTest < Test::Unit::TestCase
139
+
140
+ context "An instance of the TypeOption class" do
141
+
142
+ should "be able to generate a hash representation for the :photo type" do
143
+ to = TypeOption.new(:type, :photo)
144
+ to.to_hash.should == {:content_type => 1}
145
+ end
146
+
147
+ should "be able to generate a hash representation for the :screenshot type" do
148
+ to = TypeOption.new(:type, :screenshot)
149
+ to.to_hash.should == {:content_type => 2}
150
+ end
151
+
152
+ should "be able to generate a hash representation for the :other type" do
153
+ to = TypeOption.new(:type, :other)
154
+ to.to_hash.should == {:content_type => 3}
155
+ end
156
+
157
+ end
158
+
159
+ end
160
+
161
+ class HiddenOptionTest < Test::Unit::TestCase
162
+
163
+ context "An instance of the HiddenOption class" do
164
+
165
+ should "be able to generate a hash representation when set to true" do
166
+ ho = HiddenOption.new(:hide?, true)
167
+ ho.to_hash.should == {:hidden => 2}
168
+ end
169
+
170
+ should "be able to generate a hash representation when set to false" do
171
+ ho = HiddenOption.new(:hide?, false)
172
+ ho.to_hash.should == {:hidden => 1}
173
+ end
174
+
175
+ end
176
+
177
+ end
178
+
179
+ end
@@ -0,0 +1,176 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class ParameterListTest < Test::Unit::TestCase
5
+
6
+ context "An instance of the ParameterList class" do
7
+
8
+ setup do
9
+ @api_key = 'key'
10
+ @secret = 'foobar'
11
+
12
+ Fleakr.stubs(:api_key).with().returns(@api_key)
13
+ @parameter_list = ParameterList.new
14
+ end
15
+
16
+ should "contain the :api_key by default" do
17
+ @parameter_list[:api_key].name.should == 'api_key'
18
+ @parameter_list[:api_key].value.should == @api_key
19
+ @parameter_list[:api_key].include_in_signature?.should be(true)
20
+ end
21
+
22
+ should "be able to create an initial list of parameters" do
23
+ parameter_list = ParameterList.new(:one => 'two')
24
+ parameter_list[:one].value.should == 'two'
25
+ end
26
+
27
+ should "be able to add parameters to its list" do
28
+ parameter = ValueParameter.new('foo', 'bar')
29
+
30
+ @parameter_list << parameter
31
+ @parameter_list['foo'].should == parameter
32
+ end
33
+
34
+ should "allow access to parameters by symbol" do
35
+ parameter = ValueParameter.new('foo', 'bar')
36
+ @parameter_list << parameter
37
+
38
+ @parameter_list[:foo].should == parameter
39
+ end
40
+
41
+ should "overwrite existing values when a duplicate is added" do
42
+ length = @parameter_list.instance_variable_get(:@list).length
43
+ 2.times {@parameter_list << ValueParameter.new('foo', 'bar') }
44
+
45
+ @parameter_list.instance_variable_get(:@list).length.should == length + 1
46
+ end
47
+
48
+ should "be able to calculate the signature of the parameters" do
49
+ Fleakr.stubs(:shared_secret).with().returns(@secret)
50
+
51
+ @parameter_list << ValueParameter.new('foo', 'bar')
52
+ @parameter_list.signature.should == Digest::MD5.hexdigest("#{@secret}api_key#{@api_key}foobar")
53
+ end
54
+
55
+ should "use the correct order when signing a list of multiple parameters" do
56
+ Fleakr.stubs(:shared_secret).with().returns(@secret)
57
+
58
+ @parameter_list << ValueParameter.new('z', 'a')
59
+ @parameter_list << ValueParameter.new('a', 'z')
60
+
61
+ @parameter_list.signature.should == Digest::MD5.hexdigest("#{@secret}azapi_key#{@api_key}za")
62
+ end
63
+
64
+ should "ignore the parameters that aren't included in the signature" do
65
+ Fleakr.stubs(:shared_secret).with().returns(@secret)
66
+
67
+ @parameter_list << ValueParameter.new('foo', 'bar')
68
+ @parameter_list << ValueParameter.new('yes', 'no', false)
69
+
70
+ @parameter_list.signature.should == Digest::MD5.hexdigest("#{@secret}api_key#{@api_key}foobar")
71
+ end
72
+
73
+ should "be able to generate a boundary for post data" do
74
+ rand = '0.123'
75
+
76
+ @parameter_list.stubs(:rand).with().returns(stub(:to_s => rand))
77
+ @parameter_list.boundary.should == Digest::MD5.hexdigest(rand)
78
+ end
79
+
80
+ should "know that it doesn't need to sign the request by default" do
81
+ @parameter_list.sign?.should be(false)
82
+ end
83
+
84
+ should "know that it needs to sign the request when a shared secret is available" do
85
+ Fleakr.expects(:shared_secret).with().returns(@secret)
86
+ @parameter_list.sign?.should be(true)
87
+ end
88
+
89
+ should "know that it doesn't need to authenticate the request by default" do
90
+ @parameter_list.authenticate?.should be(false)
91
+ end
92
+
93
+ should "know to authenticate the request when a token is available" do
94
+ Fleakr.stubs(:token).with().returns(stub(:value => 'toke'))
95
+ parameter_list = ParameterList.new
96
+
97
+ parameter_list.authenticate?.should be(true)
98
+ end
99
+
100
+ should "not authenticate the request if it's been specifically told not to" do
101
+ Fleakr.expects(:token).with().never
102
+
103
+ parameter_list = ParameterList.new(:authenticate? => false)
104
+ parameter_list.authenticate?.should be(false)
105
+ end
106
+
107
+
108
+ should "know to authenticate the request when asked" do
109
+ Fleakr.expects(:token).with().returns(stub(:value => 'toke'))
110
+
111
+ parameter_list = ParameterList.new(:authenticate? => true)
112
+ parameter_list.authenticate?.should be(true)
113
+ end
114
+
115
+ should "contain the :auth_token parameter in the list if the request is to be authenticated" do
116
+ Fleakr.expects(:token).with().returns(stub(:value => 'toke'))
117
+
118
+ parameter_list = ParameterList.new(:authenticate? => true)
119
+ auth_param = parameter_list[:auth_token]
120
+
121
+ auth_param.name.should == 'auth_token'
122
+ auth_param.value.should == 'toke'
123
+ auth_param.include_in_signature?.should be(true)
124
+ end
125
+
126
+ should "include the signature in the list of parameters if the request is to be signed" do
127
+ parameter_list = ParameterList.new
128
+
129
+ parameter_list.stubs(:sign?).with().returns(true)
130
+ parameter_list.stubs(:signature).with().returns('sig')
131
+
132
+ signature_param = parameter_list[:api_sig]
133
+
134
+ signature_param.name.should == 'api_sig'
135
+ signature_param.value.should == 'sig'
136
+ signature_param.include_in_signature?.should be(false)
137
+ end
138
+
139
+ context "with associated parameters" do
140
+
141
+ setup do
142
+ @p1 = ValueParameter.new('a', 'b')
143
+ @p2 = ValueParameter.new('c', 'd')
144
+
145
+ @p1.stubs(:to_query).with().returns('q1')
146
+ @p1.stubs(:to_form).with().returns('f1')
147
+
148
+ @p2.stubs(:to_query).with().returns('q2')
149
+ @p2.stubs(:to_form).with().returns('f2')
150
+
151
+ @parameter_list.stubs(:list).with().returns('a' => @p1, 'c' => @p2)
152
+ end
153
+
154
+ should "be able to generate a query representation of itself" do
155
+ @parameter_list.to_query.should == 'q1&q2'
156
+ end
157
+
158
+ should "be able to represent a form representation of itself" do
159
+ @parameter_list.stubs(:boundary).returns('bound')
160
+
161
+ expected =
162
+ "--bound\r\n" +
163
+ "f1" +
164
+ "--bound\r\n" +
165
+ "f2" +
166
+ "--bound--"
167
+
168
+ @parameter_list.to_form.should == expected
169
+ end
170
+
171
+ end
172
+
173
+ end
174
+
175
+ end
176
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class ParameterTest < Test::Unit::TestCase
5
+
6
+ context "An instance of the Parameter class" do
7
+
8
+ should "have a name" do
9
+ parameter = Parameter.new('foo')
10
+ parameter.name.should == 'foo'
11
+ end
12
+
13
+ should "know to include it in the signature by default" do
14
+ parameter = Parameter.new('foo')
15
+ parameter.include_in_signature?.should be(true)
16
+ end
17
+
18
+ should "know not to include it in the signature" do
19
+ parameter = Parameter.new('foo', false)
20
+ parameter.include_in_signature?.should be(false)
21
+ end
22
+
23
+ should "be able to compare itself to another parameter instance" do
24
+ p1 = Parameter.new('z', 'a')
25
+ p2 = Parameter.new('a', 'z')
26
+
27
+ (p1 <=> p2).should == 1
28
+ end
29
+
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class ResponseTest < Test::Unit::TestCase
5
+
6
+ context "An instance of Response" do
7
+
8
+ should "provide the response body as an Hpricot element" do
9
+ response_xml = '<xml>'
10
+ hpricot_stub = stub()
11
+
12
+ Hpricot.expects(:XML).with(response_xml).returns(hpricot_stub)
13
+
14
+ response = Response.new(response_xml)
15
+ response.body.should == hpricot_stub
16
+ end
17
+
18
+ should "memoize the Hpricot document" do
19
+ response = Response.new('<xml>')
20
+
21
+ Hpricot.expects(:XML).with(kind_of(String)).once.returns(stub())
22
+
23
+ 2.times { response.body }
24
+ end
25
+
26
+ should "know if there are errors in the response" do
27
+ response_xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<rsp stat=\"fail\">\n\t<err code=\"1\" msg=\"User not found\" />\n</rsp>\n"
28
+ response = Response.new(response_xml)
29
+
30
+ response.error?.should be(true)
31
+ end
32
+
33
+ should "not have an error if there are no errors in the XML" do
34
+ response = Response.new(read_fixture('people.findByUsername'))
35
+ response.error.should be(nil)
36
+ end
37
+
38
+ should "have an error if there is an error in the response" do
39
+ response_xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<rsp stat=\"fail\">\n\t<err code=\"1\" msg=\"User not found\" />\n</rsp>\n"
40
+ response = Response.new(response_xml)
41
+
42
+ response.error.code.should == '1'
43
+ response.error.message.should == 'User not found'
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,149 @@
1
+ require File.dirname(__FILE__) + '/../../../test_helper'
2
+
3
+ module Fleakr::Api
4
+ class UploadRequestTest < Test::Unit::TestCase
5
+
6
+ context "An instance of the UploadRequest class" do
7
+
8
+ setup do
9
+ @secret = 'sekrit'
10
+ Fleakr.stubs(:shared_secret).with().returns(@secret)
11
+ end
12
+
13
+ should "have a collection of upload_options" do
14
+ request = UploadRequest.new('foo', :create, {:title => 'foo', :tags => %w(a b)})
15
+
16
+ option_1, option_2 = [stub(:to_hash => {:one => 'value_1'}), stub(:to_hash => {:two => 'value_2'})]
17
+
18
+ Option.expects(:for).with(:title, 'foo').returns(option_1)
19
+ Option.expects(:for).with(:tags, %w(a b)).returns(option_2)
20
+
21
+ request.upload_options.should == {:one => 'value_1', :two => 'value_2'}
22
+ end
23
+
24
+ should "create a file parameter on initialization" do
25
+ filename = '/path/to/image.jpg'
26
+
27
+ parameter = stub()
28
+ FileParameter.expects(:new).with('photo', filename).returns(parameter)
29
+
30
+ parameter_list = mock()
31
+ parameter_list.expects(:<<).with(parameter)
32
+
33
+ ParameterList.expects(:new).with({}).returns(parameter_list)
34
+
35
+ UploadRequest.new(filename)
36
+ end
37
+
38
+ should "allow setting options on initialization" do
39
+ option = stub()
40
+ option.stubs(:to_hash).with().returns({:title => 'foo'})
41
+
42
+ Option.expects(:for).with(:title, 'foo').returns(option)
43
+
44
+ ParameterList.expects(:new).with({:title => 'foo'}).returns(stub(:<<))
45
+
46
+ UploadRequest.new('filename', :create, {:title => 'foo'})
47
+ end
48
+
49
+ context "after initialization" do
50
+
51
+ setup { ParameterList.stubs(:new).returns(stub(:<< => nil)) }
52
+
53
+ should "default the type to :create" do
54
+ request = UploadRequest.new('file')
55
+ request.type.should == :create
56
+ end
57
+
58
+ should "allow setting the type to :update" do
59
+ request = UploadRequest.new('file', :update)
60
+ request.type.should == :update
61
+ end
62
+
63
+ should "know the endpoint_uri" do
64
+ request = UploadRequest.new('filename')
65
+ request.__send__(:endpoint_uri).should == URI.parse('http://api.flickr.com/services/upload/')
66
+ end
67
+
68
+ should "know the endpoint_uri for an :update request" do
69
+ request = UploadRequest.new('filename', :update)
70
+ request.__send__(:endpoint_uri).should == URI.parse('http://api.flickr.com/services/replace/')
71
+ end
72
+
73
+ should "only parse the endpoint URI once" do
74
+ request = UploadRequest.new('filename')
75
+ URI.expects(:parse).with(kind_of(String)).once.returns('uri')
76
+
77
+ 2.times { request.__send__(:endpoint_uri) }
78
+ end
79
+
80
+ should "have a collection of required headers" do
81
+ form_data = 'data'
82
+
83
+ request = UploadRequest.new('filename')
84
+ request.parameters.stubs(:boundary).with().returns('bound')
85
+ request.parameters.stubs(:to_form).with().returns(form_data)
86
+
87
+ expected = {
88
+ 'Content-Type' => 'multipart/form-data; boundary=bound'
89
+ }
90
+
91
+ request.headers.should == expected
92
+ end
93
+
94
+ should "be able to send a POST request to the API service" do
95
+ request = UploadRequest.new('filename')
96
+
97
+ uri = stub()
98
+ uri.stubs(:host).with().returns('host')
99
+ uri.stubs(:path).with().returns('path')
100
+ uri.stubs(:port).with().returns(80)
101
+
102
+ request.stubs(:endpoint_uri).with().returns(uri)
103
+
104
+ request.stubs(:headers).with().returns('header' => 'value')
105
+ request.parameters.stubs(:to_form).with().returns('form')
106
+
107
+ http = mock()
108
+ http.expects(:post).with('path', 'form', {'header' => 'value'})
109
+
110
+ Net::HTTP.expects(:start).with('host', 80).yields(http).returns(stub(:body))
111
+
112
+ request.send
113
+ end
114
+
115
+ should "get back a response from a POST operation" do
116
+ response = stub()
117
+
118
+ Net::HTTP.expects(:start).with(kind_of(String), kind_of(Fixnum)).returns(stub(:body => '<xml>'))
119
+ Response.expects(:new).with('<xml>').returns(response)
120
+
121
+ request = UploadRequest.new('filename')
122
+ request.send.should == response
123
+ end
124
+
125
+ should "be able to make a full request and response cycle" do
126
+ filename = 'filename'
127
+ response = stub(:error? => false)
128
+
129
+ UploadRequest.expects(:new).with(filename, :create, {}).returns(stub(:send => response))
130
+ UploadRequest.with_response!(filename).should == response
131
+ end
132
+
133
+ should "raise an exception when the full request / response cycle has errors" do
134
+ filename = 'filename'
135
+ response = stub(:error? => true, :error => stub(:code => '1', :message => 'User not found'))
136
+
137
+ UploadRequest.expects(:new).with(filename, :create, {}).returns(stub(:send => response))
138
+
139
+ lambda do
140
+ UploadRequest.with_response!(filename)
141
+ end.should raise_error(Fleakr::ApiError)
142
+ end
143
+
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+ end