koala 0.4 → 3.7.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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/test.yml +32 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +25 -0
  7. data/ISSUE_TEMPLATE +25 -0
  8. data/LICENSE +22 -0
  9. data/Manifest +32 -5
  10. data/PULL_REQUEST_TEMPLATE +11 -0
  11. data/Rakefile +12 -12
  12. data/changelog.md +781 -0
  13. data/code_of_conduct.md +74 -0
  14. data/koala.gemspec +28 -24
  15. data/lib/koala/api/batch_operation.rb +86 -0
  16. data/lib/koala/api/graph_api_methods.rb +504 -0
  17. data/lib/koala/api/graph_batch_api.rb +167 -0
  18. data/lib/koala/api/graph_collection.rb +129 -0
  19. data/lib/koala/api/graph_error_checker.rb +72 -0
  20. data/lib/koala/api.rb +159 -0
  21. data/lib/koala/configuration.rb +56 -0
  22. data/lib/koala/errors.rb +126 -0
  23. data/lib/koala/http_service/request.rb +133 -0
  24. data/lib/koala/http_service/response.rb +20 -0
  25. data/lib/koala/http_service/uploadable_io.rb +183 -0
  26. data/lib/koala/http_service.rb +108 -0
  27. data/lib/koala/oauth.rb +342 -0
  28. data/lib/koala/realtime_updates.rb +151 -0
  29. data/lib/koala/test_users.rb +189 -0
  30. data/lib/koala/utils.rb +41 -0
  31. data/lib/koala/version.rb +3 -0
  32. data/lib/koala.rb +51 -291
  33. data/readme.md +269 -21
  34. data/spec/cases/api_spec.rb +362 -0
  35. data/spec/cases/configuration_spec.rb +11 -0
  36. data/spec/cases/error_spec.rb +143 -0
  37. data/spec/cases/graph_api_batch_spec.rb +788 -0
  38. data/spec/cases/graph_api_spec.rb +76 -0
  39. data/spec/cases/graph_collection_spec.rb +192 -0
  40. data/spec/cases/graph_error_checker_spec.rb +147 -0
  41. data/spec/cases/http_service/request_spec.rb +250 -0
  42. data/spec/cases/http_service/response_spec.rb +24 -0
  43. data/spec/cases/http_service_spec.rb +280 -0
  44. data/spec/cases/koala_spec.rb +57 -0
  45. data/spec/cases/koala_test_spec.rb +5 -0
  46. data/spec/cases/oauth_spec.rb +647 -0
  47. data/spec/cases/realtime_updates_spec.rb +327 -0
  48. data/spec/cases/test_users_spec.rb +383 -0
  49. data/spec/cases/uploadable_io_spec.rb +266 -0
  50. data/spec/cases/utils_spec.rb +55 -0
  51. data/spec/fixtures/beach.jpg +0 -0
  52. data/spec/fixtures/cat.m4v +0 -0
  53. data/spec/fixtures/facebook_data.yml +63 -0
  54. data/spec/fixtures/mock_facebook_responses.yml +483 -0
  55. data/spec/fixtures/vcr_cassettes/app_test_accounts.yml +97 -0
  56. data/spec/fixtures/vcr_cassettes/friend_list_next_page.yml +121 -0
  57. data/spec/integration/graph_collection_spec.rb +24 -0
  58. data/spec/spec_helper.rb +25 -0
  59. data/spec/support/custom_matchers.rb +28 -0
  60. data/spec/support/graph_api_shared_examples.rb +534 -0
  61. data/spec/support/koala_test.rb +251 -0
  62. data/spec/support/mock_http_service.rb +140 -0
  63. data/spec/support/uploadable_io_shared_examples.rb +70 -0
  64. metadata +206 -62
  65. data/CHANGELOG +0 -24
  66. data/init.rb +0 -2
  67. data/lib/http_services.rb +0 -60
  68. data/test/facebook_data.yml +0 -5
  69. data/test/koala/facebook_no_access_token_tests.rb +0 -119
  70. data/test/koala/facebook_with_access_token_tests.rb +0 -106
  71. data/test/koala_tests.rb +0 -30
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Koala::Utils do
4
+ describe ".deprecate" do
5
+ before :each do
6
+ # unstub deprecate so we can test it
7
+ allow(Koala::Utils).to receive(:deprecate).and_call_original
8
+ end
9
+
10
+ it "has a deprecation prefix that includes the words Koala and deprecation" do
11
+ expect(Koala::Utils::DEPRECATION_PREFIX).to match(/koala/i)
12
+ expect(Koala::Utils::DEPRECATION_PREFIX).to match(/deprecation/i)
13
+ end
14
+
15
+ it "prints a warning with Kernel.warn" do
16
+ message = Time.now.to_s + rand.to_s
17
+ expect(Kernel).to receive(:warn)
18
+ Koala::Utils.deprecate(message)
19
+ end
20
+
21
+ it "prints the deprecation prefix and the warning" do
22
+ message = Time.now.to_s + rand.to_s
23
+ expect(Kernel).to receive(:warn).with(Koala::Utils::DEPRECATION_PREFIX + message)
24
+ Koala::Utils.deprecate(message)
25
+ end
26
+
27
+ it "only prints each unique message once" do
28
+ message = Time.now.to_s + rand.to_s
29
+ expect(Kernel).to receive(:warn).once
30
+ Koala::Utils.deprecate(message)
31
+ Koala::Utils.deprecate(message)
32
+ end
33
+ end
34
+
35
+ describe ".logger" do
36
+ it "has an accessor for logger" do
37
+ expect(Koala::Utils.methods.map(&:to_sym)).to include(:logger)
38
+ expect(Koala::Utils.methods.map(&:to_sym)).to include(:logger=)
39
+ end
40
+
41
+ it "defaults to the standard ruby logger with level set to ERROR" do |variable|
42
+ expect(Koala::Utils.logger).to be_kind_of(Logger)
43
+ expect(Koala::Utils.logger.level).to eq(Logger::ERROR)
44
+ end
45
+
46
+ logger_methods = [:debug, :info, :warn, :error, :fatal]
47
+
48
+ logger_methods.each do |logger_method|
49
+ it "should delegate #{logger_method} to the attached logger" do
50
+ expect(Koala::Utils.logger).to receive(logger_method)
51
+ Koala::Utils.send(logger_method, "Test #{logger_method} message")
52
+ end
53
+ end
54
+ end
55
+ end
Binary file
Binary file
@@ -0,0 +1,63 @@
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 a test app. If you want, you can change this to work with your own app.
9
+
10
+ # Your OAuth token should have the read_stream, publish_stream, user_photos, user_videos, and read_insights permissions.
11
+ oauth_token:
12
+
13
+ # for testing the OAuth class
14
+ # baseline app
15
+ oauth_test_data:
16
+ # 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
17
+ code:
18
+ session_key:
19
+
20
+ # These values will work out of the box
21
+ app_id: 119908831367602
22
+ secret: e45e55a333eec232d4206d2703de1307
23
+ callback_url: http://testdomain.koalatest.test/
24
+ app_access_token: 119908831367602|o3wswWQ88LYjEC9-ukR_gjRIOMw.
25
+ raw_token_string: "access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.&expires=6621"
26
+ raw_offline_access_token_string: access_token=119908831367602|2.6GneoQbnEqtSiPppZzDU4Q__.3600.1273366800-2905623|3OLa3w0x1K4C1S5cOgbs07TytAk.
27
+ valid_cookies:
28
+ # note: the tests stub the time class so these default cookies are always valid (if you're using the default app)
29
+ # if not you may want to remove the stubbing to test expiration
30
+ 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"'
31
+ offline_access_cookies:
32
+ # note: I've revoked the offline access for security reasons, so you can't make calls against this :)
33
+ fbs_119908831367602: '"access_token=119908831367602|08170230801eb225068e7a70-2905623|Q3LDCYYF8CX9cstxnZLsxiR0nwg.&expires=0&secret=78abaee300b392e275072a9f2727d436&session_key=08170230801eb225068e7a70-2905623&sig=423b8aa4b6fa1f9a571955f8e929d567&uid=2905623"'
34
+ valid_signed_cookies:
35
+ "fbsr_119908831367602": "f1--LHwjHVCxfs97hRHL-4cF-0jNxZRc6MGzo1qHLb0.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvZGUiOiIyLkFRQm90a0pBWlhVY1l3RkMuMzYwMC4xMzE0ODEzNjAwLjEtMjkwNTYyM3x4V2xya0d0UmJIZlpIclRnVWwxQmxJcVhRbjQiLCJpc3N1ZWRfYXQiOjEzMTQ4MDY2NTUsInVzZXJfaWQiOiIyOTA1NjIzIn0"
36
+
37
+
38
+ # These values from the OAuth Playground (see above) will work out of the box
39
+ # You can update this to live data if desired
40
+ # request_secret is optional and will fall back to the secret above if absent
41
+ signed_params: "zWRm0gd5oHW_jzXP_WA9CirO7c5CLHotn-SKRqH2NmU.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEzMDE5MjIwMDAsImlzc3VlZF9hdCI6MTMwMTkxNzI5OSwib2F1dGhfdG9rZW4iOiIxMTk5MDg4MzEzNjc2MDJ8Mi56VkZfNk5yTUVMSHVKYTRnSVU5dEt3X18uMzYwMC4xMzAxOTIyMDAwLTI5MDU2MjN8emdxUHNyMkJHOUxvT0s5a2VrR2dSVVJaeDBrIiwidXNlciI6eyJjb3VudHJ5IjoiZGUiLCJsb2NhbGUiOiJkZV9ERSIsImFnZSI6eyJtaW4iOjIxfX0sInVzZXJfaWQiOiIyOTA1NjIzIn0"
42
+ signed_params_result:
43
+ expires: 1301922000
44
+ algorithm: HMAC-SHA256
45
+ user_id: "2905623"
46
+ oauth_token: 119908831367602|2.zVF_6NrMELHuJa4gIU9tKw__.3600.1301922000-2905623|zgqPsr2BG9LoOK9kekGgRURZx0k
47
+ user:
48
+ country: de
49
+ locale: de_DE
50
+ age:
51
+ min: 21
52
+ issued_at: 1301917299
53
+
54
+ subscription_test_data:
55
+ subscription_path: https://testdomain.koalatest.test/subscriptions
56
+ verify_token: "myverificationtoken|1f54545d5f722733e17faae15377928f"
57
+ challenge_data:
58
+ "hub.challenge": "1290024882"
59
+ "hub.verify_token": "myverificationtoken|1f54545d5f722733e17faae15377928f"
60
+ "hub.mode": "subscribe"
61
+
62
+ vcr_data:
63
+ oauth_token: CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD
@@ -0,0 +1,483 @@
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
+ # ====== GRAPH API =====
14
+ graph_api:
15
+
16
+ # -- Common Responses --
17
+
18
+ # Error responses for when a token is required, but not given
19
+ token_required_responses: &token_required
20
+ no_token:
21
+ code: 400
22
+ body: '{"error":{"type":"OAuthAccessTokenException", "message":"An access token is required to request this resource."}}'
23
+
24
+ # Common mock item responses
25
+ item_deleted: &item_deleted
26
+ delete:
27
+ with_token: '{"success":true}'
28
+
29
+ # OAuth error response
30
+ oauth_error: &oauth_error
31
+ no_token:
32
+ code: 400
33
+ body: '{"error": {"code"=>2500, "type": "OAuthException", "message": "Error validating verification code."}}'
34
+
35
+ # Subscription error response
36
+ verification_error: &verification_error
37
+ with_token:
38
+ code: 400
39
+ body: '{"error": {"code"=>2500, "type": "OAuthException", "message": "Error validating verification code."}}'
40
+
41
+ test_user_uninstalled: &test_user_uninstalled
42
+ post:
43
+ with_token: '{"id": "777777777", "access_token":"<%= APP_ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
44
+
45
+ test_user_installed: &test_user_installed
46
+ post:
47
+ with_token: '{"id": "999999999", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
48
+
49
+ test_user_befriended: &test_user_befriended
50
+ post:
51
+ with_token: 'true'
52
+
53
+ # -- Stubbed Responses --
54
+ root:
55
+ ids=facebook,barackobama:
56
+ get:
57
+ with_token: '{"facebook":"{}","barackobama":"{}"}'
58
+ no_token: '{"facebook":"{}","barackobama":"{}"}'
59
+
60
+ # Ruby 1.8.7 and 1.9.2 generate JSON with different key ordering, hence we have to dynamically generate it here
61
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "barackobama"}]) %>:
62
+ post:
63
+ with_token: '[{"code": 200, "body":"{\"id\":\"123\"}"}, {"code": 200, "body":"{\"id\":\"456\"}"}]'
64
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me/picture"}]) %>:
65
+ post:
66
+ with_token: '[{"code": 302, "headers":[{"name":"Location","value":"https://google.com"}]}]'
67
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me/picture?redirect=false"}]) %>:
68
+ post:
69
+ with_token: '[{"code": 200, "body":"{\"data\":{\"is_silhouette\":false,\"url\":\"https:\/\/google.com\"}}"}]'
70
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "me/friends"}]) %>:
71
+ post:
72
+ with_token: '[{"code": 200, "body":"{\"id\":\"barackobama\"}"}, {"code": 200, "body":"{\"data\":[{\"id\":\"koppel\"}],\"paging\":{}}"}]'
73
+ batch=<%= JSON.dump([{"method"=>"get", "relative_url"=>"me"}, {"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/app_event_types?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
74
+ post:
75
+ with_token: '[{"code": 200, "body":"{\"id\":\"123\"}"}, {"code": 200, "body":"{\"data\":[],\"paging\":{}}"}]'
76
+ batch=<%= JSON.dump([{"method"=>"get", "relative_url"=>"2/invalidconnection"}, {"method"=>"get", "relative_url"=>"barackobama?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
77
+ post:
78
+ with_token: '[{"code": 400, "body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},{"code": 200, "body":"{\"id\":\"123\"}"}]'
79
+ batch=<%= JSON.dump([{"method"=>"post", "relative_url"=>"FEED_ITEM_BATCH/likes"}, {"method"=>"delete", "relative_url"=> "FEED_ITEM_BATCH"}]) %>:
80
+ post:
81
+ with_token: '[{"code": 200, "body": "{\"id\": \"MOCK_LIKE\"}"},{"code": 200, "body":"{\"success\":true}"}]'
82
+
83
+ # dependencies
84
+ batch=<%= JSON.dump([{"method"=>"get", "relative_url"=>"me", "name" => "getme"}, {"method"=>"get", "relative_url"=>"barackobama", "depends_on" => "getme"}]) %>:
85
+ post:
86
+ with_token: '[null,{"code": 200, "body":"{\"id\":\"123\"}"}]'
87
+ batch=<%= JSON.dump([{"method"=>"get", "relative_url"=>"2/invalidconnection", "name" => "getdata"}, {"method"=>"get", "relative_url"=>"barackobama", "depends_on" => "getdata"}]) %>:
88
+ post:
89
+ with_token: '[{"code": 400, "body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
90
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me/friends?limit=5", "name" => "get-friends"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=get-friends:$.data.*.id}"}"}]) %>:
91
+ post:
92
+ with_token: '[null,{"code": 200, "body":"{}"}]'
93
+ batch=<%= JSON.dump([{"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}"}"}]) %>:
94
+ post:
95
+ with_token: '[{"code": 200, "body":"{\"data\":[],\"paging\":{}}"},{"code": 200, "body":"{}"}]'
96
+ batch=<%= JSON.dump([{"method" => "get", "relative_url" => "me/friends?limit=5"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=i-dont-exist:$.data.*.id}"}"}]) %>:
97
+ post:
98
+ with_token:
99
+ code: 400
100
+ body: '{"error_code":190,"error_description":"Error validating access token."}'
101
+
102
+ # attached files tests
103
+ batch=<%= JSON.dump([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
104
+ post:
105
+ with_token: '[{"code": 400, body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
106
+ batch=<%= JSON.dump([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
107
+ post:
108
+ with_token: '[{"code": 200, "body":"{\"id\": \"MOCK_PHOTO\"}"}]'
109
+ batch=<%= JSON.dump([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}, {"method"=>"post", "relative_url"=>"barackobama/photos", "attached_files" => "op2_file0"}]) %>&op1_file0=[FILE]&op2_file0=[FILE]:
110
+ post:
111
+ with_token: '[{"code": 200, "body":"{\"id\": \"MOCK_PHOTO\"}"}, {"code": 200, "body":"{\"id\": \"MOCK_PHOTO\"}"}]'
112
+
113
+ /me:
114
+ no_args:
115
+ get:
116
+ <<: *token_required
117
+ with_token: '{"updated_time": 1}'
118
+ fields=id:
119
+ get:
120
+ with_token: '{"id": "2901279"}'
121
+
122
+ /me/feed:
123
+ message=Hello, world, from the test suite!:
124
+ post:
125
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
126
+ message=Hello, world, from the test suite, testing comments!:
127
+ post:
128
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
129
+ message=Hello, world, from the test suite, testing comments again!:
130
+ post:
131
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
132
+ message=Hello, world, from the test suite, testing liking!:
133
+ post:
134
+ with_token: '{"id": "MOCK_FEED_ITEM"}'
135
+ message=the cats are asleep:
136
+ post:
137
+ with_token: '{"id": "FEED_ITEM_CATS"}'
138
+ message=Hello, world, from the test suite delete method!:
139
+ post:
140
+ with_token: '{"id": "FEED_ITEM_DELETE"}'
141
+ message=Hello, world, from the test suite delete like method!:
142
+ post:
143
+ with_token: '{"id": "FEED_ITEM_DELETE"}'
144
+ message=Hello, world, from the test suite batch API!:
145
+ post:
146
+ with_token: '{"id": "FEED_ITEM_BATCH"}'
147
+ link=http://testdomain.koalatest.test/&message=Hello, world, from the test suite again!&name=OAuth Playground:
148
+ post:
149
+ with_token: '{"id": "FEED_ITEM_CONTEXT"}'
150
+ link=http://testdomain.koalatest.test/&message=body&name=It's a big question&picture=http://testdomain.koalatest.test//images/logo.png&properties=<%= JSON.dump({"Link1"=>{"text"=>"Left", "href"=>"http://testdomain.koalatest.test/"}, "other" => {"text"=>"Straight ahead", "href"=>"http://testdomain.koalatest.test/?"}}) %>&type=link:
151
+ post:
152
+ with_token: '{"id": "FEED_ITEM_DICTIONARY"}'
153
+
154
+ /me/picture:
155
+ redirect=false:
156
+ no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
157
+ with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
158
+
159
+ /me/photos:
160
+ source=[FILE]:
161
+ post:
162
+ <<: *token_required
163
+ with_token: '{"id": "MOCK_PHOTO"}'
164
+ message=This is the test message&source=[FILE]:
165
+ post:
166
+ <<: *token_required
167
+ with_token: '{"id": "MOCK_PHOTO"}'
168
+ url=http://img.slate.com/images/redesign2008/slate_logo.gif:
169
+ post:
170
+ <<: *token_required
171
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
172
+ message=my message&url=http://img.slate.com/images/redesign2008/slate_logo.gif:
173
+ post:
174
+ <<: *token_required
175
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
176
+
177
+ /me/videos:
178
+ source=[FILE]:
179
+ post:
180
+ <<: *token_required
181
+ with_token: '{"id": "MOCK_PHOTO"}'
182
+ message=This is the test message&source=[FILE]:
183
+ post:
184
+ <<: *token_required
185
+ with_token: '{"id": "MOCK_PHOTO"}'
186
+ file_url=http://techslides.com/demos/sample-videos/small.mp4:
187
+ post:
188
+ <<: *token_required
189
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
190
+ description=my message&file_url=http://techslides.com/demos/sample-videos/small.mp4:
191
+ post:
192
+ <<: *token_required
193
+ with_token: '{"id": "MOCK_PHOTO_FROM_URL"}'
194
+
195
+ /barackobama:
196
+ no_args:
197
+ get:
198
+ with_token: '{"id": 1, "name": 1, "updated_time": 1}'
199
+ no_token: '{"id": 1, "name": 1}'
200
+ metadata=1:
201
+ get:
202
+ with_token: '{"name": "Barack Obama","metadata": {"fields": [{"name": "id"}],"type": "user","connections": {}},"id": "44"}'
203
+
204
+ /facebook:
205
+ no_args:
206
+ get:
207
+ with_token: '{"id": 1, "name": 1}'
208
+ no_token: '{"id": 1, "name": 1}'
209
+
210
+ /facebook/events:
211
+ no_args:
212
+ get:
213
+ with_token: '{"data": [{}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/events?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/events?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
214
+ no_token: '{"data": [{}], "paging": {"previous": "https:\/\/graph.facebook.com\/7204941866\/events?limit=25&until=2008-09-15T18%3A30%3A25%2B0000", "next": "https:\/\/graph.facebook.com\/7204941866\/events?limit=25&until=2008-09-15T18%3A30%3A25%2B0000"}}'
215
+
216
+ /koppel/likes:
217
+ no_args:
218
+ get:
219
+ <<: *token_required
220
+ with_token: '{"data": [{}], "paging": {}}'
221
+
222
+ /koppel/picture:
223
+ no_args:
224
+ get:
225
+ no_token:
226
+ code: 302
227
+ headers:
228
+ Location: http://facebook.com/
229
+ with_token:
230
+ code: 302
231
+ headers:
232
+ Location: http://facebook.com/
233
+ type=large:
234
+ get:
235
+ no_token:
236
+ code: 302
237
+ headers:
238
+ Location: https://facebook.com/large
239
+ with_token:
240
+ code: 302
241
+ headers:
242
+ Location: https://facebook.com/large
243
+ redirect=false:
244
+ get:
245
+ no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
246
+ with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
247
+ redirect=false&type=large:
248
+ get:
249
+ no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com/large" } }'
250
+ with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com/large" } }'
251
+
252
+ /comments:
253
+ ids=http://developers.facebook.com/blog/post/472:
254
+ get:
255
+ with_token: '{"http://developers.facebook.com/blog/post/472": []}'
256
+ no_token: '{"http://developers.facebook.com/blog/post/472": []}'
257
+ ids=http://developers.facebook.com/blog/post/490,http://developers.facebook.com/blog/post/472:
258
+ get:
259
+ with_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
260
+ no_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
261
+ ids=:
262
+ get:
263
+ code: 400
264
+ body: '{"error": {"type": "OAuthException","message": "Cannot specify an empty identifier"}}'
265
+ no_args:
266
+ get:
267
+ code: 500
268
+ body: '{"error": {"type": "Exception","message": "No node specified"}}'
269
+
270
+ /search:
271
+ q=facebook&type=page:
272
+ get:
273
+ 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"}}'
274
+ "limit=25&q=facebook&type=page&until=<%= TEST_DATA['search_time'] %>":
275
+ get:
276
+ 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"}}'
277
+
278
+ '/115349521819193_113815981982767':
279
+ no_args:
280
+ delete:
281
+ <<: *token_required
282
+
283
+ /my_page:
284
+ fields=access_token:
285
+ get:
286
+ <<: *token_required
287
+ with_token: '{"access_token": "<%= APP_ACCESS_TOKEN %>"}'
288
+
289
+
290
+ '/<%= APP_ID %>':
291
+ restrictions=<%= JSON.dump({"age_distr" => "13+"}) %>:
292
+ post:
293
+ with_token: "true"
294
+
295
+ /debug_token:
296
+ input_token=<%= APP_ACCESS_TOKEN %>:
297
+ get:
298
+ with_token: '{ "data": { "app_id": <%= APP_ID %>, "application": "Social Cafe", "expires_at": 1352419328, "is_valid": true, "issued_at": 1347235328, "metadata": { "sso": "iphone-safari" }, "scopes": [ "email", "publish_actions" ], "user_id": 1207059 } }'
299
+
300
+ # -- OAuth responses --
301
+ /oauth/access_token:
302
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=<%= OAUTH_CODE %>&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
303
+ get:
304
+ no_token: access_token=<%= ACCESS_TOKEN %>
305
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&code=foo&redirect_uri=<%= OAUTH_DATA["callback_url"] %>:
306
+ get:
307
+ <<: *oauth_error
308
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&grant_type=client_credentials:
309
+ post:
310
+ no_token: access_token=<%= APP_ACCESS_TOKEN %>
311
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&fb_exchange_token=<%= ACCESS_TOKEN %>&grant_type=fb_exchange_token:
312
+ post:
313
+ no_token: access_token=<%= ACCESS_TOKEN %>&expires=5184000
314
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&fb_exchange_token=foo&grant_type=fb_exchange_token:
315
+ post:
316
+ <<: *oauth_error
317
+ /oauth/exchange_sessions:
318
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
319
+ post:
320
+ no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
321
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= [OAUTH_DATA["session_key"], OAUTH_DATA["session_key"]].join(",") %>&type=client_cred:
322
+ post:
323
+ no_token: '[{"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
324
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= ["foo"].concat([OAUTH_DATA["session_key"], OAUTH_DATA["session_key"]]).join(",") %>&type=client_cred:
325
+ post:
326
+ no_token: '[null, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}, {"access_token":"<%= ACCESS_TOKEN %>","expires":4315}]'
327
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo,bar&type=client_cred:
328
+ post:
329
+ no_token: '[null, null]'
330
+ client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=foo&type=client_cred:
331
+ post:
332
+ no_token: '[null]'
333
+
334
+
335
+
336
+ # -- Subscription Responses --
337
+ /<%= APP_ID %>/subscriptions:
338
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
339
+ post:
340
+ with_token:
341
+ code: 200
342
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>&fields=name&object=user:
343
+ post:
344
+ with_token:
345
+ code: 200
346
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
347
+ post:
348
+ with_token:
349
+ code: 400
350
+ body: '{"error":{"type":"Exception","message":"(#2200) subscription validation failed"}}'
351
+ callback_url=foo&fields=name&object=user&verify_token=<%= SUBSCRIPTION_DATA["verify_token"] %>:
352
+ post:
353
+ with_token:
354
+ code: 400
355
+ body: '{"error":{"type":"Exception","message":"(#100) callback_url URL is not properly formatted"}}'
356
+ object=user:
357
+ delete:
358
+ with_token:
359
+ code: 200
360
+ object=kittens:
361
+ delete:
362
+ with_token:
363
+ code: 400
364
+ body: '{"error":{"type":"Exception","message":"(#100) Invalid parameter"}}'
365
+ no_args:
366
+ delete:
367
+ with_token:
368
+ code: 200
369
+ get:
370
+ with_token: '{"data":[{"callback_url":"https://testdomain.koalatest.test/subscriptions", "fields":["name"], "object":"user", "active":true}]}'
371
+
372
+
373
+ callback_url=<%= SUBSCRIPTION_DATA["subscription_path"] %>:
374
+ get:
375
+ with_token: '{"data":[{"callback_url":"https://testdomain.koalatest.test/subscriptions", "fields":["name"], "object":"user", "active":true}]}'
376
+
377
+ # -- Mock Item Responses --
378
+
379
+ /MOCK_FEED_ITEM/likes:
380
+ no_args:
381
+ post:
382
+ with_token: '{"id": "MOCK_LIKE"}'
383
+
384
+ /MOCK_FEED_ITEM/comments:
385
+ message=it's my comment!:
386
+ post:
387
+ with_token: '{"id": "MOCK_COMMENT"}'
388
+
389
+ /MOCK_FEED_ITEM:
390
+ no_args:
391
+ <<: *item_deleted
392
+
393
+ /FEED_ITEM_CONTEXT:
394
+ no_args:
395
+ <<: *item_deleted
396
+ get:
397
+ with_token: '{"link":"http://testdomain.koalatest.test/", "name": "OAuth Playground"}'
398
+
399
+ /FEED_ITEM_DICTIONARY:
400
+ no_args:
401
+ <<: *item_deleted
402
+ get:
403
+ with_token: '{"link":"http://testdomain.koalatest.test/", "name": "OAuth Playground", "properties": {}}'
404
+
405
+ /FEED_ITEM_CATS:
406
+ no_args:
407
+ <<: *item_deleted
408
+ get:
409
+ with_token: '{"message": "the cats are asleep"}'
410
+
411
+ /FEED_ITEM_DELETE:
412
+ no_args:
413
+ <<: *item_deleted
414
+
415
+ /FEED_ITEM_DELETE/likes:
416
+ no_args:
417
+ <<: *item_deleted
418
+ post:
419
+ with_token: 'true'
420
+
421
+ /MOCK_COMMENT:
422
+ no_args:
423
+ <<: *item_deleted
424
+ get:
425
+ with_token: "{\"message\": \"it's my comment!\"}"
426
+ /MOCK_PHOTO:
427
+ no_args:
428
+ <<: *item_deleted
429
+ get:
430
+ with_token: "{\"name\": \"This is the test message\"}"
431
+
432
+ # -- Mock Test User Responses --
433
+ /<%= APP_ID %>/accounts/test-users:
434
+ installed=false:
435
+ <<: *test_user_uninstalled
436
+ installed=false&permissions=read_stream:
437
+ <<: *test_user_uninstalled
438
+ installed=true&permissions=:
439
+ <<: *test_user_installed
440
+ installed=true&permissions=read_stream:
441
+ <<: *test_user_installed
442
+ installed=true&permissions=read_stream,user_interests:
443
+ post:
444
+ with_token: '{"id": "888888888", "access_token":"<%= ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
445
+ no_args:
446
+ get:
447
+ 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.."}], "paging":{"next":"https://graph.facebook.com/119908831367602/accounts/test-users?access_token=119908831367602|o3wswWQ88LYjEC9-ukR_gjRIOMw&limit=50&offset=50&__after_id=100003241848740"}}'
448
+
449
+ /999999999:
450
+ no_args:
451
+ <<: *item_deleted
452
+ get:
453
+ with_token: '{"name":"Foo Baz"}'
454
+ name=Foo Baz:
455
+ post:
456
+ with_token: 'true'
457
+
458
+
459
+ /999999999/friends/888888888:
460
+ no_args:
461
+ post:
462
+ with_token: 'true'
463
+
464
+
465
+ /9999999991:
466
+ no_args:
467
+ delete:
468
+ with_token:
469
+ code: 400
470
+ body: '{"error": {"type": "OAuthException", "message": "Error validating verification code."}}'
471
+
472
+ /888888888:
473
+ no_args:
474
+ <<: *item_deleted
475
+
476
+ /888888888/friends/999999999:
477
+ no_args:
478
+ <<: *test_user_befriended
479
+
480
+
481
+ /777777777:
482
+ no_args:
483
+ <<: *item_deleted