koala 0.10.0 → 1.0.0.beta2

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 (34) hide show
  1. data/CHANGELOG +33 -7
  2. data/Manifest +8 -1
  3. data/Rakefile +4 -4
  4. data/koala.gemspec +10 -8
  5. data/lib/koala/graph_api.rb +188 -123
  6. data/lib/koala/http_services.rb +93 -17
  7. data/lib/koala/rest_api.rb +73 -6
  8. data/lib/koala/test_users.rb +18 -5
  9. data/lib/koala/uploadable_io.rb +115 -0
  10. data/lib/koala.rb +95 -72
  11. data/readme.md +18 -12
  12. data/spec/facebook_data.yml +9 -3
  13. data/spec/koala/assets/beach.jpg +0 -0
  14. data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +5 -1
  15. data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +8 -3
  16. data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +12 -61
  17. data/spec/koala/graph_api/graph_api_tests.rb +85 -0
  18. data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +167 -123
  19. data/spec/koala/http_services/http_service_tests.rb +51 -0
  20. data/spec/koala/http_services/net_http_service_tests.rb +339 -0
  21. data/spec/koala/http_services/typhoeus_service_tests.rb +162 -0
  22. data/spec/koala/live_testing_data_helper.rb +1 -1
  23. data/spec/koala/oauth/oauth_tests.rb +35 -64
  24. data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +5 -74
  25. data/spec/koala/rest_api/rest_api_tests.rb +118 -0
  26. data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +5 -3
  27. data/spec/koala/test_users/test_users_tests.rb +49 -48
  28. data/spec/koala/uploadable_io/uploadable_io_tests.rb +246 -0
  29. data/spec/koala_spec_helper.rb +30 -4
  30. data/spec/koala_spec_without_mocks.rb +3 -3
  31. data/spec/mock_facebook_responses.yml +41 -18
  32. data/spec/mock_http_service.rb +16 -3
  33. metadata +38 -8
  34. data/spec/koala/net_http_service_tests.rb +0 -186
data/lib/koala.rb CHANGED
@@ -5,8 +5,9 @@ require 'digest/md5'
5
5
  require 'rubygems'
6
6
  require 'json'
7
7
 
8
- # openssl is required to support signed_request
8
+ # OpenSSL and Base64 are required to support signed_request
9
9
  require 'openssl'
10
+ require 'base64'
10
11
 
11
12
  # include default http services
12
13
  require 'koala/http_services'
@@ -23,8 +24,11 @@ require 'koala/realtime_updates'
23
24
  # add test user methods
24
25
  require 'koala/test_users'
25
26
 
27
+ # add KoalaIO class
28
+ require 'koala/uploadable_io'
29
+
26
30
  module Koala
27
-
31
+
28
32
  module Facebook
29
33
  # Ruby client library for the Facebook Platform.
30
34
  # Copyright 2010 Facebook
@@ -40,7 +44,7 @@ module Koala
40
44
  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
41
45
  # License for the specific language governing permissions and limitations
42
46
  # under the License.
43
- #
47
+ #
44
48
  # This client library is designed to support the Graph API and the official
45
49
  # Facebook JavaScript SDK, which is the canonical way to implement
46
50
  # Facebook authentication. Read more about the Graph API at
@@ -53,7 +57,7 @@ module Koala
53
57
  @access_token = access_token
54
58
  end
55
59
  attr_reader :access_token
56
-
60
+
57
61
  def api(path, args = {}, verb = "get", options = {}, &error_checking_block)
58
62
  # Fetches the given path in the Graph API.
59
63
  args["access_token"] = @access_token || @app_access_token if @access_token || @app_access_token
@@ -63,20 +67,20 @@ module Koala
63
67
 
64
68
  # make the request via the provided service
65
69
  result = Koala.make_request(path, args, verb, options)
66
-
70
+
67
71
  # Check for any 500 errors before parsing the body
68
72
  # since we're not guaranteed that the body is valid JSON
69
73
  # in the case of a server error
70
74
  raise APIError.new({"type" => "HTTP #{result.status.to_s}", "message" => "Response body: #{result.body}"}) if result.status >= 500
