koala 1.2.0beta3 → 1.2.0beta4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -4,10 +4,15 @@ New methods:
4
4
  -- Old classes are aliased with deprecation warnings (non-breaking change)
5
5
  -- TestUsers#update lets you update the name or password of an existing test user
6
6
  -- API.get_page_access_token lets you easily fetch the access token for a page you manage (thanks, marcgg!)
7
+ -- Added version.rb (Koala::VERSION)
7
8
  Updated methods:
8
9
  -- OAuth now parses Facebook's new signed cookie format
9
10
  -- API.put_picture now accepts URLs to images (thanks, marcgg!)
10
11
  -- Bug fixes to put_picture, parse_signed_request, and the test suite (thanks, johnbhall and Will S.!)
12
+ -- Smarter GraphCollection use
13
+ -- Any pageable result will now become a GraphCollection
14
+ -- Non-pageable results from get_connections no longer error
15
+ -- GraphCollection.raw_results allows access to original result data
11
16
  Internal improvements:
12
17
  -- Koala now uses Faraday to make requests, replacing the HTTPServices (see wiki)
13
18
  -- Koala::HTTPService.http_options allows specification of default Faraday connection options
@@ -17,6 +22,7 @@ Internal improvements:
17
22
  -- Koala no longer automatically switches to Net::HTTP when uploading IO objects to Facebook
18
23
  -- RealTimeUpdates and TestUsers are no longer subclasses of API, but have their own .api objects
19
24
  -- The old .graph_api accessor is aliases to .api with a deprecation warning
25
+ -- Removed deprecation warnings for pre-1.1 batch interface
20
26
  Testing improvements:
21
27
  -- Live test suites now run against test users by default
22
28
  -- Test suite can be repeatedly run live without having to update facebook_data.yml
@@ -24,7 +30,7 @@ Testing improvements:
24
30
  -- Faraday adapter for live tests can be specified with ADAPTER=[your adapter] in the rspec command
25
31
  -- Live tests can be run against the beta server by specifying BETA=true in the rspec command
26
32
  -- Tests now pass against all rubies on Travis CI
27
- -- Expanded test coverage
33
+ -- Expanded and refactored test coverage
28
34
  -- Fixed bug with YAML parsing in Ruby 1.9
29
35
 
30
36
  v1.1
data/koala.gemspec CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{koala}
5
- s.version = "1.2.0beta3"
6
- s.date = %q{2011-09-12}
5
+ s.version = "1.2.0beta4"
6
+ s.date = %q{2011-09-21}
7
7
 
8
8
  s.summary = %q{A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication.}
9
9
  s.description = %q{Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.}
data/lib/koala.rb CHANGED
@@ -8,7 +8,6 @@ require 'openssl'
8
8
  require 'base64'
9
9
 
10
10
  # include koala modules
11
- require 'koala/http_service'
12
11
  require 'koala/oauth'
13
12
  require 'koala/graph_api'
14
13
  require 'koala/graph_batch_api'
@@ -17,11 +16,17 @@ require 'koala/graph_collection'
17
16
  require 'koala/rest_api'
18
17
  require 'koala/realtime_updates'
19
18
  require 'koala/test_users'
20
- require 'koala/utils'
19
+
20
+ # HTTP module so we can communicate with Facebook
21
+ require 'koala/http_service'
21
22
 
22
23
  # add KoalaIO class
23
24
  require 'koala/uploadable_io'
24
25
 
26
+ # miscellaneous
27
+ require 'koala/utils'
28
+ require 'koala/version'
29
+
25
30
  module Koala
26
31
 
27
32
  module Facebook
@@ -71,9 +71,7 @@ module Koala
71
71
 
72
72
  def get_connections(id, connection_name, args = {}, options = {})
73
73
  # Fetchs the connections for given object.
74
- graph_call("#{id}/#{connection_name}", args, "get", options) do |result|
75
- result ? GraphCollection.new(result, self) : nil # when facebook is down nil can be returned
76
- end
74
+ graph_call("#{id}/#{connection_name}", args, "get", options)
77
75
  end
78
76
 
79
77
  def put_connections(id, connection_name, args = {}, options = {})
@@ -174,9 +172,7 @@ module Koala
174
172
 
175
173
  def search(search_terms, args = {}, options = {})
176
174
  args.merge!({:q => search_terms}) unless search_terms.nil?
177
- graph_call("search", args, "get", options) do |result|
178
- result ? GraphCollection.new(result, self) : nil # when facebook is down nil can be returned
179
- end
175
+ graph_call("search", args, "get", options)
180
176
  end
181
177
 
182
178
  # Convenience Methods
@@ -199,14 +195,12 @@ module Koala
199
195
  def get_page(params)
200
196
  # Pages through a set of results stored in a GraphCollection
201
197
  # Used for connections and search results
202
- graph_call(*params) do |result|
203
- result ? GraphCollection.new(result, self) : nil # when facebook is down nil can be returned
204
- end
198
+ graph_call(*params)
205
199
  end
