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,362 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Koala::Facebook::API" do
|
|
4
|
+
before :each do
|
|
5
|
+
@service = Koala::Facebook::API.new
|
|
6
|
+
end
|
|
7
|
+
let(:dummy_response) { double("fake response", data: {}, status: 200, body: "", headers: {}) }
|
|
8
|
+
|
|
9
|
+
it "defaults to the globally configured token if one's provided" do
|
|
10
|
+
token = "Foo"
|
|
11
|
+
|
|
12
|
+
Koala.configure do |config|
|
|
13
|
+
config.access_token = token
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
expect(Koala::Facebook::API.new.access_token).to eq(token)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "defaults to the globally configured app_secret if one's provided" do
|
|
20
|
+
app_secret = "Foo"
|
|
21
|
+
|
|
22
|
+
Koala.configure do |config|
|
|
23
|
+
config.app_secret = app_secret
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
expect(Koala::Facebook::API.new.app_secret).to eq(app_secret)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "doesn't include an access token if none was given" do
|
|
30
|
+
expect(Koala).to receive(:make_request).with(
|
|
31
|
+
anything,
|
|
32
|
+
hash_not_including('access_token' => 1),
|
|
33
|
+
anything,
|
|
34
|
+
anything
|
|
35
|
+
).and_return(Koala::HTTPService::Response.new(200, "", ""))
|
|
36
|
+
|
|
37
|
+
@service.api('anything')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "includes an access token if given" do
|
|
41
|
+
token = 'adfadf'
|
|
42
|
+
service = Koala::Facebook::API.new token
|
|
43
|
+
|
|
44
|
+
expect(Koala).to receive(:make_request).with(
|
|
45
|
+
anything,
|
|
46
|
+
hash_including('access_token' => token),
|
|
47
|
+
anything,
|
|
48
|
+
anything
|
|
49
|
+
).and_return(Koala::HTTPService::Response.new(200, "", ""))
|
|
50
|
+
|
|
51
|
+
service.api('anything')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "doesn't add token to received arguments" do
|
|
55
|
+
token = 'adfadf'
|
|
56
|
+
service = Koala::Facebook::API.new token
|
|
57
|
+
|
|
58
|
+
expect(Koala).to receive(:make_request).with(
|
|
59
|
+
anything,
|
|
60
|
+
hash_including('access_token' => token),
|
|
61
|
+
anything,
|
|
62
|
+
anything
|
|
63
|
+
).and_return(Koala::HTTPService::Response.new(200, "", ""))
|
|
64
|
+
|
|
65
|
+
args = {}.freeze
|
|
66
|
+
service.api('anything', args)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "turns arrays of non-enumerables into comma-separated arguments by default" do
|
|
70
|
+
args = [12345, {:foo => [1, 2, "3", :four]}]
|
|
71
|
+
expected = ["/12345", {:foo => "1,2,3,four"}, "get", {}]
|
|
72
|
+
response = double('Mock KoalaResponse', :body => '', :status => 200)
|
|
73
|
+
expect(Koala).to receive(:make_request).with(*expected).and_return(response)
|
|
74
|
+
@service.api(*args)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "can be configured to leave arrays of non-enumerables as is" do
|
|
78
|
+
Koala.configure do |config|
|
|
79
|
+
config.preserve_form_arguments = true
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
args = [12345, {:foo => [1, 2, "3", :four]}]
|
|
83
|
+
expected = ["/12345", {:foo => [1, 2, "3", :four]}, "get", {}]
|
|
84
|
+
response = double('Mock KoalaResponse', :body => '', :status => 200)
|
|
85
|
+
expect(Koala).to receive(:make_request).with(*expected).and_return(response)
|
|
86
|
+
@service.api(*args)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "can be configured on a per-request basis to leave arrays as is" do
|
|
90
|
+
args = [12345, {foo: [1, 2, "3", :four]}, "get", preserve_form_arguments: true]
|
|
91
|
+
expected = ["/12345", {foo: [1, 2, "3", :four]}, "get", preserve_form_arguments: true]
|
|
92
|
+
response = double('Mock KoalaResponse', :body => '', :status => 200)
|
|
93
|
+
expect(Koala).to receive(:make_request).with(*expected).and_return(response)
|
|
94
|
+
@service.api(*args)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "doesn't turn arrays containing enumerables into comma-separated strings" do
|
|
98
|
+
params = {:foo => [1, 2, ["3"], :four]}
|
|
99
|
+
args = [12345, params]
|
|
100
|
+
# we leave this as is -- the HTTP layer can either handle it appropriately
|
|
101
|
+
# (if appropriate behavior is defined)
|
|
102
|
+
# or raise an exception
|
|
103
|
+
expected = ["/12345", params, "get", {}]
|
|
104
|
+
response = double('Mock KoalaResponse', :body => '', :status => 200)
|
|
105
|
+
expect(Koala).to receive(:make_request).with(*expected).and_return(response)
|
|
106
|
+
@service.api(*args)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "doesn't modify any data if the option format of :json is provided" do
|
|
110
|
+
args = [12345, {:foo => [1, 2, "3", :four]}, 'get', format: :json]
|
|
111
|
+
expected = ["/12345", {:foo => [1, 2, "3", :four]}, 'get', format: :json]
|
|
112
|
+
response = double('Mock KoalaResponse', :body => '', :status => 200)
|
|
113
|
+
expect(Koala).to receive(:make_request).with(*expected).and_return(response)
|
|
114
|
+
@service.api(*args)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "raises an API error if the HTTP response code is greater than or equal to 500" do
|
|
118
|
+
allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, 'response body', {}))
|
|
119
|
+
|
|
120
|
+
expect { @service.api('anything') }.to raise_exception(Koala::Facebook::APIError)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe "path manipulation" do
|
|
124
|
+
context "leading /" do
|
|
125
|
+
it "adds a leading / to the path if not present" do
|
|
126
|
+
path = "anything"
|
|
127
|
+
expect(Koala).to receive(:make_request).with("/#{path}", anything, anything, anything).and_return(Koala::HTTPService::Response.new(200, 'true', {}))
|
|
128
|
+
@service.api(path)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "doesn't change the path if a leading / is present" do
|
|
132
|
+
path = "/anything"
|
|
133
|
+
expect(Koala).to receive(:make_request).with(path, anything, anything, anything).and_return(Koala::HTTPService::Response.new(200, 'true', {}))
|
|
134
|
+
@service.api(path)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "with an access token" do
|
|
140
|
+
before(:each) do
|
|
141
|
+
@api = Koala::Facebook::API.new(@token)
|
|
142
|
+
@app_access_token = KoalaTest.app_access_token
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it_should_behave_like "Koala GraphAPI"
|
|
146
|
+
it_should_behave_like "Koala GraphAPI with an access token"
|
|
147
|
+
it_should_behave_like "Koala GraphAPI with GraphCollection"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe "without an access token" do
|
|
151
|
+
before(:each) do
|
|
152
|
+
@api = Koala::Facebook::API.new
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# In theory this should behave the same with a GraphCollection, but those tests currently hit
|
|
156
|
+
# an endpoint that now requires a token.
|
|
157
|
+
it_should_behave_like "Koala GraphAPI"
|
|
158
|
+
it_should_behave_like "Koala GraphAPI without an access token"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context '#api' do
|
|
162
|
+
let(:access_token) { 'access_token' }
|
|
163
|
+
let(:api) { Koala::Facebook::API.new(access_token) }
|
|
164
|
+
let(:path) { '/path' }
|
|
165
|
+
let(:appsecret) { 'appsecret' }
|
|
166
|
+
let(:token_args) { { 'access_token' => access_token } }
|
|
167
|
+
let(:appsecret_proof_args) { { 'appsecret_proof' => OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), appsecret, access_token) } }
|
|
168
|
+
let(:verb) { 'get' }
|
|
169
|
+
let(:response) { Koala::HTTPService::Response.new(200, '', '') }
|
|
170
|
+
|
|
171
|
+
describe "the appsecret_proof arguments" do
|
|
172
|
+
describe "with an API access token present" do
|
|
173
|
+
describe "and with an appsecret included on API initialization " do
|
|
174
|
+
let(:api) { Koala::Facebook::API.new(access_token, appsecret) }
|
|
175
|
+
|
|
176
|
+
it "will be included by default" do
|
|
177
|
+
expect(Koala).to receive(:make_request).with(path, token_args.merge(appsecret_proof_args), verb, {}).and_return(response)
|
|
178
|
+
api.api(path, {}, verb, :appsecret_proof => true)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe "but without an appsecret included on API initialization" do
|
|
183
|
+
it "will not be included" do
|
|
184
|
+
expect(Koala).to receive(:make_request).with(path, token_args, verb, {}).and_return(response)
|
|
185
|
+
api.api(path, {}, verb, :appsecret_proof => true)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe "but without an API access token present" do
|
|
191
|
+
describe "and with an appsecret included on API initialization " do
|
|
192
|
+
let(:api) { Koala::Facebook::API.new(nil, appsecret) }
|
|
193
|
+
|
|
194
|
+
it "will not be included" do
|
|
195
|
+
expect(Koala).to receive(:make_request).with(path, {}, verb, {}).and_return(response)
|
|
196
|
+
api.api(path, {}, verb, :appsecret_proof => true)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
describe "but without an appsecret included on API initialization" do
|
|
201
|
+
let(:api) { Koala::Facebook::API.new }
|
|
202
|
+
|
|
203
|
+
it "will not be included" do
|
|
204
|
+
expect(Koala).to receive(:make_request).with(path, {}, verb, {}).and_return(response)
|
|
205
|
+
api.api(path, {}, verb, :appsecret_proof => true)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
describe "#graph_call" do
|
|
213
|
+
it "passes all arguments to the api method" do
|
|
214
|
+
user = KoalaTest.user1
|
|
215
|
+
args = {}
|
|
216
|
+
verb = 'get'
|
|
217
|
+
opts = {:a => :b}
|
|
218
|
+
expect(@service).to receive(:api).with(user, args, verb, opts).and_return(dummy_response)
|
|
219
|
+
@service.graph_call(user, args, verb, opts)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "throws an APIError if the result hash has an error key" do
|
|
223
|
+
allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, '{"error": "An error occurred!"}', {}))
|
|
224
|
+
expect { @service.graph_call(KoalaTest.user1, {}) }.to raise_exception(Koala::Facebook::APIError)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "passes the results through GraphCollection.evaluate" do
|
|
228
|
+
allow(@service).to receive(:api).and_return(dummy_response)
|
|
229
|
+
expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).with(dummy_response, @service)
|
|
230
|
+
@service.graph_call("/me")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "returns the results of GraphCollection.evaluate" do
|
|
234
|
+
expected = {}
|
|
235
|
+
allow(@service).to receive(:api).and_return(dummy_response)
|
|
236
|
+
expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).and_return(expected)
|
|
237
|
+
expect(@service.graph_call("/me")).to eq(expected)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "returns the post_processing block's results if one is supplied" do
|
|
241
|
+
other_result = [:a, 2, :three]
|
|
242
|
+
block = Proc.new {|r| other_result}
|
|
243
|
+
allow(@service).to receive(:api).and_return(dummy_response)
|
|
244
|
+
expect(@service.graph_call("/me", {}, "get", {}, &block)).to eq(other_result)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it "gets the status of a Koala::HTTPService::Response if requested" do
|
|
248
|
+
response = Koala::HTTPService::Response.new(200, '', {})
|
|
249
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
250
|
+
|
|
251
|
+
expect(@service.graph_call('anything', {}, 'get', http_component: :status)).to eq(200)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it "gets the headers of a Koala::HTTPService::Response if requested" do
|
|
255
|
+
headers = {"a" => 2}
|
|
256
|
+
response = Koala::HTTPService::Response.new(200, '', headers)
|
|
257
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
258
|
+
|
|
259
|
+
expect(@service.graph_call('anything', {}, 'get', :http_component => :headers)).to eq(headers)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "returns the entire response if http_component => :response" do
|
|
263
|
+
http_component = :response
|
|
264
|
+
response = Koala::HTTPService::Response.new(200, '', {})
|
|
265
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
266
|
+
expect(@service.graph_call('anything', {}, 'get', :http_component => http_component)).to eq(response)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it "returns the body of the request as JSON if no http_component is given" do
|
|
270
|
+
result = {"a" => 2}
|
|
271
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, {})
|
|
272
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
273
|
+
|
|
274
|
+
expect(@service.graph_call('anything')).to eq(result)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "handles rogue true/false as responses" do
|
|
278
|
+
expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'true', {}))
|
|
279
|
+
expect(@service.graph_call('anything')).to be_truthy
|
|
280
|
+
|
|
281
|
+
expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'false', {}))
|
|
282
|
+
expect(@service.graph_call('anything')).to be_falsey
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
describe "Rate limit hook" do
|
|
287
|
+
it "is called when x-business-use-case-usage header is present" do
|
|
288
|
+
api = Koala::Facebook::API.new('', '', ->(limits) {
|
|
289
|
+
expect(limits["x-business-use-case-usage"]).to eq({"123456789012345"=>[{"type"=>"messenger", "call_count"=>1, "total_cputime"=>1, "total_time"=>1, "estimated_time_to_regain_access"=>0}]})
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
result = {"a" => 2}
|
|
293
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, { "x-business-use-case-usage" => "{\"123456789012345\":[{\"type\":\"messenger\",\"call_count\":1,\"total_cputime\":1,\"total_time\":1,\"estimated_time_to_regain_access\":0}]}" })
|
|
294
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
295
|
+
|
|
296
|
+
api.graph_call('anything')
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it "is called when x-ad-account-usage header is present" do
|
|
300
|
+
api = Koala::Facebook::API.new('', '', ->(limits) {
|
|
301
|
+
expect(limits["x-ad-account-usage"]).to eq({"acc_id_util_pct"=>9.67})
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
result = {"a" => 2}
|
|
305
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, { "x-ad-account-usage" => "{\"acc_id_util_pct\":9.67}" })
|
|
306
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
307
|
+
|
|
308
|
+
api.graph_call('anything')
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "is called when x-app-usage header is present" do
|
|
312
|
+
api = Koala::Facebook::API.new('', '', ->(limits) {
|
|
313
|
+
expect(limits["x-app-usage"]).to eq({"call_count"=>0, "total_cputime"=>0, "total_time"=>0})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
result = {"a" => 2}
|
|
317
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, { "x-app-usage" => "{\"call_count\":0,\"total_cputime\":0,\"total_time\":0}" })
|
|
318
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
319
|
+
|
|
320
|
+
api.graph_call('anything')
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
it "isn't called if none of the rate limit header is present" do
|
|
324
|
+
rate_limit_hook_called = false
|
|
325
|
+
|
|
326
|
+
api = Koala::Facebook::API.new('', '', ->(limits) {
|
|
327
|
+
rate_limit_hook_called = true
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
result = {"a" => 2}
|
|
331
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, {})
|
|
332
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
333
|
+
|
|
334
|
+
api.graph_call('anything')
|
|
335
|
+
|
|
336
|
+
expect(rate_limit_hook_called).to be(false)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "isn't called if no rate limit hook is defined" do
|
|
340
|
+
api = Koala::Facebook::API.new('', '', ->(limits) {
|
|
341
|
+
#noop
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
result = {"a" => 2}
|
|
345
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, { "x-ad-account-usage" => "{\"acc_id_util_pct\"9.67}"})
|
|
346
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
347
|
+
|
|
348
|
+
expect(Koala::Utils.logger).to receive(:error).with("JSON::ParserError: expected ':' after object key at line 1 column 19 while parsing x-ad-account-usage = {\"acc_id_util_pct\"9.67}")
|
|
349
|
+
api.graph_call('anything')
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it "logs an error if the rate limit header can't be properly parsed" do
|
|
353
|
+
api = Koala::Facebook::API.new('', '', nil)
|
|
354
|
+
|
|
355
|
+
result = {"a" => 2}
|
|
356
|
+
response = Koala::HTTPService::Response.new(200, result.to_json, {})
|
|
357
|
+
allow(Koala).to receive(:make_request).and_return(response)
|
|
358
|
+
|
|
359
|
+
api.graph_call('anything')
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
RSpec.describe Koala::Configuration do
|
|
4
|
+
let(:config) { Koala::Configuration.new }
|
|
5
|
+
|
|
6
|
+
it "defaults the HTTPService's DEFAULT_SERVERS" do
|
|
7
|
+
Koala::HTTPService::DEFAULT_SERVERS.each_pair do |key, value|
|
|
8
|
+
expect(config.public_send(key)).to eq(value)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
BUC_USAGE_JSON = "{\"123456789012345\":[{\"type\":\"messenger\",\"call_count\":1,\"total_cputime\":1,\"total_time\":1,\"estimated_time_to_regain_access\":0}]}"
|
|
4
|
+
ADA_USAGE_JSON = "{\"acc_id_util_pct\":9.67}"
|
|
5
|
+
APP_USAGE_JSON = "{\"call_count\":0,\"total_cputime\":0,\"total_time\":0}"
|
|
6
|
+
|
|
7
|
+
describe Koala::Facebook::APIError do
|
|
8
|
+
it "is a Koala::KoalaError" do
|
|
9
|
+
expect(Koala::Facebook::APIError.new(nil, nil)).to be_a(Koala::KoalaError)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
[:fb_error_type, :fb_error_code, :fb_error_subcode, :fb_error_message, :fb_error_user_msg, :fb_error_user_title, :fb_error_trace_id, :fb_error_rev, :fb_error_debug, :http_status, :response_body].each do |accessor|
|
|
13
|
+
it "has an accessor for #{accessor}" do
|
|
14
|
+
expect(Koala::Facebook::APIError.instance_methods.map(&:to_sym)).to include(accessor)
|
|
15
|
+
expect(Koala::Facebook::APIError.instance_methods.map(&:to_sym)).to include(:"#{accessor}=")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "sets http_status to the provided status" do
|
|
20
|
+
error_response = '{ "error": {"type": "foo", "other_details": "bar"} }'
|
|
21
|
+
expect(Koala::Facebook::APIError.new(400, error_response).response_body).to eq(error_response)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "sets response_body to the provided response body" do
|
|
25
|
+
expect(Koala::Facebook::APIError.new(400, '').http_status).to eq(400)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "with an error_info hash" do
|
|
29
|
+
let(:error) {
|
|
30
|
+
error_info = {
|
|
31
|
+
'type' => 'type',
|
|
32
|
+
'message' => 'message',
|
|
33
|
+
'code' => 1,
|
|
34
|
+
'error_subcode' => 'subcode',
|
|
35
|
+
'error_user_msg' => 'error user message',
|
|
36
|
+
'error_user_title' => 'error user title',
|
|
37
|
+
'fbtrace_id' => 'fb trace id',
|
|
38
|
+
'x-fb-trace-id' => 'x-fb trace id',
|
|
39
|
+
'x-fb-debug' => 'fb debug token',
|
|
40
|
+
'x-fb-rev' => 'fb revision',
|
|
41
|
+
'x-business-use-case-usage' => BUC_USAGE_JSON,
|
|
42
|
+
'x-ad-account-usage' => ADA_USAGE_JSON,
|
|
43
|
+
'x-app-usage' => APP_USAGE_JSON
|
|
44
|
+
}
|
|
45
|
+
Koala::Facebook::APIError.new(400, '', error_info)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
:fb_error_type => 'type',
|
|
50
|
+
:fb_error_message => 'message',
|
|
51
|
+
:fb_error_code => 1,
|
|
52
|
+
:fb_error_subcode => 'subcode',
|
|
53
|
+
:fb_error_user_msg => 'error user message',
|
|
54
|
+
:fb_error_user_title => 'error user title',
|
|
55
|
+
:fb_error_trace_id => 'fb trace id',
|
|
56
|
+
:fb_error_debug_trace_id => 'x-fb trace id',
|
|
57
|
+
:fb_error_debug => 'fb debug token',
|
|
58
|
+
:fb_error_rev => 'fb revision',
|
|
59
|
+
:fb_buc_usage => JSON.parse(BUC_USAGE_JSON),
|
|
60
|
+
:fb_ada_usage => JSON.parse(ADA_USAGE_JSON),
|
|
61
|
+
:fb_app_usage => JSON.parse(APP_USAGE_JSON)
|
|
62
|
+
}.each_pair do |accessor, value|
|
|
63
|
+
it "sets #{accessor} to #{value}" do
|
|
64
|
+
expect(error.send(accessor)).to eq(value)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "sets the error message appropriately" do
|
|
69
|
+
expect(error.message).to eq("type: type, code: 1, error_subcode: subcode, message: message, error_user_title: error user title, error_user_msg: error user message, fbtrace_id: fb trace id, x-fb-trace-id: x-fb trace id, x-fb-debug: fb debug token, x-fb-rev: fb revision [HTTP 400]")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "with an error_info string" do
|
|
74
|
+
it "sets the error message \"error_info [HTTP http_status]\"" do
|
|
75
|
+
error_info = "Facebook is down."
|
|
76
|
+
error = Koala::Facebook::APIError.new(400, '', error_info)
|
|
77
|
+
expect(error.message).to eq("Facebook is down. [HTTP 400]")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "with no error_info and a response_body containing error JSON" do
|
|
82
|
+
it "should extract the error info from the response body" do
|
|
83
|
+
response_body = '{ "error": { "type": "type", "message": "message", "code": 1, "error_subcode": "subcode", "error_user_msg": "error user message", "error_user_title": "error user title" } }'
|
|
84
|
+
error = Koala::Facebook::APIError.new(400, response_body)
|
|
85
|
+
{
|
|
86
|
+
:fb_error_type => 'type',
|
|
87
|
+
:fb_error_message => 'message',
|
|
88
|
+
:fb_error_code => 1,
|
|
89
|
+
:fb_error_subcode => 'subcode',
|
|
90
|
+
:fb_error_user_msg => 'error user message',
|
|
91
|
+
:fb_error_user_title => 'error user title',
|
|
92
|
+
:fb_buc_usage => nil,
|
|
93
|
+
:fb_ada_usage => nil,
|
|
94
|
+
:fb_app_usage => nil
|
|
95
|
+
}.each_pair do |accessor, value|
|
|
96
|
+
expect(error.send(accessor)).to eq(value)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe Koala::KoalaError do
|
|
104
|
+
it "is a StandardError" do
|
|
105
|
+
expect(Koala::KoalaError.new).to be_a(StandardError)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe Koala::Facebook::OAuthSignatureError do
|
|
110
|
+
it "is a Koala::KoalaError" do
|
|
111
|
+
expect(Koala::KoalaError.new).to be_a(Koala::KoalaError)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe Koala::Facebook::BadFacebookResponse do
|
|
116
|
+
it "is a Koala::Facebook::APIError" do
|
|
117
|
+
expect(Koala::Facebook::BadFacebookResponse.new(nil, nil)).to be_a(Koala::Facebook::APIError)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe Koala::Facebook::OAuthTokenRequestError do
|
|
122
|
+
it "is a Koala::Facebook::APIError" do
|
|
123
|
+
expect(Koala::Facebook::OAuthTokenRequestError.new(nil, nil)).to be_a(Koala::Facebook::APIError)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
describe Koala::Facebook::ServerError do
|
|
128
|
+
it "is a Koala::Facebook::APIError" do
|
|
129
|
+
expect(Koala::Facebook::ServerError.new(nil, nil)).to be_a(Koala::Facebook::APIError)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe Koala::Facebook::ClientError do
|
|
134
|
+
it "is a Koala::Facebook::APIError" do
|
|
135
|
+
expect(Koala::Facebook::ClientError.new(nil, nil)).to be_a(Koala::Facebook::APIError)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe Koala::Facebook::AuthenticationError do
|
|
140
|
+
it "is a Koala::Facebook::ClientError" do
|
|
141
|
+
expect(Koala::Facebook::AuthenticationError.new(nil, nil)).to be_a(Koala::Facebook::ClientError)
|
|
142
|
+
end
|
|
143
|
+
end
|