71
-
72
- # Parse the body as JSON and check for errors if provided a mechanism to do so
75
+
76
+ # Parse the body as JSON and check for errors if provided a mechanism to do so
73
77
  # Note: Facebook sometimes sends results like "true" and "false", which aren't strictly objects
74
78
  # and cause JSON.parse to fail -- so we account for that by wrapping the result in []
75
79
  body = response = JSON.parse("[#{result.body.to_s}]")[0]
76
80
  if error_checking_block
77
81
  yield(body)
78
82
  end
79
-
83
+
80
84
  # now return the desired information
81
85
  if options[:http_component]
82
86
  result.send(options[:http_component])
@@ -85,57 +89,57 @@ module Koala
85
89
  end
86
90
  end
87
91
  end
88
-
92
+
89
93
  class GraphAPI < API
90
94
  include GraphAPIMethods
91
95
  end
92
-
96
+
93
97
  class RestAPI < API
94
98
  include RestAPIMethods
95
99
  end
96
-
100
+
97
101
  class GraphAndRestAPI < API
98
102
  include GraphAPIMethods
99
103
  include RestAPIMethods
100
104
  end
101
-
105
+
102
106
  class RealtimeUpdates < API
103
107
  include RealtimeUpdateMethods
104
108
  end
105
-
109
+
106
110
  class TestUsers < API
107
111
  include TestUserMethods
108
112
  # make the Graph API accessible in case someone wants to make other calls to interact with their users
109
113
  attr_reader :graph_api
110
114
  end
111
-
112
- class APIError < Exception
115
+
116
+ class APIError < StandardError
113
117
  attr_accessor :fb_error_type
114
118
  def initialize(details = {})
115
- self.fb_error_type = details["type"]
119
+ self.fb_error_type = details["type"]
116
120
  super("#{fb_error_type}: #{details["message"]}")
117
121
  end
118
122
  end
119
-
120
-
123
+
124
+
121
125
  class OAuth
122
126
  attr_reader :app_id, :app_secret, :oauth_callback_url
123
127
  def initialize(app_id, app_secret, oauth_callback_url = nil)
124
128
  @app_id = app_id
125
129
  @app_secret = app_secret
126
- @oauth_callback_url = oauth_callback_url
130
+ @oauth_callback_url = oauth_callback_url
127
131
  end
128
132
 
129
133
  def get_user_info_from_cookie(cookie_hash)
130
134
  # Parses the cookie set by the official Facebook JavaScript SDK.
131
- #
135
+ #
132
136
  # cookies should be a Hash, like the one Rails provides
133
- #
137
+ #
134
138
  # If the user is logged in via Facebook, we return a dictionary with the
135
139
  # keys "uid" and "access_token". The former is the user's Facebook ID,
136
140
  # and the latter can be used to make authenticated requests to the Graph API.
137
141
  # If the user is not logged in, we return None.
138
- #
142
+ #
139
143
  # Download the official Facebook JavaScript SDK at
140
144
  # http://github.com/facebook/connect-js/. Read more about Facebook
141
145
  # authentication at http://developers.facebook.com/docs/authentication/.
@@ -150,21 +154,21 @@ module Koala
150
154
 
151
155
  # generate the signature and make sure it matches what we expect
152
156
  auth_string = components.keys.sort.collect {|a| a == "sig" ? nil : "#{a}=#{components[a]}"}.reject {|a| a.nil?}.join("")
153
- sig = Digest::MD5.hexdigest(auth_string + @app_secret)
157
+ sig = Digest::MD5.hexdigest(auth_string + @app_secret)
154
158
  sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
155
159
  end
156
160
  end
157
161
  alias_method :get_user_info_from_cookies, :get_user_info_from_cookie
158
-
162
+
159
163
  def get_user_from_cookie(cookies)
160
164
  if info = get_user_info_from_cookies(cookies)
161
165
  string = info["uid"]
162
166
  end
163
167
  end
164
168
  alias_method :get_user_from_cookies, :get_user_from_cookie
165
-
169
+
166
170
  # URLs
167
-
171
+
168
172
  def url_for_oauth_code(options = {})
169
173
  # for permissions, see http://developers.facebook.com/docs/authentication/permissions