206
200
 
207
201
  # Batch API
208
202
  def batch(http_options = {}, &block)
209
- batch_client = GraphBatchAPI.new(access_token)
203
+ batch_client = GraphBatchAPI.new(access_token, self)
210
204
  if block
211
205
  yield batch_client
212
206
  batch_client.execute(http_options)
@@ -214,15 +208,7 @@ module Koala
214
208
  batch_client
215
209
  end
216
210
  end
217
-
218
- def self.included(base)
219
- base.class_eval do
220
- def self.batch
221
- raise NoMethodError, "The BatchAPI signature has changed (the original implementation was not thread-safe). Please see https://github.com/arsduo/koala/wiki/Batch-requests. (This message will be removed in the final 1.1 release.)"
222
- end
223
- end
224
- end
225
-
211
+
226
212
  # Direct access to the Facebook API
227
213
  # see any of the above methods for example invocations
228
214
  def graph_call(path, args = {}, verb = "get", options = {}, &post_processing)
@@ -231,10 +217,15 @@ module Koala
231
217
  raise error if error
232
218
  end
233
219
 
234
- # now process as appropriate (get picture header, make GraphCollection, etc.)
220
+ # turn this into a GraphCollection if it's pageable
221
+ result = GraphCollection.evaluate(result, self)
222
+
223
+ # now process as appropriate for the given call (get picture header, etc.)
235
224
  post_processing ? post_processing.call(result) : result
236
225
  end
237
226
 
227
+ private
228
+
238
229
  def check_response(response)
239
230
  # check for Graph API-specific errors
240
231
  # this returns an error, which is immediately raised (non-batch)
@@ -244,8 +235,6 @@ module Koala
244
235
  end
245
236
  end
246
237
 
247
- private
248
-
249
238
  def parse_media_args(media_args, method)
250
239
  # photo and video uploads can accept different types of arguments (see above)
251
240
  # so here, we parse the arguments into a form directly usable in put_object
@@ -4,6 +4,13 @@ module Koala
4
4
 
5
5
  def self.included(base)
6
6
  base.class_eval do
7
+ attr_reader :original_api
8
+
9
+ def initialize(access_token, api)
10
+ super(access_token)
11
+ @original_api = api
12
+ end
13
+
7
14
  alias_method :graph_call_outside_batch, :graph_call
8
15
  alias_method :graph_call, :graph_call_in_batch
9
16
 
@@ -46,7 +53,7 @@ module Koala
46
53
  batch_op.to_batch_params(access_token)
47
54
  })
48
55
 
49
- graph_call_outside_batch('/', args, 'post', http_options) do |response|
56
+ batch_result = graph_call_outside_batch('/', args, 'post', http_options) do |response|
50
57
  # map the results with post-processing included
51
58
  index = 0 # keep compat with ruby 1.8 - no with_index for map
52
59
  response.map do |call_result|
@@ -80,6 +87,9 @@ module Koala
80
87
  end
81
88
  end
82
89
  end
90
+
91
+ # turn any results that are pageable into GraphCollections
92
+ batch_result.inject([]) {|processed_results, raw| processed_results << GraphCollection.evaluate(raw, @original_api)}
83
93
  end
84
94
 
85
95
  end
@@ -10,12 +10,17 @@ module Koala
10
10
  # It also allows access to paging information and the
11
11
  # ability to get the next/previous page in the collection
12
12
  # by calling next_page or previous_page.
13
- attr_reader :paging
14
- attr_reader :api
13
+ attr_reader :paging, :api, :raw_response
15
14
 
15
+ def self.evaluate(response, api)
16
+ # turn the response into a GraphCollection if it's pageable; if not, return the original response
17
+ response.is_a?(Hash) && response["data"].is_a?(Array) ? self.new(response, api) : response
18
+ end
19
+
16
20
  def initialize(response, api)
17
21
  super response["data"]
18
22
  @paging = response["paging"]
23
+ @raw_response = response
19
24
  @api = api
20
25
  end
21
26
 
@@ -71,7 +71,7 @@ module Koala
71
71
  end
72
72
 
73
73
  def list_subscriptions
74
- @graph_api.graph_call(subscription_path)["data"]
74
+ @graph_api.graph_call(subscription_path)
75
75
  end
76
76
 
77
77
  def graph_api
@@ -35,7 +35,7 @@ module Koala
35
35
  end
36
36
 
37
37
  def list
38
- @api.graph_call(accounts_path)["data"]
38
+ @api.graph_call(accounts_path)
39
39
  end
40
40
 
41
41
  def delete(test_user)
@@ -72,7 +72,6 @@ module Koala
72
72
  end
73
73
 
74
74
  def create_network(network_size, installed = true, permissions = '')
75
- network_size = 50 if network_size > 50 # FB's max is 50
76
75
  users = (0...network_size).collect { create(installed, permissions) }
77
76
  friends = users.clone
