koala 1.0.0.beta → 1.1.0

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 (69) hide show
  1. data/.autotest +12 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG +42 -4
  5. data/Gemfile +7 -0
  6. data/LICENSE +1 -1
  7. data/Manifest +5 -2
  8. data/Rakefile +13 -14
  9. data/autotest/discover.rb +1 -0
  10. data/koala.gemspec +35 -20
  11. data/lib/koala/batch_operation.rb +74 -0
  12. data/lib/koala/graph_api.rb +196 -143
  13. data/lib/koala/graph_batch_api.rb +87 -0
  14. data/lib/koala/graph_collection.rb +54 -0
  15. data/lib/koala/http_services/net_http_service.rb +92 -0
  16. data/lib/koala/http_services/typhoeus_service.rb +37 -0
  17. data/lib/koala/http_services.rb +15 -124
  18. data/lib/koala/oauth.rb +181 -0
  19. data/lib/koala/realtime_updates.rb +5 -14
  20. data/lib/koala/rest_api.rb +13 -8
  21. data/lib/koala/test_users.rb +21 -8
  22. data/lib/koala/uploadable_io.rb +175 -0
  23. data/lib/koala.rb +48 -240
  24. data/readme.md +60 -28
  25. data/spec/cases/api_base_spec.rb +101 -0
  26. data/spec/cases/graph_and_rest_api_spec.rb +31 -0
  27. data/spec/cases/graph_api_batch_spec.rb +609 -0
  28. data/spec/cases/graph_api_spec.rb +25 -0
  29. data/spec/cases/http_services/http_service_spec.rb +129 -0
  30. data/spec/cases/http_services/net_http_service_spec.rb +532 -0
  31. data/spec/cases/http_services/typhoeus_service_spec.rb +152 -0
  32. data/spec/cases/koala_spec.rb +55 -0
  33. data/spec/cases/oauth_spec.rb +409 -0
  34. data/spec/cases/realtime_updates_spec.rb +184 -0
  35. data/spec/cases/rest_api_spec.rb +25 -0
  36. data/spec/{koala/test_users/test_users_tests.rb → cases/test_users_spec.rb} +47 -34
  37. data/spec/cases/uploadable_io_spec.rb +193 -0
  38. data/spec/fixtures/cat.m4v +0 -0
  39. data/spec/{facebook_data.yml → fixtures/facebook_data.yml} +12 -14
  40. data/spec/{mock_facebook_responses.yml → fixtures/mock_facebook_responses.yml} +408 -306
  41. data/spec/spec_helper.rb +19 -0
  42. data/spec/support/graph_api_shared_examples.rb +495 -0
  43. data/spec/support/json_testing_fix.rb +18 -0
  44. data/spec/{koala → support}/live_testing_data_helper.rb +39 -42
  45. data/spec/support/mock_http_service.rb +96 -0
  46. data/spec/support/rest_api_shared_examples.rb +285 -0
  47. data/spec/support/setup_mocks_or_live.rb +51 -0
  48. data/spec/support/uploadable_io_shared_examples.rb +76 -0
  49. metadata +110 -64
  50. data/init.rb +0 -2
  51. data/spec/koala/api_base_tests.rb +0 -102
  52. data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +0 -14
  53. data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +0 -16
  54. data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +0 -63
  55. data/spec/koala/graph_api/graph_api_tests.rb +0 -86
  56. data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +0 -154
  57. data/spec/koala/graph_api/graph_collection_tests.rb +0 -104
  58. data/spec/koala/net_http_service_tests.rb +0 -430
  59. data/spec/koala/oauth/oauth_tests.rb +0 -409
  60. data/spec/koala/realtime_updates/realtime_updates_tests.rb +0 -187
  61. data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +0 -25
  62. data/spec/koala/rest_api/rest_api_tests.rb +0 -118
  63. data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +0 -38
  64. data/spec/koala/typhoeus_service_tests.rb +0 -156
  65. data/spec/koala_spec.rb +0 -18
  66. data/spec/koala_spec_helper.rb +0 -70
  67. data/spec/koala_spec_without_mocks.rb +0 -19
  68. data/spec/mock_http_service.rb +0 -96
  69. /data/spec/{koala/assets → fixtures}/beach.jpg +0 -0
@@ -1,118 +0,0 @@
1
- shared_examples_for "Koala RestAPI" do
2
- # REST_CALL
3
- describe "when making a rest request" do
4
- it "should use the proper path" do
5
- method = stub('methodName')
6
- @api.should_receive(:api).with(
7
- "method/#{method}",
8
- anything,
9
- anything,
10
- anything
11
- )
12
-
13
- @api.rest_call(method)
14
- end
15
-
16
- it "should always use the rest api" do
17
- @api.should_receive(:api).with(
18
- anything,
19
- anything,
20
- anything,
21
- hash_including(:rest_api => true)
22
- )
23
-
24
- @api.rest_call('anything')
25
- end
26
-
27
- it "should set the read_only option to true if the method is listed in the read-only list" do
28
- method = Koala::Facebook::RestAPI::READ_ONLY_METHODS.first
29
-
30
- @api.should_receive(:api).with(
31
- anything,
32
- anything,
33
- anything,
34
- hash_including(:read_only => true)
35
- )
36
-
37
- @api.rest_call(method)
38
- end
39
-
40
- it "should set the read_only option to false if the method is not inthe read-only list" do
41
- method = "I'm not a read-only method"
42
-
43
- @api.should_receive(:api).with(
44
- anything,
45
- anything,
46
- anything,
47
- hash_including(:read_only => false)
48
- )
49
-
50
- @api.rest_call(method)
51
- end
52
-
53
-
54
- it "should take an optional hash of arguments" do
55
- args = {:arg1 => 'arg1'}
56
-
57
- @api.should_receive(:api).with(
58
- anything,
59
- hash_including(args),
60
- anything,
61
- anything
62
- )
63
-
64
- @api.rest_call('anything', args)
65
- end
66
-
67
- it "should always ask for JSON" do
68
- @api.should_receive(:api).with(
69
- anything,
70
- hash_including('format' => 'json'),
71
- anything,
72
- anything
73
- )
74
-
75
- @api.rest_call('anything')
76
- end
77
-
78
- it "should pass any options provided to the API" do
79
- options = {:a => 2}
80
-
81
- @api.should_receive(:api).with(
82
- anything,
83
- hash_including('format' => 'json'),
84
- anything,
85
- hash_including(options)
86
- )
87
-
88
- @api.rest_call('anything', {}, options)
89
- end
90
-
91
- it "should throw an APIError if the result hash has an error key" do
92
- Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error_code" => "An error occurred!"}, {}))
93
- lambda { @api.rest_call("koppel", {}) }.should raise_exception(Koala::Facebook::APIError)
94
- end
95
-
96
- describe "when making a FQL request" do
97
- it "should call fql.query method" do
98
- @api.should_receive(:rest_call).with(
99
- "fql.query",
100
- anything
101
- ).and_return(Koala::Response.new(200, "2", {}))
102
-
103
- @api.fql_query stub('query string')
104
- end
105
-
106
- it "should pass a query argument" do
107
- query = stub('query string')
108
-
109
- @api.should_receive(:rest_call).with(
110
- anything,
111
- hash_including("query" => query)
112
- )
113
-
114
- @api.fql_query(query)
115
- end
116
- end
117
- end
118
- end
@@ -1,38 +0,0 @@
1
- shared_examples_for "Koala RestAPI with an access token" do
2
- # FQL
3
- it "should be able to access public information via FQL" do
4
- result = @api.fql_query('select first_name from user where uid = 216743')
5
- result.size.should == 1
6
- result.first['first_name'].should == 'Chris'
7
- end
8
-
9
- it "should be able to access protected information via FQL" do
10
- # Tests agains the permissions fql table
11
-
12
- # get the current user's ID
13
- # we're sneakily using the Graph API, which should be okay since it has its own tests
14
- g = Koala::Facebook::GraphAPI.new(@token)
15
- id = g.get_object("me", :fields => "id")["id"]
16
-
17
- # now send a query about your permissions
18
- result = @api.fql_query("select read_stream from permissions where uid = #{id}")
19
-
20
- result.size.should == 1
21
- # we assume that you have read_stream permissions, so we can test against that
22
- # (should we keep this?)
23
- result.first["read_stream"].should == 1
24
- end
25
- end
26
-
27
- class FacebookRestAPIWithAccessTokenTests < Test::Unit::TestCase
28
- describe "Koala RestAPI with an access token" do
29
- include LiveTestingDataHelper
30
-
31
- before :each do
32
- @api = Koala::Facebook::RestAPI.new(@token)
33
- end
34
-
35
- it_should_behave_like "Koala RestAPI"
36
- it_should_behave_like "Koala RestAPI with an access token"
37
- end
38
- end
@@ -1,156 +0,0 @@
1
- require 'koala/http_services'
2
- class TyphoeusServiceTests < Test::Unit::TestCase
3
- module Bear
4
- include Koala::TyphoeusService
5
- end
6
-
7
- describe "TyphoeusService module holder class Bear" do
8
- before :each do
9
- # reset the always_use_ssl parameter
10
- Bear.always_use_ssl = nil
11
- end
12
-
13
- it "should define a make_request static module method" do
14
- Bear.respond_to?(:make_request).should be_true
15
- end
16
-
17
- it "should include the Koala::HTTPService module defining common features" do
18
- Bear.included_modules.include?(Koala::HTTPService).should be_true
19
- end
20
-
21
- describe "when making a request" do
22
- before(:each) do
23
- # Setup stubs for make_request to execute without exceptions
24
- @mock_body = stub('Typhoeus response body')
25
- @mock_headers_hash = stub({:value => "headers hash"})
26
- @mock_http_response = stub(Typhoeus::Response, :code => 1, :headers_hash => @mock_headers_hash, :body => @mock_body)
27
-
28
- # Typhoeus is an included module, so we stub methods on Bear itself
29
- Bear.stub(:post).and_return(@mock_http_response)
30
- Bear.stub(:get).and_return(@mock_http_response)
31
- end
32
-
33
- it "should use POST if verb is not GET" do
34
- Bear.should_receive(:post).and_return(@mock_http_response)
35
- Bear.make_request('anything', {}, 'anything')
36
- end
37
-
38
- it "should use GET if that verb is specified" do
39
- Bear.should_receive(:get).and_return(@mock_http_response)
40
- Bear.make_request('anything', {}, 'get')
41
- end
42
-
43
- describe "the connection" do
44
- it "should use SSL if the request has an access token" do
45
- Bear.should_receive(:post).with(/https\:/, anything)
46
-
47
- Bear.make_request('anything', {"access_token" => "123"}, 'anything')
48
- end
49
-
50
- it "should use SSL if always_use_ssl is true, even if there's no token" do
51
- Bear.should_receive(:post).with(/https\:/, anything)
52
-
53
- Bear.always_use_ssl = true
54
- Bear.make_request('anything', {}, 'anything')
55
- end
56
-
57
- it "should use SSL if the :use_ssl option is provided, even if there's no token" do
58
- Bear.should_receive(:post).with(/https\:/, anything)
59
-
60
- Bear.always_use_ssl = true
61
- Bear.make_request('anything', {}, 'anything', :use_ssl => true)
62
- end
63
-
64
- it "should not use SSL if always_use_ssl is false and there's no token" do
65
- Bear.should_receive(:post).with(/http\:/, anything)
66
-
67
- Bear.make_request('anything', {}, 'anything')
68
- end
69
-
70
- it "should use the graph server by default" do
71
- Bear.should_receive(:post).with(Regexp.new(Koala::Facebook::GRAPH_SERVER), anything)
72
-
73
- Bear.make_request('anything', {}, 'anything')
74
- end
75
-
76
- it "should use the REST server if the :rest_api option is true" do
77
- Bear.should_receive(:post).with(Regexp.new(Koala::Facebook::REST_SERVER), anything)
78
-
79
- Bear.make_request('anything', {}, 'anything', :rest_api => true)
80
- end
81
- end
82
-
83
- it "should pass the arguments to Typhoeus under the :params key" do
84
- args = {:a => 2}
85
- Bear.should_receive(:post).with(anything, hash_including(:params => args))
86
-
87
- Bear.make_request('anything', args, "post")
88
- end
89
-
90
- it "should add the method to the arguments if the method isn't get or post" do
91
- method = "telekenesis"
92
- Bear.should_receive(:post).with(anything, hash_including(:params => {:method => method}))
93
-
94
- Bear.make_request('anything', {}, method)
95
- end
96
-
97
- it "should pass :typhoeus_options to Typhoeus if provided" do
98
- t_options = {:a => :b}
99
- Bear.should_receive(:post).with(anything, hash_including(t_options))
100
-
101
- Bear.make_request("anything", {}, "post", :typhoeus_options => t_options)
102
- end
103
-
104
- it "should include the path in the request" do
105
- path = "/a/b/c/1"
106
- Bear.should_receive(:post).with(Regexp.new(path), anything)
107
-
108
- Bear.make_request(path, {}, "post")
109
- end
110
-
111
- describe "the returned value" do
112
- before(:each) do
113
- @response = Bear.make_request('anything', {}, 'anything')
114
- end
115
-
116
- it "should return a Koala::Response object" do
117
- @response.class.should == Koala::Response
118
- end
119
-
120
- it "should return a Koala::Response with the right status" do
121
- @response.status.should == @mock_http_response.code
122
- end
123
-
124
- it "should reutrn a Koala::Response with the right body" do
125
- @response.body.should == @mock_body
126
- end
127
-
128
- it "should return a Koala::Response with the Net::HTTPResponse object as headers" do
129
- @response.headers.should == @mock_headers_hash
130
- end
131
- end # describe return value
132
- end
133
-
134
- describe "with file upload" do
135
- it "should include an interface to NetHTTPService called NetHTTPInterface" do
136
- # we should be able to access it
137
- lambda { Koala::TyphoeusService::NetHTTPInterface }.should_not raise_exception(Exception)
138
- Koala::TyphoeusService::NetHTTPInterface.included_modules.include?(Koala::NetHTTPService).should be_true
139
- end
140
-
141
- it "should call the NetHTTPInterface if multipart is required" do
142
- method = "any_method"
143
- args = {}
144
- verb = "get"
145
- options = {}
146
-
147
- Bear.stub(:params_require_multipart?).and_return(true)
148
- Koala::TyphoeusService::NetHTTPInterface.should_receive(:make_request).with(method, args, verb, options)
149
-
150
- Bear.make_request(method, args, verb, options)
151
- end
152
-
153
- # for live tests, run the Graph API tests with Typhoues, which will run file uploads
154
- end
155
- end
156
- end
data/spec/koala_spec.rb DELETED
@@ -1,18 +0,0 @@
1
- require 'koala_spec_helper'
2
- require 'mock_http_service'
3
-
4
- # Runs Koala specs using stubs for HTTP requests
5
- #
6
- # Valid OAuth token and code are not necessary to run these
7
- # specs. Because of this, specs do not fail due to Facebook
8
- # imposed rate-limits or server timeouts.
9
- #
10
- # However as a result they are more brittle since
11
- # we are not testing the latest responses from the Facebook servers.
12
- # Therefore, to be certain all specs pass with the current
13
- # Facebook services, run koala_spec_without_mocks.rb.
14
-
15
-
16
- Koala.http_service = Koala::MockHTTPService
17
-
18
- $testing_data = Koala::MockHTTPService::TEST_DATA
@@ -1,70 +0,0 @@
1
- if defined?(RUBY_VERSION) && RUBY_VERSION =~ /1\.9/
2
- require 'test/unit'
3
- require 'rspec'
4
-
5
- Rspec.configure do |c|
6
- c.mock_with :rspec
7
- end
8
-
9
- else
10
- # Ruby 1.8.x
11
- require 'test/unit'
12
- require 'rubygems'
13
-
14
- require 'spec/test/unit'
15
- end
16
-
17
- # load the libraries
18
- require 'koala'
19
-
20
- # load testing data libraries
21
- require 'koala/live_testing_data_helper'
22
-
23
- # API tests
24
- require 'koala/api_base_tests'
25
-
26
- require 'koala/graph_api/graph_api_tests'
27
- require 'koala/graph_api/graph_collection_tests'
28
- require 'koala/graph_api/graph_api_no_access_token_tests'
29
- require 'koala/graph_api/graph_api_with_access_token_tests'
30
-
31
- require 'koala/rest_api/rest_api_tests'
32
- require 'koala/rest_api/rest_api_no_access_token_tests'
33
- require 'koala/rest_api/rest_api_with_access_token_tests'
34
-
35
- require 'koala/graph_and_rest_api/graph_and_rest_api_no_token_tests'
36
- require 'koala/graph_and_rest_api/graph_and_rest_api_with_token_tests'
37
-
38
- # OAuth tests
39
- require 'koala/oauth/oauth_tests'
40
-
41
- # Subscriptions tests
42
- require 'koala/realtime_updates/realtime_updates_tests'
43
-
44
- # Test users tests
45
- require 'koala/test_users/test_users_tests'
46
-
47
- # Services tests
48
- require 'koala/net_http_service_tests'
49
- begin
50
- require 'koala/typhoeus_service_tests'
51
- rescue LoadError
52
- puts "Typhoeus tests will not be run because Typhoeus is not installed."
53
- end
54
-
55
- module KoalaTest
56
- def self.validate_user_info(token)
57
- print "Validating permissions for live testing..."
58
- # make sure we have the necessary permissions
59
- api = Koala::Facebook::GraphAndRestAPI.new(token)
60
- uid = api.get_object("me")["id"]
61
- perms = api.fql_query("select read_stream, publish_stream, user_photos from permissions where uid = #{uid}")[0]
62
- perms.each_pair do |perm, value|
63
- unless value == 1
64
- puts "failed!\n" # put a new line after the print above
65
- raise ArgumentError, "Your access token must have the read_stream, publish_stream, and user_photos permissions. You have: #{perms.inspect}"
66
- end
67
- end
68
- puts "done!"
69
- end
70
- end
@@ -1,19 +0,0 @@
1
- require 'koala_spec_helper'
2
-
3
- # Runs Koala specs through the Facebook servers
4
- #
5
- # Note that you need a valid OAuth token and code for these
6
- # specs to run. See facebook_data.yml for more information.
7
-
8
- # load testing data (see note in readme.md)
9
- $testing_data = YAML.load_file(File.join(File.dirname(__FILE__), 'facebook_data.yml')) rescue {}
10
-
11
- unless $testing_data["oauth_token"]
12
- puts "Access token tests will fail until you store a valid token in facebook_data.yml"
13
- end
14
-
15
- unless $testing_data["oauth_test_data"] && $testing_data["oauth_test_data"]["code"] && $testing_data["oauth_test_data"]["secret"]
16
- puts "OAuth code tests will fail until you store valid data for the user's OAuth code and the app secret in facebook_data.yml"
17
- end
18
-
19
- KoalaTest.validate_user_info $testing_data["oauth_token"]
@@ -1,96 +0,0 @@
1
- require 'erb'
2
- require 'yaml'
3
-
4
- module Koala
5
- module MockHTTPService
6
- # Mocks all HTTP requests for with koala_spec_with_mocks.rb
7
- IS_MOCK = true # this lets our tests figure out if we want to stub methods
8
-
9
- # Mocked values to be included in TEST_DATA used in specs
10
- ACCESS_TOKEN = '*'
11
- OAUTH_CODE = 'OAUTHCODE'
12
-
13
- # Loads testing data
14
- TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), 'facebook_data.yml'))
15
- TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
16
- TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
17
-
18
- # Useful in mock_facebook_responses.yml
19
- OAUTH_DATA = TEST_DATA['oauth_test_data']
20
- OAUTH_DATA.merge!({
21
- 'app_access_token' => Koala::MockHTTPService::ACCESS_TOKEN,
22
- 'session_key' => "session_key",
23
- 'multiple_session_keys' => ["session_key", "session_key_2"]
24
- })
25
- APP_ID = OAUTH_DATA['app_id']
26
- SECRET = OAUTH_DATA['secret']
27
- SUBSCRIPTION_DATA = TEST_DATA["subscription_test_data"]
28
-
29
- # Loads the mock response data via ERB to substitue values for TEST_DATA (see oauth/access_token)
30
- mock_response_file_path = File.join(File.dirname(__FILE__), 'mock_facebook_responses.yml')
31
- RESPONSES = YAML.load(ERB.new(IO.read(mock_response_file_path)).result(binding))
32
-
33
- def self.included(base)
34
- base.class_eval do
35
-
36
- include Koala::HTTPService
37
-
38
- def self.make_request(path, args, verb, options = {})
39
- path = 'root' if path == '' || path == '/'
40
- verb ||= 'get'
41
- server = options[:rest_api] ? 'rest_api' : 'graph_api'
42
- with_token = args.delete('access_token') == ACCESS_TOKEN ? 'with_token' : 'no_token'
43
-
44
- # Assume format is always JSON
45
- args.delete('format')
46
-
47
- # Create a hash key for the arguments
48
- args = create_params_key(args)
49
-
50
- begin
51
- response = RESPONSES[server][path][args][verb][with_token]
52
-
53
- # Raises an error of with_token/no_token key is missing
54
- raise NoMethodError unless response
55
-
56
- # create response class object
57
- response_object = if response.is_a? String
58
- Koala::Response.new(200, response, {})
59
- else
60
- Koala::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
61
- end
62
-
63
- rescue NoMethodError
64
- # Raises an error message with the place in the data YML
65
- # to place a mock as well as a URL to request from
66
- # Facebook's servers for the actual data
67
- # (Don't forget to replace ACCESS_TOKEN with a real access token)
68
-
69
- data_trace = [server, path, args, verb, with_token] * ': '
70
-
71
- args = args == 'no_args' ? '' : "#{args}&"
72
- args += 'format=json'
73
- args += "&access_token=#{ACCESS_TOKEN}" if with_token
74
-
75
- raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[path, args].join('?')}"
76
- end
77
-
78
- response_object
79
- end
80
-
81
- protected
82
- def self.create_params_key(params_hash)
83
- if params_hash.empty?
84
- 'no_args'
85
- else
86
- params_hash.sort{ |a,b| a[0].to_s <=> b[0].to_s}.map do |arr|
87
- arr[1] = '[FILE]' if arr[1].kind_of?(File) || is_valid_file_hash?(arr[1])
88
- arr.join('=')
89
- end.join('&')
90
- end
91
- end
92
-
93
- end # class_eval
94
- end # included
95
- end
96
- end
File without changes