170
174
  permissions = options[:permissions]
@@ -174,54 +178,71 @@ module Koala
174
178
  raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback
175
179
 
176
180
  # Creates the URL for oauth authorization for a given callback and optional set of permissions
177
- "https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}"
181
+ "https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}"
178
182
  end
179
-
183
+
180
184
  def url_for_access_token(code, options = {})
181
185
  # Creates the URL for the token corresponding to a given code generated by Facebook
182
186
  callback = options[:callback] || @oauth_callback_url
183
187
  raise ArgumentError, "url_for_access_token must get a callback either from the OAuth object or in the parameters!" unless callback
184
188
  "https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
185
189
  end
186
-
190
+
187
191
  def get_access_token_info(code)
188
192
  # convenience method to get a parsed token from Facebook for a given code
189
193
  # should this require an OAuth callback URL?
190
194
  get_token_from_server(:code => code, :redirect_uri => @oauth_callback_url)
191
195
  end
192
-
196
+
193
197
  def get_access_token(code)
194
198
  # upstream methods will throw errors if needed
195
- if info = get_access_token_info(code)
196
- string = info["access_token"]
199
+ if info = get_access_token_info(code)
200
+ string = info["access_token"]
197
201
  end
198
202
  end
199
-
203
+
200
204
  def get_app_access_token_info
201
- # convenience method to get a the application's sessionless access token
205
+ # convenience method to get a the application's sessionless access token
202
206
  get_token_from_server({:type => 'client_cred'}, true)
203
207
  end
204
-
208
+
205
209
  def get_app_access_token
206
210
  if info = get_app_access_token_info
207
- string = info["access_token"]
211
+ string = info["access_token"]
208
212
  end
209
213
  end
210
-
211
- # signed_request
212
- def parse_signed_request(request)
213
- # Facebook's signed requests come in two parts -- the signature and the data payload
214
- # see http://developers.facebook.com/docs/authentication/canvas
215
- encoded_sig, payload = request.split(".")
216
-
217
- sig = base64_url_decode(encoded_sig)
218
-
219
- # if the signature matches, return the data, decoded and parsed as JSON
220
- if OpenSSL::HMAC.digest("sha256", @app_secret, payload) == sig
221
- JSON.parse(base64_url_decode(payload))
222
- else
223
- nil
224
- end
214
+
215
+ # provided directly by Facebook
216
+ # see https://github.com/facebook/crypto-request-examples/blob/master/sample.rb
217
+ # and http://developers.facebook.com/docs/authentication/canvas/encryption_proposal
218
+ def parse_signed_request(input, max_age = 3600)
219
+ encoded_sig, encoded_envelope = input.split('.', 2)
220
+ envelope = JSON.parse(base64_url_decode(encoded_envelope))
221
+ algorithm = envelope['algorithm']
222
+
223
+ raise 'Invalid request. (Unsupported algorithm.)' \
224
+ if algorithm != 'AES-256-CBC HMAC-SHA256' && algorithm != 'HMAC-SHA256'
225
+
226
+ raise 'Invalid request. (Too old.)' \
227
+ if algorithm == "AES-256-CBC HMAC-SHA256" && envelope['issued_at'].to_i < Time.now.to_i - max_age
228
+
229
+ raise 'Invalid request. (Invalid signature.)' \
230
+ if base64_url_decode(encoded_sig) !=
231
+ OpenSSL::HMAC.hexdigest(
232
+ 'sha256', @app_secret, encoded_envelope).split.pack('H*')
233
+
234
+ # for requests that are signed, but not encrypted, we're done
235
+ return envelope if algorithm == 'HMAC-SHA256'
236
+
237
+ # otherwise, decrypt the payload
238
+ cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
239
+ cipher.decrypt
240
+ cipher.key = @app_secret
241
+ cipher.iv = base64_url_decode(envelope['iv'])
242
+ cipher.padding = 0
243
+ decrypted_data = cipher.update(base64_url_decode(envelope['payload']))
244
+ decrypted_data << cipher.final
245
+ return JSON.parse(decrypted_data.strip)
225
246
  end
226
247
 
227
248
  # from session keys
@@ -231,69 +252,70 @@ module Koala
231
252
  :type => 'client_cred',
