tyler_koala 1.2.0beta

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 (49) hide show
  1. data/.autotest +12 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +185 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE +22 -0
  7. data/Manifest +39 -0
  8. data/Rakefile +16 -0
  9. data/autotest/discover.rb +1 -0
  10. data/koala.gemspec +50 -0
  11. data/lib/koala.rb +119 -0
  12. data/lib/koala/batch_operation.rb +74 -0
  13. data/lib/koala/graph_api.rb +281 -0
  14. data/lib/koala/graph_batch_api.rb +87 -0
  15. data/lib/koala/graph_collection.rb +54 -0
  16. data/lib/koala/http_service.rb +161 -0
  17. data/lib/koala/oauth.rb +181 -0
  18. data/lib/koala/realtime_updates.rb +89 -0
  19. data/lib/koala/rest_api.rb +95 -0
  20. data/lib/koala/test_users.rb +102 -0
  21. data/lib/koala/uploadable_io.rb +180 -0
  22. data/lib/koala/utils.rb +7 -0
  23. data/readme.md +160 -0
  24. data/spec/cases/api_base_spec.rb +101 -0
  25. data/spec/cases/error_spec.rb +30 -0
  26. data/spec/cases/graph_and_rest_api_spec.rb +48 -0
  27. data/spec/cases/graph_api_batch_spec.rb +600 -0
  28. data/spec/cases/graph_api_spec.rb +42 -0
  29. data/spec/cases/http_service_spec.rb +420 -0
  30. data/spec/cases/koala_spec.rb +21 -0
  31. data/spec/cases/oauth_spec.rb +428 -0
  32. data/spec/cases/realtime_updates_spec.rb +198 -0
  33. data/spec/cases/rest_api_spec.rb +41 -0
  34. data/spec/cases/test_users_spec.rb +281 -0
  35. data/spec/cases/uploadable_io_spec.rb +206 -0
  36. data/spec/cases/utils_spec.rb +8 -0
  37. data/spec/fixtures/beach.jpg +0 -0
  38. data/spec/fixtures/cat.m4v +0 -0
  39. data/spec/fixtures/facebook_data.yml +61 -0
  40. data/spec/fixtures/mock_facebook_responses.yml +439 -0
  41. data/spec/spec_helper.rb +43 -0
  42. data/spec/support/graph_api_shared_examples.rb +502 -0
  43. data/spec/support/json_testing_fix.rb +42 -0
  44. data/spec/support/koala_test.rb +163 -0
  45. data/spec/support/mock_http_service.rb +98 -0
  46. data/spec/support/ordered_hash.rb +205 -0
  47. data/spec/support/rest_api_shared_examples.rb +285 -0
  48. data/spec/support/uploadable_io_shared_examples.rb +70 -0
  49. metadata +221 -0
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Koala::Facebook::RestAPI" do
4
+ describe "class consolidation" do
5
+ before :each do
6
+ Koala::Utils.stub(:deprecate) # avoid actual messages to stderr
7
+ end
8
+
9
+ it "still allows you to instantiate a GraphAndRestAPI object" do
10
+ api = Koala::Facebook::RestAPI.new("token").should be_a(Koala::Facebook::RestAPI)
11
+ end
12
+
13
+ it "ultimately creates an API object" do
14
+ api = Koala::Facebook::RestAPI.new("token").should be_a(Koala::Facebook::API)
15
+ end
16
+
17
+ it "fires a depreciation warning" do
18
+ Koala::Utils.should_receive(:deprecate)
19
+ api = Koala::Facebook::RestAPI.new("token")
20
+ end
21
+ end
22
+
23
+ context "without an access token" do
24
+ before :each do
25
+ @api = Koala::Facebook::API.new
26
+ end
27
+
28
+ it_should_behave_like "Koala RestAPI"
29
+ it_should_behave_like "Koala RestAPI without an access token"
30
+ end
31
+
32
+ context "with an access token" do
33
+ before :each do
34
+ @api = Koala::Facebook::API.new(@token)
35
+ end
36
+
37
+ it_should_behave_like "Koala RestAPI"
38
+ it_should_behave_like "Koala RestAPI with an access token"
39
+ end
40
+
41
+ end
@@ -0,0 +1,281 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Koala::Facebook::TestUsers" do
4
+ context "with access token" do
5
+ before :all do
6
+ # get oauth data
7
+ @app_id = KoalaTest.app_id
8
+ @secret = KoalaTest.secret
9
+ @app_access_token = KoalaTest.app_access_token
10
+
11
+ # check OAuth data
12
+ unless @app_id && @secret && @app_access_token
13
+ raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
14
+ end
15
+ end
16
+
17
+ describe "when initializing" do
18
+ # basic initialization
19
+ it "should initialize properly with an app_id and an app_access_token" do
20
+ test_users = Koala::Facebook::TestUsers.new(:app_id => @app_id, :app_access_token => @app_access_token)
21
+ test_users.should be_a(Koala::Facebook::TestUsers)
22
+ end
23
+
24
+ # init with secret / fetching the token
25
+ it "should initialize properly with an app_id and a secret" do
26
+ test_users = Koala::Facebook::TestUsers.new(:app_id => @app_id, :secret => @secret)
27
+ test_users.should be_a(Koala::Facebook::TestUsers)
28
+ end
29
+
30
+ it "should use the OAuth class to fetch a token when provided an app_id and a secret" do
31
+ oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
32
+ token = oauth.get_app_access_token
33
+ oauth.should_receive(:get_app_access_token).and_return(token)
34
+ Koala::Facebook::OAuth.should_receive(:new).with(@app_id, @secret).and_return(oauth)
35
+ test_users = Koala::Facebook::TestUsers.new(:app_id => @app_id, :secret => @secret)
36
+ end
37
+
38
+ # attributes
39
+ it "should allow read access to app_id, app_access_token, and secret" do
40
+ # in Ruby 1.9, .method returns symbols
41
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should include(:app_id)
42
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should_not include(:app_id=)
43
+ end
44
+
45
+ it "should allow read access to app_access_token" do
46
+ # in Ruby 1.9, .method returns symbols
47
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should include(:app_access_token)
48
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should_not include(:app_access_token=)
49
+ end
50
+
51
+ it "should allow read access to secret" do
52
+ # in Ruby 1.9, .method returns symbols
53
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should include(:secret)
54
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should_not include(:secret=)
55
+ end
56
+
57
+ it "should allow read access to api" do
58
+ # in Ruby 1.9, .method returns symbols
59
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should include(:api)
60
+ Koala::Facebook::TestUsers.instance_methods.map(&:to_sym).should_not include(:api=)
61
+ end
62
+
63
+ # old graph_api accessor
64
+ it "returns the api object when graph_api is called" do
65
+ test_users = Koala::Facebook::TestUsers.new(:app_id => @app_id, :secret => @secret)
66
+ test_users.graph_api.should == test_users.api
67
+ end
68
+
69
+ it "fire a deprecation warning when graph_api is called" do
70
+ test_users = Koala::Facebook::TestUsers.new(:app_id => @app_id, :secret => @secret)
71
+ Koala::Utils.should_receive(:deprecate)
72
+ test_users.graph_api
73
+ end
74
+ end
75
+
76
+ describe "when used without network" do
77
+ before :each do
78
+ @test_users = Koala::Facebook::TestUsers.new({:app_access_token => @app_access_token, :app_id => @app_id})
79
+ end
80
+
81
+ # TEST USER MANAGEMENT
82
+
83
+ describe ".create" do
84
+ it "should create a test user when not given installed" do
85
+ result = @test_users.create(false)
86
+ @temporary_object_id = result["id"]
87
+ result.should be_a(Hash)
88
+ (result["id"] && result["access_token"] && result["login_url"]).should
89
+ end
90
+
91
+ it "should create a test user when not given installed, ignoring permissions" do
92
+ result = @test_users.create(false, "read_stream")
93
+ @temporary_object_id = result["id"]
94
+ result.should be_a(Hash)
95
+ (result["id"] && result["access_token"] && result["login_url"]).should
96
+ end
97
+
98
+ it "should accept permissions as a string" do
99
+ @test_users.graph_api.should_receive(:graph_call).with(anything, hash_including("permissions" => "read_stream,publish_stream"), anything, anything)
100
+ result = @test_users.create(true, "read_stream,publish_stream")
101
+ end
102
+
103
+ it "should accept permissions as an array" do
104
+ @test_users.graph_api.should_receive(:graph_call).with(anything, hash_including("permissions" => "read_stream,publish_stream"), anything, anything)
105
+ result = @test_users.create(true, ["read_stream", "publish_stream"])
106
+ end
107
+
108
+ it "should create a test user when given installed and a permission" do
109
+ result = @test_users.create(true, "read_stream")
110
+ @temporary_object_id = result["id"]
111
+ result.should be_a(Hash)
112
+ (result["id"] && result["access_token"] && result["login_url"]).should
113
+ end
114
+
115
+ it "lets you specify other graph arguments, like uid and access token" do
116
+ args = {:uid => "some test user ID", :owner_access_token => "some owner access token"}
117
+ @test_users.graph_api.should_receive(:graph_call).with(anything, hash_including(args), anything, anything)
118
+ @test_users.create(true, nil, args)
119
+ end
120
+
121
+ it "lets you specify http options that get passed through to the graph call" do
122
+ options = {:some_http_option => true}
123
+ @test_users.graph_api.should_receive(:graph_call).with(anything, anything, anything, options)
124
+ @test_users.create(true, nil, {}, options)
125
+ end
126
+ end
127
+
128
+ describe ".delete" do
129
+ before :each do
130
+ @user1 = @test_users.create(true, "read_stream")
131
+ @user2 = @test_users.create(true, "read_stream,user_interests")
132
+ end
133
+
134
+ after :each do
135
+ @test_users.delete(@user1) if @user1
136
+ @test_users.delete(@user2) if @user2
137
+ end
138
+
139
+ it "should delete a user by id" do
140
+ @test_users.delete(@user1['id']).should be_true
141
+ @user1 = nil
142
+ end
143
+
144
+ it "should delete a user by hash" do
145
+ @test_users.delete(@user2).should be_true
146
+ @user2 = nil
147
+ end
148
+
149
+ it "should not delete users when provided a false ID" do
150
+ lambda { @test_users.delete("#{@user1['id']}1") }.should raise_exception(Koala::Facebook::APIError)
151
+ end
152
+ end
153
+
154
+ describe ".delete_all" do
155
+ it "should delete all users found by the list commnand" do
156
+ array = [1, 2, 3]
157
+ @test_users.should_receive(:list).and_return(array)
158
+ array.each {|i| @test_users.should_receive(:delete).with(i) }
159
+ @test_users.delete_all
160
+ end
161
+ end
162
+
163
+ describe ".update" do
164
+ before :each do
165
+ @updates = {:name => "Foo Baz"}
166
+ end
167
+
168
+ it "makes a POST with the test user Graph API " do
169
+ user = @test_users.create(true)
170
+ @test_users.graph_api.should_receive(:graph_call).with(anything, anything, "post", anything)
171
+ @test_users.update(user, @updates)
172
+ end
173
+
174
+ it "makes a request to the test user with the update params " do
175
+ user = @test_users.create(true)
176
+ @test_users.graph_api.should_receive(:graph_call).with(user["id"], @updates, anything, anything)
177
+ @test_users.update(user, @updates)
178
+ end
179
+
180
+ it "works" do
181
+ user = @test_users.create(true)
182
+ @test_users.update(user, @updates)
183
+ user_info = Koala::Facebook::API.new(user["access_token"]).get_object(user["id"])
184
+ user_info["name"].should == @updates[:name]
185
+ end
186
+ end
187
+
188
+ describe "with existing users" do
189
+ before :each do
190
+ @user1 = @test_users.create(true, "read_stream")
191
+ @user2 = @test_users.create(true, "read_stream,user_interests")
192
+ end
193
+
194
+ after :each do
195
+ @test_users.delete(@user1)
196
+ @test_users.delete(@user2)
197
+ end
198
+
199
+ it "should list test users" do
200
+ result = @test_users.list
201
+ result.should be_an(Array)
202
+ first_user, second_user = result[0], result[1]
203
+ (first_user["id"] && first_user["access_token"] && first_user["login_url"]).should
204
+ (second_user["id"] && second_user["access_token"] && second_user["login_url"]).should
205
+ end
206
+
207
+ it "should make two users into friends with string hashes" do
208
+ result = @test_users.befriend(@user1, @user2)
209
+ result.should be_true
210
+ end
211
+
212
+ it "should make two users into friends with symbol hashes" do
213
+ new_user_1 = {}
214
+ @user1.each_pair {|k, v| new_user_1[k.to_sym] = v}
215
+ new_user_2 = {}
216
+ @user2.each_pair {|k, v| new_user_2[k.to_sym] = v}
217
+
218
+ result = @test_users.befriend(new_user_1, new_user_2)
219
+ result.should be_true
220
+ end
221
+
222
+ it "should not accept user IDs anymore" do
223
+ lambda { @test_users.befriend(@user1["id"], @user2["id"]) }.should raise_exception
224
+ end
225
+ end # with existing users
226
+
227
+ end # when used without network
228
+
229
+ describe "when creating a network of friends" do
230
+ before :each do
231
+ @test_users = Koala::Facebook::TestUsers.new({:app_access_token => @app_access_token, :app_id => @app_id})
232
+ @network = []
233
+
234
+ if KoalaTest.mock_interface?
235
+ id_counter = 999999900
236
+ @test_users.stub!(:create).and_return do
237
+ id_counter += 1
238
+ {"id" => id_counter, "access_token" => @token, "login_url" => "https://www.facebook.com/platform/test_account.."}
239
+ end
240
+ @test_users.stub!(:befriend).and_return(true)
241
+ @test_users.stub!(:delete).and_return(true)
242
+ end
243
+ end
244
+
245
+ describe "tests that create users" do
246
+ before :each do
247
+ test_users = Koala::Facebook::TestUsers.new({:app_access_token => @app_access_token, :app_id => @app_id})
248
+ test_users.delete_all
249
+ end
250
+
251
+ after :each do
252
+ test_users = Koala::Facebook::TestUsers.new({:app_access_token => @app_access_token, :app_id => @app_id})
253
+ test_users.delete_all
254
+ end
255
+
256
+ it "should create a 5 person network" do
257
+ size = 5
258
+ @network = @test_users.create_network(size)
259
+ @network.should be_a(Array)
260
+ @network.size.should == size
261
+ end
262
+ end
263
+
264
+ it "should limit to a 50 person network" do
265
+ @test_users.should_receive(:create).exactly(50).times
266
+ @test_users.stub!(:befriend)
267
+ @network = @test_users.create_network(51)
268
+ end
269
+
270
+ it "should pass on the installed and permissions parameters to create" do
271
+ perms = ["read_stream", "offline_access"]
272
+ installed = false
273
+ count = 25
274
+ @test_users.should_receive(:create).exactly(count).times.with(installed, perms)
275
+ @test_users.stub!(:befriend)
276
+ @network = @test_users.create_network(count, installed, perms)
277
+ end
278
+
279
+ end # when creating network
280
+ end
281
+ end # describe Koala TestUsers
@@ -0,0 +1,206 @@
1
+ # fake MIME::Types
2
+ module Koala::MIME
3
+ module Types
4
+ def self.type_for(type)
5
+ # this should be faked out in tests
6
+ nil
7
+ end
8
+ end
9
+ end
10
+
11
+ describe "Koala::UploadableIO" do
12
+ def rails_3_mocks
13
+ tempfile = stub('Tempfile', :path => "foo")
14
+ uploaded_file = stub('ActionDispatch::Http::UploadedFile',
15
+ :content_type => true,
16
+ :tempfile => tempfile,
17
+ :original_filename => "bar"
18
+ )
19
+ tempfile.stub!(:respond_to?).with(:path).and_return(true)
20
+
21
+ [tempfile, uploaded_file]
22
+ end
23
+
24
+ def sinatra_mocks
25
+ {:type => "type", :tempfile => "Tempfile", :filename => "foo.bar"}
26
+ end
27
+
28
+ describe "the constructor" do
29
+ describe "when given a file path" do
30
+ before(:each) do
31
+ @path = BEACH_BALL_PATH
32
+ @koala_io_params = [@path]
33
+ end
34
+
35
+ describe "and a content type" do
36
+ before :each do
37
+ @stub_type = stub("image/jpg")
38
+ @koala_io_params.concat([@stub_type])
39
+ end
40
+
41
+ it "returns an UploadIO with the same file path" do
42
+ Koala::UploadableIO.new(*@koala_io_params).io_or_path.should == @path
43
+ end
44
+
45
+ it "returns an UploadIO with the same content type" do
46
+ Koala::UploadableIO.new(*@koala_io_params).content_type.should == @stub_type
47
+ end
48
+
49
+ it "returns an UploadIO with the file's name" do
50
+ Koala::UploadableIO.new(*@koala_io_params).filename.should == File.basename(@path)
51
+ end
52
+ end
53
+
54
+ describe "and no content type" do
55
+ it_should_behave_like "determining a mime type"
56
+ end
57
+ end
58
+
59
+ describe "when given a File object" do
60
+ before(:each) do
61
+ @file = File.open(BEACH_BALL_PATH)
62
+ @koala_io_params = [@file]
63
+ end
64
+
65
+ describe "and a content type" do
66
+ before :each do
67
+ @koala_io_params.concat(["image/jpg"])
68
+ end
69
+
70
+ it "returns an UploadIO with the same io" do
71
+ Koala::UploadableIO.new(*@koala_io_params).io_or_path.should == @koala_io_params[0]
72
+ end
73
+
74
+ it "returns an UploadableIO with the same content_type" do
75
+ content_stub = @koala_io_params[1] = stub('Content Type')
76
+ Koala::UploadableIO.new(*@koala_io_params).content_type.should == content_stub
77
+ end
78
+
79
+ it "returns an UploadableIO with the right filename" do
80
+ Koala::UploadableIO.new(*@koala_io_params).filename.should == File.basename(@file.path)
81
+ end
82
+ end
83
+
84
+ describe "and no content type" do
85
+ it_should_behave_like "determining a mime type"
86
+ end
87
+ end
88
+
89
+ describe "when given a Rails 3 ActionDispatch::Http::UploadedFile" do
90
+ before(:each) do
91
+ @tempfile, @uploaded_file = rails_3_mocks
92
+ end
93
+
94
+ it "gets the path from the tempfile associated with the UploadedFile" do
95
+ expected_path = stub('Tempfile')
96
+ @tempfile.should_receive(:path).and_return(expected_path)
97
+ Koala::UploadableIO.new(@uploaded_file).io_or_path.should == expected_path
98
+ end
99
+
100
+ it "gets the content type via the content_type method" do
101
+ expected_content_type = stub('Content Type')
102
+ @uploaded_file.should_receive(:content_type).and_return(expected_content_type)
103
+ Koala::UploadableIO.new(@uploaded_file).content_type.should == expected_content_type
104
+ end
105
+
106
+ it "gets the filename from the UploadedFile" do
107
+ Koala::UploadableIO.new(@uploaded_file).filename.should == @uploaded_file.original_filename
108
+ end
109
+ end
110
+
111
+ describe "when given a Sinatra file parameter hash" do
112
+ before(:each) do
113
+ @file_hash = sinatra_mocks
114
+ end
115
+
116
+ it "gets the io_or_path from the :tempfile key" do
117
+ expected_file = stub('File')
118
+ @file_hash[:tempfile] = expected_file
119
+
120
+ uploadable = Koala::UploadableIO.new(@file_hash)
121
+ uploadable.io_or_path.should == expected_file
122
+ end
123
+
124
+ it "gets the content type from the :type key" do
125
+ expected_content_type = stub('Content Type')
126
+ @file_hash[:type] = expected_content_type
127
+
128
+ uploadable = Koala::UploadableIO.new(@file_hash)
129
+ uploadable.content_type.should == expected_content_type
130
+ end
131
+
132
+ it "gets the content type from the :type key" do
133
+ uploadable = Koala::UploadableIO.new(@file_hash)
134
+ uploadable.filename.should == @file_hash[:filename]
135
+ end
136
+ end
137
+
138
+ describe "for files with with recognizable MIME types" do
139
+ # what that means is tested below
140
+ it "should accept a file object alone" do
141
+ params = [BEACH_BALL_PATH]
142
+ lambda { Koala::UploadableIO.new(*params) }.should_not raise_exception(Koala::KoalaError)
143
+ end
144
+
145
+ it "should accept a file path alone" do
146
+ params = [BEACH_BALL_PATH]
147
+ lambda { Koala::UploadableIO.new(*params) }.should_not raise_exception(Koala::KoalaError)
148
+ end
149
+ end
150
+ end
151
+
152
+ describe "getting an UploadableIO" do
153
+ before(:each) do
154
+ @upload_io = stub("UploadIO")
155
+ UploadIO.stub!(:new).with(anything, anything, anything).and_return(@upload_io)
156
+ end
157
+
158
+ context "if no filename was provided" do
159
+ it "should call the constructor with the content type, file name, and a dummy file name" do
160
+ UploadIO.should_receive(:new).with(BEACH_BALL_PATH, "content/type", anything).and_return(@upload_io)
161
+ Koala::UploadableIO.new(BEACH_BALL_PATH, "content/type").to_upload_io.should == @upload_io
162
+ end
163
+ end
164
+
165
+ context "if a filename was provided" do
166
+ it "should call the constructor with the content type, file name, and the filename" do
167
+ filename = "file"
168
+ UploadIO.should_receive(:new).with(BEACH_BALL_PATH, "content/type", filename).and_return(@upload_io)
169
+ Koala::UploadableIO.new(BEACH_BALL_PATH, "content/type", filename).to_upload_io
170
+ end
171
+ end
172
+ end
173
+
174
+ describe "getting a file" do
175
+ it "returns the File if initialized with a file" do
176
+ f = File.new(BEACH_BALL_PATH)
177
+ Koala::UploadableIO.new(f).to_file.should == f
178
+ end
179
+
180
+ it "should open up and return a file corresponding to the path if io_or_path is a path" do
181
+ result = stub("File")
182
+ File.should_receive(:open).with(BEACH_BALL_PATH).and_return(result)
183
+ Koala::UploadableIO.new(BEACH_BALL_PATH).to_file.should == result
184
+ end
185
+ end
186
+
187
+ describe "#binary_content?" do
188
+ it "returns true for Rails 3 file uploads" do
189
+ Koala::UploadableIO.binary_content?(rails_3_mocks.last).should be_true
190
+ end
191
+
192
+ it "returns true for Sinatra file uploads" do
193
+ Koala::UploadableIO.binary_content?(rails_3_mocks.last).should be_true
194
+ end
195
+
196
+ it "returns true for File objects" do
197
+ Koala::UploadableIO.binary_content?(File.open(BEACH_BALL_PATH)).should be_true
198
+ end
199
+
200
+ it "returns false for everything else" do
201
+ Koala::UploadableIO.binary_content?(StringIO.new).should be_false
202
+ Koala::UploadableIO.binary_content?(BEACH_BALL_PATH).should be_false
203
+ Koala::UploadableIO.binary_content?(nil).should be_false
204
+ end
205
+ end
206
+ end # describe UploadableIO