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.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +32 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.yardopts +3 -0
- data/Gemfile +25 -0
- data/ISSUE_TEMPLATE +25 -0
- data/LICENSE +22 -0
- data/Manifest +32 -5
- data/PULL_REQUEST_TEMPLATE +11 -0
- data/Rakefile +12 -12
- data/changelog.md +781 -0
- data/code_of_conduct.md +74 -0
- data/koala.gemspec +28 -24
- data/lib/koala/api/batch_operation.rb +86 -0
- data/lib/koala/api/graph_api_methods.rb +504 -0
- data/lib/koala/api/graph_batch_api.rb +167 -0
- data/lib/koala/api/graph_collection.rb +129 -0
- data/lib/koala/api/graph_error_checker.rb +72 -0
- data/lib/koala/api.rb +159 -0
- data/lib/koala/configuration.rb +56 -0
- data/lib/koala/errors.rb +126 -0
- data/lib/koala/http_service/request.rb +133 -0
- data/lib/koala/http_service/response.rb +20 -0
- data/lib/koala/http_service/uploadable_io.rb +183 -0
- data/lib/koala/http_service.rb +108 -0
- data/lib/koala/oauth.rb +342 -0
- data/lib/koala/realtime_updates.rb +151 -0
- data/lib/koala/test_users.rb +189 -0
- data/lib/koala/utils.rb +41 -0
- data/lib/koala/version.rb +3 -0
- data/lib/koala.rb +51 -291
- data/readme.md +269 -21
- data/spec/cases/api_spec.rb +362 -0
- data/spec/cases/configuration_spec.rb +11 -0
- data/spec/cases/error_spec.rb +143 -0
- data/spec/cases/graph_api_batch_spec.rb +788 -0
- data/spec/cases/graph_api_spec.rb +76 -0
- data/spec/cases/graph_collection_spec.rb +192 -0
- data/spec/cases/graph_error_checker_spec.rb +147 -0
- data/spec/cases/http_service/request_spec.rb +250 -0
- data/spec/cases/http_service/response_spec.rb +24 -0
- data/spec/cases/http_service_spec.rb +280 -0
- data/spec/cases/koala_spec.rb +57 -0
- data/spec/cases/koala_test_spec.rb +5 -0
- data/spec/cases/oauth_spec.rb +647 -0
- data/spec/cases/realtime_updates_spec.rb +327 -0
- data/spec/cases/test_users_spec.rb +383 -0
- data/spec/cases/uploadable_io_spec.rb +266 -0
- data/spec/cases/utils_spec.rb +55 -0
- data/spec/fixtures/beach.jpg +0 -0
- data/spec/fixtures/cat.m4v +0 -0
- data/spec/fixtures/facebook_data.yml +63 -0
- data/spec/fixtures/mock_facebook_responses.yml +483 -0
- data/spec/fixtures/vcr_cassettes/app_test_accounts.yml +97 -0
- data/spec/fixtures/vcr_cassettes/friend_list_next_page.yml +121 -0
- data/spec/integration/graph_collection_spec.rb +24 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/custom_matchers.rb +28 -0
- data/spec/support/graph_api_shared_examples.rb +534 -0
- data/spec/support/koala_test.rb +251 -0
- data/spec/support/mock_http_service.rb +140 -0
- data/spec/support/uploadable_io_shared_examples.rb +70 -0
- metadata +206 -62
- data/CHANGELOG +0 -24
- data/init.rb +0 -2
- data/lib/http_services.rb +0 -60
- data/test/facebook_data.yml +0 -5
- data/test/koala/facebook_no_access_token_tests.rb +0 -119
- data/test/koala/facebook_with_access_token_tests.rb +0 -106
- data/test/koala_tests.rb +0 -30
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'base64'
|
|
3
|
+
|
|
4
|
+
describe "Koala::Facebook::RealtimeUpdates" do
|
|
5
|
+
before :all do
|
|
6
|
+
# get oauth data
|
|
7
|
+
@app_id = KoalaTest.app_id
|
|
8
|
+
@secret = KoalaTest.secret
|
|
9
|
+
@callback_url = KoalaTest.oauth_test_data["callback_url"]
|
|
10
|
+
@app_access_token = KoalaTest.app_access_token
|
|
11
|
+
|
|
12
|
+
# check OAuth data
|
|
13
|
+
unless @app_id && @secret && @callback_url && @app_access_token
|
|
14
|
+
raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# get subscription data
|
|
18
|
+
@verify_token = KoalaTest.subscription_test_data["verify_token"]
|
|
19
|
+
@challenge_data = KoalaTest.subscription_test_data["challenge_data"]
|
|
20
|
+
@subscription_path = KoalaTest.subscription_test_data["subscription_path"]
|
|
21
|
+
|
|
22
|
+
# check subscription data
|
|
23
|
+
unless @verify_token && @challenge_data && @subscription_path
|
|
24
|
+
raise Exception, "Must supply verify_token and equivalent challenge_data to run subscription tests!"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
before :each do
|
|
29
|
+
@updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe ".new" do
|
|
33
|
+
# basic initialization
|
|
34
|
+
it "initializes properly with an app_id and an app_access_token" do
|
|
35
|
+
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
|
36
|
+
expect(updates).to be_a(Koala::Facebook::RealtimeUpdates)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "with global defaults" do
|
|
40
|
+
let(:app_id) { :app_id }
|
|
41
|
+
let(:app_secret) { :app_secret }
|
|
42
|
+
let(:app_access_token) { :app_access_token }
|
|
43
|
+
|
|
44
|
+
before :each do
|
|
45
|
+
Koala.configure do |config|
|
|
46
|
+
config.app_id = app_id
|
|
47
|
+
config.app_secret = app_secret
|
|
48
|
+
config.app_access_token = app_access_token
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "defaults to the configured data if not otherwise provided" do
|
|
53
|
+
rtu = Koala::Facebook::RealtimeUpdates.new
|
|
54
|
+
expect(rtu.app_id).to eq(app_id)
|
|
55
|
+
expect(rtu.secret).to eq(app_secret)
|
|
56
|
+
expect(rtu.app_access_token).to eq(app_access_token)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "lets you override app_id" do
|
|
60
|
+
other_value = :another_id
|
|
61
|
+
rtu = Koala::Facebook::RealtimeUpdates.new(app_id: other_value)
|
|
62
|
+
expect(rtu.app_id).to eq(other_value)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "lets you override secret" do
|
|
66
|
+
other_value = :another_secret
|
|
67
|
+
rtu = Koala::Facebook::RealtimeUpdates.new(secret: other_value)
|
|
68
|
+
expect(rtu.secret).to eq(other_value)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "lets you override app_id" do
|
|
72
|
+
other_value = :another_token
|
|
73
|
+
rtu = Koala::Facebook::RealtimeUpdates.new(app_access_token: other_value)
|
|
74
|
+
expect(rtu.app_access_token).to eq(other_value)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# attributes
|
|
79
|
+
it "allows read access to app_id" do
|
|
80
|
+
# in Ruby 1.9, .method returns symbols
|
|
81
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).to include(:app_id)
|
|
82
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).not_to include(:app_id=)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "allows read access to app_access_token" do
|
|
86
|
+
# in Ruby 1.9, .method returns symbols
|
|
87
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).to include(:app_access_token)
|
|
88
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).not_to include(:app_access_token=)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "allows read access to secret" do
|
|
92
|
+
# in Ruby 1.9, .method returns symbols
|
|
93
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).to include(:secret)
|
|
94
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).not_to include(:secret=)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "allows read access to api" do
|
|
98
|
+
# in Ruby 1.9, .method returns symbols
|
|
99
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).to include(:api)
|
|
100
|
+
expect(Koala::Facebook::RealtimeUpdates.instance_methods.map(&:to_sym)).not_to include(:api=)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# init with secret / fetching the token
|
|
104
|
+
it "initializes properly with an app_id and a secret" do
|
|
105
|
+
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
|
106
|
+
expect(updates).to be_a(Koala::Facebook::RealtimeUpdates)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "sets up the API with the app access token" do
|
|
110
|
+
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
|
111
|
+
expect(updates.api).to be_a(Koala::Facebook::API)
|
|
112
|
+
expect(updates.api.access_token).to eq(@app_access_token)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "#app_access_token" do
|
|
117
|
+
it "fetches an app_token from Facebook when provided an app_id and a secret" do
|
|
118
|
+
# integration test
|
|
119
|
+
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :secret => @secret)
|
|
120
|
+
expect(updates.app_access_token).not_to be_nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "returns the provided token if provided" do
|
|
124
|
+
updates = Koala::Facebook::RealtimeUpdates.new(app_id: @app_id, app_access_token: @app_access_token)
|
|
125
|
+
expect(updates.app_access_token).to eq(@app_access_token)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe "#subscribe" do
|
|
130
|
+
it "makes a POST to the subscription path" do
|
|
131
|
+
expect(@updates.api).to receive(:graph_call).with(@updates.subscription_path, anything, "post", anything)
|
|
132
|
+
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "properly formats the subscription request" do
|
|
136
|
+
obj = "user"
|
|
137
|
+
fields = "name"
|
|
138
|
+
expect(@updates.api).to receive(:graph_call).with(anything, hash_including(
|
|
139
|
+
:object => obj,
|
|
140
|
+
:fields => fields,
|
|
141
|
+
:callback_url => @subscription_path,
|
|
142
|
+
:verify_token => @verify_token
|
|
143
|
+
), anything, anything)
|
|
144
|
+
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "accepts an options hash" do
|
|
148
|
+
options = {:a => 2, :b => "c"}
|
|
149
|
+
expect(@updates.api).to receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
|
150
|
+
@updates.subscribe("user", "name", @subscription_path, @verify_token, options)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
describe "in practice" do
|
|
154
|
+
it "sends a subscription request" do
|
|
155
|
+
expect { @updates.subscribe("user", "name", @subscription_path, @verify_token) }.to_not raise_error
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "fails if you try to hit an invalid path on your valid server" do
|
|
159
|
+
expect { result = @updates.subscribe("user", "name", @subscription_path + "foo", @verify_token) }.to raise_exception(Koala::Facebook::APIError)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "fails to send a subscription request to an invalid server" do
|
|
163
|
+
expect { @updates.subscribe("user", "name", "foo", @verify_token) }.to raise_exception(Koala::Facebook::APIError)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
describe "#unsubscribe" do
|
|
169
|
+
it "makes a DELETE to the subscription path" do
|
|
170
|
+
expect(@updates.api).to receive(:graph_call).with(@updates.subscription_path, anything, "delete", anything)
|
|
171
|
+
@updates.unsubscribe("user")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "includes the object if provided" do
|
|
175
|
+
obj = "user"
|
|
176
|
+
expect(@updates.api).to receive(:graph_call).with(anything, hash_including(:object => obj), anything, anything)
|
|
177
|
+
@updates.unsubscribe(obj)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "accepts an options hash" do
|
|
181
|
+
options = {:a => 2, :b => "C"}
|
|
182
|
+
expect(@updates.api).to receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
|
183
|
+
@updates.unsubscribe("user", options)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe "in practice" do
|
|
187
|
+
it "unsubscribes a valid individual object successfully" do
|
|
188
|
+
expect { @updates.unsubscribe("user") }.to_not raise_error
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "unsubscribes all subscriptions successfully" do
|
|
192
|
+
expect { @updates.unsubscribe }.to_not raise_error
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "fails when an invalid object is provided to unsubscribe" do
|
|
196
|
+
expect { @updates.unsubscribe("kittens") }.to raise_error(Koala::Facebook::APIError)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
describe "#list_subscriptions" do
|
|
202
|
+
it "GETs the subscription path" do
|
|
203
|
+
expect(@updates.api).to receive(:graph_call).with(@updates.subscription_path, anything, "get", anything)
|
|
204
|
+
@updates.list_subscriptions
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "accepts options" do
|
|
208
|
+
options = {:a => 3, :b => "D"}
|
|
209
|
+
expect(@updates.api).to receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
|
210
|
+
@updates.list_subscriptions(options)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe "in practice" do
|
|
214
|
+
it "lists subscriptions properly" do
|
|
215
|
+
expect(@updates.list_subscriptions).to be_a(Array)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe "#subscription_path" do
|
|
221
|
+
it "returns the app_id/subscriptions" do
|
|
222
|
+
expect(@updates.subscription_path).to eq("#{@app_id}/subscriptions")
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
describe "#validate_update" do
|
|
227
|
+
it "raises an error if no secret is defined" do
|
|
228
|
+
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => "foo")
|
|
229
|
+
expect {
|
|
230
|
+
updates.validate_update("", {})
|
|
231
|
+
}.to raise_exception(Koala::Facebook::AppSecretNotDefinedError)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "returns false if there is no X-Hub-Signature header" do
|
|
235
|
+
expect(@updates.validate_update("", {})).to be_falsey
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "returns false if the signature doesn't match the body" do
|
|
239
|
+
expect(@updates.validate_update("", {"X-Hub-Signature" => "sha1=badsha1"})).to be_falsey
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "results true if the signature matches the body with the secret" do
|
|
243
|
+
body = "BODY"
|
|
244
|
+
signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body).chomp
|
|
245
|
+
expect(@updates.validate_update(body, {"X-Hub-Signature" => "sha1=#{signature}"})).to be_truthy
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "results true with alternate HTTP_X_HUB_SIGNATURE header" do
|
|
249
|
+
body = "BODY"
|
|
250
|
+
signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body).chomp
|
|
251
|
+
expect(@updates.validate_update(body, {"HTTP_X_HUB_SIGNATURE" => "sha1=#{signature}"})).to be_truthy
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
describe ".meet_challenge" do
|
|
257
|
+
it "returns false if hub.mode isn't subscribe" do
|
|
258
|
+
params = {'hub.mode' => 'not subscribe'}
|
|
259
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(params)).to be_falsey
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "doesn't evaluate the block if hub.mode isn't subscribe" do
|
|
263
|
+
params = {'hub.mode' => 'not subscribe'}
|
|
264
|
+
block_evaluated = false
|
|
265
|
+
Koala::Facebook::RealtimeUpdates.meet_challenge(params){|token| block_evaluated = true}
|
|
266
|
+
expect(block_evaluated).to be_falsey
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "returns false if not given a verify_token or block" do
|
|
270
|
+
params = {'hub.mode' => 'subscribe'}
|
|
271
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(params)).to be_falsey
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe "and mode is 'subscribe'" do
|
|
275
|
+
before(:each) do
|
|
276
|
+
@params = {'hub.mode' => 'subscribe'}
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
describe "and a token is given" do
|
|
280
|
+
before(:each) do
|
|
281
|
+
@token = 'token'
|
|
282
|
+
@params['hub.verify_token'] = @token
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
it "returns false if the given verify token doesn't match" do
|
|
286
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token + '1')).to be_falsey
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "returns the challenge if the given verify token matches" do
|
|
290
|
+
@params['hub.challenge'] = 'challenge val'
|
|
291
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(@params, @token)).to eq(@params['hub.challenge'])
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
describe "and a block is given" do
|
|
296
|
+
before :each do
|
|
297
|
+
@params['hub.verify_token'] = @token
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it "gives the block the token as a parameter" do
|
|
301
|
+
Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
|
302
|
+
expect(token).to eq(@token)
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "returns false if the given block return false" do
|
|
307
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
|
308
|
+
false
|
|
309
|
+
end).to be_falsey
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it "returns false if the given block returns nil" do
|
|
313
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
|
314
|
+
nil
|
|
315
|
+
end).to be_falsey
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "returns the challenge if the given block returns true" do
|
|
319
|
+
@params['hub.challenge'] = 'challenge val'
|
|
320
|
+
expect(Koala::Facebook::RealtimeUpdates.meet_challenge(@params) do |token|
|
|
321
|
+
true
|
|
322
|
+
end).to be_truthy
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|