232
253
  :sessions => sessions.join(",")
233
254
  }, true, "exchange_sessions")
234
-
255
+
235
256
  # Facebook returns an empty body in certain error conditions
236
- if response == ""
257
+ if response == ""
237
258
  raise APIError.new({
238
- "type" => "ArgumentError",
259
+ "type" => "ArgumentError",
239
260
  "message" => "get_token_from_session_key received an error (empty response body) for sessions #{sessions.inspect}!"
240
261
  })
241
262
  end
242
-
263
+
243
264
  JSON.parse(response)
244
265
  end
245
-
266
+
246
267
  def get_tokens_from_session_keys(sessions)
247
268
  # get the original hash results
248
269
  results = get_token_info_from_session_keys(sessions)
249
270
  # now recollect them as just the access tokens
250
271
  results.collect { |r| r ? r["access_token"] : nil }
251
272
  end
252
-
273
+
253
274
  def get_token_from_session_key(session)
254
275
  # convenience method for a single key
255
276
  # gets the overlaoded strings automatically
256
277
  get_tokens_from_session_keys([session])[0]
257
278
  end
258
-
279
+
259
280
  protected
260
-
281
+
261
282
  def get_token_from_server(args, post = false)
262
283
  # fetch the result from Facebook's servers
263
284
  result = fetch_token_string(args, post)
264
-
285
+
265
286
  # if we have an error, parse the error JSON and raise an error
266
287
  raise APIError.new((JSON.parse(result)["error"] rescue nil) || {}) if result =~ /error/
267
288
 
268
289
  # otherwise, parse the access token
269
- parse_access_token(result)
290
+ parse_access_token(result)
270
291
  end
271
-
292
+
272
293
  def parse_access_token(response_text)
273
294
  components = response_text.split("&").inject({}) do |hash, bit|
274
295
  key, value = bit.split("=")
275
296
  hash.merge!(key => value)
276
297
  end
277
- components
298
+ components
278
299
  end
279
300
 
280
301
  def fetch_token_string(args, post = false, endpoint = "access_token")
281
302
  Koala.make_request("/oauth/#{endpoint}", {
282
- :client_id => @app_id,
303
+ :client_id => @app_id,
283
304
  :client_secret => @app_secret
284
- }.merge!(args), post ? "post" : "get").body
305
+ }.merge!(args), post ? "post" : "get", :use_ssl => true).body
285
306
  end
286
-
307
+
287
308
  # base 64
288
- def base64_url_decode(string)
289
- # to properly decode what Facebook provides, we need to add == to the end
290
- # and translate certain characters to others before running the actual decoding
291
- # see http://developers.facebook.com/docs/authentication/canvas
292
- "#{string}==".tr("-_", "+/").unpack("m")[0]
309
+ # directly from https://github.com/facebook/crypto-request-examples/raw/master/sample.rb
310
+ def base64_url_decode(str)
311
+ str += '=' * (4 - str.length.modulo(4))
312
+ Base64.decode64(str.gsub('-', '+').gsub('_', '/'))
293
313
  end
294
314
  end
295
315
  end
296
316
 
317
+ class KoalaError< StandardError; end
318
+
297
319
  # finally, set up the http service Koala methods used to make requests
298
320
  # you can use your own (for HTTParty, etc.) by calling Koala.http_service = YourModule
299
321
  def self.http_service=(service)
@@ -301,8 +323,9 @@ module Koala
301
323
  end
302
324
 
303
325
  # by default, try requiring Typhoeus -- if that works, use it
326
+ # if you have Typheous and don't want to use it (or want another service),
327
+ # you can run Koala.http_service = NetHTTPService (or MyHTTPService)
304
328
  begin
305
- require 'typhoeus'
306
329
  Koala.http_service = TyphoeusService
307
330
  rescue LoadError
308
331
  Koala.http_service = NetHTTPService
data/readme.md CHANGED
@@ -1,28 +1,34 @@
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 (including photo uploads), 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 500 lines of code.)
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
+ 1.0 beta
11
+ ---
12
+ Version 1.0 is currently in beta, chock-full of great new features. To download the beta, just add --pre when installing the gem:
13
+
14
+ sudo gem install koala --pre
15
+
10
16
  Graph API
