koala 1.2.1 → 1.3.0rc1

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --order rand
data/CHANGELOG CHANGED
@@ -1,3 +1,21 @@
1
+ v1.3
2
+ New methods:
3
+ -- OAuth#url_for_dialog creates URLs for Facebook dialog pages
4
+ -- API#set_app_restrictions handles JSON-encoding app restrictions
5
+ -- GraphCollection.parse_page_url now exposes useful functionality for non-Rails apps
6
+ Updated methods:
7
+ -- OAuth#url_for_access_token and #url_for_oauth_code now include any provided options as URL parameters
8
+ -- APIError#raw_response allows access to the raw error response received from Facebook
9
+ -- Utils.deprecate only prints each message once (no more spamming)
10
+ -- API#get_page_access_token now accepts additional arguments and HTTP options (like other calls)
11
+ Internal improvements:
12
+ -- FQL queries now use the Graph API behind-the-scenes
13
+ Testing improvements:
14
+ -- Expanded/improved test coverage
15
+ -- The test suite no longer users any hard-coded user IDs
16
+ -- KoalaTest.test_user_api allows access to the TestUsers instance
17
+ -- Configured tests to run in random order using RSpec 2.8.0rc1
18
+
1
19
  v1.2.1
2
20
  New methods:
3
21
  -- RestAPI.set_app_properties handles JSON-encoding application properties
@@ -32,17 +32,17 @@ Gem::Specification.new do |s|
32
32
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
33
33
  s.add_runtime_dependency(%q<multi_json>, ["~> 1.0"])
34
34
  s.add_runtime_dependency(%q<faraday>, ["~> 0.7.0"])
35
- s.add_development_dependency(%q<rspec>, ["~> 2.5"])
35
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0rc1"])
36
36
  s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
37
37
  else
38
38
  s.add_dependency(%q<multi_json>, ["~> 1.0"])
39
- s.add_dependency(%q<rspec>, ["~> 2.5"])
39
+ s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
40
40
  s.add_dependency(%q<rake>, ["~> 0.8.7"])
41
41
  s.add_dependency(%q<faraday>, ["~> 0.7.0"])
42
42
  end
43
43
  else
44
44
  s.add_dependency(%q<multi_json>, ["~> 1.0"])
45
- s.add_dependency(%q<rspec>, ["~> 2.5"])
45
+ s.add_dependency(%q<rspec>, ["~> 2.8.0rc1"])
46
46
  s.add_dependency(%q<rake>, ["~> 0.8.7"])
47
47
  s.add_dependency(%q<faraday>, ["~> 0.7.0"])
48
48
  end
@@ -100,8 +100,9 @@ module Koala
100
100
  # Errors
101
101
 
102
102
  class APIError < StandardError
103
- attr_accessor :fb_error_type
103
+ attr_accessor :fb_error_type, :raw_response
104
104
  def initialize(details = {})
105
+ self.raw_response = details
105
106
  self.fb_error_type = details["type"]
106
107
  super("#{fb_error_type}: #{details["message"]}")
107
108
  end
@@ -176,9 +176,24 @@ module Koala
176
176
  end
177
177
 
178
178
  # Convenience Methods
179
+ #
180
+ # in general, we're trying to avoid adding convenience methods to Koala
181
+ # except to support cases where the Facebook API requires non-standard input
182
+ # such as JSON-encoding arguments, posts directly to objects, etc.
183
+
184
+ def fql_query(query, args = {}, options = {})
185
+ get_object("fql", args.merge(:q => query), options)
186
+ end
179
187
 
180
- def get_page_access_token(object_id)
181
- result = get_object(object_id, :fields => "access_token") do
188
+ def fql_multiquery(queries = {}, args = {}, options = {})
189
+ if results = get_object("fql", args.merge(:q => MultiJson.encode(queries)), options)
190
+ # simplify the multiquery result format
191
+ results.inject({}) {|outcome, data| outcome[data["name"]] = data["fql_result_set"]; outcome}
192
+ end
193
+ end
194
+
195
+ def get_page_access_token(object_id, args = {}, options = {})
196
+ result = get_object(object_id, args.merge(:fields => "access_token"), options) do
182
197
  result ? result["access_token"] : nil
