cotweet_koala 0.8.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,94 @@
1
+ shared_examples_for "Koala RestAPI without an access token" 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
+ :rest_api => true
22
+ )
23
+
24
+ @api.rest_call('anything')
25
+ end
26
+
27
+ it "should take an optional hash of arguments" do
28
+ args = {:arg1 => 'arg1'}
29
+
30
+ @api.should_receive(:api).with(
31
+ anything,
32
+ hash_including(args),
33
+ anything,
34
+ anything
35
+ )
36
+
37
+ @api.rest_call('anything', args)
38
+ end
39
+
40
+ it "should always ask for JSON" do
41
+ @api.should_receive(:api).with(
42
+ anything,
43
+ hash_including('format' => 'json'),
44
+ anything,
45
+ anything
46
+ )
47
+
48
+ @api.rest_call('anything')
49
+ end
50
+ end
51
+
52
+ # FQL_QUERY
53
+ describe "when making a FQL request" do
54
+ it "should call fql.query method" do
55
+ @api.should_receive(:rest_call).with(
56
+ "fql.query",
57
+ anything
58
+ ).and_return(Koala::Response.new(200, "2", {}))
59
+
60
+ @api.fql_query stub('query string')
61
+ end
62
+
63
+ it "should pass a query argument" do
64
+ query = stub('query string')
65
+
66
+ @api.should_receive(:rest_call).with(
67
+ anything,
68
+ hash_including("query" => query)
69
+ )
70
+
71
+ @api.fql_query(query)
72
+ end
73
+
74
+ it "should be able to access public information via FQL" do
75
+ @result = @api.fql_query("select first_name from user where uid = 216743")
76
+ @result.size.should == 1
77
+ @result.first["first_name"].should == "Chris"
78
+ end
79
+
80
+ it "should not be able to access protected information via FQL" do
81
+ lambda { @api.fql_query("select read_stream from permissions where uid = 216743") }.should raise_error(Koala::Facebook::APIError)
82
+ end
83
+ end
84
+ end
85
+
86
+ class FacebookRestAPINoAccessTokenTest < Test::Unit::TestCase
87
+ before :each do
88
+ @api = Koala::Facebook::RestAPI.new
89
+ end
90
+
91
+ describe "Koala RestAPI without an access token" do
92
+ it_should_behave_like "Koala RestAPI without an access token"
93
+ end
94
+ end
@@ -0,0 +1,36 @@
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
+ it_should_behave_like "live testing examples"
30
+ it_should_behave_like "Koala RestAPI with an access token"
31
+
32
+ before :each do
33
+ @api = Koala::Facebook::RestAPI.new(@token)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
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
@@ -0,0 +1,30 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'spec/test/unit'
4
+
5
+ # load the libraries
6
+ require 'koala'
7
+
8
+ # load testing data libraries
9
+ require 'koala/live_testing_data_helper'
10
+
11
+ # API tests
12
+ require 'koala/api_base_tests'
13
+
14
+ require 'koala/graph_api/graph_api_no_access_token_tests'
15
+ require 'koala/graph_api/graph_api_with_access_token_tests'
16
+
17
+ require 'koala/rest_api/rest_api_no_access_token_tests'
18
+ require 'koala/rest_api/rest_api_with_access_token_tests'
19
+
20
+ require 'koala/graph_and_rest_api/graph_and_rest_api_no_token_tests'
21
+ require 'koala/graph_and_rest_api/graph_and_rest_api_with_token_tests'
22
+
23
+ # OAuth tests
24
+ require 'koala/oauth/oauth_tests'
25
+
26
+ # Subscriptions tests
27
+ require 'koala/realtime_updates/realtime_updates_tests'
28
+
29
+ # Services tests
30
+ require 'koala/net_http_service_tests'
@@ -0,0 +1,19 @@
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
+ # I'm seeing a bug with spec and gets where the facebook_test_suite.rb file gets read in when gets is called
10
+ # until that's solved, we'll need to store/update tokens in the access_token file
11
+ $testing_data = YAML.load_file(File.join(File.dirname(__FILE__), 'facebook_data.yml')) rescue {}
12
+
13
+ unless $testing_data["oauth_token"]
14
+ puts "Access token tests will fail until you store a valid token in facebook_data.yml"
15
+ end
16
+
17
+ unless $testing_data["oauth_test_data"] && $testing_data["oauth_test_data"]["code"] && $testing_data["oauth_test_data"]["secret"]
18
+ puts "Cookie tests will fail until you store valid data for the cookie hash, app_id, and app secret in facebook_data.yml"
19
+ end
@@ -0,0 +1,228 @@
1
+ # Responses by MockHTTPService are taken directly from
2
+ # this file.
3
+ #
4
+ # Structure
5
+ # ----------
6
+ #
7
+ # path:
8
+ # arguments: # sorted by key
9
+ # method: # HTTP method (GET, POST, DELETE, etc.)
10
+ # with_token:
11
+ # no_token:
12
+
13
+ # ====== REST API =====
14
+ rest_api:
15
+
16
+ # -- Stubbed Responses --
17
+ method/fql.query:
18
+ query=select first_name from user where uid = 216743:
19
+ get:
20
+ no_token: '[{"first_name":"Chris"}]'
21
+ with_token: '[{"first_name":"Chris"}]'
22
+ query=select read_stream from permissions where uid = 216743:
23
+ get:
24
+ with_token: '[{"read_stream":1}]'
25
+ no_token: '{"error_code":104,"error_msg":"Requires valid signature","request_args":[{"key":"method","value":"fql.query"},{"key":"format","value":"json"},{"key":"query","value":"select read_stream from permissions where uid = 216743"}]}'
26
+
27
+
28
+ # ====== GRAPH API =====
29
+ graph_api:
30
+
31
+ # -- Common Responses --
32
+
33
+ # Error responses for when a token is required, but not given
34
+ token_required_responses: &token_required
35
+ no_token: '{"error":{"type":"OAuthAccessTokenException", "message":"An access token is required to request this resource."}}'
36
+
37
+ # Common mock item responses
38
+ item_deleted: &item_deleted
39
+ delete:
40
+ with_token: 'true'
41
+
42
+ # OAuth error response
43
+ oauth_error: &oauth_error
44
+ no_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
45
+
46
+ # Subscription error response
47
+ verification_error: &verification_error
48
+ with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
49
+
50
+ # -- Stubbed Responses --
51
+ root:
52
+ ids=contextoptional,naitik:
53
+ get:
54
+ with_token: '[{}, {}]'
55
+ no_token: '[{}, {}]'
56
+ me:
57
+ no_args:
58
+ get:
59
+ <<: *token_required
60
+ with_token: '{"updated_time": 1}'
61
+ fields=id:
62
+ get:
63
+ with_token: '{"id": "216743"}'
64
+
65
+ me/feed:
66
+ message=Hello, world, from the test suite!:
67
+ post:
68
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
69
+ message=Hello, world, from the test suite, testing comments!:
70
+ post:
71
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
72
+ message=the cats are asleep:
73
+ post:
74
+ with_token: '{"id": "FEED_ITEM_CATS"}'
75
+ message=Hello, world, from the test suite delete method!:
76
+ post:
77
+ with_token: '{"id": "FEED_ITEM_DELETE"}'
78
+ link=http://www.contextoptional.com/&message=Hello, world, from the test suite again!&name=Context Optional:
79
+ post:
80
+ with_token: '{"id": "FEED_ITEM_CONTEXT"}'
81
+
82
+ koppel:
83
+ no_args:
84
+ get:
85
+ with_token: '{"id": 1, "name": 1, "updated_time": 1}'
86
+ no_token: '{"id": 1, "name": 1}'
87
+
88
+ contextoptional:
89
+ no_args:
90
+ get:
91
+ with_token: '{"id": 1, "name": 1}'
92
+ no_token: '{"id": 1, "name": 1}'
93
+
94
+ contextoptional/likes:
95
+ no_args:
96
+ get:
97
+ with_token: '{"data": [{}]}'
98
+ no_token: '{"data": [{}]}'
99
+
100
+ lukeshepard/likes:
101
+ no_args:
102
+ get:
103
+ <<: *token_required
104
+ with_token: '{"data": [{}]}'
105
+
106
+ chris.baclig/picture:
107
+ no_args:
108
+ get:
109
+ no_token:
110
+ code: 302
111
+ headers:
112
+ Location: http://facebook.com/
113
+ with_token:
114
+ code: 302
115
+ headers:
116
+ Location: http://facebook.com/
117
+ type=large:
118
+ get:
119
+ no_token:
120
+ code: 302
121
+ headers:
122
+ Location: http://facebook.com/large
123
+ with_token:
124
+ code: 302
125
+ headers:
126
+ Location: http://facebook.com/large
127
+
128
+
129
+ search:
130
+ q=facebook:
131
+ get:
132
+ with_token: '{"data": [{"id": "507731521_100412693339488"}]}'
133
+ no_token: '{"data": [{"id": "507731521_100412693339488"}]}'
134
+
135
+ '115349521819193_113815981982767':
136
+ no_args:
137
+ delete:
138
+ <<: *token_required
139
+
140
+ # -- OAuth responses --
141
+ oauth/access_token:
142
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=<%= OAUTH_CODE %>&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
143
+ get:
144
+ no_token: access_token=<%= ACCESS_TOKEN %>
145
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
146
+ get:
147
+ <<: *oauth_error
148
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&type=client_cred:
149
+ post:
150
+ no_token: access_token=<%= ACCESS_TOKEN %>
151
+ oauth/exchange_sessions:
152
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
153
+ post:
154
+ no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
155
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["multiple_session_keys"].join(",") %>&type=client_cred:
156
+ post:
157
+ no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
158
+
159
+
160
+
161
+ # -- Subscription Responses --
162
+ <%= APP_ID %>/subscriptions:
163
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
164
+ post:
165
+ with_token:
166
+ code: 200
167
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
168
+ post:
169
+ with_token: '{"error":{"type":"Exception","message":"(#2200) subscription validation failed"}}'
170
+ callback_url=foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
171
+ post:
172
+ with_token: '{"error":{"type":"Exception","message":"(#100) callback_url URL is not properly formatted"}}'
173
+ object=user:
174
+ delete:
175
+ with_token:
176
+ code: 200
177
+ object=kittens:
178
+ delete:
179
+ with_token: '{"error":{"type":"Exception","message":"(#100) Invalid parameter"}}'
180
+ no_args:
181
+ delete:
182
+ with_token:
183
+ code: 200
184
+ get:
185
+ with_token: '{"data":[{"callback_url":"http://oauth.twoalex.com/subscriptions", "fields":["name"], "object":"user", "active":true}]}'
186
+
187
+
188
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>:
189
+ get:
190
+ with_token: '{"data":[{"callback_url":"http://oauth.twoalex.com/subscriptions", "fields":["name"], "object":"user", "active":true}]}'
191
+
192
+ # -- Mock Item Responses --
193
+
194
+ MOCK_FEED_ITEM/likes:
195
+ no_args:
196
+ post:
197
+ with_token: '{"id": "MOCK_LIKE"}'
198
+
199
+ MOCK_FEED_ITEM/comments:
200
+ message=it's my comment!:
201
+ post:
202
+ with_token: '{"id": "MOCK_COMMENT"}'
203
+
204
+ MOCK_FEED_ITEM:
205
+ no_args:
206
+ <<: *item_deleted
207
+
208
+ FEED_ITEM_CONTEXT:
209
+ no_args:
210
+ <<: *item_deleted
211
+ get:
212
+ with_token: '{"link":"http://www.contextoptional.com/", "name": "Context Optional"}'
213
+
214
+ FEED_ITEM_CATS:
215
+ no_args:
216
+ <<: *item_deleted
217
+ get:
218
+ with_token: '{"message": "the cats are asleep"}'
219
+
220
+ FEED_ITEM_DELETE:
221
+ no_args:
222
+ <<: *item_deleted
223
+
224
+ MOCK_COMMENT:
225
+ no_args:
226
+ <<: *item_deleted
227
+ get:
228
+ with_token: "{\"message\": \"it\'s my comment!\"}"
@@ -0,0 +1,81 @@
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
+
8
+ # Mocked values to be included in TEST_DATA used in specs
9
+ ACCESS_TOKEN = '*'
10
+ OAUTH_CODE = 'OAUTHCODE'
11
+
12
+ # Loads testing data
13
+ TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), 'facebook_data.yml'))
14
+ TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
15
+ TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
16
+
17
+ # Useful in mock_facebook_responses.yml
18
+ OAUTH_DATA = TEST_DATA['oauth_test_data']
19
+ OAUTH_DATA.merge!({
20
+ 'app_access_token' => Koala::MockHTTPService::ACCESS_TOKEN,
21
+ 'session_key' => "session_key",
22
+ 'multiple_session_keys' => ["session_key", "session_key_2"]
23
+ })
24
+ APP_ID = OAUTH_DATA['app_id']
25
+ SECRET = OAUTH_DATA['secret']
26
+ SUBSCRIPTION_DATA = TEST_DATA["subscription_test_data"]
27
+
28
+ # Loads the mock response data via ERB to substitue values for TEST_DATA (see oauth/access_token)
29
+ mock_response_file_path = File.join(File.dirname(__FILE__), 'mock_facebook_responses.yml')
30
+ RESPONSES = YAML.load(ERB.new(IO.read(mock_response_file_path)).result(binding))
31
+
32
+ def self.included(base)
33
+ base.class_eval do
34
+
35
+ def self.make_request(path, args, verb, options = {})
36
+ path = 'root' if path == ''
37
+ verb ||= 'get'
38
+ server = options[:rest_api] ? 'rest_api' : 'graph_api'
39
+ with_token = args.delete('access_token') == ACCESS_TOKEN ? 'with_token' : 'no_token'
40
+
41
+ # Assume format is always JSON
42
+ args.delete('format')
43
+
44
+ # Create a hash key for the arguments
45
+ args = args.empty? ? 'no_args' : args.sort{|a,b| a[0].to_s <=> b[0].to_s }.map{|arr| arr.join('=')}.join('&')
46
+
47
+ begin
48
+ response = RESPONSES[server][path][args][verb][with_token]
49
+
50
+ # Raises an error of with_token/no_token key is missing
51
+ raise NoMethodError unless response
52
+
53
+ # create response class object
54
+ response_object = if response.is_a? String
55
+ Koala::Response.new(200, response, {})
56
+ else
57
+ Koala::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
58
+ end
59
+
60
+ rescue NoMethodError
61
+ # Raises an error message with the place in the data YML
62
+ # to place a mock as well as a URL to request from
63
+ # Facebook's servers for the actual data
64
+ # (Don't forget to replace ACCESS_TOKEN with a real access token)
65
+
66
+ data_trace = [server, path, args, verb, with_token] * ': '
67
+
68
+ args = args == 'no_args' ? '' : "#{args}&"
69
+ args += 'format=json'
70
+ args += "&access_token=#{ACCESS_TOKEN}" if with_token
71
+
72
+ raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[path, args].join('?')}"
73
+ end
74
+
75
+ response_object
76
+ end
77
+
78
+ end # class_eval
79
+ end # included
80
+ end
81
+ end