78
77
  users.each do |user|
@@ -0,0 +1,3 @@
1
+ module Koala
2
+ VERSION = "1.2.0beta4"
3
+ end
@@ -98,4 +98,29 @@ describe "Koala::Facebook::API" do
98
98
  end
99
99
  end
100
100
 
101
+ describe "with an access token" do
102
+ before(:each) do
103
+ @api = Koala::Facebook::API.new(@token)
104
+ end
105
+
106
+ it_should_behave_like "Koala RestAPI"
107
+ it_should_behave_like "Koala RestAPI with an access token"
108
+
109
+ it_should_behave_like "Koala GraphAPI"
110
+ it_should_behave_like "Koala GraphAPI with an access token"
111
+ it_should_behave_like "Koala GraphAPI with GraphCollection"
112
+ end
113
+
114
+ describe "without an access token" do
115
+ before(:each) do
116
+ @api = Koala::Facebook::API.new
117
+ end
118
+
119
+ it_should_behave_like "Koala RestAPI"
120
+ it_should_behave_like "Koala RestAPI without an access token"
121
+
122
+ it_should_behave_like "Koala GraphAPI"
123
+ it_should_behave_like "Koala GraphAPI without an access token"
124
+ it_should_behave_like "Koala GraphAPI with GraphCollection"
125
+ end
101
126
  end
@@ -19,30 +19,4 @@ describe "Koala::Facebook::GraphAndRestAPI" do
19
19
  api = Koala::Facebook::GraphAndRestAPI.new("token")
20
20
  end
21
21
  end
22
-
23
- describe "with an access token" do
24
- before(:each) do
25
- @api = Koala::Facebook::API.new(@token)
26
- end
27
-
28
- it_should_behave_like "Koala RestAPI"
29
- it_should_behave_like "Koala RestAPI with an access token"
30
-
31
- it_should_behave_like "Koala GraphAPI"
32
- it_should_behave_like "Koala GraphAPI with an access token"
33
- it_should_behave_like "Koala GraphAPI with GraphCollection"
34
- end
35
-
36
- describe "without an access token" do
37
- before(:each) do
38
- @api = Koala::Facebook::API.new
39
- end
40
-
41
- it_should_behave_like "Koala RestAPI"
42
- it_should_behave_like "Koala RestAPI without an access token"
43
-
44
- it_should_behave_like "Koala GraphAPI"
45
- it_should_behave_like "Koala GraphAPI without an access token"
46
- it_should_behave_like "Koala GraphAPI with GraphCollection"
47
- end
48
22
  end
@@ -430,7 +430,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
430
430
  end
431
431
 
432
432
  describe "usage tests" do
433
- it "can get two results at once" do
433
+ it "gets two results at once" do
434
434
  me, koppel = @api.batch do |batch_api|
435
435
  batch_api.get_object('me')
436
436
  batch_api.get_object(KoalaTest.user1)
@@ -439,7 +439,15 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
439
439
  koppel['id'].should_not be_nil
440
440
  end
441
441
 
442
- it 'should be able to make mixed calls inside of a batch' do
442
+ it 'makes mixed calls inside of a batch' do
443
+ me, friends = @api.batch do |batch_api|
444
+ batch_api.get_object('me')
445
+ batch_api.get_connections('me', 'friends')
446
+ end
447
+ friends.should be_a(Koala::Facebook::GraphCollection)
448
+ end
449
+
450
+ it 'turns pageable results into GraphCollections' do
443
451
  me, friends = @api.batch do |batch_api|
444
452
  batch_api.get_object('me')
445
453
  batch_api.get_connections('me', 'friends')
@@ -448,14 +456,14 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
448
456
  friends.should be_an(Array)
449
457
  end
450
458
 
451
- it 'should be able to make a get_picture call inside of a batch' do
459
+ it 'makes a get_picture call inside of a batch' do
452
460
  pictures = @api.batch do |batch_api|
453
461
  batch_api.get_picture('me')
454
462
  end
455
463
  pictures.first.should_not be_empty
456
464
  end
457
465
 
458
- it "should handle requests for two different tokens" do
466
+ it "handles requests for two different tokens" do
459
467
  me, insights = @api.batch do |batch_api|
460
468
  batch_api.get_object('me')
461
469
  batch_api.get_connections(@app_id, 'insights', {}, {"access_token" => @app_api.access_token})
@@ -571,30 +579,4 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
571
579
  end
572
580
  end
573
581
  end
574
-
575
- describe "new interface" do
576
- it "includes a deprecation warning on GraphAPI" do
577
- begin
578
- Koala::Facebook::GraphAPI.batch do
579
- end
580
- rescue NoMethodError => @err
581
- end
582
-
583
- # verify the message points people to the wiki page
584
- @err.should
585
- @err.message.should =~ /https\:\/\/github.com\/arsduo\/koala\/wiki\/Batch-requests/
586
- end
587
-
588
- it "includes a deprecation warning on GraphAndRESTAPI" do
589
- begin
590
- Koala::Facebook::GraphAndRestAPI.batch do
591
- end
592
- rescue NoMethodError => @err
593
- end
594
-
595
- # verify the message points people to the wiki page
596
- @err.should
597
- @err.message.should =~ /https\:\/\/github.com\/arsduo\/koala\/wiki\/Batch-requests/
598
- end
599
- end
600
582
  end
