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
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Koala::Utils do
4
+ it "has a deprecate method" do
5
+ Koala::Utils.should respond_to(:deprecate)
6
+ end
7
+
8
+ # AFAIK there's no way to test that (Kernel.)warn receives the text
9
+ # Kernel.should_receive(:warn) doesn't seem to work, even though the text gets printed
10
+ end
@@ -1,23 +1,24 @@
1
- # Check out http://oauth.twoalex.com/ to easily generate tokens, cookies, etc.
2
- # Those values will work with the default settings in this yaml.
1
+ # Testing data
2
+
3
+ # IMPORTANT NOTE: live tests will run against a test users automatically
4
+ # If you want to run them against a real user or test users on a different account, you can
5
+ # by enter an OAuth token, code, and session_key (for real users) or changing the app_id and secret (for test users)
6
+ # (note for real users: this will leave some photos and videos posted to your wall, since they can't be deleted through the API)
7
+
8
+ # These values are configured to work with the OAuth Playground app by default
3
9
  # Of course, you can change this to work with your own app.
4
- # Just remember to update all fields!
5
-
6
- # You must supply this value yourself to test the GraphAPI class.
7
- # Your OAuth token should have publish_stream, read_stream, and user_photos permissions.
8
- oauth_token:
10
+ # Check out http://oauth.twoalex.com/ to easily generate tokens, cookies, etc.
11
+
12
+ # Your OAuth token should have the read_stream, publish_stream, user_photos, user_videos, and read_insights permissions.
13
+ oauth_token:
9
14
 
10
- # for testing the OAuth class
15
+ # for testing the OAuth class
11
16
  # baseline app
12
- oauth_test_data:
13
- # You must supply this value yourself, since they will expire.
14
- code:
15
- # easiest way to get session keys: use multiple test accounts with the Javascript login at http://oauth.twoalex.com
16
- session_key:
17
- multiple_session_keys:
18
- -
19
- -
20
-
17
+ oauth_test_data:
18
+ # the following two values are not needed for most of the test suite, but the relevant tests will not run if they're not present
19
+ code:
20
+ session_key:
21
+
21
22
  # These values will work out of the box
22
23
  app_id: 119908831367602
23
24
  secret: e45e55a333eec232d4206d2703de1307
@@ -25,13 +26,13 @@ oauth_test_data:
25
26
  app_access_token: 119908831367602|o3wswWQ88LYjEC9-ukR_gjRIOMw.
26
27
  raw_token_string: "access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.&expires=6621"
27
28
  raw_offline_access_token_string: access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.
28
- valid_cookies:
29
+ valid_cookies:
29
30
  # note: the tests stub the time class so these default cookies are always valid (if you're using the default app)
30
31
  # if not you may want to remove the stubbing to test expiration
31
32
  fbs_119908831367602: '"access_token=119908831367602|2.LKE7ksSPOx0V_8mHPr2NHQ__.3600.1273363200-2905623|CMpi0AYbn03Oukzv94AUha2qbO4.&expires=1273363200&secret=lT_9zm5r5IbJ6Aa5O54nFw__&session_key=2.LKE7ksSPOx0V_8mHPr2NHQ__.3600.1273363200-2905623&sig=9515e93113921f9476a4efbdd4a3c746&uid=2905623"'
32
33
  expired_cookies:
33
34
  fbs_119908831367602: '"access_token=119908831367602|2.xv9mi6QSOpr474s4n2X_pw__.3600.1273287600-2905623|yVt5WH_S6J5p3gFa5_5lBzckhws.&expires=1273287600&secret=V_E79ovQnXqxGctFuC_n5A__&session_key=2.xv9mi6QSOpr474s4n2X_pw__.3600.1273287600-2905623&sig=eeef60838c0c800258d89b7e6ddddddb&uid=2905623"'
34
- offline_access_cookies:
35
+ offline_access_cookies:
35
36
  # note: I've revoked the offline access for security reasons, so you can't make calls against this :)
36
37
  fbs_119908831367602: '"access_token=119908831367602|08170230801eb225068e7a70-2905623|Q3LDCYYF8CX9cstxnZLsxiR0nwg.&expires=0&secret=78abaee300b392e275072a9f2727d436&session_key=08170230801eb225068e7a70-2905623&sig=423b8aa4b6fa1f9a571955f8e929d567&uid=2905623"'
37
38
 
@@ -44,17 +45,17 @@ oauth_test_data:
44
45
  algorithm: HMAC-SHA256
45
46
  user_id: "2905623"
46
47
  oauth_token: 119908831367602|2.zVF_6NrMELHuJa4gIU9tKw__.3600.1301922000-2905623|zgqPsr2BG9LoOK9kekGgRURZx0k
