koala 0.10.0 → 1.0.0.beta
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.
- data/CHANGELOG +23 -7
- data/Manifest +4 -0
- data/Rakefile +4 -4
- data/koala.gemspec +9 -7
- data/lib/koala.rb +88 -72
- data/lib/koala/graph_api.rb +16 -3
- data/lib/koala/http_services.rb +100 -16
- data/lib/koala/rest_api.rb +73 -6
- data/readme.md +11 -11
- data/spec/facebook_data.yml +9 -3
- data/spec/koala/assets/beach.jpg +0 -0
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +5 -1
- data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +8 -3
- data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +10 -61
- data/spec/koala/graph_api/graph_api_tests.rb +86 -0
- data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +129 -125
- data/spec/koala/live_testing_data_helper.rb +1 -1
- data/spec/koala/net_http_service_tests.rb +259 -15
- data/spec/koala/oauth/oauth_tests.rb +35 -64
- data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +5 -74
- data/spec/koala/rest_api/rest_api_tests.rb +118 -0
- data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +5 -3
- data/spec/koala/test_users/test_users_tests.rb +38 -45
- data/spec/koala/typhoeus_service_tests.rb +156 -0
- data/spec/koala_spec_helper.rb +26 -4
- data/spec/koala_spec_without_mocks.rb +3 -3
- data/spec/mock_facebook_responses.yml +22 -4
- data/spec/mock_http_service.rb +15 -1
- metadata +32 -7
@@ -0,0 +1,86 @@
|
|
1
|
+
shared_examples_for "Koala GraphAPI" do
|
2
|
+
# all Graph API instances should pass these tests, regardless of configuration
|
3
|
+
|
4
|
+
# API
|
5
|
+
it "should never use the rest api server" do
|
6
|
+
Koala.should_receive(:make_request).with(
|
7
|
+
anything,
|
8
|
+
anything,
|
9
|
+
anything,
|
10
|
+
hash_not_including(:rest_api => true)
|
11
|
+
).and_return(Koala::Response.new(200, "", {}))
|
12
|
+
|
13
|
+
@api.api("anything")
|
14
|
+
end
|
15
|
+
|
16
|
+
# GRAPH CALL
|
17
|
+
describe "graph_call" do
|
18
|
+
it "should pass all arguments to the api method" do
|
19
|
+
args = ["koppel", {}, "get", {:a => :b}]
|
20
|
+
|
21
|
+
@api.should_receive(:api).with(*args)
|
22
|
+
|
23
|
+
@api.graph_call(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should throw an APIError if the result hash has an error key" do
|
27
|
+
Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error" => "An error occurred!"}, {}))
|
28
|
+
lambda { @api.graph_call("koppel", {}) }.should raise_exception(Koala::Facebook::APIError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# SEARCH
|
33
|
+
it "should be able to search" do
|
34
|
+
result = @api.search("facebook")
|
35
|
+
result.length.should be_an(Integer)
|
36
|
+
end
|
37
|
+
|
38
|
+
# DATA
|
39
|
+
# access public info
|
40
|
+
|
41
|
+
it "should get public data about a user" do
|
42
|
+
result = @api.get_object("koppel")
|
43
|
+
# the results should have an ID and a name, among other things
|
44
|
+
(result["id"] && result["name"]).should_not be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should get public data about a Page" do
|
48
|
+
result = @api.get_object("contextoptional")
|
49
|
+
# the results should have an ID and a name, among other things
|
50
|
+
(result["id"] && result["name"]).should
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should be able to get multiple objects" do
|
54
|
+
results = @api.get_objects(["contextoptional", "naitik"])
|
55
|
+
results.length.should == 2
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be able to access a user's picture" do
|
59
|
+
@api.get_picture("chris.baclig").should =~ /http\:\/\//
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be able to access a user's picture, given a picture type" do
|
63
|
+
@api.get_picture("chris.baclig", {:type => 'large'}).should =~ /^http\:\/\//
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should be able to access connections from public Pages" do
|
67
|
+
result = @api.get_connections("contextoptional", "photos")
|
68
|
+
result.should be_a(Array)
|
69
|
+
end
|
70
|
+
|
71
|
+
# SEARCH
|
72
|
+
it "should be able to search" do
|
73
|
+
result = @api.search("facebook")
|
74
|
+
result.length.should be_an(Integer)
|
75
|
+
end
|
76
|
+
|
77
|
+
# PAGING THROUGH COLLECTIONS
|
78
|
+
# see also graph_collection_tests
|
79
|
+
it "should make a request for a page when provided a specific set of page params" do
|
80
|
+
query = [1, 2]
|
81
|
+
@api.should_receive(:graph_call).with(*query)
|
82
|
+
@api.get_page(query)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
@@ -1,150 +1,154 @@
|
|
1
1
|
shared_examples_for "Koala GraphAPI with an access token" do
|
2
|
-
it "should get public data about a user" do
|
3
|
-
result = @api.get_object("koppel")
|
4
|
-
# the results should have an ID and a name, among other things
|
5
|
-
(result["id"] && result["name"]).should_not be_nil
|
6
|
-
end
|
7
2
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
it "should get private data about a user" do
|
4
|
+
result = @api.get_object("koppel")
|
5
|
+
# updated_time should be a pretty fixed test case
|
6
|
+
result["updated_time"].should_not be_nil
|
7
|
+
end
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
9
|
+
it "should get data about 'me'" do
|
10
|
+
result = @api.get_object("me")
|
11
|
+
result["updated_time"].should
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be able to get multiple objects" do
|
15
|
+
result = @api.get_objects(["contextoptional", "naitik"])
|
16
|
+
result.length.should == 2
|
17
|
+
end
|
18
|
+
it "should be able to access connections from users" do
|
19
|
+
result = @api.get_connections("lukeshepard", "likes")
|
20
|
+
result.length.should > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# PUT
|
24
|
+
it "should be able to write an object to the graph" do
|
25
|
+
result = @api.put_wall_post("Hello, world, from the test suite!")
|
26
|
+
@temporary_object_id = result["id"]
|
27
|
+
@temporary_object_id.should_not be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# DELETE
|
31
|
+
it "should be able to delete posts" do
|
32
|
+
result = @api.put_wall_post("Hello, world, from the test suite delete method!")
|
33
|
+
object_id_to_delete = result["id"]
|
34
|
+
delete_result = @api.delete_object(object_id_to_delete)
|
35
|
+
delete_result.should == true
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
it "should be able to delete likes" do
|
39
|
+
result = @api.put_wall_post("Hello, world, from the test suite delete method!")
|
40
|
+
@temporary_object_id = result["id"]
|
41
|
+
@api.put_like(@temporary_object_id)
|
42
|
+
delete_like_result = @api.delete_like(@temporary_object_id)
|
43
|
+
delete_like_result.should == true
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
# additional put tests
|
47
|
+
it "should be able to verify messages posted to a wall" do
|
48
|
+
message = "the cats are asleep"
|
49
|
+
put_result = @api.put_wall_post(message)
|
50
|
+
@temporary_object_id = put_result["id"]
|
51
|
+
get_result = @api.get_object(@temporary_object_id)
|
52
|
+
|
53
|
+
# make sure the message we sent is the message that got posted
|
54
|
+
get_result["message"].should == message
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be able to post a message with an attachment to a feed" do
|
58
|
+
result = @api.put_wall_post("Hello, world, from the test suite again!", {:name => "Context Optional", :link => "http://www.contextoptional.com/"})
|
59
|
+
@temporary_object_id = result["id"]
|
60
|
+
@temporary_object_id.should_not be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be able to post photos to the user's wall with an open file object" do
|
64
|
+
file_hash = {
|
65
|
+
"content_type" => "image/jpg",
|
66
|
+
"path" => File.join(File.dirname(__FILE__), "..", "assets", "beach.jpg"),
|
67
|
+
"file" => File.open(File.join(File.dirname(__FILE__), "..", "assets", "beach.jpg"))
|
68
|
+
}
|
69
|
+
result = @api.put_picture(file_hash)
|
70
|
+
@temporary_object_id = result["id"]
|
71
|
+
@temporary_object_id.should_not be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be able to post photos to the user's wall without an open file object" do
|
75
|
+
file_hash = {
|
76
|
+
"content_type" => "image/jpg",
|
77
|
+
"path" => File.join(File.dirname(__FILE__), "..", "assets", "beach.jpg")
|
78
|
+
}
|
79
|
+
result = @api.put_picture(file_hash)
|
80
|
+
@temporary_object_id = result["id"]
|
81
|
+
@temporary_object_id.should_not be_nil
|
82
|
+
end
|
47
83
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
84
|
+
it "should be able to verify a photo posted to a user's wall" do
|
85
|
+
file_hash = {
|
86
|
+
"content_type" => "image/jpg",
|
87
|
+
"path" => File.join(File.dirname(__FILE__), "..", "assets", "beach.jpg")
|
88
|
+
}
|
89
|
+
expected_message = "This is the test message"
|
55
90
|
|
91
|
+
result = @api.put_picture(file_hash, :message => expected_message)
|
92
|
+
@temporary_object_id = result["id"]
|
93
|
+
@temporary_object_id.should_not be_nil
|
56
94
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
result = @api.put_wall_post("Hello, world, from the test suite delete method!")
|
67
|
-
object_id_to_delete = result["id"]
|
68
|
-
delete_result = @api.delete_object(object_id_to_delete)
|
69
|
-
delete_result.should == true
|
70
|
-
end
|
95
|
+
get_result = @api.get_object(@temporary_object_id)
|
96
|
+
get_result["name"].should == expected_message
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should be able to verify a message with an attachment posted to a feed" do
|
100
|
+
attachment = {"name" => "Context Optional", "link" => "http://www.contextoptional.com/"}
|
101
|
+
result = @api.put_wall_post("Hello, world, from the test suite again!", attachment)
|
102
|
+
@temporary_object_id = result["id"]
|
103
|
+
get_result = @api.get_object(@temporary_object_id)
|
71
104
|
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@temporary_object_id = put_result["id"]
|
77
|
-
get_result = @api.get_object(@temporary_object_id)
|
78
|
-
|
79
|
-
# make sure the message we sent is the message that got posted
|
80
|
-
get_result["message"].should == message
|
81
|
-
end
|
105
|
+
# make sure the result we fetch includes all the parameters we sent
|
106
|
+
it_matches = attachment.inject(true) {|valid, param| valid && (get_result[param[0]] == attachment[param[0]])}
|
107
|
+
it_matches.should == true
|
108
|
+
end
|
82
109
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@temporary_object_id.should_not be_nil
|
87
|
-
end
|
88
|
-
|
89
|
-
it "should be able to verify a message with an attachment posted to a feed" do
|
90
|
-
attachment = {"name" => "Context Optional", "link" => "http://www.contextoptional.com/"}
|
91
|
-
result = @api.put_wall_post("Hello, world, from the test suite again!", attachment)
|
92
|
-
@temporary_object_id = result["id"]
|
93
|
-
get_result = @api.get_object(@temporary_object_id)
|
94
|
-
|
95
|
-
# make sure the result we fetch includes all the parameters we sent
|
96
|
-
it_matches = attachment.inject(true) {|valid, param| valid && (get_result[param[0]] == attachment[param[0]])}
|
97
|
-
it_matches.should == true
|
98
|
-
end
|
110
|
+
it "should be able to comment on an object" do
|
111
|
+
result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
|
112
|
+
@temporary_object_id = result["id"]
|
99
113
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
# this will be deleted when the post gets deleted
|
105
|
-
comment_result = @api.put_comment(@temporary_object_id, "it's my comment!")
|
106
|
-
comment_result.should_not be_nil
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should be able to verify a comment posted about an object" do
|
110
|
-
message_text = "Hello, world, from the test suite, testing comments!"
|
111
|
-
result = @api.put_wall_post(message_text)
|
112
|
-
@temporary_object_id = result["id"]
|
113
|
-
|
114
|
-
# this will be deleted when the post gets deleted
|
115
|
-
comment_text = "it's my comment!"
|
116
|
-
comment_result = @api.put_comment(@temporary_object_id, comment_text)
|
117
|
-
get_result = @api.get_object(comment_result["id"])
|
118
|
-
|
119
|
-
# make sure the text of the comment matches what we sent
|
120
|
-
get_result["message"].should == comment_text
|
121
|
-
end
|
114
|
+
# this will be deleted when the post gets deleted
|
115
|
+
comment_result = @api.put_comment(@temporary_object_id, "it's my comment!")
|
116
|
+
comment_result.should_not be_nil
|
117
|
+
end
|
122
118
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
119
|
+
it "should be able to verify a comment posted about an object" do
|
120
|
+
message_text = "Hello, world, from the test suite, testing comments!"
|
121
|
+
result = @api.put_wall_post(message_text)
|
122
|
+
@temporary_object_id = result["id"]
|
128
123
|
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
124
|
+
# this will be deleted when the post gets deleted
|
125
|
+
comment_text = "it's my comment!"
|
126
|
+
comment_result = @api.put_comment(@temporary_object_id, comment_text)
|
127
|
+
get_result = @api.get_object(comment_result["id"])
|
134
128
|
|
135
|
-
#
|
136
|
-
|
129
|
+
# make sure the text of the comment matches what we sent
|
130
|
+
get_result["message"].should == comment_text
|
131
|
+
end
|
137
132
|
|
138
|
-
|
133
|
+
it "should be able to like an object" do
|
134
|
+
result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
|
135
|
+
@temporary_object_id = result["id"]
|
136
|
+
like_result = @api.put_like(@temporary_object_id)
|
137
|
+
like_result.should be_true
|
138
|
+
end
|
139
139
|
end
|
140
140
|
|
141
141
|
class FacebookWithAccessTokenTests < Test::Unit::TestCase
|
142
142
|
describe "Koala GraphAPI with an access token" do
|
143
143
|
include LiveTestingDataHelper
|
144
|
-
|
145
|
-
|
144
|
+
|
146
145
|
before :each do
|
147
146
|
@api = Koala::Facebook::GraphAPI.new(@token)
|
148
147
|
end
|
148
|
+
|
149
|
+
it_should_behave_like "Koala GraphAPI"
|
150
|
+
it_should_behave_like "Koala GraphAPI with an access token"
|
151
|
+
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
152
|
+
|
149
153
|
end
|
150
154
|
end
|
@@ -19,7 +19,7 @@ module LiveTestingDataHelper
|
|
19
19
|
errors = []
|
20
20
|
|
21
21
|
if count > 0
|
22
|
-
print "\nCleaning up #{count} temporary #{count > 1 ? "objects" : "object"}..."
|
22
|
+
print "\nCleaning up #{count} temporary #{count > 1 ? "objects" : "object (#{@temporary_object_ids.first})"}..."
|
23
23
|
@temporary_object_ids.each do |id|
|
24
24
|
# get our API
|
25
25
|
api = @api || (@test_users ? @test_users.graph_api : nil)
|
@@ -5,10 +5,19 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
5
5
|
end
|
6
6
|
|
7
7
|
describe "NetHTTPService module holder class Bear" do
|
8
|
+
before :each do
|
9
|
+
# reset the always_use_ssl parameter
|
10
|
+
Bear.always_use_ssl = nil
|
11
|
+
end
|
12
|
+
|
8
13
|
it "should define a make_request static module method" do
|
9
14
|
Bear.respond_to?(:make_request).should be_true
|
10
15
|
end
|
11
16
|
|
17
|
+
it "should include the Koala::HTTPService module defining common features" do
|
18
|
+
Bear.included_modules.include?(Koala::HTTPService).should be_true
|
19
|
+
end
|
20
|
+
|
12
21
|
describe "when making a request" do
|
13
22
|
before(:each) do
|
14
23
|
# Setup stubs for make_request to execute without exceptions
|
@@ -16,7 +25,7 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
16
25
|
@mock_body = stub('Net::HTTPResponse body')
|
17
26
|
@http_request_result = [@mock_http_response, @mock_body]
|
18
27
|
|
19
|
-
# to_ary is called in Ruby 1.9 to provide backwards compatibility
|
28
|
+
# to_ary is called in Ruby 1.9 to provide backwards compatibility
|
20
29
|
# with the response, body = http.get() syntax we use
|
21
30
|
@mock_http_response.stub!(:to_ary).and_return(@http_request_result)
|
22
31
|
|
@@ -31,33 +40,102 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
31
40
|
Net::HTTP.stub(:new).and_return(@http_mock)
|
32
41
|
end
|
33
42
|
|
34
|
-
|
35
|
-
|
36
|
-
|
43
|
+
describe "the connection" do
|
44
|
+
it "should use POST if verb is not GET" do
|
45
|
+
@http_yield_mock.should_receive(:post).and_return(@mock_http_response)
|
46
|
+
@http_mock.should_receive(:start).and_yield(@http_yield_mock)
|
37
47
|
|
38
|
-
|
48
|
+
Bear.make_request('anything', {}, 'anything')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should use GET if that verb is specified" do
|
52
|
+
@http_yield_mock.should_receive(:get).and_return(@mock_http_response)
|
53
|
+
@http_mock.should_receive(:start).and_yield(@http_yield_mock)
|
54
|
+
|
55
|
+
Bear.make_request('anything', {}, 'get')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should add the method to the arguments if it's not get or post" do
|
59
|
+
args = {}
|
60
|
+
method = "telekenesis"
|
61
|
+
# since the arguments get encoded later, we'll test for merge!
|
62
|
+
# even though that's somewhat testing internal implementation
|
63
|
+
args.should_receive(:merge!).with(:method => method)
|
64
|
+
|
65
|
+
Bear.make_request('anything', args, method)
|
66
|
+
end
|
39
67
|
end
|
40
68
|
|
41
|
-
|
42
|
-
|
69
|
+
describe "if the request has an access token" do
|
70
|
+
before :each do
|
71
|
+
@args = {"access_token" => "123"}
|
72
|
+
end
|
43
73
|
|
44
|
-
|
74
|
+
it "should use SSL" do
|
75
|
+
@http_mock.should_receive('use_ssl=').with(true)
|
76
|
+
|
77
|
+
Bear.make_request('anything', @args, 'anything')
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should set the port to 443" do
|
81
|
+
Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
|
82
|
+
|
83
|
+
Bear.make_request('anything', @args, 'anything')
|
84
|
+
end
|
45
85
|
end
|
46
86
|
|
47
|
-
|
48
|
-
|
87
|
+
describe "if always_use_ssl is true" do
|
88
|
+
before :each do
|
89
|
+
Bear.always_use_ssl = true
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should use SSL" do
|
93
|
+
@http_mock.should_receive('use_ssl=').with(true)
|
49
94
|
|
50
|
-
|
95
|
+
Bear.make_request('anything', {}, 'anything')
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should set the port to 443" do
|
99
|
+
Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
|
100
|
+
|
101
|
+
Bear.make_request('anything', {}, 'anything')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "if the use_ssl option is provided" do
|
106
|
+
it "should use SSL" do
|
107
|
+
@http_mock.should_receive('use_ssl=').with(true)
|
108
|
+
|
109
|
+
Bear.make_request('anything', {}, 'anything', :use_ssl => true)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should set the port to 443" do
|
113
|
+
Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
|
114
|
+
|
115
|
+
Bear.make_request('anything', {}, 'anything', :use_ssl => true)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "if there's no token and always_use_ssl isn't true" do
|
120
|
+
it "should not use SSL" do
|
121
|
+
@http_mock.should_not_receive('use_ssl=')
|
122
|
+
Bear.make_request('anything', {}, 'anything')
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should not set the port" do
|
126
|
+
Net::HTTP.should_receive(:new).with(anything, nil).and_return(@http_mock)
|
127
|
+
Bear.make_request('anything', {}, 'anything')
|
128
|
+
end
|
51
129
|
end
|
52
130
|
|
53
131
|
it "should use the graph server by default" do
|
54
132
|
Net::HTTP.should_receive(:new).with(Koala::Facebook::GRAPH_SERVER, anything).and_return(@http_mock)
|
55
|
-
Bear.make_request('anything', {}, 'anything')
|
133
|
+
Bear.make_request('anything', {}, 'anything')
|
56
134
|
end
|
57
135
|
|
58
136
|
it "should use the REST server if the :rest_api option is true" do
|
59
137
|
Net::HTTP.should_receive(:new).with(Koala::Facebook::REST_SERVER, anything).and_return(@http_mock)
|
60
|
-
Bear.make_request('anything', {}, 'anything', :rest_api => true)
|
138
|
+
Bear.make_request('anything', {}, 'anything', :rest_api => true)
|
61
139
|
end
|
62
140
|
|
63
141
|
it "should turn off vertificate validaiton warnings" do
|
@@ -82,7 +160,7 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
82
160
|
path = mock('Path')
|
83
161
|
@http_yield_mock.should_receive(:post).with(path, anything).and_return(@http_request_result)
|
84
162
|
|
85
|
-
Bear.make_request(path, {}, 'post')
|
163
|
+
Bear.make_request(path, {}, 'post')
|
86
164
|
end
|
87
165
|
|
88
166
|
it "should use encoded parameters" do
|
@@ -94,6 +172,45 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
94
172
|
|
95
173
|
Bear.make_request('anything', args, 'post')
|
96
174
|
end
|
175
|
+
|
176
|
+
describe "with multipart/form-data" do
|
177
|
+
before(:each) do
|
178
|
+
Bear.stub(:encode_multipart_params)
|
179
|
+
Bear.stub("params_require_multipart?").and_return(true)
|
180
|
+
|
181
|
+
@multipart_request_stub = stub('Stub Multipart Request')
|
182
|
+
Net::HTTP::Post::Multipart.stub(:new).and_return(@multipart_request_stub)
|
183
|
+
|
184
|
+
@file_stub = stub('fake File', "kind_of?" => true, "path" => 'anypath.jpg')
|
185
|
+
|
186
|
+
@http_yield_mock.stub(:request).with(@multipart_request_stub).and_return(@http_request_result)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should use multipart/form-data if any parameter is a valid file hash" do
|
190
|
+
@http_yield_mock.should_receive(:request).with(@multipart_request_stub).and_return(@http_request_result)
|
191
|
+
|
192
|
+
Bear.make_request('anything', {}, 'post')
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should use the given request path for the request" do
|
196
|
+
args = {"file" => @file_stub}
|
197
|
+
expected_path = 'expected/path'
|
198
|
+
|
199
|
+
Net::HTTP::Post::Multipart.should_receive(:new).with(expected_path, anything).and_return(@multipart_request_stub)
|
200
|
+
|
201
|
+
Bear.make_request(expected_path, {}, 'post')
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should use multipart encoded arguments for the request" do
|
205
|
+
args = {"file" => @file_stub}
|
206
|
+
expected_params = stub('Stub Multipart Params')
|
207
|
+
|
208
|
+
Bear.should_receive(:encode_multipart_params).with(args).and_return(expected_params)
|
209
|
+
Net::HTTP::Post::Multipart.should_receive(:new).with(anything, expected_params).and_return(@multipart_request_stub)
|
210
|
+
|
211
|
+
Bear.make_request('anything', args, 'post')
|
212
|
+
end
|
213
|
+
end
|
97
214
|
end
|
98
215
|
|
99
216
|
describe "via GET" do
|
@@ -125,7 +242,7 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
125
242
|
end
|
126
243
|
|
127
244
|
it "should return a Koala::Response with the right status" do
|
128
|
-
@response.status.should == @mock_http_response.code
|
245
|
+
@response.status.should == @mock_http_response.code
|
129
246
|
end
|
130
247
|
|
131
248
|
it "should reutrn a Koala::Response with the right body" do
|
@@ -182,5 +299,132 @@ class NetHTTPServiceTests < Test::Unit::TestCase
|
|
182
299
|
end
|
183
300
|
end
|
184
301
|
end
|
302
|
+
|
303
|
+
describe "when detecting if multipart posting is needed" do
|
304
|
+
it "should be true if any parameter value requires multipart post" do
|
305
|
+
valid_file_hash = stub("Stub Valid File Hash")
|
306
|
+
|
307
|
+
Bear.stub!("is_valid_file_hash?").and_return(false)
|
308
|
+
Bear.stub!("is_valid_file_hash?").with(valid_file_hash).and_return(true)
|
309
|
+
|
310
|
+
args = {
|
311
|
+
"key1" => "val",
|
312
|
+
"key2" => "val",
|
313
|
+
"key3" => valid_file_hash,
|
314
|
+
"key4" => "val"
|
315
|
+
}
|
316
|
+
|
317
|
+
Bear.params_require_multipart?(args).should be_true
|
318
|
+
end
|
319
|
+
|
320
|
+
describe "and looking at individual values" do
|
321
|
+
before(:each) do
|
322
|
+
@valid_hash = {
|
323
|
+
"content_type" => 1,
|
324
|
+
"path" => 1
|
325
|
+
}
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should only accept hashes" do
|
329
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_true
|
330
|
+
|
331
|
+
@valid_hash.stub!("kind_of?").with(Hash).and_return(false)
|
332
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_false
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should always require a content_type key" do
|
336
|
+
@valid_hash.delete("content_type")
|
337
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_false
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should always require the path key" do
|
341
|
+
@valid_hash.delete("path")
|
342
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_false
|
343
|
+
end
|
344
|
+
|
345
|
+
describe "with file IOs" do
|
346
|
+
before :each do
|
347
|
+
@stub_file = stub('Stub IO File')
|
348
|
+
@valid_hash["file"] = @stub_file
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should accept hashes with the file object that responds to read" do
|
352
|
+
@stub_file.should_receive("respond_to?").with(:read).and_return(true)
|
353
|
+
|
354
|
+
@valid_hash["file"] = @stub_file
|
355
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_true
|
356
|
+
end
|
357
|
+
|
358
|
+
it "should not accept hashes with a file object that does not respond to read" do
|
359
|
+
@stub_file.should_receive("respond_to?").with(:read).and_return(false)
|
360
|
+
|
361
|
+
@valid_hash["file"] = @stub_file
|
362
|
+
Bear.is_valid_file_hash?(@valid_hash).should be_false
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
describe "when encoding multipart/form-data params" do
|
370
|
+
it "should replace valid file hashes with file objects with UploadIO objects" do
|
371
|
+
file_hash_stub = {
|
372
|
+
"path" => "Fake File Name",
|
373
|
+
"content_type" => "Fake Content Type"
|
374
|
+
}
|
375
|
+
|
376
|
+
# UploadIO should be created
|
377
|
+
uploadio_stub = stub("UploadIO Shell Stub")
|
378
|
+
UploadIO.should_receive("new").with(file_hash_stub["path"], file_hash_stub["content_type"]).and_return(uploadio_stub)
|
379
|
+
|
380
|
+
# Ruby 1.9 test compatibility
|
381
|
+
content_stub = "UploadIOContent Stub"
|
382
|
+
uploadio_stub.stub(:to_ary).and_return([content_stub])
|
383
|
+
|
384
|
+
args = {
|
385
|
+
"not_a_file" => "not a file",
|
386
|
+
"file" => file_hash_stub
|
387
|
+
}
|
388
|
+
|
389
|
+
# Check that is_valid_file_hash is called on the file_hash_stub
|
390
|
+
Bear.stub!("is_valid_file_hash?").and_return(false)
|
391
|
+
Bear.should_receive("is_valid_file_hash?").with(file_hash_stub).and_return(true)
|
392
|
+
|
393
|
+
result = Bear.encode_multipart_params(args)
|
394
|
+
|
395
|
+
result["not_a_file"] == args["not_a_file"]
|
396
|
+
result["file"] == content_stub
|
397
|
+
end
|
398
|
+
|
399
|
+
it "should replace valid file hashes with file objects with UploadIO objects" do
|
400
|
+
file_hash_stub = {
|
401
|
+
"file" => "Fake File IO",
|
402
|
+
"path" => "Fake File Name",
|
403
|
+
"content_type" => "Fake Content Type"
|
404
|
+
}
|
405
|
+
|
406
|
+
# UploadIO should be created
|
407
|
+
uploadio_stub = stub("UploadIO Shell Stub")
|
408
|
+
UploadIO.should_receive("new").with(file_hash_stub["file"], file_hash_stub["content_type"], file_hash_stub["path"]).and_return(uploadio_stub)
|
409
|
+
|
410
|
+
# Ruby 1.9 test compatibility
|
411
|
+
content_stub = "UploadIOContent Stub"
|
412
|
+
uploadio_stub.stub(:to_ary).and_return([content_stub])
|
413
|
+
|
414
|
+
args = {
|
415
|
+
"not_a_file" => "not a file",
|
416
|
+
"file" => file_hash_stub
|
417
|
+
}
|
418
|
+
|
419
|
+
# Check that is_valid_file_hash is called on the file_hash_stub
|
420
|
+
Bear.stub!("is_valid_file_hash?").and_return(false)
|
421
|
+
Bear.should_receive("is_valid_file_hash?").with(file_hash_stub).and_return(true)
|
422
|
+
|
423
|
+
result = Bear.encode_multipart_params(args)
|
424
|
+
|
425
|
+
result["not_a_file"] == args["not_a_file"]
|
426
|
+
result["file"] == content_stub
|
427
|
+
end
|
428
|
+
end
|
185
429
|
end
|
186
430
|
end
|