@@ -19,24 +19,4 @@ describe "Koala::Facebook::GraphAPI" do
19
19
  api = Koala::Facebook::GraphAPI.new("token")
20
20
  end
21
21
  end
22
-
23
- context "with an access token" do
24
- before :each do
25
- @api = Koala::Facebook::API.new(@token)
26
- end
27
-
28
- it_should_behave_like "Koala GraphAPI"
29
- it_should_behave_like "Koala GraphAPI with an access token"
30
- it_should_behave_like "Koala GraphAPI with GraphCollection"
31
- end
32
-
33
- context "without an access token" do
34
- before :each do
35
- @api = Koala::Facebook::API.new
36
- end
37
-
38
- it_should_behave_like "Koala GraphAPI"
39
- it_should_behave_like "Koala GraphAPI without an access token"
40
- it_should_behave_like "Koala GraphAPI with GraphCollection"
41
- end
42
22
  end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe Koala::Facebook::GraphCollection do
4
+ before(:each) do
5
+ @result = {
6
+ "data" => [1, 2, :three],
7
+ "paging" => {:paging => true}
8
+ }
9
+ @api = Koala::Facebook::API.new("123")
10
+ @collection = Koala::Facebook::GraphCollection.new(@result, @api)
11
+ end
12
+
13
+ it "subclasses Array" do
14
+ Koala::Facebook::GraphCollection.ancestors.should include(Array)
15
+ end
16
+
17
+ it "creates an array-like object" do
18
+ Koala::Facebook::GraphCollection.new(@result, @api).should be_an(Array)
19
+ end
20
+
21
+ it "contains the result data" do
22
+ @result["data"].each_with_index {|r, i| @collection[i].should == r}
23
+ end
24
+
25
+ it "has a read-only paging attribute" do
26
+ @collection.methods.map(&:to_sym).should include(:paging)
27
+ @collection.methods.map(&:to_sym).should_not include(:paging=)
28
+ end
29
+
30
+ it "sets paging to results['paging']" do
31
+ @collection.paging.should == @result["paging"]
32
+ end
33
+
34
+ it "sets raw_response to the original results" do
35
+ @collection.raw_response.should == @result
36
+ end
37
+
38
+ it "sets the API to the provided API" do
39
+ @collection.api.should == @api
40
+ end
41
+
42
+ describe "when getting a whole page" do
43
+ before(:each) do
44
+ @second_page = {
45
+ "data" => [:second, :page, :data],
46
+ "paging" => {}
47
+ }
48
+ @base = stub("base")
49
+ @args = stub("args")
50
+ @page_of_results = stub("page of results")
51
+ end
52
+
53
+ it "should return the previous page of results" do
54
+ @collection.should_receive(:previous_page_params).and_return([@base, @args])
55
+ @api.should_receive(:api).with(@base, @args, anything, anything).and_return(@second_page)
56
+ Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
57
+ @collection.previous_page.should == @page_of_results
58
+ end
59
+
60
+ it "should return the next page of results" do
61
+ @collection.should_receive(:next_page_params).and_return([@base, @args])
62
+ @api.should_receive(:api).with(@base, @args, anything, anything).and_return(@second_page)
63
+ Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
64
+
65
+ @collection.next_page.should == @page_of_results
66
+ end
67
+
68
+ it "should return nil it there are no other pages" do
69
+ %w{next previous}.each do |this|
70
+ @collection.should_receive("#{this}_page_params".to_sym).and_return(nil)
71
+ @collection.send("#{this}_page").should == nil
72
+ end
73
+ end
74
+ end
75
+
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
80
+ end
81
+
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
85
+ end
86
+ end
87
+
88
+ describe "#evaluate" do
89
+ it "returns the original result if it's provided a non-hash result" do
90
+ result = []
91
+ Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
92
+ end
93
+
94
+ it "returns the original result if it's provided a nil result" do
95
+ result = nil
96
+ Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
97
+ end
98
+
99
+ it "returns the original result if the result doesn't have a data key" do
100
+ result = {"paging" => {}}
101
+ Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
102
+ end
103
+
104
+ it "returns the original result if the result's data key isn't an array" do
105
+ result = {"data" => {}, "paging" => {}}
106
+ Koala::Facebook::GraphCollection.evaluate(result, @api).should == result
107
+ end
108
+
109
+ it "returns a new GraphCollection of the result if it has an array data key and a paging key" do
110
+ result = {"data" => [], "paging" => {}}
111
+ expected = :foo
112
+ Koala::Facebook::GraphCollection.should_receive(:new).with(result, @api).and_return(expected)
113
+ Koala::Facebook::GraphCollection.evaluate(result, @api).should == expected
114
+ end
115
+ end
116
+ end
@@ -1,6 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Koala" do
4
+ it "has a version" do
5
+ Koala.const_defined?("VERSION").should be_true
6
+ end
7
+
4
8
  it "has an http_service accessor" do