183
198
  end
184
199
  end
@@ -190,6 +205,10 @@ module Koala
190
205
  args.merge!(:ids => urls.respond_to?(:join) ? urls.join(",") : urls)
191
206
  get_object("comments", args, options)
192
207
  end
208
+
209
+ def set_app_restrictions(app_id, restrictions_hash, args = {}, options = {})
210
+ graph_call(app_id, args.merge(:restrictions => MultiJson.encode(restrictions_hash)), "post", options)
211
+ end
193
212
 
194
213
  # GraphCollection support
195
214
  def get_page(params)
@@ -38,7 +38,8 @@ module Koala
38
38
 
39
39
  def check_graph_batch_api_response(response)
40
40
  if response.is_a?(Hash) && response["error"] && !response["error"].is_a?(Hash)
41
- APIError.new("type" => "Error #{response["error"]}", "message" => response["error_description"])
41
+ # old error format -- see http://developers.facebook.com/blog/post/596/
42
+ APIError.new({"type" => "Error #{response["error"]}", "message" => response["error_description"]}.merge(response))
42
43
  else
43
44
  check_graph_api_response(response)
44
45
  end
@@ -41,8 +41,12 @@ module Koala
41
41
  parse_page_url(@paging[this])
42
42
  end
43
43
  end
44
-
44
+
45
45
  def parse_page_url(url)
46
+ GraphCollection.parse_page_url(url)
47
+ end
48
+
49
+ def self.parse_page_url(url)
46
50
  match = url.match(/.com\/(.*)\?(.*)/)
47
51
  base = match[1]
48
52
  args = match[2]
@@ -11,9 +11,8 @@ module Koala
11
11
  end
12
12
 
13
13
  module HTTPService
14
- # common functionality for all HTTP services
15
-
16
14
  class << self
15
+
17
16
  attr_accessor :faraday_middleware, :http_options
18
17
  end
19
18
 
@@ -1,5 +1,8 @@
1
1
  module Koala
2
2
  module Facebook
3
+
4
+ DIALOG_HOST = "www.facebook.com"
5
+
3
6
  class OAuth
4
7
  attr_reader :app_id, :app_secret, :oauth_callback_url
5
8
  def initialize(app_id, app_secret, oauth_callback_url = nil)
@@ -7,7 +10,7 @@ module Koala
7
10
  @app_secret = app_secret
8
11
  @oauth_callback_url = oauth_callback_url
9
12
  end
10
-
13
+
11
14
  def get_user_info_from_cookie(cookie_hash)
12
15
  # Parses the cookie set Facebook's JavaScript SDK.
13
16
  # You can pass Rack/Rails/Sinatra's cookie hash directly to this method.
@@ -34,27 +37,36 @@ module Koala
34
37
  alias_method :get_user_from_cookies, :get_user_from_cookie
35
38
 
36
39
  # URLs
37
-
40
+
38
41
  def url_for_oauth_code(options = {})
39
42
  # for permissions, see http://developers.facebook.com/docs/authentication/permissions
40
- permissions = options[:permissions]
41
- scope = permissions ? "&scope=#{permissions.is_a?(Array) ? permissions.join(",") : permissions}" : ""
42
- display = options.has_key?(:display) ? "&display=#{options[:display]}" : ""
43
-
44
- callback = options[:callback] || @oauth_callback_url
45
- raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback
46
-
43
+ if permissions = options.delete(:permissions)
44
+ options[:scope] = permissions.is_a?(Array) ? permissions.join(",") : permissions
45
+ end
46
+ url_options = {:client_id => @app_id}.merge(options)
47
+
47
48
  # Creates the URL for oauth authorization for a given callback and optional set of permissions