47
- user:
48
+ user:
48
49
  country: de
49
50
  locale: de_DE
50
- age:
51
+ age:
51
52
  min: 21
52
53
  issued_at: 1301917299
53
54
 
54
55
  subscription_test_data:
55
56
  subscription_path: http://oauth.twoalex.com/subscriptions
56
57
  verify_token: "myverificationtoken|1f54545d5f722733e17faae15377928f"
57
- challenge_data:
58
+ challenge_data:
58
59
  "hub.challenge": "1290024882"
59
60
  "hub.verify_token": "myverificationtoken|1f54545d5f722733e17faae15377928f"
60
61
  "hub.mode": "subscribe"
@@ -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,29 +10,29 @@
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
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"}]}'
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
26
 
27
27
  /method/fql.multiquery:
28
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)"}) %>':
29
- get:
29
+ get:
30
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 = 216743"}]}'
32
- 'queries=<%= MultiJson.encode({"query1" => "select first_name from user where uid = 216743", "query2" => "select first_name from user where uid = 2905623"}) %>':
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
33
  get:
34
- with_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Chris"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
35
- no_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Chris"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
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
36
 
37
37
 
38
38
 
@@ -45,7 +45,7 @@ graph_api:
45
45
  # Error responses for when a token is required, but not given
46
46
  token_required_responses: &token_required
47
47
  no_token: '{"error":{"type":"OAuthAccessTokenException", "message":"An access token is required to request this resource."}}'
48
-
48
+
49
49
  # Common mock item responses
50
50
  item_deleted: &item_deleted
51
51
  delete:
@@ -58,22 +58,27 @@ graph_api:
58
58
  # Subscription error response
59
59
  verification_error: &verification_error
60
60
  with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
61
-
62
- test_user_no_perms: &test_user_no_perms
61
+
62
+ test_user_uninstalled: &test_user_uninstalled
63
63
  post:
64
64
  with_token: '{"id": "777777777", "access_token":"<%= APP_ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
65
-
65
+
66
+ test_user_installed: &test_user_installed
67
+ post:
68
+ with_token: '{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
69
+
66
70
  test_user_befriended: &test_user_befriended
67
71
  post:
68
72
  with_token: 'true'
69
-
73
+
70
74
  # -- Stubbed Responses --
71
75
  root:
72
- ids=contextoptional,naitik:
76
+ ids=contextoptional,koppel:
73
77
  get:
74
- with_token: '{"contextoptional":"{}","naitik":"{}"}'
75
- no_token: '{"contextoptional":"{}","naitik":"{}"}'
76
- # Ruby 1.8.7 and 1.9.2 generate JSON with different key ordering, hence we have to dynamically generate it here
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
77
82
  batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "koppel"}]) %>:
78
83
  post:
79
84
  with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"id\":\"456\"}"}]'
@@ -92,6 +97,17 @@ graph_api:
92
97
  batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"FEED_ITEM_BATCH/likes"}, {"method"=>"delete", "relative_url"=> "FEED_ITEM_BATCH"}]) %>:
93
98
  post:
94
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]'
95
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}"}"}]) %>:
96
112
  post:
97
113
  with_token: '[null,{"body":"{}"}]'
@@ -101,18 +117,7 @@ graph_api:
101
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}"}"}]) %>:
102
118
  post:
103
119
  with_token: '{"error":190,"error_description":"Error validating access token."}'
104
- batch=<%= MultiJson.encode([{"method" => "post", "relative_url" => "method/fql.query", "body" => "query=select+name+from+user+where+uid%3D4"}]) %>:
105
- post:
106
- with_token: '[{"body":"[{\"name\":\"Mark Zuckerberg\"}]"}]'
107
-
108
- # dependencies
109
- batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"me", "name" => "getme"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getme"}]) %>:
110
- post: &batch_dependent
111
- with_token: '[null,{"body":"{\"id\":\"123\"}"}]'
112
- batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights", "name" => "getdata"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getdata"}]) %>:
113
- post:
114
- with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
115
-
120
+
116
121
  # attached files tests
117
122
  batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
118
123
  post:
@@ -125,34 +130,37 @@ graph_api:
125
130
  with_token: '[{"body":"{\"id\": \"MOCK_PHOTO\"}"}, {"body":"{\"id\": \"MOCK_PHOTO\"}"}]'
126
131
 
127
132
 
133
+
134
+
128
135
  /me:
129
136
  no_args:
130
137
  get:
131
138
  <<: *token_required
132
139
  with_token: '{"updated_time": 1}'
133
140
  fields=id:
134
- get:
135
- with_token: '{"id": "216743"}'
136
-
141
+ get:
142
+ with_token: '{"id": "2901279"}'
143
+
137
144
  /me/feed:
