koala 1.1.0 → 1.2.0beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.travis.yml +2 -1
  2. data/CHANGELOG +26 -0
  3. data/Gemfile +6 -2
  4. data/Rakefile +0 -1
  5. data/koala.gemspec +8 -8
  6. data/lib/koala.rb +42 -45
  7. data/lib/koala/batch_operation.rb +15 -15
  8. data/lib/koala/graph_api.rb +81 -58
  9. data/lib/koala/graph_batch_api.rb +10 -10
  10. data/lib/koala/graph_collection.rb +6 -6
  11. data/lib/koala/http_service.rb +177 -0
  12. data/lib/koala/oauth.rb +2 -2
  13. data/lib/koala/realtime_updates.rb +20 -17
  14. data/lib/koala/rest_api.rb +1 -1
  15. data/lib/koala/test_users.rb +33 -16
  16. data/lib/koala/uploadable_io.rb +47 -42
  17. data/lib/koala/utils.rb +11 -0
  18. data/readme.md +38 -38
  19. data/spec/cases/api_base_spec.rb +2 -2
  20. data/spec/cases/error_spec.rb +32 -0
  21. data/spec/cases/graph_and_rest_api_spec.rb +20 -3
  22. data/spec/cases/graph_api_batch_spec.rb +88 -97
  23. data/spec/cases/graph_api_spec.rb +21 -4
  24. data/spec/cases/http_service_spec.rb +446 -0
  25. data/spec/cases/koala_spec.rb +33 -38
  26. data/spec/cases/oauth_spec.rb +219 -200
  27. data/spec/cases/realtime_updates_spec.rb +45 -31
  28. data/spec/cases/rest_api_spec.rb +23 -7
  29. data/spec/cases/test_users_spec.rb +112 -52
  30. data/spec/cases/uploadable_io_spec.rb +49 -36
  31. data/spec/cases/utils_spec.rb +10 -0
  32. data/spec/fixtures/facebook_data.yml +23 -22
  33. data/spec/fixtures/mock_facebook_responses.yml +126 -96
  34. data/spec/spec_helper.rb +29 -5
  35. data/spec/support/graph_api_shared_examples.rb +59 -52
  36. data/spec/support/json_testing_fix.rb +35 -11
  37. data/spec/support/koala_test.rb +163 -0
  38. data/spec/support/mock_http_service.rb +6 -4
  39. data/spec/support/ordered_hash.rb +205 -0
  40. data/spec/support/rest_api_shared_examples.rb +37 -37
  41. data/spec/support/uploadable_io_shared_examples.rb +2 -8
  42. metadata +78 -79
  43. data/lib/koala/http_services.rb +0 -46
  44. data/lib/koala/http_services/net_http_service.rb +0 -92
  45. data/lib/koala/http_services/typhoeus_service.rb +0 -37
  46. data/spec/cases/http_services/http_service_spec.rb +0 -129
  47. data/spec/cases/http_services/net_http_service_spec.rb +0 -532
  48. data/spec/cases/http_services/typhoeus_service_spec.rb +0 -152
  49. data/spec/support/live_testing_data_helper.rb +0 -40
  50. data/spec/support/setup_mocks_or_live.rb +0 -51
data/spec/spec_helper.rb CHANGED
@@ -4,16 +4,40 @@ rescue LoadError
4
4
  puts 'Although not required, bundler is recommended for running the tests.'
5
5
  end
6
6
 
7
- # load the libraries
7
+ # In Ruby 1.9.2 versions before patchlevel 290, the default Psych
8
+ # parser has an issue with YAML merge keys, which
9
+ # fixtures/mock_facebook_responses.yml relies heavily on.
10
+ #
11
+ # Anyone using an earlier version will see missing mock response
12
+ # errors when running the test suite similar to this:
13
+ #
14
+ # RuntimeError:
15
+ # Missing a mock response for graph_api: /me/videos: source=[FILE]: post: with_token
16
+ # API PATH: /me/videos?source=[FILE]&format=json&access_token=*
17
+ #
18
+ # For now, it seems the best fix is to just downgrade to the old syck YAML parser
19
+ # for these troubled versions.
20
+ #
21
+ # See https://github.com/tenderlove/psych/issues/8 for more details
22
+ YAML::ENGINE.yamler = 'syck' if RUBY_VERSION == '1.9.2' && RUBY_PATCHLEVEL < 290
23
+
24
+ # load the library
8
25
  require 'koala'
9
26
 
10
- # load testing data libraries
11
- require 'support/live_testing_data_helper'
12
- require 'support/json_testing_fix' # ensure consistent to_json behavior
27
+ # ensure consistent to_json behavior
28
+ # this must be required first so mock_http_service loads the YAML as expected
29
+ require 'support/ordered_hash'
30
+ require 'support/json_testing_fix'
31
+
32
+ # set up our testing environment
13
33
  require 'support/mock_http_service'
34
+ require 'support/koala_test'
35
+ # load testing data and (if needed) create test users or validate real users
36
+ KoalaTest.setup_test_environment!
37
+
38
+ # load supporting files for our tests
14
39
  require 'support/rest_api_shared_examples'
15
40
  require 'support/graph_api_shared_examples'
16
41
  require 'support/uploadable_io_shared_examples'
17
- require 'support/setup_mocks_or_live'
18
42
 
19
43
  BEACH_BALL_PATH = File.join(File.dirname(__FILE__), "fixtures", "beach.jpg")
@@ -16,7 +16,7 @@ shared_examples_for "Koala GraphAPI" do
16
16
  # GRAPH CALL
17
17
  describe "graph_call" do
18
18
  it "should pass all arguments to the api method" do
19
- args = ["koppel", {}, "get", {:a => :b}]
19
+ args = [KoalaTest.user1, {}, "get", {:a => :b}]
20
20
 
21
21
  @api.should_receive(:api).with(*args)
22
22
 
@@ -25,7 +25,7 @@ shared_examples_for "Koala GraphAPI" do
25
25
 
26
26
  it "should throw an APIError if the result hash has an error key" do
27
27
  Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error" => "An error occurred!"}, {}))
28
- lambda { @api.graph_call("koppel", {}) }.should raise_exception(Koala::Facebook::APIError)
28
+ lambda { @api.graph_call(KoalaTest.user1, {}) }.should raise_exception(Koala::Facebook::APIError)
29
29
  end
30
30
  end
31
31
 
@@ -40,13 +40,13 @@ shared_examples_for "Koala GraphAPI" do
40
40
 
41
41
  # get_object
42
42
  it "should get public data about a user" do
43
- result = @api.get_object("koppel")
43
+ result = @api.get_object(KoalaTest.user1)
44
44
  # the results should have an ID and a name, among other things
45
45
  (result["id"] && result["name"]).should_not be_nil
46
46
  end
47
47
 
48
48
  it "should get public data about a Page" do
49
- result = @api.get_object("contextoptional")
49
+ result = @api.get_object(KoalaTest.page)
50
50
  # the results should have an ID and a name, among other things
51
51
  (result["id"] && result["name"]).should
52
52
  end
@@ -55,14 +55,14 @@ shared_examples_for "Koala GraphAPI" do
55
55
  results = @api.get_objects([])
56
56
  results.should == []
57
57
  end
58
-
58
+
59
59
  it "should be able to get multiple objects" do
60
- results = @api.get_objects(["contextoptional", "naitik"])
60
+ results = @api.get_objects([KoalaTest.page, KoalaTest.user1])
61
61
  results.should have(2).items
62
62
  end
63
63
 
64
64
  it "should be able to get multiple objects if they're a string" do
65
- results = @api.get_objects("contextoptional,naitik")
65
+ results = @api.get_objects("contextoptional,#{KoalaTest.user1}")
66
66
  results.should have(2).items
67
67
  end
68
68
 
@@ -71,11 +71,11 @@ shared_examples_for "Koala GraphAPI" do
71
71
  end
72
72
 
73
73
  it "should be able to access a user's picture, given a picture type" do
74
- @api.get_picture("lukeshepard", {:type => 'large'}).should =~ /^http[s]*\:\/\//
74
+ @api.get_picture(KoalaTest.user2, {:type => 'large'}).should =~ /^http[s]*\:\/\//
75
75
  end
76
76
 
77
77
  it "should be able to access connections from public Pages" do
78
- result = @api.get_connections("contextoptional", "photos")
78
+ result = @api.get_connections(KoalaTest.page, "photos")
79
79
  result.should be_a(Array)
80
80
  end
81
81
 
@@ -107,7 +107,7 @@ end
107
107
 
108
108
  shared_examples_for "Koala GraphAPI with an access token" do
109
109
  it "should get private data about a user" do
110
- result = @api.get_object("koppel")
110
+ result = @api.get_object(KoalaTest.user1)
111
111
  # updated_time should be a pretty fixed test case
112
112
  result["updated_time"].should_not be_nil
113
113
  end
@@ -118,11 +118,11 @@ shared_examples_for "Koala GraphAPI with an access token" do
118
118
  end
119
119
 
120
120
  it "should be able to get multiple objects" do
121
- result = @api.get_objects(["contextoptional", "naitik"])
121
+ result = @api.get_objects([KoalaTest.page, KoalaTest.user1])
122
122
  result.length.should == 2
123
123
  end
124
124
  it "should be able to access connections from users" do
125
- result = @api.get_connections("lukeshepard", "likes")
125
+ result = @api.get_connections(KoalaTest.user2, "friends")
126
126
  result.length.should > 0
127
127
  end
128
128
 
@@ -168,52 +168,63 @@ shared_examples_for "Koala GraphAPI with an access token" do
168
168
 
169
169
  describe ".put_picture" do
170
170
  it "should be able to post photos to the user's wall with an open file object" do
171
- content_type = "image/jpg"
171
+ content_type = "image/jpg"
172
172
  file = File.open(File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg"))
173
-
173
+
174
174
  result = @api.put_picture(file, content_type)
175
- @temporary_object_id = result["id"]
175
+ @temporary_object_id = result["id"]
176
176
  @temporary_object_id.should_not be_nil
177
177
  end
178
178
 
179
- it "uses the base HTTP service if the upload is a StringIO or similar" do
180
- source = stub("UploadIO")
181
- Koala::UploadableIO.stub(:new).and_return(source)
182
- source.stub(:requires_base_http_service).and_return(true)
183
- Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(:http_service => Koala.base_http_service)).and_return(Koala::Response.new(200, "[]", {}))
184
- @api.put_picture(StringIO.new)
185
- end
186
-
187
179
  it "should be able to post photos to the user's wall without an open file object" do
188
180
  content_type = "image/jpg",
189
181
  file_path = File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg")
190
-
182
+
191
183
  result = @api.put_picture(file_path, content_type)
192
- @temporary_object_id = result["id"]
184
+ @temporary_object_id = result["id"]
193
185
  @temporary_object_id.should_not be_nil
194
186
  end
195
-
187
+
196
188
  it "should be able to verify a photo posted to a user's wall" do
197
189
  content_type = "image/jpg",
198
190
  file_path = File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg")
199
-
191
+
200
192
  expected_message = "This is the test message"
201
-
193
+
202
194
  result = @api.put_picture(file_path, content_type, :message => expected_message)
203
- @temporary_object_id = result["id"]
195
+ @temporary_object_id = result["id"]
204
196
  @temporary_object_id.should_not be_nil
205
-
197
+
206
198
  get_result = @api.get_object(@temporary_object_id)
207
199
  get_result["name"].should == expected_message
208
200
  end
