koala 0.10.0 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/koala/graph_api.rb
CHANGED
@@ -142,7 +142,7 @@ module Koala
|
|
142
142
|
# Writes a wall post to the given profile's wall.
|
143
143
|
#
|
144
144
|
# We default to writing to the authenticated user's wall if no
|
145
|
-
# profile_id is specified.
|
145
|
+
# profile_id is specified.
|
146
146
|
#
|
147
147
|
# attachment adds a structured attachment to the status message being
|
148
148
|
# posted to the Wall. It should be a dictionary of the form:
|
@@ -155,7 +155,14 @@ module Koala
|
|
155
155
|
|
156
156
|
self.put_object(profile_id, "feed", attachment.merge({:message => message}))
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
|
+
def put_picture(file_hash, args = {}, target_id = "me")
|
160
|
+
raise APIError.new("type" => "KoalaInvaliFileFormat", "message" => "put_picture requires a hash describing the File to upload (see HTTPService::is_valid_file_hash?") unless file_hash.kind_of?(Hash)
|
161
|
+
|
162
|
+
args["source"] = file_hash
|
163
|
+
self.put_object(target_id, "photos", args)
|
164
|
+
end
|
165
|
+
|
159
166
|
def put_comment(object_id, message)
|
160
167
|
# Writes the given comment on the given post.
|
161
168
|
self.put_object(object_id, "comments", {:message => message})
|
@@ -165,9 +172,15 @@ module Koala
|
|
165
172
|
# Likes the given post.
|
166
173
|
self.put_object(object_id, "likes")
|
167
174
|
end
|
175
|
+
|
176
|
+
def delete_like(object_id)
|
177
|
+
raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Unliking requires an access token"}) unless @access_token
|
178
|
+
graph_call("#{object_id}/likes", {}, "delete")
|
179
|
+
end
|
168
180
|
|
169
181
|
def delete_object(id)
|
170
182
|
# Deletes the object with the given ID from the graph.
|
183
|
+
raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "Unliking requires an access token"}) unless @access_token
|
171
184
|
graph_call(id, {}, "delete")
|
172
185
|
end
|
173
186
|
|
@@ -189,4 +202,4 @@ module Koala
|
|
189
202
|
end
|
190
203
|
end
|
191
204
|
end
|
192
|
-
end
|
205
|
+
end
|
data/lib/koala/http_services.rb
CHANGED
@@ -8,62 +8,146 @@ module Koala
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
module HTTPService
|
12
|
+
# common functionality for all HTTP services
|
13
|
+
def self.included(base)
|
14
|
+
base.class_eval do
|
15
|
+
class << self
|
16
|
+
attr_accessor :always_use_ssl
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
def self.params_require_multipart?(param_hash)
|
21
|
+
param_hash.any? { |key, value| is_valid_file_hash?(value) }
|
22
|
+
end
|
23
|
+
|
24
|
+
# A file hash can take two forms:
|
25
|
+
# - A hash with "content_type" and "path" keys where "path" is the local path
|
26
|
+
# to the file to be uploaded.
|
27
|
+
# - A hash with the "file" key containing an already-opened IO that responds to "read"
|
28
|
+
# as well as "content_type" and the "path" key to the original file
|
29
|
+
# ("path"" is required by multipart-post even for opened files)
|
30
|
+
#
|
31
|
+
# Valid inputs for a file to be posted via multipart/form-data
|
32
|
+
# are based on the criteria for an UploadIO to be created
|
33
|
+
# See : https://github.com/nicksieger/multipart-post/blob/master/lib/composite_io.rb
|
34
|
+
def self.is_valid_file_hash?(value)
|
35
|
+
value.kind_of?(Hash) and value.key?("content_type") and value.key?("path") and (
|
36
|
+
!value.key?("file") or value["file"].respond_to?(:read)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
11
43
|
module NetHTTPService
|
12
44
|
# this service uses Net::HTTP to send requests to the graph
|
13
45
|
def self.included(base)
|
14
46
|
base.class_eval do
|
15
|
-
require
|
16
|
-
require
|
47
|
+
require "net/http" unless defined?(Net::HTTP)
|
48
|
+
require "net/https"
|
49
|
+
require "net/http/post/multipart"
|
50
|
+
|
51
|
+
include Koala::HTTPService
|
17
52
|
|
18
53
|
def self.make_request(path, args, verb, options = {})
|
19
54
|
# We translate args to a valid query string. If post is specified,
|
20
55
|
# we send a POST request to the given path with the given arguments.
|
21
56
|
|
57
|
+
# by default, we use SSL only for private requests
|
58
|
+
# this makes public requests faster
|
59
|
+
private_request = args["access_token"] || @always_use_ssl || options[:use_ssl]
|
60
|
+
|
22
61
|
# if the verb isn't get or post, send it as a post argument
|
23
62
|
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
24
63
|
|
25
64
|
server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
|
26
|
-
http = Net::HTTP.new(server, 443)
|
27
|
-
http.use_ssl = true
|
28
|
-
|
65
|
+
http = Net::HTTP.new(server, private_request ? 443 : nil)
|
66
|
+
http.use_ssl = true if private_request
|
67
|
+
|
68
|
+
# we turn off certificate validation to avoid the
|
29
69
|
# "warning: peer certificate won't be verified in this SSL session" warning
|
30
70
|
# not sure if this is the right way to handle it
|
31
71
|
# see http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
|
32
72
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
73
|
|
34
|
-
result = http.start
|
35
|
-
response, body =
|
74
|
+
result = http.start do |http|
|
75
|
+
response, body = if verb == "post"
|
76
|
+
if params_require_multipart? args
|
77
|
+
http.request Net::HTTP::Post::Multipart.new path, encode_multipart_params(args)
|
78
|
+
else
|
79
|
+
http.post(path, encode_params(args))
|
80
|
+
end
|
81
|
+
else
|
82
|
+
http.get("#{path}?#{encode_params(args)}")
|
83
|
+
end
|
84
|
+
|
36
85
|
Koala::Response.new(response.code.to_i, body, response)
|
37
|
-
|
86
|
+
end
|
38
87
|
end
|
39
88
|
|
40
89
|
protected
|
41
90
|
def self.encode_params(param_hash)
|
42
91
|
# unfortunately, we can't use to_query because that's Rails, not Ruby
|
43
92
|
# if no hash (e.g. no auth token) return empty string
|
44
|
-
((param_hash || {}).collect do |key_and_value|
|
93
|
+
((param_hash || {}).collect do |key_and_value|
|
45
94
|
key_and_value[1] = key_and_value[1].to_json if key_and_value[1].class != String
|
46
95
|
"#{key_and_value[0].to_s}=#{CGI.escape key_and_value[1]}"
|
47
96
|
end).join("&")
|
48
97
|
end
|
98
|
+
|
99
|
+
def self.encode_multipart_params(param_hash)
|
100
|
+
Hash[*param_hash.collect do |key, value|
|
101
|
+
if is_valid_file_hash?(value)
|
102
|
+
if value.key?("file")
|
103
|
+
value = UploadIO.new(value["file"], value["content_type"], value["path"])
|
104
|
+
else
|
105
|
+
value = UploadIO.new(value["path"], value['content_type'])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
[key, value]
|
110
|
+
end.flatten]
|
111
|
+
end
|
49
112
|
end
|
50
113
|
end
|
51
114
|
end
|
52
115
|
|
53
116
|
module TyphoeusService
|
54
117
|
# this service uses Typhoeus to send requests to the graph
|
118
|
+
|
119
|
+
# used for multipart file uploads (see below)
|
120
|
+
class NetHTTPInterface
|
121
|
+
include NetHTTPService
|
122
|
+
end
|
123
|
+
|
55
124
|
def self.included(base)
|
56
125
|
base.class_eval do
|
57
|
-
require
|
126
|
+
require "typhoeus" unless defined?(Typhoeus)
|
58
127
|
include Typhoeus
|
128
|
+
|
129
|
+
include Koala::HTTPService
|
59
130
|
|
60
131
|
def self.make_request(path, args, verb, options = {})
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
132
|
+
unless params_require_multipart?(args)
|
133
|
+
# if the verb isn't get or post, send it as a post argument
|
134
|
+
args.merge!({:method => verb}) && verb = "post" if verb != "get" && verb != "post"
|
135
|
+
server = options[:rest_api] ? Facebook::REST_SERVER : Facebook::GRAPH_SERVER
|
136
|
+
|
137
|
+
# you can pass arguments directly to Typhoeus using the :typhoeus_options key
|
138
|
+
typhoeus_options = {:params => args}.merge(options[:typhoeus_options] || {})
|
139
|
+
|
140
|
+
# by default, we use SSL only for private requests (e.g. with access token)
|
141
|
+
# this makes public requests faster
|
142
|
+
prefix = (args["access_token"] || @always_use_ssl || options[:use_ssl]) ? "https" : "http"
|
143
|
+
|
144
|
+
response = self.send(verb, "#{prefix}://#{server}#{path}", typhoeus_options)
|
145
|
+
Koala::Response.new(response.code, response.body, response.headers_hash)
|
146
|
+
else
|
147
|
+
# we have to use NetHTTPService for multipart for file uploads
|
148
|
+
# until Typhoeus integrates support
|
149
|
+
Koala::TyphoeusService::NetHTTPInterface.make_request(path, args, verb, options)
|
150
|
+
end
|
67
151
|
end
|
68
152
|
end # class_eval
|
69
153
|
end
|
data/lib/koala/rest_api.rb
CHANGED
@@ -1,23 +1,90 @@
|
|
1
1
|
module Koala
|
2
2
|
module Facebook
|
3
3
|
REST_SERVER = "api.facebook.com"
|
4
|
-
|
4
|
+
|
5
5
|
module RestAPIMethods
|
6
6
|
def fql_query(fql)
|
7
7
|
rest_call('fql.query', 'query' => fql)
|
8
8
|
end
|
9
|
-
|
10
|
-
def rest_call(method, args = {})
|
11
|
-
|
9
|
+
|
10
|
+
def rest_call(method, args = {}, options = {})
|
11
|
+
options = options.merge!(:rest_api => true, :read_only => READ_ONLY_METHODS.include?(method))
|
12
|
+
|
13
|
+
response = api("method/#{method}", args.merge('format' => 'json'), 'get', options) do |response|
|
12
14
|
# check for REST API-specific errors
|
13
15
|
if response.is_a?(Hash) && response["error_code"]
|
14
16
|
raise APIError.new("type" => response["error_code"], "message" => response["error_msg"])
|
15
17
|
end
|
16
18
|
end
|
17
|
-
|
19
|
+
|
18
20
|
response
|
19
21
|
end
|
22
|
+
|
23
|
+
# read-only methods for which we can use API-read
|
24
|
+
# taken directly from the FB PHP library (https://github.com/facebook/php-sdk/blob/master/src/facebook.php)
|
25
|
+
READ_ONLY_METHODS = [
|
26
|
+
'admin.getallocation',
|
27
|
+
'admin.getappproperties',
|
28
|
+
'admin.getbannedusers',
|
29
|
+
'admin.getlivestreamvialink',
|
30
|
+
'admin.getmetrics',
|
31
|
+
'admin.getrestrictioninfo',
|
32
|
+
'application.getpublicinfo',
|
33
|
+
'auth.getapppublickey',
|
34
|
+
'auth.getsession',
|
35
|
+
'auth.getsignedpublicsessiondata',
|
36
|
+
'comments.get',
|
37
|
+
'connect.getunconnectedfriendscount',
|
38
|
+
'dashboard.getactivity',
|
39
|
+
'dashboard.getcount',
|
40
|
+
'dashboard.getglobalnews',
|
41
|
+
'dashboard.getnews',
|
42
|
+
'dashboard.multigetcount',
|
43
|
+
'dashboard.multigetnews',
|
44
|
+
'data.getcookies',
|
45
|
+
'events.get',
|
46
|
+
'events.getmembers',
|
47
|
+
'fbml.getcustomtags',
|
48
|
+
'feed.getappfriendstories',
|
49
|
+
'feed.getregisteredtemplatebundlebyid',
|
50
|
+
'feed.getregisteredtemplatebundles',
|
51
|
+
'fql.multiquery',
|
52
|
+
'fql.query',
|
53
|
+
'friends.arefriends',
|
54
|
+
'friends.get',
|
55
|
+
'friends.getappusers',
|
56
|
+
'friends.getlists',
|
57
|
+
'friends.getmutualfriends',
|
58
|
+
'gifts.get',
|
59
|
+
'groups.get',
|
60
|
+
'groups.getmembers',
|
61
|
+
'intl.gettranslations',
|
62
|
+
'links.get',
|
63
|
+
'notes.get',
|
64
|
+
'notifications.get',
|
65
|
+
'pages.getinfo',
|
66
|
+
'pages.isadmin',
|
67
|
+
'pages.isappadded',
|
68
|
+
'pages.isfan',
|
69
|
+
'permissions.checkavailableapiaccess',
|
70
|
+
'permissions.checkgrantedapiaccess',
|
71
|
+
'photos.get',
|
72
|
+
'photos.getalbums',
|
73
|
+
'photos.gettags',
|
74
|
+
'profile.getinfo',
|
75
|
+
'profile.getinfooptions',
|
76
|
+
'stream.get',
|
77
|
+
'stream.getcomments',
|
78
|
+
'stream.getfilters',
|
79
|
+
'users.getinfo',
|
80
|
+
'users.getloggedinuser',
|
81
|
+
'users.getstandardinfo',
|
82
|
+
'users.hasapppermission',
|
83
|
+
'users.isappuser',
|
84
|
+
'users.isverified',
|
85
|
+
'video.getuploadlimits'
|
86
|
+
]
|
20
87
|
end
|
21
|
-
|
88
|
+
|
22
89
|
end # module Facebook
|
23
90
|
end # module Koala
|
data/readme.md
CHANGED
@@ -1,28 +1,28 @@
|
|
1
1
|
Koala
|
2
2
|
====
|
3
|
-
Koala (<a href="http://github.com/arsduo/koala" target="_blank">http://github.com/arsduo/koala</a>) is a new Facebook library for Ruby, supporting the Graph API, the old REST API, realtime updates, and OAuth validation. We wrote Koala with four goals:
|
3
|
+
Koala (<a href="http://github.com/arsduo/koala" target="_blank">http://github.com/arsduo/koala</a>) is a new Facebook library for Ruby, supporting the Graph API, the old REST API, realtime updates, and OAuth validation. We wrote Koala with four goals:
|
4
4
|
|
5
|
-
* Lightweight: Koala should be as light and simple as Facebook’s own new libraries, providing API accessors and returning simple JSON. (We clock in, with comments, just over
|
5
|
+
* Lightweight: Koala should be as light and simple as Facebook’s own new libraries, providing API accessors and returning simple JSON. (We clock in, with comments, just over 750 lines of code.)
|
6
6
|
* Fast: Koala should, out of the box, be quick. In addition to supporting the vanilla Ruby networking libraries, it natively supports Typhoeus, our preferred gem for making fast HTTP requests. Of course, That brings us to our next topic:
|
7
7
|
* Flexible: Koala should be useful to everyone, regardless of their current configuration. (We have no dependencies beyond the JSON gem. Koala also has a built-in mechanism for using whichever HTTP library you prefer to make requests against the graph.)
|
8
8
|
* Tested: Koala should have complete test coverage, so you can rely on it. (Our complete test coverage can be run against either mocked responses or the live Facebook servers.)
|
9
9
|
|
10
10
|
Graph API
|
11
11
|
----
|
12
|
-
The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
|
12
|
+
The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
|
13
13
|
|
14
14
|
graph = Koala::Facebook::GraphAPI.new(oauth_access_token)
|
15
15
|
profile = graph.get_object("me")
|
16
16
|
friends = graph.get_connections("me", "friends")
|
17
17
|
graph.put_object("me", "feed", :message => "I am writing on my wall!")
|
18
18
|
|
19
|
-
The response of most requests is the JSON data returned from the Facebook servers as a Hash.
|
19
|
+
The response of most requests is the JSON data returned from the Facebook servers as a Hash.
|
20
20
|
|
21
21
|
When retrieving data that returns an array of results (for example, when calling GraphAPI#get_connections or GraphAPI#search) a GraphCollection object (a sub-class of Array) will be returned, which contains added methods for getting the next and previous page of results:
|
22
|
-
|
22
|
+
|
23
23
|
# Returns the feed items for the currently logged-in user as a GraphCollection
|
24
24
|
feed = graph.get_connections("me", "feed")
|
25
|
-
|
25
|
+
|
26
26
|
# GraphCollection is a sub-class of Array, so you can use it as a usual Array
|
27
27
|
first_entry = feed[0]
|
28
28
|
last_entry = feed.last
|
@@ -33,7 +33,7 @@ When retrieving data that returns an array of results (for example, when calling
|
|
33
33
|
# Returns an array describing the URL for the next page: [path, arguments]
|
34
34
|
# This is useful for paging across multiple requests
|
35
35
|
next_path, next_args = feed.next_page_params
|
36
|
-
|
36
|
+
|
37
37
|
# You can use those params to easily get the next (or prevous) page
|
38
38
|
page = graph.get_page(feed.next_page_params)
|
39
39
|
|
@@ -41,15 +41,15 @@ Check out the wiki for more examples.
|
|
41
41
|
|
42
42
|
The old-school REST API
|
43
43
|
-----
|
44
|
-
Where the Graph API and the old REST API overlap, you should choose the Graph API. Unfortunately, that overlap is far from complete, and there are many important API calls that can't yet be done via the Graph.
|
44
|
+
Where the Graph API and the old REST API overlap, you should choose the Graph API. Unfortunately, that overlap is far from complete, and there are many important API calls that can't yet be done via the Graph.
|
45
45
|
|
46
46
|
Koala now supports the old-school REST API using OAuth access tokens; to use this, instantiate your class using the RestAPI class:
|
47
47
|
|
48
48
|
@rest = Koala::Facebook::RestAPI.new(oauth_access_token)
|
49
49
|
@rest.fql_query(my_fql_query) # convenience method
|
50
50
|
@rest.rest_call("stream.publish", arguments_hash) # generic version
|
51
|
-
|
52
|
-
We reserve the right to expand the built-in REST API coverage to additional convenience methods in the future, depending on how fast Facebook moves to fill in the gaps.
|
51
|
+
|
52
|
+
We reserve the right to expand the built-in REST API coverage to additional convenience methods in the future, depending on how fast Facebook moves to fill in the gaps.
|
53
53
|
|
54
54
|
(If you want the power of both APIs in the palm of your hand, try out the GraphAndRestAPI class.)
|
55
55
|
|
@@ -119,7 +119,7 @@ Some resources to help you as you play with Koala and the Graph API:
|
|
119
119
|
Testing
|
120
120
|
-----
|
121
121
|
|
122
|
-
Unit tests are provided for all of Koala's methods. By default, these tests run against mock responses and hence are ready out of the box:
|
122
|
+
Unit tests are provided for all of Koala's methods. By default, these tests run against mock responses and hence are ready out of the box:
|
123
123
|
# From the spec directory
|
124
124
|
spec koala_spec.rb
|
125
125
|
|
data/spec/facebook_data.yml
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# Just remember to update all fields!
|
5
5
|
|
6
6
|
# You must supply this value yourself to test the GraphAPI class.
|
7
|
-
# Your OAuth token should have publish_stream and
|
7
|
+
# Your OAuth token should have publish_stream, read_stream, and user_photos permissions.
|
8
8
|
oauth_token:
|
9
9
|
|
10
10
|
# for testing the OAuth class
|
@@ -44,8 +44,14 @@ oauth_test_data:
|
|
44
44
|
signed_request_result:
|
45
45
|
"0": payload
|
46
46
|
algorithm: HMAC-SHA256
|
47
|
-
|
48
|
-
|
47
|
+
# signed params
|
48
|
+
# examples from http://developers.facebook.com/docs/authentication/canvas/encryption_proposal
|
49
|
+
signed_params: t63pZQ4Q3ZTHJt0hOsKrY2pb28xRlduW0pg4lL_Zhl4.eyJhbGdvcml0aG0iOiJBRVMtMjU2LUNCQyBITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTI4NzYwMTk4OCwiaXYiOiJmRExKQ1cteWlYbXVOYTI0ZVNhckpnIiwicGF5bG9hZCI6IllHeW00cG9Rbk1UckVnaUFPa0ZUVkk4NWxsNVJ1VWlFbC1JZ3FmeFRPVEhRTkl2VlZJOFk4a1Z1T29lS2FXT2Vhc3NXRlRFdjBRZ183d0NDQkVlbjdsVUJCemxGSjFWNjNISjNBZjBTSW5nY3hXVEo3TDZZTGF0TW13WGdEQXZXbjVQc2ZxeldrNG1sOWg5RExuWXB0V0htREdMNmlCaU9oTjdXeUk3cDZvRXBWcmlGdUp3X2NoTG9QYjhhM3ZHRG5vVzhlMlN4eDA2QTJ4MnhraWFwdmcifQ
|
50
|
+
signed_params_secret: 13750c9911fec5865d01f3bd00bdf4db
|
51
|
+
signed_params_result:
|
52
|
+
access_token: "101244219942650|2.wdrSr7KyE_VwQ0fjwOfW9A__.3600.1287608400-499091902|XzxMQd-_4tjlC2VEgide4rmg6LI"
|
53
|
+
expires_in: 6412
|
54
|
+
user_id: "499091902"
|
49
55
|
|
50
56
|
subscription_test_data:
|
51
57
|
subscription_path: http://oauth.twoalex.com/subscriptions
|
Binary file
|
@@ -3,8 +3,12 @@ class GraphAndRestAPINoTokenTests < Test::Unit::TestCase
|
|
3
3
|
before(:each) do
|
4
4
|
@api = Koala::Facebook::GraphAndRestAPI.new
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
|
+
it_should_behave_like "Koala RestAPI"
|
7
8
|
it_should_behave_like "Koala RestAPI without an access token"
|
9
|
+
|
10
|
+
it_should_behave_like "Koala GraphAPI"
|
8
11
|
it_should_behave_like "Koala GraphAPI without an access token"
|
12
|
+
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
9
13
|
end
|
10
14
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
class GraphAndRestAPIWithTokenTests < Test::Unit::TestCase
|
2
2
|
describe "Koala GraphAndRestAPI without an access token" do
|
3
3
|
include LiveTestingDataHelper
|
4
|
-
|
5
|
-
it_should_behave_like "Koala GraphAPI with an access token"
|
6
|
-
|
4
|
+
|
7
5
|
before(:each) do
|
8
6
|
@api = Koala::Facebook::GraphAndRestAPI.new(@token)
|
9
7
|
end
|
8
|
+
|
9
|
+
it_should_behave_like "Koala RestAPI"
|
10
|
+
it_should_behave_like "Koala RestAPI with an access token"
|
11
|
+
|
12
|
+
it_should_behave_like "Koala GraphAPI"
|
13
|
+
it_should_behave_like "Koala GraphAPI with an access token"
|
14
|
+
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
10
15
|
end
|
11
16
|
end
|
@@ -1,9 +1,4 @@
|
|
1
1
|
shared_examples_for "Koala GraphAPI without 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
|
6
|
-
end
|
7
2
|
|
8
3
|
it "should not get private data about a user" do
|
9
4
|
result = @api.get_object("koppel")
|
@@ -11,46 +6,14 @@ shared_examples_for "Koala GraphAPI without an access token" do
|
|
11
6
|
result["updated_time"].should be_nil
|
12
7
|
end
|
13
8
|
|
14
|
-
it "should get public data about a Page" do
|
15
|
-
result = @api.get_object("contextoptional")
|
16
|
-
# the results should have an ID and a name, among other things
|
17
|
-
(result["id"] && result["name"]).should
|
18
|
-
end
|
19
|
-
|
20
9
|
it "should not be able to get data about 'me'" do
|
21
10
|
lambda { @api.get_object("me") }.should raise_error(Koala::Facebook::APIError)
|
22
11
|
end
|
23
12
|
|
24
|
-
it "should be able to get multiple objects" do
|
25
|
-
results = @api.get_objects(["contextoptional", "naitik"])
|
26
|
-
results.length.should == 2
|
27
|
-
end
|
28
|
-
|
29
13
|
it "shouldn't be able to access connections from users" do
|
30
14
|
lambda { @api.get_connections("lukeshepard", "likes") }.should raise_error(Koala::Facebook::APIError)
|
31
15
|
end
|
32
16
|
|
33
|
-
it "should be able to access a user's picture" do
|
34
|
-
@api.get_picture("chris.baclig").should =~ /http\:\/\//
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should be able to access a user's picture, given a picture type" do
|
38
|
-
@api.get_picture("chris.baclig", {:type => 'large'}).should =~ /^http\:\/\//
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should be able to access connections from public Pages" do
|
42
|
-
result = @api.get_connections("contextoptional", "photos")
|
43
|
-
result.should be_a(Array)
|
44
|
-
end
|
45
|
-
|
46
|
-
# paging
|
47
|
-
# see also graph_collection_tests
|
48
|
-
it "should make a request for a page when provided a specific set of page params" do
|
49
|
-
query = [1, 2]
|
50
|
-
@api.should_receive(:graph_call).with(*query)
|
51
|
-
@api.get_page(query)
|
52
|
-
end
|
53
|
-
|
54
17
|
it "should not be able to put an object" do
|
55
18
|
lambda { @result = @api.put_object("lukeshepard", "feed", :message => "Hello, world") }.should raise_error(Koala::Facebook::APIError)
|
56
19
|
puts "Error! Object #{@result.inspect} somehow put onto Luke Shepard's wall!" if @result
|
@@ -60,7 +23,7 @@ shared_examples_for "Koala GraphAPI without an access token" do
|
|
60
23
|
it "should not be able to post to a feed" do
|
61
24
|
(lambda do
|
62
25
|
attachment = {:name => "Context Optional", :link => "http://www.contextoptional.com/"}
|
63
|
-
@result = @api.put_wall_post("Hello, world", attachment, "contextoptional")
|
26
|
+
@result = @api.put_wall_post("Hello, world", attachment, "contextoptional")
|
64
27
|
end).should raise_error(Koala::Facebook::APIError)
|
65
28
|
puts "Error! Object #{@result.inspect} somehow put onto Context Optional's wall!" if @result
|
66
29
|
end
|
@@ -68,7 +31,7 @@ shared_examples_for "Koala GraphAPI without an access token" do
|
|
68
31
|
it "should not be able to comment on an object" do
|
69
32
|
# random public post on the ContextOptional wall
|
70
33
|
lambda { @result = @api.put_comment("7204941866_119776748033392", "The hackathon was great!") }.should raise_error(Koala::Facebook::APIError)
|
71
|
-
puts "Error! Object #{@result.inspect} somehow commented on post 7204941866_119776748033392!" if @result
|
34
|
+
puts "Error! Object #{@result.inspect} somehow commented on post 7204941866_119776748033392!" if @result
|
72
35
|
end
|
73
36
|
|
74
37
|
it "should not be able to like an object" do
|
@@ -76,29 +39,13 @@ shared_examples_for "Koala GraphAPI without an access token" do
|
|
76
39
|
end
|
77
40
|
|
78
41
|
# DELETE
|
79
|
-
it "should not be able to delete posts" do
|
42
|
+
it "should not be able to delete posts" do
|
80
43
|
# test post on the Ruby SDK Test application
|
81
44
|
lambda { @result = @api.delete_object("115349521819193_113815981982767") }.should raise_error(Koala::Facebook::APIError)
|
82
45
|
end
|
83
|
-
|
84
|
-
# SEARCH
|
85
|
-
it "should be able to search" do
|
86
|
-
result = @api.search("facebook")
|
87
|
-
result.length.should be_an(Integer)
|
88
|
-
end
|
89
|
-
|
90
|
-
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
91
46
|
|
92
|
-
|
93
|
-
|
94
|
-
Koala.should_receive(:make_request).with(
|
95
|
-
anything,
|
96
|
-
anything,
|
97
|
-
anything,
|
98
|
-
hash_not_including(:rest_api => true)
|
99
|
-
).and_return(Koala::Response.new(200, "", {}))
|
100
|
-
|
101
|
-
@api.api("anything")
|
47
|
+
it "should not be able to delete a like" do
|
48
|
+
lambda { @api.delete_like("7204941866_119776748033392") }.should raise_error(Koala::Facebook::APIError)
|
102
49
|
end
|
103
50
|
end
|
104
51
|
|
@@ -106,9 +53,11 @@ class FacebookNoAccessTokenTests < Test::Unit::TestCase
|
|
106
53
|
describe "Koala GraphAPI without an access token" do
|
107
54
|
before :each do
|
108
55
|
@api = Koala::Facebook::GraphAPI.new
|
109
|
-
end
|
110
|
-
|
56
|
+
end
|
57
|
+
|
58
|
+
it_should_behave_like "Koala GraphAPI"
|
111
59
|
it_should_behave_like "Koala GraphAPI without an access token"
|
60
|
+
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
61
|
+
|
112
62
|
end
|
113
63
|
end
|
114
|
-
|