5
9
  Koala.should respond_to(:http_service)
6
10
  Koala.should respond_to(:http_service=)
@@ -13,6 +13,13 @@ describe "Koala::Facebook::TestUsers" do
13
13
  raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
14
14
  end
15
15
  end
16
+
17
+ after :each do
18
+ # clean up any test users
19
+ ((@network || []) + [@user1, @user2]).each do |u|
20
+ puts "Unable to delete test user #{u.inspect}" if u && (!@test_users.delete(u) rescue false)
21
+ end
22
+ end
16
23
 
17
24
  describe "when initializing" do
18
25
  # basic initialization
@@ -131,11 +138,6 @@ describe "Koala::Facebook::TestUsers" do
131
138
  @user2 = @test_users.create(true, "read_stream,user_interests")
132
139
  end
133
140
 
134
- after :each do
135
- @test_users.delete(@user1) if @user1
136
- @test_users.delete(@user2) if @user2
137
- end
138
-
139
141
  it "should delete a user by id" do
140
142
  @test_users.delete(@user1['id']).should be_true
141
143
  @user1 = nil
@@ -191,11 +193,6 @@ describe "Koala::Facebook::TestUsers" do
191
193
  @user2 = @test_users.create(true, "read_stream,user_interests")
192
194
  end
193
195
 
194
- after :each do
195
- @test_users.delete(@user1)
196
- @test_users.delete(@user2)
197
- end
198
-
199
196
  it "should list test users" do
200
197
  result = @test_users.list
201
198
  result.should be_an(Array)
@@ -251,10 +248,11 @@ describe "Koala::Facebook::TestUsers" do
251
248
  end
252
249
  end
253
250
 
254
- it "should limit to a 50 person network" do
255
- @test_users.should_receive(:create).exactly(50).times
251
+ it "has no built-in network size limit" do
252
+ times = 100
253
+ @test_users.should_receive(:create).exactly(times).times
256
254
  @test_users.stub!(:befriend)
257
- @network = @test_users.create_network(51)
255
+ @network = @test_users.create_network(times)
258
256
  end
259
257
 
260
258
  it "should pass on the installed and permissions parameters to create" do
@@ -87,10 +87,10 @@ graph_api:
87
87
  with_token: '[{"headers":[{"name":"Location","value":"http://google.com"}]}]'
88
88
  batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "me/friends"}]) %>:
89
89
  post:
90
- with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[]}"}]'
90
+ with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[],\"paging\":{}}"}]'
91
91
  batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"me"}, {"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
92
92
  post:
93
- with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[]}"}]'
93
+ with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[],\"paging\":{}}"}]'
94
94
  batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights"}, {"method"=>"get", "relative_url"=>"koppel?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
95
95
  post:
96
96
  with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},{"body":"{\"id\":\"123\"}"}]'
@@ -113,7 +113,7 @@ graph_api:
113
113
  with_token: '[null,{"body":"{}"}]'
114
114
  batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5", "name" => "get-friends", "omit_response_on_success" => false}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=get-friends:$.data.*.id}"}"}]) %>:
115
115
  post:
116
- with_token: '[{"body":"{\"data\":[]}"},{"body":"{}"}]'
116
+ with_token: '[{"body":"{\"data\":[],\"paging\":{}}"},{"body":"{}"}]'
117
117
  batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=i-dont-exist:$.data.*.id}"}"}]) %>:
118
118
  post:
119
119
  with_token: '{"error":190,"error_description":"Error validating access token."}'
@@ -211,7 +211,7 @@ graph_api:
211
211
  no_args:
212
212
  get:
213
213
  <<: *token_required
214
- with_token: '{"data": [{}]}'
214
+ with_token: '{"data": [{}], "paging": {}}'
215
215
 
216
216
  /lukeshepard/picture:
217
217
  type=large:
@@ -261,7 +261,7 @@ graph_api:
261
261
  get:
262
262
  with_token: '{"data": [{"id": "507731521_100412693339488"}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
263
263
  no_token: '{"data": [{"id": "507731521_100412693339488"}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
264
- "limit=25&q=facebook&until=2010-09-23T21:17:33+0000":
264
+ "limit=25&q=facebook&until=<%= TEST_DATA['search_time'] %>":
265
265
  get:
266
266
  with_token: '{"data": [{"id": "507731521_100412693339488"}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
267
267
  no_token: '{"data": [{"id": "507731521_100412693339488"}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/photos?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
@@ -17,9 +17,7 @@ shared_examples_for "Koala GraphAPI" do
17
17
  describe "graph_call" do
18
18
  it "should pass all arguments to the api method" do
19
19
  args = [KoalaTest.user1, {}, "get", {:a => :b}]
20
-
21
20
  @api.should_receive(:api).with(*args)
22
-
23
21
  @api.graph_call(*args)
24
22
  end
25
23
 
@@ -27,6 +25,27 @@ shared_examples_for "Koala GraphAPI" do
27
25
  Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error" => "An error occurred!"}, {}))
28
26
  lambda { @api.graph_call(KoalaTest.user1, {}) }.should raise_exception(Koala::Facebook::APIError)
29
27
  end
28
+
29
+ it "passes the results through GraphCollection.evaluate" do
30
+ result = {}
31
+ @api.stub(:api).and_return(result)
32
+ Koala::Facebook::GraphCollection.should_receive(:evaluate).with(result, @api)
33
+ @api.graph_call("/me")
34
+ end
35
+
36
+ it "returns the results of GraphCollection.evaluate" do
37
+ expected = {}
38
+ @api.stub(:api).and_return([])
39
+ Koala::Facebook::GraphCollection.should_receive(:evaluate).and_return(expected)
40
+ @api.graph_call("/me").should == expected
41
+ end
42
+
43
+ it "returns the post_processing block's results if one is supplied" do
44
+ other_result = [:a, 2, :three]
45
+ block = Proc.new {|r| other_result}
46
+ @api.stub(:api).and_return({})
47
+ @api.graph_call("/me", {}, "get", {}, &block).should == other_result
48
+ end
30
49
  end
31
50
 
32
51
  # SEARCH
@@ -349,12 +368,6 @@ end
349
368
 
350
369
  # GraphCollection
351
370
  shared_examples_for "Koala GraphAPI with GraphCollection" do
352
-
353
- it "should create an array-like object" do
354
- call = @api.graph_call("contextoptional/photos")
355
- Koala::Facebook::GraphCollection.new(call, @api).should be_an(Array)
356
- end
357
-
358
371
  describe "when getting a collection" do
359
372
  # GraphCollection methods
360
373
  it "should get a GraphCollection when getting connections" do
@@ -380,74 +393,14 @@ shared_examples_for "Koala GraphAPI with GraphCollection" do
380
393
  end
381
394
 
382
395
  it "should get a GraphCollection when paging through results" do
383
- @results = @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=>"2010-09-23T21:17:33+0000"}])
396
+ @results = @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=> KoalaTest.search_time}])
384
397
  @results.should be_a(Koala::Facebook::GraphCollection)
385
398
  end
386
399
 
387
400
  it "should return nil if the page call fails with nil" do
388
401
  # this happens sometimes
389
402
  @api.should_receive(:graph_call).and_return(nil)
390
- @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=>"2010-09-23T21:17:33+0000"}]).should be_nil
391
- end
392
-
393
- # GraphCollection attributes
394
- describe "the GraphCollection" do
395
- before(:each) do
396
- @result = @api.get_connections(KoalaTest.page, "photos")
397
- end
398
-
399
- it "should have a read-only paging attribute" do
400
- @result.methods.map(&:to_sym).should include(:paging)
401
- @result.methods.map(&:to_sym).should_not include(:paging=)
402
- end
403
-
404
- describe "when getting a whole page" do
405
- before(:each) do
406
- @second_page = stub("page of Fb graph results")
407
- @base = stub("base")
408
- @args = stub("args")
409
- @page_of_results = stub("page of results")
410
- end
411
-
412
- it "should return the previous page of results" do
413
- @result.should_receive(:previous_page_params).and_return([@base, @args])
414
- @api.should_receive(:graph_call).with(@base, @args).and_yield(@second_page)
415
- Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
416
-
417
- @result.previous_page#.should == @page_of_results
418
- end
419
-
420
- it "should return the next page of results" do
421
- @result.should_receive(:next_page_params).and_return([@base, @args])
422
- @api.should_receive(:graph_call).with(@base, @args).and_yield(@second_page)
423
- Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
424
-
425
- @result.next_page#.should == @page_of_results
426
- end
427
-
428
- it "should return nil it there are no other pages" do
429
- %w{next previous}.each do |this|
430
- @result.should_receive("#{this}_page_params".to_sym).and_return(nil)
431
- @result.send("#{this}_page").should == nil
432
- end
433
- end
434
- end
435
-
436
- describe "when parsing page paramters" do
437
- before(:each) do
438
- @graph_collection = Koala::Facebook::GraphCollection.new({"data" => []}, Koala::Facebook::API.new)
439
- end
440
-
441
- it "should return the base as the first array entry" do
442
- base = "url_path"
443
- @graph_collection.parse_page_url("anything.com/#{base}?anything").first.should == base
444
- end
445
-
446
- it "should return the arguments as a hash as the last array entry" do
447
- args_hash = {"one" => "val_one", "two" => "val_two"}
448
- @graph_collection.parse_page_url("anything.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
449
- end
450
- end
403
+ @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=> KoalaTest.search_time}]).should be_nil
451
404
  end
452
405
  end
453
406
  end
@@ -3,7 +3,7 @@ module KoalaTest
3
3
 
4
4
  class << self
5
5
  attr_accessor :oauth_token, :app_id, :secret, :app_access_token, :code, :session_key
6
- attr_accessor :oauth_test_data, :subscription_test_data
6
+ attr_accessor :oauth_test_data, :subscription_test_data, :search_time
7
7
  end
8
8
 
9
9
  # Test setup
@@ -84,6 +84,9 @@ module KoalaTest
84
84
  self.secret = data["oauth_test_data"]["secret"]
85
85
  self.code = data["oauth_test_data"]["code"]
86
86
  self.session_key = data["oauth_test_data"]["session_key"]
87
+
88
+ # fix the search time so it can be used in the mock responses
89
+ self.search_time = data["search_time"] || (Time.now - 3600).to_s
87
90
  end
88
91
 
89
92
  def self.testing_permissions
@@ -97,15 +100,34 @@ module KoalaTest
97
100
  print "Setting up test users..."
98
101
  @test_user_api = Koala::Facebook::TestUsers.new(:app_id => self.app_id, :secret => self.secret)
99
102
 
100
- # create two test users with specific names and befriend them
101
- @live_testing_user = @test_user_api.create(true, testing_permissions, :name => user1_name)
102
- @live_testing_friend = @test_user_api.create(true, testing_permissions, :name => user2_name)
103
- @test_user_api.befriend(@live_testing_user, @live_testing_friend)
104
- self.oauth_token = @live_testing_user["access_token"]
103
+ RSpec.configure do |config|
104
+ config.before :all do
105
+ # before each test module, create two test users with specific names and befriend them
106
+ KoalaTest.create_test_users
107
+ end
108
+
109
+ config.after :all do
110
+ # after each test module, delete the test users to avoid cluttering up the application
111
+ KoalaTest.destroy_test_users
112
+ end
113
+ end
105
114
 
106
115
  puts "done."
107
116
  end
108
117
 
118
+ def self.create_test_users
119
+ @live_testing_user = @test_user_api.create(true, KoalaTest.testing_permissions, :name => KoalaTest.user1_name)
120
+ @live_testing_friend = @test_user_api.create(true, KoalaTest.testing_permissions, :name => KoalaTest.user2_name)
121
+ @test_user_api.befriend(@live_testing_user, @live_testing_friend)
122
+ self.oauth_token = @live_testing_user["access_token"]
123
+ end
124
+
125
+ def self.destroy_test_users
126
+ [@live_testing_user, @live_testing_friend].each do |u|
127
+ puts "Unable to delete test user #{u.inspect}" if u && !(@test_user_api.delete(u) rescue false)
128
+ end
129
+ end
130
+
109
131
  def self.validate_user_info(token)
110
132
  print "Validating permissions for live testing..."
111
133
  # make sure we have the necessary permissions
@@ -18,7 +18,8 @@ module Koala
18
18
  TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'fixtures', 'facebook_data.yml'))
19
19
  TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
20
20
  TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
21
-
21
+ TEST_DATA['search_time'] = (Time.now - 3600).to_s
22
+
22
23
  # Useful in mock_facebook_responses.yml
23
24
  OAUTH_DATA = TEST_DATA['oauth_test_data']
24
25
  OAUTH_DATA.merge!({
metadata CHANGED
@@ -1,72 +1,86 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: koala
3
- version: !ruby/object:Gem::Version
4
- version: 1.2.0beta3
5
- prerelease: 5
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 1
7
+ - 2
8
+ - 0beta4
9
+ version: 1.2.0beta4
6
10
  platform: ruby
7
- authors:
11
+ authors:
8
12
  - Alex Koppel, Chris Baclig, Rafi Jacoby, Context Optional
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2011-09-12 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: multi_json
16
- requirement: &70118378561560 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
16
+
17
+ date: 2011-09-21 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ requirement: &id001 !ruby/object:Gem::Requirement
22
+ requirements:
19
23
  - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '1.0'
22
- type: :runtime
24
+ - !ruby/object:Gem::Version
25
+ segments:
26
+ - 1
27
+ - 0
28
+ version: "1.0"
29
+ name: multi_json
23
30
  prerelease: false
24
- version_requirements: *70118378561560
25
- - !ruby/object:Gem::Dependency
26
- name: faraday
27
- requirement: &70118378560320 !ruby/object:Gem::Requirement
28
- none: false
29
- requirements:
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: &id002 !ruby/object:Gem::Requirement
35
+ requirements:
30
36
  - - ~>
31
- - !ruby/object:Gem::Version
37
+ - !ruby/object:Gem::Version
38
+ segments:
39
+ - 0
40
+ - 7
41
+ - 0
32
42
  version: 0.7.0
33
- type: :runtime
43
+ name: faraday
34
44
  prerelease: false
35
- version_requirements: *70118378560320
36
- - !ruby/object:Gem::Dependency
37
- name: rspec
38
- requirement: &70118378559340 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ requirements:
41
50
  - - ~>
42
- - !ruby/object:Gem::Version
43
- version: '2.5'
44
- type: :development
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 2
54
+ - 5
55
+ version: "2.5"
56
+ name: rspec
45
57
  prerelease: false
46
- version_requirements: *70118378559340
47
- - !ruby/object:Gem::Dependency
48
- name: rake
49
- requirement: &70118378557940 !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
58
+ type: :development
59
+ version_requirements: *id003
60
+ - !ruby/object:Gem::Dependency
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ requirements:
52
63
  - - ~>
53
- - !ruby/object:Gem::Version
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ - 8
68
+ - 7
54
69
  version: 0.8.7
55
- type: :development
70
+ name: rake
56
71
  prerelease: false
57
- version_requirements: *70118378557940
58
- description: Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write
59
- access to the social graph via the Graph and REST APIs, as well as support for realtime
60
- updates and OAuth and Facebook Connect authentication. Koala is fully tested and
61
- supports Net::HTTP and Typhoeus connections out of the box and can accept custom
62
- modules for other services.
72
+ type: :development
73
+ version_requirements: *id004
74
+ description: Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write access to the social graph via the Graph and REST APIs, as well as support for realtime updates and OAuth and Facebook Connect authentication. Koala is fully tested and supports Net::HTTP and Typhoeus connections out of the box and can accept custom modules for other services.
63
75
  email: alex@alexkoppel.com
64
76
  executables: []
77
+
65
78
  extensions: []
66
- extra_rdoc_files:
79
+
80
+ extra_rdoc_files:
67
81
  - readme.md
68
82
  - CHANGELOG
69
- files:
83
+ files:
70
84
  - .autotest
71
85
  - .gitignore
72
86
  - .travis.yml
@@ -89,12 +103,14 @@ files:
89
103
  - lib/koala/test_users.rb
90
104
  - lib/koala/uploadable_io.rb
91
105
  - lib/koala/utils.rb
106
+ - lib/koala/version.rb
92
107
  - readme.md
93
- - spec/cases/api_base_spec.rb
108
+ - spec/cases/api_spec.rb
94
109
  - spec/cases/error_spec.rb
95
110
  - spec/cases/graph_and_rest_api_spec.rb
96
111
  - spec/cases/graph_api_batch_spec.rb
97
112
  - spec/cases/graph_api_spec.rb
113
+ - spec/cases/graph_collection_spec.rb
98
114
  - spec/cases/http_service_spec.rb
99
115
  - spec/cases/koala_spec.rb
100
116
  - spec/cases/oauth_spec.rb
@@ -115,44 +131,47 @@ files:
115
131
  - spec/support/ordered_hash.rb
116
132
  - spec/support/rest_api_shared_examples.rb
117
133
  - spec/support/uploadable_io_shared_examples.rb
134
+ has_rdoc: true
118
135
  homepage: http://github.com/arsduo/koala
119
136
  licenses: []
137
+
120
138
  post_install_message:
121
- rdoc_options:
139
+ rdoc_options:
122
140
  - --line-numbers
123
141
  - --inline-source
124
142
  - --title
125
143
  - Koala
126
- require_paths:
144
+ require_paths:
127
145
  - lib
128
- required_ruby_version: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ! '>='
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- segments:
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ segments:
135
151
  - 0
136
- hash: -3213298653109204495
137
- required_rubygems_version: !ruby/object:Gem::Requirement
138
- none: false
139
- requirements:
140
- - - ! '>='
141
- - !ruby/object:Gem::Version
142
- version: '1.2'
152
+ version: "0"
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ segments:
158
+ - 1
159
+ - 2
160
+ version: "1.2"
143
161
  requirements: []
162
+
144
163
  rubyforge_project:
145
- rubygems_version: 1.8.8
164
+ rubygems_version: 1.3.6
146
165
  signing_key:
147
166
  specification_version: 3
148
- summary: A lightweight, flexible library for Facebook with support for the Graph API,
149
- the REST API, realtime updates, and OAuth authentication.
150
- test_files:
151
- - spec/cases/api_base_spec.rb
167
+ summary: A lightweight, flexible library for Facebook with support for the Graph API, the REST API, realtime updates, and OAuth authentication.
168
+ test_files:
169
+ - spec/cases/api_spec.rb
152
170
  - spec/cases/error_spec.rb
153
171
  - spec/cases/graph_and_rest_api_spec.rb
154
172
  - spec/cases/graph_api_batch_spec.rb
155
173
  - spec/cases/graph_api_spec.rb
174
+ - spec/cases/graph_collection_spec.rb
156
175
  - spec/cases/http_service_spec.rb
157
176
  - spec/cases/koala_spec.rb
158
177
  - spec/cases/oauth_spec.rb