201
+
202
+
203
+ describe "using a URL instead of a file" do
204
+ before :each do
205
+ @url = "http://img.slate.com/images/redesign2008/slate_logo.gif"
206
+ end
207
+
208
+ it "should be able to post photo to the user's wall using a URL" do
209
+ result = @api.put_picture(@url)
210
+ @temporary_object_id = result["id"]
211
+ @temporary_object_id.should_not be_nil
212
+ end
213
+
214
+ it "should be able to post photo to the user's wall using a URL and an additional param" do
215
+ result = @api.put_picture(@url, :message => "my message")
216
+ @temporary_object_id = result["id"]
217
+ @temporary_object_id.should_not be_nil
218
+ end
219
+ end
209
220
  end
210
-
221
+
211
222
  describe ".put_video" do
212
223
  before :each do
213
- @cat_movie = File.join(File.dirname(__FILE__), "..", "fixtures", "cat.m4v")
214
- @content_type = "video/mpeg4"
224
+ @cat_movie = File.join(File.dirname(__FILE__), "..", "fixtures", "cat.m4v")
225
+ @content_type = "video/mpeg4"
215
226
  end
216
-
227
+
217
228
  it "should set options[:video] to true" do
218
229
  source = stub("UploadIO")
219
230
  Koala::UploadableIO.stub(:new).and_return(source)
@@ -221,26 +232,19 @@ shared_examples_for "Koala GraphAPI with an access token" do
221
232
  Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(:video => true)).and_return(Koala::Response.new(200, "[]", {}))
222
233
  @api.put_video("foo")
223
234
  end
224
-
235
+
225
236
  it "should be able to post videos to the user's wall with an open file object" do
226
237
  file = File.open(@cat_movie)
227
238
 
228
239
  result = @api.put_video(file, @content_type)
229
- @temporary_object_id = result["id"]
240
+ @temporary_object_id = result["id"]
230
241
  @temporary_object_id.should_not be_nil
231
242
  end
232
243
 
233
- it "uses the base HTTP service if the upload is a StringIO or similar" do
234
- source = stub("UploadIO")
235
- Koala::UploadableIO.stub(:new).and_return(source)
236
- source.stub(:requires_base_http_service).and_return(true)
237
- Koala.should_receive(:make_request).with(anything, anything, anything, hash_including(:http_service => Koala.base_http_service)).and_return(Koala::Response.new(200, "[]", {}))
238
- @api.put_video(StringIO.new)
239
- end
240
244
 
241
245
  it "should be able to post videos to the user's wall without an open file object" do
242
246
  result = @api.put_video(@cat_movie, @content_type)
243
- @temporary_object_id = result["id"]
247
+ @temporary_object_id = result["id"]
244
248
  @temporary_object_id.should_not be_nil
245
249
  end
246
250
 
@@ -290,6 +294,12 @@ shared_examples_for "Koala GraphAPI with an access token" do
290
294
  like_result.should be_true
291
295
  end
292
296
 
297
+ # Page Access Token Support
298
+ it "gets a page's access token" do
299
+ # we can't test this live since test users (or random real users) can't be guaranteed to have pages to manage
300
+ @api.should_receive(:api).with("my_page", {:fields => "access_token"}, "get", anything)
301
+ @api.get_page_access_token("my_page")
302
+ end
293
303
 
294
304
  # test all methods to make sure they pass data through to the API
295
305
  # we run the tests here (rather than in the common shared example group)
@@ -348,14 +358,14 @@ shared_examples_for "Koala GraphAPI with GraphCollection" do
348
358
  describe "when getting a collection" do
349
359
  # GraphCollection methods
350
360
  it "should get a GraphCollection when getting connections" do
351
- @result = @api.get_connections("contextoptional", "photos")
361
+ @result = @api.get_connections(KoalaTest.page, "photos")
352
362
  @result.should be_a(Koala::Facebook::GraphCollection)
353
363
  end
354
364
 
355
365
  it "should return nil if the get_collections call fails with nil" do
356
366
  # this happens sometimes
357
367
  @api.should_receive(:graph_call).and_return(nil)