138
- message=Hello, world, from the test suite!:
139
- post:
145
+ message=Hello, world, from the test suite!:
146
+ post:
140
147
  with_token: '{"id": "MOCK_FEED_ITEM"}'
141
148
  message=Hello, world, from the test suite, testing comments!:
142
149
  post:
143
150
  with_token: '{"id": "MOCK_FEED_ITEM"}'
144
- message=the cats are asleep:
145
- post:
151
+ message=the cats are asleep:
152
+ post:
146
153
  with_token: '{"id": "FEED_ITEM_CATS"}'
147
- message=Hello, world, from the test suite delete method!:
148
- post:
154
+ message=Hello, world, from the test suite delete method!:
155
+ post:
149
156
  with_token: '{"id": "FEED_ITEM_DELETE"}'
150
- message=Hello, world, from the test suite batch API!:
151
- post:
157
+ message=Hello, world, from the test suite batch API!:
158
+ post:
152
159
  with_token: '{"id": "FEED_ITEM_BATCH"}'
153
160
  link=http://oauth.twoalex.com/&message=Hello, world, from the test suite again!&name=OAuth Playground:
154
161
  post:
155
162
  with_token: '{"id": "FEED_ITEM_CONTEXT"}'
163
+
156
164
  /me/photos:
157
165
  source=[FILE]:
158
166
  post:
@@ -162,6 +170,15 @@ graph_api:
162
170
  post:
163
171
  <<: *token_required
164
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
+
165
182
  /me/videos:
166
183
  source=[FILE]:
167
184
  post:
@@ -177,25 +194,25 @@ graph_api:
177
194
  get:
178
195
  with_token: '{"id": 1, "name": 1, "updated_time": 1}'
179
196
  no_token: '{"id": 1, "name": 1}'
180
-
197
+
181
198
  /contextoptional:
182
199
  no_args:
183
200
  get:
184
201
  with_token: '{"id": 1, "name": 1}'
185
202
  no_token: '{"id": 1, "name": 1}'
186
-
187
- /contextoptional/photos:
188
- no_args:
189
- get:
203
+
204
+ /contextoptional/photos:
205
+ no_args:
206
+ get:
190
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"}}'
191
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"}}'
192
-
193
- /lukeshepard/likes:
194
- no_args:
195
- get:
209
+
210
+ /lukeshepard/friends:
211
+ no_args:
212
+ get:
196
213
  <<: *token_required
197
214
  with_token: '{"data": [{}]}'
198
-
215
+
199
216
  /lukeshepard/picture:
200
217
  type=large:
201
218
  get:
@@ -207,8 +224,8 @@ graph_api:
207
224
  code: 302
208
225
  headers:
209
226
  Location: https://facebook.com/large
210
-
211
-
227
+
228
+
212
229
  /chris.baclig/picture:
213
230
  no_args:
214
231
  get:
@@ -223,11 +240,11 @@ graph_api:
223
240
 
224
241
  /comments:
225
242
  ids=http://developers.facebook.com/blog/post/472:
226
- get:
243
+ get:
227
244
  with_token: '{"http://developers.facebook.com/blog/post/472": []}'
228
245
  no_token: '{"http://developers.facebook.com/blog/post/472": []}'
229
246
  ids=http://developers.facebook.com/blog/post/490,http://developers.facebook.com/blog/post/472:
230
- get:
247
+ get:
231
248
  with_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
232
249
  no_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
233
250
  ids=:
@@ -237,64 +254,70 @@ graph_api:
237
254
  no_args:
238
255
  get:
239
256
  body: '{"error": {"type": "Exception","message": "No node specified"}}'
240
- code: 500
257
+ code: 500
241
258
 
242
259
  /search:
243
260
  q=facebook:
244
- get:
261
+ get:
245
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"}}'
246
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"}}'
247
264
  "limit=25&q=facebook&until=2010-09-23T21:17:33+0000":
248
- get:
265
+ get:
249
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"}}'
250
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"}}'
251
-
268
+
252
269
  '/115349521819193_113815981982767':
253
270
  no_args:
254
271
  delete:
255
272
  <<: *token_required
256
-
273
+
274
+ /my_page:
275
+ fields=access_token:
276
+ get:
277
+ <<: *token_required
278
+ with_token: '{"access_token": "<%= APP_ACCESS_TOKEN %>"}'
279
+
257
280
  # -- OAuth responses --
258
- /oauth/access_token:
281
+ /oauth/access_token:
259
282
  client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=<%= OAUTH_CODE %>&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
260
283
  get:
261
284
  no_token: access_token=<%= ACCESS_TOKEN %>
262
- client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
263
- get:
285
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
286
+ get:
264
287
  <<: *oauth_error
265
288
  client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&type=client_cred:
266
289
  post:
267
290
  no_token: access_token=<%= APP_ACCESS_TOKEN %>
268
291
  /oauth/exchange_sessions:
269
- 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:
270
293
  post:
271
294
  no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
272
- 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:
273
296
  post:
274
297
  no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
275
- 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:
276
299
  post:
277
300
  no_token: '[null, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
278
- 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:
279
302
  post:
280
303
  no_token: '[null, null]'
281
- 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:
282
305
  post:
283
306
  no_token: '[null]'
284
307
 
285
308
 
286
309
 
287
- # -- Subscription Responses --
310
+ # -- Subscription Responses --
288
311
  /<%= APP_ID %>/subscriptions:
289
312
  callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
290
- post:
313
+ post:
291
314
  with_token:
292
315
  code: 200
293
316
  callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
294
- post:
317
+ post:
295
318
  with_token: '{"error":{"type":"Exception","message":"(#2200) subscription validation failed"}}'
296
319
  callback_url=foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
297
- post:
320
+ post:
298
321
  with_token: '{"error":{"type":"Exception","message":"(#100) callback_url URL is not properly formatted"}}'
299
322
  object=user:
300
323
  delete:
@@ -304,7 +327,7 @@ graph_api:
304
327
  delete:
305
328
  with_token: '{"error":{"type":"Exception","message":"(#100) Invalid parameter"}}'
306
329
  no_args:
307
- delete:
330
+ delete:
308
331
  with_token:
309
332
  code: 200
310
333
  get:
@@ -321,28 +344,28 @@ graph_api:
321
344
  no_args:
322
345
  post:
323
346
  with_token: '{"id": "MOCK_LIKE"}'
324
-
347
+
325
348
  /MOCK_FEED_ITEM/comments:
326
349
  message=it's my comment!:
327
350
  post:
328
351
  with_token: '{"id": "MOCK_COMMENT"}'
329
-
352
+
330
353
  /MOCK_FEED_ITEM:
331
354
  no_args:
332
355
  <<: *item_deleted
333
-
356
+
334
357
  /FEED_ITEM_CONTEXT:
335
- no_args:
358
+ no_args:
336
359
  <<: *item_deleted
337
360
  get:
338
361
  with_token: '{"link":"http://oauth.twoalex.com/", "name": "OAuth Playground"}'
339
-
362
+
340
363
  /FEED_ITEM_CATS:
341
364
  no_args:
342
365
  <<: *item_deleted
343
- get:
366
+ get:
344
367
  with_token: '{"message": "the cats are asleep"}'
345
-
368
+
346
369
  /FEED_ITEM_DELETE:
347
370
  no_args:
348
371
  <<: *item_deleted
@@ -350,9 +373,9 @@ graph_api:
350
373
  /FEED_ITEM_DELETE/likes:
351
374
  no_args:
352
375
  <<: *item_deleted
353
- post:
376
+ post:
354
377
  with_token: 'true'
355
-
378
+
356
379
  /MOCK_COMMENT:
357
380
  no_args:
358
381
  <<: *item_deleted
@@ -363,26 +386,33 @@ graph_api:
363
386
  <<: *item_deleted
364
387
  get:
365
388
  with_token: "{\"name\": \"This is the test message\"}"
366
-
389
+
367
390
  # -- Mock Test User Responses --
368
391
  /<%= APP_ID %>/accounts/test-users:
369
392
  installed=false:
370
- <<: *test_user_no_perms
393
+ <<: *test_user_uninstalled
371
394
  installed=false&permissions=read_stream:
372
- <<: *test_user_no_perms
395
+ <<: *test_user_uninstalled
396
+ installed=true&permissions=:
397
+ <<: *test_user_installed
373
398
  installed=true&permissions=read_stream:
374
- post:
375
- with_token: '{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
399
+ <<: *test_user_installed
376
400
  installed=true&permissions=read_stream,user_interests:
377
401
  post:
378
402
  with_token: '{"id": "888888888", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
379
403
  no_args:
380
404
  get:
381
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.."}]}'
382
-
406
+
383
407
  /999999999:
384
408
  no_args:
385
409
  <<: *item_deleted
410
+ get:
411
+ with_token: '{"name":"Foo Baz"}'
412
+ name=Foo Baz:
413
+ post:
414
+ with_token: 'true'
415
+
386
416
 
387
417
  /999999999/friends/888888888:
388
418
  no_args:
@@ -394,10 +424,10 @@ graph_api:
394
424
  no_args:
395
425
  delete:
396
426
  with_token: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
397
-
427
+
398
428
  /888888888:
399
429
  no_args:
400
- <<: *item_deleted
430
+ <<: *item_deleted
401
431
 
402
432
  /888888888/friends/999999999:
403
433
  no_args: