koala 1.0.0 → 1.2.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 (54) hide show
  1. data/.autotest +12 -0
  2. data/.gitignore +3 -1
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +62 -2
  5. data/Gemfile +8 -0
  6. data/Rakefile +0 -1
  7. data/autotest/discover.rb +1 -0
  8. data/koala.gemspec +13 -14
  9. data/lib/koala/batch_operation.rb +74 -0
  10. data/lib/koala/graph_api.rb +145 -132
  11. data/lib/koala/graph_batch_api.rb +97 -0
  12. data/lib/koala/graph_collection.rb +59 -0
  13. data/lib/koala/http_service.rb +176 -0
  14. data/lib/koala/oauth.rb +191 -0
  15. data/lib/koala/realtime_updates.rb +23 -29
  16. data/lib/koala/rest_api.rb +13 -8
  17. data/lib/koala/test_users.rb +33 -17
  18. data/lib/koala/uploadable_io.rb +153 -87
  19. data/lib/koala/utils.rb +11 -0
  20. data/lib/koala/version.rb +3 -0
  21. data/lib/koala.rb +59 -217
  22. data/readme.md +92 -53
  23. data/spec/cases/{api_base_spec.rb → api_spec.rb} +31 -6
  24. data/spec/cases/error_spec.rb +32 -0
  25. data/spec/cases/graph_and_rest_api_spec.rb +12 -21
  26. data/spec/cases/graph_api_batch_spec.rb +582 -0
  27. data/spec/cases/graph_api_spec.rb +11 -14
  28. data/spec/cases/graph_collection_spec.rb +116 -0
  29. data/spec/cases/http_service_spec.rb +446 -0
  30. data/spec/cases/koala_spec.rb +54 -0
  31. data/spec/cases/oauth_spec.rb +319 -213
  32. data/spec/cases/realtime_updates_spec.rb +45 -31
  33. data/spec/cases/rest_api_spec.rb +23 -7
  34. data/spec/cases/test_users_spec.rb +123 -75
  35. data/spec/cases/uploadable_io_spec.rb +120 -37
  36. data/spec/cases/utils_spec.rb +10 -0
  37. data/spec/fixtures/cat.m4v +0 -0
  38. data/spec/fixtures/facebook_data.yml +26 -24
  39. data/spec/fixtures/mock_facebook_responses.yml +203 -78
  40. data/spec/spec_helper.rb +30 -5
  41. data/spec/support/graph_api_shared_examples.rb +149 -118
  42. data/spec/support/json_testing_fix.rb +42 -0
  43. data/spec/support/koala_test.rb +187 -0
  44. data/spec/support/mock_http_service.rb +62 -58
  45. data/spec/support/ordered_hash.rb +205 -0
  46. data/spec/support/rest_api_shared_examples.rb +139 -15
  47. data/spec/support/uploadable_io_shared_examples.rb +2 -8
  48. metadata +90 -114
  49. data/lib/koala/http_services.rb +0 -146
  50. data/spec/cases/http_services/http_service_spec.rb +0 -54
  51. data/spec/cases/http_services/net_http_service_spec.rb +0 -350
  52. data/spec/cases/http_services/typhoeus_service_spec.rb +0 -144
  53. data/spec/support/live_testing_data_helper.rb +0 -40
  54. data/spec/support/setup_mocks_or_live.rb +0 -52
@@ -1,6 +1,6 @@
1
- # Responses by MockHTTPService are taken directly from
1
+ # Responses by MockHTTPService are taken directly from
2
2
  # this file.
3
- #
3
+ #
4
4
  # Structure
5
5
  # ----------
6
6
  #
@@ -10,19 +10,31 @@
10
10
  # with_token:
11
11
  # no_token:
12
12
 
13
- # ====== REST API =====
13
+ # ====== REST API =====
14
14
  rest_api:
15
15
 
16
16
  # -- Stubbed Responses --
17
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:
18
+ query=select first_name from user where uid = 2901279:
19
+ get:
20
+ no_token: '[{"first_name":"Luke"}]'
21
+ with_token: '[{"first_name":"Luke"}]'
22
+ query=select read_stream from permissions where uid = 2901279:
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 = 2901279"}]}'
26
+
27
+ /method/fql.multiquery:
28
+ 'queries=<%= MultiJson.encode({"query1" => "select post_id from stream where source_id = me()", "query2" => "select fromid from comment where post_id in (select post_id from #query1)", "query3" => "select uid, name from user where uid in (select fromid from #query2)"}) %>':
23
29
  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"}]}'
30
+ with_token: '[{"name":"query1", "fql_result_set":[]},{"name":"query2", "fql_result_set":[]},{"name":"query3", "fql_result_set":[]}]'
31
+ 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 = 2901279"}]}'
32
+ 'queries=<%= MultiJson.encode({"query1" => "select first_name from user where uid = 2901279", "query2" => "select first_name from user where uid = 2905623"}) %>':
33
+ get:
34
+ with_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Luke"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
35
+ no_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Luke"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
36
+
37
+
26
38
 
27
39
 
28
40
  # ====== GRAPH API =====
@@ -33,7 +45,7 @@ graph_api:
33
45
  # Error responses for when a token is required, but not given
34
46
  token_required_responses: &token_required
35
47
  no_token: '{"error":{"type":"OAuthAccessTokenException", "message":"An access token is required to request this resource."}}'
36
-
48
+
37
49
  # Common mock item responses
38
50
  item_deleted: &item_deleted
39
51
  delete:
@@ -46,46 +58,109 @@ graph_api:
46
58
  # Subscription error response
47
59
  verification_error: &verification_error
48
60
  with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
49
-
50
- test_user_no_perms: &test_user_no_perms
61
+
62
+ test_user_uninstalled: &test_user_uninstalled
63
+ post:
64
+ with_token: '{"id": "777777777", "access_token":"<%= APP_ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
65
+
66
+ test_user_installed: &test_user_installed
51
67
  post:
52
- with_token: '{"id": "777777777", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
53
-
68
+ with_token: '{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
69
+
54
70
  test_user_befriended: &test_user_befriended
55
71
  post:
56
72
  with_token: 'true'
57
-
73
+
58
74
  # -- Stubbed Responses --
59
75
  root:
60
- ids=contextoptional,naitik:
76
+ ids=contextoptional,koppel:
61
77
  get:
62
- with_token: '[{}, {}]'
63
- no_token: '[{}, {}]'
78
+ with_token: '{"contextoptional":"{}","koppel":"{}"}'
79
+ no_token: '{"contextoptional":"{}","koppel":"{}"}'
80
+
81
+ # Ruby 1.8.7 and 1.9.2 generate JSON with different key ordering, hence we have to dynamically generate it here
82
+ batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "koppel"}]) %>:
83
+ post:
84
+ with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"id\":\"456\"}"}]'
85
+ batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/picture"}]) %>:
86
+ post:
87
+ with_token: '[{"headers":[{"name":"Location","value":"http://google.com"}]}]'
88
+ batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "me/friends"}]) %>:
89
+ post:
90
+ with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[],\"paging\":{}}"}]'
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
+ post:
93
+ with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[],\"paging\":{}}"}]'
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
+ post:
96
+ with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},{"body":"{\"id\":\"123\"}"}]'
97
+ batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"FEED_ITEM_BATCH/likes"}, {"method"=>"delete", "relative_url"=> "FEED_ITEM_BATCH"}]) %>:
98
+ post:
99
+ with_token: '[{"body": "{\"id\": \"MOCK_LIKE\"}"},{"body":true}]'
100
+ batch=<%= MultiJson.encode([{"method" => "post", "relative_url" => "method/fql.query", "body" => "query=select+first_name+from+user+where+uid%3D2905623"}]) %>:
101
+ post:
102
+ with_token: '[{"body":"[{\"first_name\":\"Alex\"}]"}]'
103
+
104
+ # dependencies
105
+ batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"me", "name" => "getme"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getme"}]) %>:
106
+ post:
107
+ with_token: '[null,{"body":"{\"id\":\"123\"}"}]'
108
+ batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights", "name" => "getdata"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getdata"}]) %>:
109
+ post:
110
+ with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
111
+ batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5", "name" => "get-friends"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=get-friends:$.data.*.id}"}"}]) %>:
112
+ post:
113
+ with_token: '[null,{"body":"{}"}]'
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
+ post:
116
+ with_token: '[{"body":"{\"data\":[],\"paging\":{}}"},{"body":"{}"}]'
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
+ post:
119
+ with_token: '{"error":190,"error_description":"Error validating access token."}'
120
+
121
+ # attached files tests
122
+ batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
123
+ post:
124
+ with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
125
+ batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
126
+ post:
127
+ with_token: '[{"body":"{\"id\": \"MOCK_PHOTO\"}"}]'
128
+ batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}, {"method"=>"post", "relative_url"=>"koppel/photos", "attached_files" => "op2_file0"}]) %>&op1_file0=[FILE]&op2_file0=[FILE]:
129
+ post:
130
+ with_token: '[{"body":"{\"id\": \"MOCK_PHOTO\"}"}, {"body":"{\"id\": \"MOCK_PHOTO\"}"}]'
131
+
132
+
133
+
134
+
64
135
  /me:
65
136
  no_args:
66
137
  get:
67
138
  <<: *token_required
68
139
  with_token: '{"updated_time": 1}'
69
140
  fields=id:
70
- get:
71
- with_token: '{"id": "216743"}'
72
-
141
+ get:
142
+ with_token: '{"id": "2901279"}'
143
+
73
144
  /me/feed:
74
- message=Hello, world, from the test suite!:
75
- post:
145
+ message=Hello, world, from the test suite!:
146
+ post:
76
147
  with_token: '{"id": "MOCK_FEED_ITEM"}'
77
148
  message=Hello, world, from the test suite, testing comments!:
78
149
  post:
79
150
  with_token: '{"id": "MOCK_FEED_ITEM"}'
80
- message=the cats are asleep:
81
- post:
151
+ message=the cats are asleep:
152
+ post:
82
153
  with_token: '{"id": "FEED_ITEM_CATS"}'
83
- message=Hello, world, from the test suite delete method!:
84
- post:
154
+ message=Hello, world, from the test suite delete method!:
155
+ post:
85
156
  with_token: '{"id": "FEED_ITEM_DELETE"}'
157
+ message=Hello, world, from the test suite batch API!:
158
+ post:
159
+ with_token: '{"id": "FEED_ITEM_BATCH"}'
86
160
  link=http://oauth.twoalex.com/&message=Hello, world, from the test suite again!&name=OAuth Playground:
87
161
  post:
88
162
  with_token: '{"id": "FEED_ITEM_CONTEXT"}'
163
+
89
164
  /me/photos:
90
165
  source=[FILE]:
91
166
  post:
@@ -95,30 +170,49 @@ graph_api:
95
170
  post:
96
171
  <<: *token_required
97
172
  with_token: '{"id": "MOCK_PHOTO"}'
173
+ url=http://img.slate.com/images/redesign2008/slate_logo.gif:
174
+ post:
175
+ <<: *token_required
176
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
177
+ message=my message&url=http://img.slate.com/images/redesign2008/slate_logo.gif:
178
+ post:
179
+ <<: *token_required
180
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
181
+
182
+ /me/videos:
183
+ source=[FILE]:
184
+ post:
185
+ <<: *token_required
186
+ with_token: '{"id": "MOCK_PHOTO"}'
187
+ message=This is the test message&source=[FILE]:
188
+ post:
189
+ <<: *token_required
190
+ with_token: '{"id": "MOCK_PHOTO"}'
191
+
98
192
  /koppel:
99
193
  no_args:
100
194
  get:
101
195
  with_token: '{"id": 1, "name": 1, "updated_time": 1}'
102
196
  no_token: '{"id": 1, "name": 1}'
103
-
197
+
104
198
  /contextoptional:
105
199
  no_args:
106
200
  get:
107
201
  with_token: '{"id": 1, "name": 1}'
108
202
  no_token: '{"id": 1, "name": 1}'
109
-
110
- /contextoptional/photos:
111
- no_args:
112
- get:
203
+
204
+ /contextoptional/photos:
205
+ no_args:
206
+ get:
113
207
  with_token: '{"data": [{}], "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"}}'
114
208
  no_token: '{"data": [{}], "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"}}'
115
-
116
- /lukeshepard/likes:
117
- no_args:
118
- get:
209
+
210
+ /lukeshepard/friends:
211
+ no_args:
212
+ get:
119
213
  <<: *token_required
120
- with_token: '{"data": [{}]}'
121
-
214
+ with_token: '{"data": [{}], "paging": {}}'
215
+
122
216
  /lukeshepard/picture:
123
217
  type=large:
124
218
  get:
@@ -130,8 +224,8 @@ graph_api:
130
224
  code: 302