358
- @api.get_connections("contextoptional", "photos").should be_nil
368
+ @api.get_connections(KoalaTest.page, "photos").should be_nil
359
369
  end
360
370
 
361
371
  it "should get a GraphCollection when searching" do
@@ -383,7 +393,7 @@ shared_examples_for "Koala GraphAPI with GraphCollection" do
383
393
  # GraphCollection attributes
384
394
  describe "the GraphCollection" do
385
395
  before(:each) do
386
- @result = @api.get_connections("contextoptional", "photos")
396
+ @result = @api.get_connections(KoalaTest.page, "photos")
387
397
  end
388
398
 
389
399
  it "should have a read-only paging attribute" do
@@ -425,7 +435,7 @@ shared_examples_for "Koala GraphAPI with GraphCollection" do
425
435
 
426
436
  describe "when parsing page paramters" do
427
437
  before(:each) do
428
- @graph_collection = Koala::Facebook::GraphCollection.new({"data" => []}, Koala::Facebook::GraphAPI.new)
438
+ @graph_collection = Koala::Facebook::GraphCollection.new({"data" => []}, Koala::Facebook::API.new)
429
439
  end
430
440
 
431
441
  it "should return the base as the first array entry" do
@@ -456,12 +466,11 @@ shared_examples_for "Koala GraphAPI without an access token" do
456
466
  end
457
467
 
458
468
  it "shouldn't be able to access connections from users" do
459
- lambda { @api.get_connections("lukeshepard", "likes") }.should raise_error(Koala::Facebook::APIError)
469
+ lambda { @api.get_connections("lukeshepard", "friends") }.should raise_error(Koala::Facebook::APIError)
460
470
  end
461
471
 
462
472
  it "should not be able to put an object" do
463
473
  lambda { @result = @api.put_object("lukeshepard", "feed", :message => "Hello, world") }.should raise_error(Koala::Facebook::APIError)
464
- puts "Error! Object #{@result.inspect} somehow put onto Luke Shepard's wall!" if @result
465
474
  end
466
475
 
467
476
  # these are not strictly necessary as the other put methods resolve to put_object, but are here for completeness
@@ -470,13 +479,11 @@ shared_examples_for "Koala GraphAPI without an access token" do
470
479
  attachment = {:name => "OAuth Playground", :link => "http://oauth.twoalex.com/"}
471
480
  @result = @api.put_wall_post("Hello, world", attachment, "contextoptional")
472
481
  end).should raise_error(Koala::Facebook::APIError)
473
- puts "Error! Object #{@result.inspect} somehow put onto Context Optional's wall!" if @result
474
482
  end
475
483
 
476
484
  it "should not be able to comment on an object" do
477
485
  # random public post on the ContextOptional wall
478
486
  lambda { @result = @api.put_comment("7204941866_119776748033392", "The hackathon was great!") }.should raise_error(Koala::Facebook::APIError)
479
- puts "Error! Object #{@result.inspect} somehow commented on post 7204941866_119776748033392!" if @result
480
487
  end
481
488
 
482
489
  it "should not be able to like an object" do
@@ -1,18 +1,42 @@
1
1
  # when testing across Ruby versions, we found that JSON string creation inconsistently ordered keys
2
2
  # which is a problem because our mock testing service ultimately matches strings to see if requests are mocked
3
3
  # this fix solves that problem by ensuring all hashes are created with a consistent key order every time
4
-
5
4
  module MultiJson
6
5
  self.engine = :ok_json
6
+
7
+ class << self
8
+ def encode_with_ordering(object)
9
+ # if it's a hash, recreate it with k/v pairs inserted in sorted-by-key order
10
+ # (for some reason, REE fails if we don't assign the ternary result as a local variable
11
+ # separately from calling encode_original)
12
+ encode_original(sort_object(object))
13
+ end
14
+
15
+ alias_method :encode_original, :encode
16
+ alias_method :encode, :encode_with_ordering
7
17
 