11
17
  ----
12
- The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
18
+ The Graph API is the simple, slick new interface to Facebook's data. Using it with Koala is quite straightforward:
13
19
 
14
20
  graph = Koala::Facebook::GraphAPI.new(oauth_access_token)
15
21
  profile = graph.get_object("me")
16
22
  friends = graph.get_connections("me", "friends")
17
23
  graph.put_object("me", "feed", :message => "I am writing on my wall!")
18
24
 
19
- The response of most requests is the JSON data returned from the Facebook servers as a Hash.
25
+ The response of most requests is the JSON data returned from the Facebook servers as a Hash.
20
26
 
21
27
  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
-
28
+
23
29
  # Returns the feed items for the currently logged-in user as a GraphCollection
24
30
  feed = graph.get_connections("me", "feed")
25
-
31
+
26
32
  # GraphCollection is a sub-class of Array, so you can use it as a usual Array
27
33
  first_entry = feed[0]
28
34
  last_entry = feed.last
@@ -33,7 +39,7 @@ When retrieving data that returns an array of results (for example, when calling
33
39
  # Returns an array describing the URL for the next page: [path, arguments]
34
40
  # This is useful for paging across multiple requests
35
41
  next_path, next_args = feed.next_page_params
36
-
42
+
37
43
  # You can use those params to easily get the next (or prevous) page
38
44
  page = graph.get_page(feed.next_page_params)
39
45
 
@@ -41,15 +47,15 @@ Check out the wiki for more examples.
41
47
 
42
48
  The old-school REST API
43
49
  -----
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.
50
+ 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
51
 
46
52
  Koala now supports the old-school REST API using OAuth access tokens; to use this, instantiate your class using the RestAPI class:
47
53
 
48
54
  @rest = Koala::Facebook::RestAPI.new(oauth_access_token)
49
55
  @rest.fql_query(my_fql_query) # convenience method
50
56
  @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.
57
+
58
+ 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
59
 
54
60
  (If you want the power of both APIs in the palm of your hand, try out the GraphAndRestAPI class.)
55
61
 
@@ -119,7 +125,7 @@ Some resources to help you as you play with Koala and the Graph API:
119
125
  Testing
120
126
  -----
121
127
 
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:
128
+ 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
129
  # From the spec directory
124
130
  spec koala_spec.rb
125
131
 
@@ -127,4 +133,4 @@ You can also run live tests against Facebook's servers:
127
133
  # Again from the spec directory
128
134
  spec koala_spec_without_mocks.rb
129
135
 
130
- Important Note: to run the live tests, you have to provide some of your own data: a valid OAuth access token with publish\_stream and read\_stream permissions and an OAuth code that can be used to generate an access token. You can get these data at the OAuth Playground; if you want to use your own app, remember to swap out the app ID, secret, and other values. (The file also provides valid values for other tests, which you're welcome to swap out for data specific to your own application.)
136
+ Important Note: to run the live tests, you have to provide some of your own data: a valid OAuth access token with publish\_stream, read\_stream, and user\_photos permissions and an OAuth code that can be used to generate an access token. You can get these data at the OAuth Playground; if you want to use your own app, remember to swap out the app ID, secret, and other values. (The file also provides valid values for other tests, which you're welcome to swap out for data specific to your own application.)
@@ -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 read_stream permissions.
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
- it_should_behave_like "Koala RestAPI with an access token"
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,39 +39,27 @@ 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
- # API
93
- it "should never use the rest api server" do
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
 
105
52
  class FacebookNoAccessTokenTests < Test::Unit::TestCase
106
53
  describe "Koala GraphAPI without an access token" do
54
+ include LiveTestingDataHelper
55
+
107
56
  before :each do
108
57
  @api = Koala::Facebook::GraphAPI.new
109
- end
110
-
58
+ end
59
+
60
+ it_should_behave_like "Koala GraphAPI"
111
61
  it_should_behave_like "Koala GraphAPI without an access token"
62
+ it_should_behave_like "Koala GraphAPI with GraphCollection"
63
+
112
64
  end
113
65
  end
114
-