48
- "https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}#{display}"
49
+ build_url("https://#{GRAPH_SERVER}/oauth/authorize", true, url_options)
49
50
  end
50
51
 
51
52
  def url_for_access_token(code, options = {})
52
53
  # Creates the URL for the token corresponding to a given code generated by Facebook
53
- callback = options[:callback] || @oauth_callback_url
54
- raise ArgumentError, "url_for_access_token must get a callback either from the OAuth object or in the parameters!" unless callback
55
- "https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
54
+ url_options = {
55
+ :client_id => @app_id,
56
+ :code => code,
57
+ :client_secret => @app_secret
58
+ }.merge(options)
59
+ build_url("https://#{GRAPH_SERVER}/oauth/access_token", true, url_options)
56
60
  end
57
61
 
62
+ def url_for_dialog(dialog_type, options = {})
63
+ # some endpoints require app_id, some client_id, supply both doesn't seem to hurt
64
+ url_options = {:app_id => @app_id, :client_id => @app_id}.merge(options)
65
+ build_url("http://#{DIALOG_HOST}/dialog/#{dialog_type}", true, url_options)
66
+ end
67
+
68
+ # access tokens
69
+
58
70
  def get_access_token_info(code, options = {})
59
71
  # convenience method to get a parsed token from Facebook for a given code
60
72
  # should this require an OAuth callback URL?
@@ -189,6 +201,14 @@ module Koala
189
201
  str += '=' * (4 - str.length.modulo(4))
190
202
  Base64.decode64(str.tr('-_', '+/'))
191
203
  end
204
+
205
+ def build_url(base, require_redirect_uri = false, url_options = {})
206
+ if require_redirect_uri && !(url_options[:redirect_uri] ||= url_options.delete(:callback) || @oauth_callback_url)
207
+ raise ArgumentError, "url_for_dialog must get a callback either from the OAuth object or in the parameters!"
208
+ end
209
+
210
+ "#{base}?#{Koala::HTTPService.encode_params(url_options)}"
211
+ end
192
212
  end
193
213
  end
194
214
  end
@@ -2,18 +2,7 @@ module Koala
2
2
  module Facebook
3
3
  REST_SERVER = "api.facebook.com"
4
4
 
5
- module RestAPIMethods
6
- def fql_query(fql, args = {}, options = {})
7
- rest_call('fql.query', args.merge(:query => fql), options)
8
- end
9
-
10
- def fql_multiquery(queries = {}, args = {}, options = {})
11
- if results = rest_call('fql.multiquery', args.merge(:queries => MultiJson.encode(queries)), options)
12
- # simplify the multiquery result format
13
- results.inject({}) {|outcome, data| outcome[data["name"]] = data["fql_result_set"]; outcome}
14
- end
15
- end
16
-
5
+ module RestAPIMethods
17
6
  def set_app_properties(properties, args = {}, options = {})
18
7
  raise APIError.new({"type" => "KoalaMissingAccessToken", "message" => "setAppProperties requires an access token"}) unless @access_token
19
8
  rest_call("admin.setAppProperties", args.merge(:properties => MultiJson.encode(properties)), options, "post")
@@ -1,10 +1,13 @@
1
1
  module Koala
2
2
  module Utils
3
+
4
+ DEPRECATION_PREFIX = "KOALA: Deprecation warning: "
3
5
  def self.deprecate(message)
4
- begin
5
- send(:warn, "KOALA: Deprecation warning: #{message}")
6
- rescue Exception => err
7
- puts "Unable to issue Koala deprecation warning! #{err.message}"
6
+ @posted_deprecations ||= []
7
+ unless @posted_deprecations.include?(message)
8
+ # only include each message once
9
+ Kernel.warn("#{DEPRECATION_PREFIX}#{message}")
10
+ @posted_deprecations << message
8
11
  end
9
12
  end
10
13
  end
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0rc1"
3
3
  end
data/readme.md CHANGED
@@ -6,13 +6,8 @@ Koala
6
6
 
7
7
  * Lightweight: Koala should be as light and simple as Facebook’s own libraries, providing API accessors and returning simple JSON.
8
8
  * Fast: Koala should, out of the box, be quick. Out of the box, we use Facebook's faster read-only servers when possible and if available, the Typhoeus gem to make snappy Facebook requests. Of course, that brings us to our next topic:
9
- * Flexible: Koala should be useful to everyone, regardless of their current configuration. (We support JRuby, Rubinius, and REE as well as vanilla Ruby, and use the Faraday library to provide complete flexibility over how HTTP requests are made.)
10
- * Tested: Koala should have complete test coverage, so you can rely on it. (Our test coverage is complete and can be run against either mocked responses or the live Facebook servers.)
11
-
12
- Facebook Changes on October 1, 2011
13
- ---
14
-
15
- Koala 1.2 supports all of Facebook's new authentication schemes, which were introduced on October 1, 2011. If you have the appropriate calls to get_user_info_from_cookies (apps using the Javascript SDK) and/or parse_signed_params (for Canvas and tab apps), your application should work without a hitch. For more information, see Facebook's [OAuth 2.0 and HTTPS Migration](https://developers.facebook.com/docs/oauth2-https-migration/) guide.
9
+ * Flexible: Koala should be useful to everyone, regardless of their current configuration. We support JRuby, Rubinius, and REE as well as vanilla Ruby (1.8.7, 1.9.2, and 1.9.3), and use the Faraday library to provide complete flexibility over how HTTP requests are made.
10
+ * Tested: Koala should have complete test coverage, so you can rely on it. Our test coverage is complete and can be run against either mocked responses or the live Facebook servers; we're also on [Travis CI](travis-ci.org/arsduo/koala/).
16
11
 
17
12
  Installation
18
13
  ---
@@ -35,7 +30,10 @@ The Graph API is the simple, slick new interface to Facebook's data. Using it w
35
30
  profile = @graph.get_object("me")
36
31
  friends = @graph.get_connections("me", "friends")
37
32
  @graph.put_object("me", "feed", :message => "I am writing on my wall!")
38
-
33
+
34
+ # three-part queries are easy too!
35
+ @graph.get_connection("me", "mutualfriends/#{friend_id}")
36
+
39
37
  # you can even use the new Timeline API
40
38
  # see https://developers.facebook.com/docs/beta/opengraph/tutorial/
41
39
  @graph.put_connections("me", "namespace:action", :object => object_url)
@@ -131,7 +129,7 @@ Koala makes it easy to interact with your applications using the RealtimeUpdates
131
129
  You can do just about anything with your real-time update subscriptions using the RealtimeUpdates class:
132
130
 
133
131
  # Add/modify a subscription to updates for when the first_name or last_name fields of any of your users is changed
134
- @updates.subscribe("user", "first_name, last_name", callback_token, verify_token)
132
+ @updates.subscribe("user", "first_name, last_name", callback_url, verify_token)
135
133
 
136
134
  # Get an array of your current subscriptions (one hash for each object you've subscribed to)
137
135
  @updates.list_subscriptions
@@ -179,6 +177,8 @@ Some resources to help you as you play with Koala and the Graph API:
179
177
  * The <a href="http://groups.google.com/group/koala-users">Koala users group</a> on Google Groups, the place for your Koala and API questions
180
178
  * Facebook's <a href="http://developers.facebook.com/tools/explorer/">Graph API Explorer</a>, where you can play with the Graph API in your browser
181
179
  * The Koala-powered <a href="http://oauth.twoalex.com" target="_blank">OAuth Playground</a>, where you can easily generate OAuth access tokens and any other data needed to test out the APIs or OAuth
180
+ * Follow Koala on <a href="http://www.facebook.com/pages/Koala/315368291823667">Facebook</a> and <a href="https://twitter.com/#!/koala_fb">Twitter</a> for SDK updates and occasional news about Facebook API changes.
181
+
182
182
 
183
183
  Testing
184
184
  -----
@@ -10,6 +10,16 @@ describe Koala::Facebook::APIError do
10
10
  Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:fb_error_type=)
11
11
  end
12
12
 
13
+ it "has an accessor for raw_response" do
14
+ Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:raw_response)
15
+ Koala::Facebook::APIError.instance_methods.map(&:to_sym).should include(:raw_response=)
16
+ end
17
+
18
+ it "sets raw_response to the provided error details" do
19
+ error_response = {"type" => "foo", "other_details" => "bar"}
20
+ Koala::Facebook::APIError.new(error_response).raw_response.should == error_response
21
+ end
22
+
13
23
  it "sets fb_error_type to details['type']" do
14
24
  type = "foo"
15
25
  Koala::Facebook::APIError.new("type" => type).fb_error_type.should == type
@@ -22,7 +22,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
22
22
  }
23
23
  end
24
24
 
25
- describe "#new" do
25
+ describe ".new" do
26
26
  it "makes http_options accessible" do
27
27
  Koala::Facebook::BatchOperation.new(@args).http_options.should == @args[:http_options]
28
28
  end
@@ -108,7 +108,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
108
108
 
109
109
  end
110
110
 
111
- describe ".to_batch_params" do
111
+ describe "#to_batch_params" do
112
112
  describe "handling arguments and URLs" do
113
113
  shared_examples_for "request with no body" do
114
114
  it "adds the args to the URL string, with ? if no args previously present" do
@@ -263,7 +263,6 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
263
263
  end
264
264
 
265
265
  describe "GraphAPI batch interface" do
266
-
267
266
  it "returns nothing for a batch operation" do
268
267
  Koala.stub(:make_request).and_return(Koala::Response.new(200, "[]", {}))
269
268
  @api.batch do |batch_api|
@@ -366,18 +365,69 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
366
365
  end
367
366
 
368
367
  describe "processing the request" do
369
- it "throws an error if the response is not 200" do
370
- Koala.stub(:make_request).and_return(Koala::Response.new(500, "[]", {}))
371
- expect { Koala::Facebook::API.new("foo").batch do |batch_api|
372
- batch_api.get_object('me')
373
- end }.to raise_exception(Koala::Facebook::APIError)
368
+ it "returns the result headers as a hash if http_component is headers" do
369
+ Koala.stub(:make_request).and_return(Koala::Response.new(200, '[{"code":203,"headers":[{"name":"Content-Type","value":"text/javascript; charset=UTF-8"}],"body":"{\"id\":\"1234\"}"}]', {}))
370
+ result = @api.batch do |batch_api|
371
+ batch_api.get_object(KoalaTest.user1, {}, :http_component => :headers)
372
+ end
373
+ result[0].should == {"Content-Type" => "text/javascript; charset=UTF-8"}
374
374
  end
375
+
376
+ describe "if it errors" do
377
+ it "raises an APIError if the response is not 200" do
378
+ Koala.stub(:make_request).and_return(Koala::Response.new(500, "[]", {}))
379
+ expect {
380
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
381
+ }.to raise_exception(Koala::Facebook::APIError)
382
+ end
375
383
 
376
- it "throws an error if the response is a Batch API-style error" do
377
- Koala.stub(:make_request).and_return(Koala::Response.new(200, '{"error":190,"error_description":"Error validating access token."}', {}))
378
- expect { Koala::Facebook::API.new("foo").batch do |batch_api|
379
- batch_api.get_object('me')
380
- end }.to raise_exception(Koala::Facebook::APIError)
384
+ context "with the old style" do
385
+ before :each do
386
+ Koala.stub(:make_request).and_return(Koala::Response.new(200, '{"error":190,"error_description":"Error validating access token."}', {}))
387
+ end
388
+
389
+ it "throws an error if the response is an old Batch API-style error" do
390
+ expect {
391
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
392
+ }.to raise_exception(Koala::Facebook::APIError)
393
+ end
394
+
395
+ it "provides a type for the error if the response is an old Batch API-style error" do
396
+ begin
397
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
398
+ rescue Koala::Facebook::APIError => err
399
+ end
400
+ err.fb_error_type.should
401
+ end
402
+
403
+ it "passes all the error details if an old Batch API-style error is raised" do
404
+ begin
405
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
406
+ rescue Koala::Facebook::APIError => err
407
+ end
408
+ err.raw_response["error"].should == 190
409
+ end
410
+ end
411
+
412
+ context "with the new style" do
413
+ before :each do
414
+ Koala.stub(:make_request).and_return(Koala::Response.new(200, '{"error":{"message":"Request 0 cannot depend on an unresolved request with name f. Requests can only depend on preceding requests","type":"GraphBatchException"}}', {}))
415
+ end
416
+
417
+ it "throws an error if the response is a new Graph API-style error" do
418
+ expect {
419
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
420
+ }.to raise_exception(Koala::Facebook::APIError)
421
+ end
422
+
423
+ it "passes all the error details if an old Batch API-style error is raised" do
424
+ begin
425
+ Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
426
+ rescue Koala::Facebook::APIError => err
427
+ end
428
+ err.raw_response["message"].should
429
+ end
430
+ end
381
431
  end
382
432
 
383
433
  it "returns the result status if http_component is status" do
@@ -387,14 +437,6 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
387
437
  end
388
438
  result[0].should == 203
389
439
  end
390
-
391
- it "returns the result headers as a hash if http_component is headers" do
392
- Koala.stub(:make_request).and_return(Koala::Response.new(200, '[{"code":203,"headers":[{"name":"Content-Type","value":"text/javascript; charset=UTF-8"}],"body":"{\"id\":\"1234\"}"}]', {}))
393
- result = @api.batch do |batch_api|
394
- batch_api.get_object(KoalaTest.user1, {}, :http_component => :headers)
395
- end
396
- result[0].should == {"Content-Type" => "text/javascript; charset=UTF-8"}
397
- end
398
440
  end
399
441
 
400
442
  it "is thread safe" do
@@ -74,18 +74,34 @@ describe Koala::Facebook::GraphCollection do
74
74
  end
75
75
 
76
76
  describe "when parsing page paramters" do
77
- it "should return the base as the first array entry" do
78
- base = "url_path"
79
- @collection.parse_page_url("anything.com/#{base}?anything").first.should == base
77
+ describe "#parse_page_url" do
78
+ it "should pass the url to the class method" do
79
+ url = stub("url")
80
+ Koala::Facebook::GraphCollection.should_receive(:parse_page_url).with(url)
81
+ @collection.parse_page_url(url)
82
+ end
83
+
84
+ it "should return the result of the class method" do
85
+ parsed_content = stub("parsed_content")
86
+ Koala::Facebook::GraphCollection.stub(:parse_page_url).and_return(parsed_content)
87
+ @collection.parse_page_url(stub("url")).should == parsed_content
88
+ end
80
89
  end
90
+
91
+ describe ".parse_page_url" do
92
+ it "should return the base as the first array entry" do
93
+ base = "url_path"
94
+ Koala::Facebook::GraphCollection.parse_page_url("anything.com/#{base}?anything").first.should == base
95
+ end
81
96
 
82
- it "should return the arguments as a hash as the last array entry" do
83
- args_hash = {"one" => "val_one", "two" => "val_two"}
84
- @collection.parse_page_url("anything.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
97
+ it "should return the arguments as a hash as the last array entry" do
98
+ args_hash = {"one" => "val_one", "two" => "val_two"}
99
+ Koala::Facebook::GraphCollection.parse_page_url("anything.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
100
+ end
85
101
  end
86
102
  end
87
103
 
88
- describe "#evaluate" do
104
+ describe ".evaluate" do
89
105
  it "returns the original result if it's provided a non-hash result" do
90
106
  result = []
91
107
  Koala::Facebook::GraphCollection.evaluate(result, @api).should == result