8
- def encode_with_ordering(object)
9
- # if it's a hash, recreate it with k/v pairs inserted in sorted-by-key order
10
- # (for some reason, REE 1.8.7 fails if we don't assign the ternary result as a local variable
11
- # separate from calling encode_original)
12
- new_object = object.is_a?(Hash) ? object.keys.sort.inject({}) {|hash, k| hash[k] = object[k]; hash} : object
13
- encode_original(new_object)
14
- end
18
+ def decode_with_ordering(string)
19
+ sort_object(decode_original(string))
20
+ end
21
+
22
+ alias_method :decode_original, :decode
23
+ alias_method :decode, :decode_with_ordering
24
+
25
+ private
26
+
27
+ def sort_object(object)
28
+ if object.is_a?(Hash)
29
+ sort_hash(object)
30
+ elsif object.is_a?(Array)
31
+ object.collect {|item| item.is_a?(Hash) ? sort_hash(item) : item}
32
+ else
33
+ object
34
+ end
35
+ end
15
36
 
16
- alias_method :encode_original, :encode
17
- alias_method :encode, :encode_with_ordering
18
- end
37
+ def sort_hash(unsorted_hash)
38
+ sorted_hash = KoalaTest::OrderedHash.new(sorted_hash)
39
+ unsorted_hash.keys.sort {|a, b| a.to_s <=> b.to_s}.inject(sorted_hash) {|hash, k| hash[k] = unsorted_hash[k]; hash}
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,163 @@
1
+ # small helper method for live testing
2
+ module KoalaTest
3
+
4
+ class << self
5
+ attr_accessor :oauth_token, :app_id, :secret, :app_access_token, :code, :session_key
6
+ attr_accessor :oauth_test_data, :subscription_test_data
7
+ end
8
+
9
+ # Test setup
10
+
11
+ def self.setup_test_environment!
12
+ setup_rspec
13
+
14
+ unless ENV['LIVE']
15
+ # By default the Koala specs are run using stubs for HTTP requests,
16
+ # so they won't fail due to Facebook-imposed rate limits or server timeouts.
17
+ #
18
+ # However as a result they are more brittle since
19
+ # we are not testing the latest responses from the Facebook servers.
20
+ # To be certain all specs pass with the current Facebook services,
21
+ # run LIVE=true bundle exec rake spec.
22
+ Koala.http_service = Koala::MockHTTPService
23
+ KoalaTest.setup_test_data(Koala::MockHTTPService::TEST_DATA)
24
+ else
25
+ # Runs Koala specs through the Facebook servers
26
+ # using data for a real app
27
+ live_data = YAML.load_file(File.join(File.dirname(__FILE__), '../fixtures/facebook_data.yml'))
28
+ KoalaTest.setup_test_data(live_data)
29
+
30
+ # allow live tests with different adapters
31
+ adapter = ENV['ADAPTER'] || "typhoeus"# use Typhoeus by default if available
32
+ begin
33
+ require adapter
34
+ Faraday.default_adapter = adapter.to_sym
35
+ rescue LoadError
36
+ puts "Unable to load adapter #{adapter}, using Net::HTTP."
37
+ end
38
+
39
+ # use a test user unless the developer wants to test against a real profile
40
+ unless token = KoalaTest.oauth_token
41
+ KoalaTest.setup_test_users
42
+ else
43
+ KoalaTest.validate_user_info(token)
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.setup_rspec
49
+ # set up a global before block to set the token for tests
50
+ # set the token up for
51
+ RSpec.configure do |config|
52
+ config.before :each do
53
+ @token = KoalaTest.oauth_token
54
+ Koala::Utils.stub(:deprecate) # never fire deprecation warnings
55
+ end
56
+
57
+ config.after :each do
58
+ # clean up any objects posted to Facebook
59
+ if @temporary_object_id && !KoalaTest.mock_interface?
60
+ api = @api || (@test_users ? @test_users.graph_api : nil)
61
+ raise "Unable to locate API when passed temporary object to delete!" unless api
62
+
63
+ # wait 10ms to allow Facebook to propagate data so we can delete it
64
+ sleep(0.01)
65
+
66
+ # clean up any objects we've posted
67
+ result = (api.delete_object(@temporary_object_id) rescue false)
68
+ # if we errored out or Facebook returned false, track that
69
+ puts "Unable to delete #{@temporary_object_id}: #{result} (probably a photo or video, which can't be deleted through the API)" unless result
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def self.setup_test_data(data)
76
+ # make data accessible to all our tests
77
+ self.oauth_test_data = data["oauth_test_data"]
78
+ self.subscription_test_data = data["subscription_test_data"]
79
+ self.oauth_token = data["oauth_token"]
80
+ self.app_id = data["oauth_test_data"]["app_id"]
81
+ self.app_access_token = data["oauth_test_data"]["app_access_token"]
82
+ self.secret = data["oauth_test_data"]["secret"]
83
+ self.code = data["oauth_test_data"]["code"]
84
+ self.session_key = data["oauth_test_data"]["session_key"]
85
+ end
86
+
87
+ def self.testing_permissions
88
+ "read_stream, publish_stream, user_photos, user_videos, read_insights"
89
+ end
90
+
91
+ def self.setup_test_users
92
+ # note: we don't have to delete the two test users explicitly, since the test user specs do that for us
93
+ # technically, this is a point of brittleness and would break if the tests were run out of order
94
+ # however, for now we can live with it since it would slow tests way too much to constantly recreate our test users
95
+ print "Setting up test users..."
96
+ @test_user_api = Koala::Facebook::TestUsers.new(:app_id => self.app_id, :secret => self.secret)
97
+
98
+ # create two test users with specific names and befriend them
99
+ @live_testing_user = @test_user_api.create(true, testing_permissions, :name => user1_name)
100
+ @live_testing_friend = @test_user_api.create(true, testing_permissions, :name => user2_name)
101
+ @test_user_api.befriend(@live_testing_user, @live_testing_friend)
102
+ self.oauth_token = @live_testing_user["access_token"]
103
+
104
+ puts "done."
105
+ end
106
+
107
+ def self.validate_user_info(token)
108
+ print "Validating permissions for live testing..."
109
+ # make sure we have the necessary permissions
110
+ api = Koala::Facebook::API.new(token)
111
+ perms = api.fql_query("select #{testing_permissions} from permissions where uid = me()")[0]
112
+ perms.each_pair do |perm, value|
113
+ if value == (perm == "read_insights" ? 1 : 0) # live testing depends on insights calls failing
114
+ puts "failed!\n" # put a new line after the print above
115
+ raise ArgumentError, "Your access token must have the read_stream, publish_stream, and user_photos permissions, and lack read_insights. You have: #{perms.inspect}"
116
+ end
117
+ end
118
+ puts "done!"
119
+ end
120
+
121
+ # Info about the testing environment
122
+ def self.real_user?
123
+ !(mock_interface? || @test_user)
124
+ end
125
+
126
+ def self.test_user?
127
+ !!@test_user_api
128
+ end
129
+
130
+ def self.mock_interface?
131
+ Koala.http_service == Koala::MockHTTPService
132
+ end
133
+
134
+ # Data for testing
135
+ def self.user1
136
+ test_user? ? @live_testing_user["id"] : "koppel"
137
+ end
138
+
139
+ def self.user1_id
140
+ test_user? ? @live_testing_user["id"] : 2905623
141
+ end
142
+
143
+ def self.user1_name
144
+ "Alex"
145
+ end
146
+
147
+ def self.user2
148
+ test_user? ? @live_testing_friend["id"] : "lukeshepard"
149
+ end
150
+
151
+ def self.user2_id
152
+ test_user? ? @live_testing_friend["id"] : 2901279
153
+ end
154
+
155
+ def self.user2_name
156
+ "Luke"
157
+ end
158
+
159
+ def self.page
160
+ "contextoptional"
161
+ end
162
+
163
+ end