131
225
  headers:
132
226
  Location: https://facebook.com/large
133
-
134
-
227
+
228
+
135
229
  /chris.baclig/picture:
136
230
  no_args:
137
231
  get:
@@ -144,62 +238,86 @@ graph_api:
144
238
  headers:
145
239
  Location: http://facebook.com/
146
240
 
241
+ /comments:
242
+ ids=http://developers.facebook.com/blog/post/472:
243
+ get:
244
+ with_token: '{"http://developers.facebook.com/blog/post/472": []}'
245
+ no_token: '{"http://developers.facebook.com/blog/post/472": []}'
246
+ ids=http://developers.facebook.com/blog/post/490,http://developers.facebook.com/blog/post/472:
247
+ get:
248
+ with_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
249
+ no_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
250
+ ids=:
251
+ get:
252
+ body: '{"error": {"type": "OAuthException","message": "Cannot specify an empty identifier"}}'
253
+ code: 400
254
+ no_args:
255
+ get:
256
+ body: '{"error": {"type": "Exception","message": "No node specified"}}'
257
+ code: 500
258
+
147
259
  /search:
148
260
  q=facebook:
149
- get:
261
+ get:
150
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"}}'
151
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"}}'
152
- "limit=25&q=facebook&until=2010-09-23T21:17:33+0000":
153
- get:
264
+ "limit=25&q=facebook&until=<%= TEST_DATA['search_time'] %>":
265
+ get:
154
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"}}'
155
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"}}'
156
-
268
+
157
269
  '/115349521819193_113815981982767':
158
270
  no_args:
159
271
  delete:
160
272
  <<: *token_required
161
-
273
+
274
+ /my_page:
275
+ fields=access_token:
276
+ get:
277
+ <<: *token_required
278
+ with_token: '{"access_token": "<%= APP_ACCESS_TOKEN %>"}'
279
+
162
280
  # -- OAuth responses --
163
- /oauth/access_token:
281
+ /oauth/access_token:
164
282
  client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=<%= OAUTH_CODE %>&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
165
283
  get:
166
284
  no_token: access_token=<%= ACCESS_TOKEN %>
167
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
168
- get:
285
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
286
+ get:
169
287
  <<: *oauth_error
170
288
  client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&type=client_cred:
171
289
  post:
172
- no_token: access_token=<%= ACCESS_TOKEN %>
290
+ no_token: access_token=<%= APP_ACCESS_TOKEN %>
173
291
  /oauth/exchange_sessions:
174
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
292
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
175
293
  post:
176
294
  no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
177
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["multiple_session_keys"].join(",") %>&type=client_cred:
295
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= [OAUTH_DATA["session_key"], OAUTH_DATA["session_key"]].join(",") %>&type=client_cred:
178
296
  post:
179
297
  no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
180
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= ["foo"].concat(OAUTH_DATA["multiple_session_keys"]).join(",") %>&type=client_cred:
298
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= ["foo"].concat([OAUTH_DATA["session_key"], OAUTH_DATA["session_key"]]).join(",") %>&type=client_cred:
181
299
  post:
182
300
  no_token: '[null, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
183
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo,bar&type=client_cred:
301
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo,bar&type=client_cred:
184
302
  post:
185
303
  no_token: '[null, null]'
186
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo&type=client_cred:
304
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo&type=client_cred:
187
305
  post:
188
306
  no_token: '[null]'
189
307
 
190
308
 
191
309
 
192
- # -- Subscription Responses --
310
+ # -- Subscription Responses --
193
311
  /<%= APP_ID %>/subscriptions:
194
312
  callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
195
- post:
313
+ post:
196
314
  with_token:
197
315
  code: 200
198
316
  callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
199
- post:
317
+ post:
200
318
  with_token: '{"error":{"type":"Exception","message":"(#2200) subscription validation failed"}}'
201
319
  callback_url=foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
202
- post:
320
+ post:
203
321
  with_token: '{"error":{"type":"Exception","message":"(#100) callback_url URL is not properly formatted"}}'
204
322
  object=user:
205
323
  delete:
@@ -209,7 +327,7 @@ graph_api:
209
327
  delete:
210
328
  with_token: '{"error":{"type":"Exception","message":"(#100) Invalid parameter"}}'
211
329
  no_args:
212
- delete:
330
+ delete:
213
331
  with_token:
214
332
  code: 200
215
333
  get:
@@ -226,28 +344,28 @@ graph_api:
226
344
  no_args:
227
345
  post:
228
346
  with_token: '{"id": "MOCK_LIKE"}'
229
-
347
+
230
348
  /MOCK_FEED_ITEM/comments:
231
349
  message=it's my comment!:
232
350
  post:
233
351
  with_token: '{"id": "MOCK_COMMENT"}'
234
-
352
+
235
353
  /MOCK_FEED_ITEM:
236
354
  no_args:
237
355
  <<: *item_deleted
238
-
356
+
239
357
  /FEED_ITEM_CONTEXT:
240
- no_args:
358
+ no_args:
241
359
  <<: *item_deleted
242
360
  get:
243
361
  with_token: '{"link":"http://oauth.twoalex.com/", "name": "OAuth Playground"}'
244
-
362
+
245
363
  /FEED_ITEM_CATS:
246
364
  no_args:
247
365
  <<: *item_deleted
248
- get:
366
+ get:
249
367
  with_token: '{"message": "the cats are asleep"}'
250
-
368
+
251
369
  /FEED_ITEM_DELETE:
252
370
  no_args:
253
371
  <<: *item_deleted
@@ -255,9 +373,9 @@ graph_api:
255
373
  /FEED_ITEM_DELETE/likes:
256
374
  no_args:
257
375
  <<: *item_deleted
258
- post:
376
+ post:
259
377
  with_token: 'true'
260
-
378
+
261
379
  /MOCK_COMMENT:
262
380
  no_args:
263
381
  <<: *item_deleted
@@ -268,26 +386,33 @@ graph_api:
268
386
  <<: *item_deleted
269
387
  get:
270
388
  with_token: "{\"name\": \"This is the test message\"}"
271
-
389
+
272
390
  # -- Mock Test User Responses --
273
391
  /<%= APP_ID %>/accounts/test-users:
274
392
  installed=false:
275
- <<: *test_user_no_perms
393
+ <<: *test_user_uninstalled
276
394
  installed=false&permissions=read_stream:
277
- <<: *test_user_no_perms
395
+ <<: *test_user_uninstalled
396
+ installed=true&permissions=:
397
+ <<: *test_user_installed
278
398
  installed=true&permissions=read_stream:
279
- post:
280
- with_token: '{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
399
+ <<: *test_user_installed
281
400
  installed=true&permissions=read_stream,user_interests:
282
401
  post:
283
402
  with_token: '{"id": "888888888", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
284
403
  no_args:
285
404
  get:
286
405
  with_token: '{"data":[{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}, {"id": "888888888", "access_token":"119908831367602|o3wswWQ88LYjEC9-ukR_gjRIOMw.", "login_url":"https://www.facebook.com/platform/test_account.."}]}'
287
-
406
+
288
407
  /999999999:
289
408
  no_args:
290
409
  <<: *item_deleted
410
+ get:
411
+ with_token: '{"name":"Foo Baz"}'
412
+ name=Foo Baz:
413
+ post:
414
+ with_token: 'true'
415
+
291
416
 
292
417
  /999999999/friends/888888888:
293
418
  no_args:
@@ -299,10 +424,10 @@ graph_api:
299
424
  no_args:
300
425
  delete:
301
426
  with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
302
-
427
+
303
428
  /888888888:
304
429
  no_args:
305
- <<: *item_deleted
430
+ <<: *item_deleted
306
431
 
307
432
  /888888888/friends/999999999:
308
433
  no_args:
@@ -311,4 +436,4 @@ graph_api:
311
436
 
312
437
  /777777777:
313
438
  no_args:
314
- <<: *item_deleted
439
+ <<: *item_deleted
data/spec/spec_helper.rb CHANGED
@@ -1,18 +1,43 @@
1
1
  begin
2
2
  require 'bundler/setup'
3
3
  rescue LoadError
4
- puts 'although not required, bundler is recommened for running the tests'
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'
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
12
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
13
39
  require 'support/rest_api_shared_examples'
14
40
  require 'support/graph_api_shared_examples'
15
41
  require 'support/uploadable_io_shared_examples'
16
- require 'support/setup_mocks_or_live'
17
42
 
18
43
  BEACH_BALL_PATH = File.join(File.dirname(__FILE__), "fixtures", "beach.jpg")