koala 3.0.0.beta1 → 3.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,11 +14,7 @@ module Koala
14
14
  # @option options :beta use the beta tier
15
15
  # @option options :use_ssl force https, even if not needed
16
16
  # @option options :json whether or not to send JSON to Facebook
17
- def initialize(path: nil, args: {}, verb: nil, options: {})
18
- # we still support Ruby 2.0 so we can't use required keyword arguments
19
- raise ArgumentError, "Missing required argument verb" unless verb
20
- raise ArgumentError, "Missing required argument path" unless path
21
-
17
+ def initialize(path:, verb:, args: {}, options: {})
22
18
  @raw_path = path
23
19
  @raw_args = args
24
20
  @raw_verb = verb
@@ -9,6 +9,12 @@ module Koala
9
9
  @body = body
10
10
  @headers = headers
11
11
  end
12
+
13
+ def data
14
+ # quirks_mode is needed because Facebook sometimes returns a raw true or false value --
15
+ # in Ruby 2.4 we can drop that.
16
+ @data ||= JSON.parse(body, quirks_mode: true) unless body.empty?
17
+ end
12
18
  end
13
19
  end
14
20
  end
@@ -146,11 +146,12 @@ module Koala
146
146
  raise ArgumentError, "TestUsers#befriend requires hash arguments for both users with id and access_token"
147
147
  end
148
148
 
149
- u1_graph_api = API.new(user1_token)
150
- u2_graph_api = API.new(user2_token)
149
+ u1_graph_api = API.new(user1_token, secret)
150
+ u2_graph_api = API.new(user2_token, secret)
151
151
 
152
- u1_graph_api.graph_call("#{user1_id}/friends/#{user2_id}", {}, "post", options) &&
153
- u2_graph_api.graph_call("#{user2_id}/friends/#{user1_id}", {}, "post", options)
152
+ # if we have a secret token, flag that we want the appsecret_proof to be generated
153
+ u1_graph_api.graph_call("#{user1_id}/friends/#{user2_id}", {}, "post", options.merge(appsecret_proof: !!secret)) &&
154
+ u2_graph_api.graph_call("#{user2_id}/friends/#{user1_id}", {}, "post", options.merge(appsecret_proof: !!secret))
154
155
  end
155
156
 
156
157
  # Create a network of test users, all of whom are friends and have the same permissions.
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "3.0.0.beta1"
2
+ VERSION = "3.0.0.beta2"
3
3
  end
@@ -1,9 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Koala::Facebook::API" do
4
- before(:each) do
4
+ before :each do
5
5
  @service = Koala::Facebook::API.new
6
6
  end
7
+ let(:dummy_response) { double("fake response", data: {}, status: 200, body: "", headers: {}) }
7
8
 
8
9
  it "doesn't include an access token if none was given" do
9
10
  expect(Koala).to receive(:make_request).with(
@@ -57,24 +58,6 @@ describe "Koala::Facebook::API" do
57
58
  expect(service.app_secret).to eq(secret)
58
59
  end
59
60
 
60
- it "gets the attribute of a Koala::HTTPService::Response given by the http_component parameter" do
61
- http_component = :method_name
62
-
63
- response = double('Mock KoalaResponse', :body => '', :status => 200)
64
- result = double("result")
65
- allow(response).to receive(http_component).and_return(result)
66
- allow(Koala).to receive(:make_request).and_return(response)
67
-
68
- expect(@service.api('anything', {}, 'get', :http_component => http_component)).to eq(result)
69
- end
70
-
71
- it "returns the entire response if http_component => :response" do
72
- http_component = :response
73
- response = double('Mock KoalaResponse', :body => '', :status => 200)
74
- allow(Koala).to receive(:make_request).and_return(response)
75
- expect(@service.api('anything', {}, 'get', :http_component => http_component)).to eq(response)
76
- end
77
-
78
61
  it "turns arrays of non-enumerables into comma-separated arguments by default" do
79
62
  args = [12345, {:foo => [1, 2, "3", :four]}]
80
63
  expected = ["/12345", {:foo => "1,2,3,four"}, "get", {}]
@@ -123,43 +106,12 @@ describe "Koala::Facebook::API" do
123
106
  @service.api(*args)
124
107
  end
125
108
 
126
- it "returns the body of the request as JSON if no http_component is given" do
127
- response = double('response', :body => 'body', :status => 200)
128
- allow(Koala).to receive(:make_request).and_return(response)
129
-
130
- json_body = double('JSON body')
131
- allow(JSON).to receive(:parse).and_return([json_body])
132
-
133
- expect(@service.api('anything')).to eq(json_body)
134
- end
135
-
136
- it "executes an error checking block if provided" do
137
- response = Koala::HTTPService::Response.new(200, '{}', {})
138
- allow(Koala).to receive(:make_request).and_return(response)
139
-
140
- yield_test = double('Yield Tester')
141
- expect(yield_test).to receive(:pass)
142
-
143
- @service.api('anything', {}, "get") do |arg|
144
- yield_test.pass
145
- expect(arg).to eq(response)
146
- end
147
- end
148
-
149
109
  it "raises an API error if the HTTP response code is greater than or equal to 500" do
150
110
  allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, 'response body', {}))
151
111
 
152
112
  expect { @service.api('anything') }.to raise_exception(Koala::Facebook::APIError)
153
113
  end
154
114
 
155
- it "handles rogue true/false as responses" do
156
- expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'true', {}))
157
- expect(@service.api('anything')).to be_truthy
158
-
159
- expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'false', {}))
160
- expect(@service.api('anything')).to be_falsey
161
- end
162
-
163
115
  describe "path manipulation" do
164
116
  context "leading /" do
165
117
  it "adds a leading / to the path if not present" do
@@ -179,6 +131,7 @@ describe "Koala::Facebook::API" do
179
131
  describe "with an access token" do
180
132
  before(:each) do
181
133
  @api = Koala::Facebook::API.new(@token)
134
+ @app_access_token = KoalaTest.app_access_token
182
135
  end
183
136
 
184
137
  it_should_behave_like "Koala GraphAPI"
@@ -191,9 +144,10 @@ describe "Koala::Facebook::API" do
191
144
  @api = Koala::Facebook::API.new
192
145
  end
193
146
 
147
+ # In theory this should behave the same with a GraphCollection, but those tests currently hit
148
+ # an endpoint that now requires a token.
194
149
  it_should_behave_like "Koala GraphAPI"
195
150
  it_should_behave_like "Koala GraphAPI without an access token"
196
- it_should_behave_like "Koala GraphAPI with GraphCollection"
197
151
  end
198
152
 
199
153
  context '#api' do
@@ -246,4 +200,78 @@ describe "Koala::Facebook::API" do
246
200
  end
247
201
  end
248
202
  end
203
+
204
+ describe "#graph_call" do
205
+ it "passes all arguments to the api method" do
206
+ user = KoalaTest.user1
207
+ args = {}
208
+ verb = 'get'
209
+ opts = {:a => :b}
210
+ expect(@service).to receive(:api).with(user, args, verb, opts).and_return(dummy_response)
211
+ @service.graph_call(user, args, verb, opts)
212
+ end
213
+
214
+ it "throws an APIError if the result hash has an error key" do
215
+ allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(500, '{"error": "An error occurred!"}', {}))
216
+ expect { @service.graph_call(KoalaTest.user1, {}) }.to raise_exception(Koala::Facebook::APIError)
217
+ end
218
+
219
+ it "passes the results through GraphCollection.evaluate" do
220
+ allow(@service).to receive(:api).and_return(dummy_response)
221
+ expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).with(dummy_response.data, @service)
222
+ @service.graph_call("/me")
223
+ end
224
+
225
+ it "returns the results of GraphCollection.evaluate" do
226
+ expected = {}
227
+ allow(@service).to receive(:api).and_return(dummy_response)
228
+ expect(Koala::Facebook::API::GraphCollection).to receive(:evaluate).and_return(expected)
229
+ expect(@service.graph_call("/me")).to eq(expected)
230
+ end
231
+
232
+ it "returns the post_processing block's results if one is supplied" do
233
+ other_result = [:a, 2, :three]
234
+ block = Proc.new {|r| other_result}
235
+ allow(@service).to receive(:api).and_return(dummy_response)
236
+ expect(@service.graph_call("/me", {}, "get", {}, &block)).to eq(other_result)
237
+ end
238
+
239
+ it "gets the status of a Koala::HTTPService::Response if requested" do
240
+ response = Koala::HTTPService::Response.new(200, '', {})
241
+ allow(Koala).to receive(:make_request).and_return(response)
242
+
243
+ expect(@service.graph_call('anything', {}, 'get', http_component: :status)).to eq(200)
244
+ end
245
+
246
+ it "gets the headers of a Koala::HTTPService::Response if requested" do
247
+ headers = {"a" => 2}
248
+ response = Koala::HTTPService::Response.new(200, '', headers)
249
+ allow(Koala).to receive(:make_request).and_return(response)
250
+
251
+ expect(@service.graph_call('anything', {}, 'get', :http_component => :headers)).to eq(headers)
252
+ end
253
+
254
+ it "returns the entire response if http_component => :response" do
255
+ http_component = :response
256
+ response = Koala::HTTPService::Response.new(200, '', {})
257
+ allow(Koala).to receive(:make_request).and_return(response)
258
+ expect(@service.graph_call('anything', {}, 'get', :http_component => http_component)).to eq(response)
259
+ end
260
+
261
+ it "returns the body of the request as JSON if no http_component is given" do
262
+ result = {"a" => 2}
263
+ response = Koala::HTTPService::Response.new(200, result.to_json, {})
264
+ allow(Koala).to receive(:make_request).and_return(response)
265
+
266
+ expect(@service.graph_call('anything')).to eq(result)
267
+ end
268
+
269
+ it "handles rogue true/false as responses" do
270
+ expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'true', {}))
271
+ expect(@service.graph_call('anything')).to be_truthy
272
+
273
+ expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, 'false', {}))
274
+ expect(@service.graph_call('anything')).to be_falsey
275
+ end
276
+ end
249
277
  end
@@ -473,12 +473,12 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
473
473
 
474
474
  describe "usage tests" do
475
475
  it "gets two results at once" do
476
- me, koppel = @api.batch do |batch_api|
476
+ me, barackobama = @api.batch do |batch_api|
477
477
  batch_api.get_object('me')
478
478
  batch_api.get_object(KoalaTest.user1)
479
479
  end
480
480
  expect(me['id']).not_to be_nil
481
- expect(koppel['id']).not_to be_nil
481
+ expect(barackobama['id']).not_to be_nil
482
482
  end
483
483
 
484
484
  it 'makes mixed calls inside of a batch' do
@@ -502,7 +502,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
502
502
  pictures = @api.batch do |batch_api|
503
503
  batch_api.get_picture('me')
504
504
  end
505
- expect(pictures.first).to match(/http\:\/\//) # works both live & stubbed
505
+ expect(pictures.first).to match(/https\:\/\//) # works both live & stubbed
506
506
  end
507
507
 
508
508
  it 'takes an after processing block for a get_picture call inside of a batch' do
@@ -510,40 +510,40 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
510
510
  @api.batch do |batch_api|
511
511
  batch_api.get_picture('me') { |pic| picture = pic }
512
512
  end
513
- expect(picture).to match(/http\:\/\//) # works both live & stubbed
513
+ expect(picture).to match(/https\:\/\//) # works both live & stubbed
514
514
  end
515
515
 
516
516
  it "handles requests for two different tokens" do
517
- me, insights = @api.batch do |batch_api|
517
+ me, app_event_types = @api.batch do |batch_api|
518
518
  batch_api.get_object('me')
519
- batch_api.get_connections(@app_id, 'insights', {}, {"access_token" => @app_api.access_token})
519
+ batch_api.get_connections(@app_id, 'app_event_types', {}, {"access_token" => @app_api.access_token})
520
520
  end
521
521
  expect(me['id']).not_to be_nil
522
- expect(insights).to be_an(Koala::Facebook::API::GraphCollection)
522
+ expect(app_event_types).to be_an(Koala::Facebook::API::GraphCollection)
523
523
  end
524
524
 
525
525
  it "handles requests passing the access token option as a symbol instead of a string" do
526
- me, insights = @api.batch do |batch_api|
526
+ me, app_event_types = @api.batch do |batch_api|
527
527
  batch_api.get_object('me')
528
- batch_api.get_connections(@app_id, 'insights', {}, {:access_token => @app_api.access_token})
528
+ batch_api.get_connections(@app_id, 'app_event_types', {}, {:access_token => @app_api.access_token})
529
529
  end
530
530
  expect(me['id']).not_to be_nil
531
- expect(insights).to be_an(Koala::Facebook::API::GraphCollection)
531
+ expect(app_event_types).to be_an(Koala::Facebook::API::GraphCollection)
532
532
  end
533
533
 
534
534
  it "preserves batch-op specific access tokens in GraphCollection returned from batch" do
535
535
  # Provide an alternate token for a batch operation
536
536
  @other_access_token_args = { 'access_token' => @app_api.access_token }
537
537
 
538
- # make a batch call for insights using another token
539
- me, insights = @api.batch do |batch_api|
538
+ # make a batch call for app_event_types using another token
539
+ me, app_event_types = @api.batch do |batch_api|
540
540
  batch_api.get_object('me')
541
- batch_api.get_connections(@app_id, 'insights', {}, @other_access_token_args)
541
+ batch_api.get_connections(@app_id, 'app_event_types', {}, @other_access_token_args)
542
542
  end
543
543
 
544
544
  # The alternate token is returned with the next page parameters
545
545
  # The GraphCollection should receive a request for the next_page_params during paging
546
- expect(insights).to receive(:next_page_params).and_return([double("base"), @other_access_token_args.dup])
546
+ expect(app_event_types).to receive(:next_page_params).and_return([double("base"), @other_access_token_args.dup])
547
547
 
548
548
  # The alternate access token should pass through to making the request
549
549
  # Koala should receive a request during paging using the alternate token
@@ -555,23 +555,23 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
555
555
  ).and_return(Koala::HTTPService::Response.new(200, "", ""))
556
556
 
557
557
  # Page the collection
558
- insights.next_page
558
+ app_event_types.next_page
559
559
  end
560
560
 
561
561
  it "inserts errors in the appropriate place, without breaking other results" do
562
- failed_call, koppel = @api.batch do |batch_api|
562
+ failed_call, barackobama = @api.batch do |batch_api|
563
563
  batch_api.get_connection("2", "invalidconnection")
564
564
  batch_api.get_object(KoalaTest.user1, {}, {"access_token" => @app_api.access_token})
565
565
  end
566
566
  expect(failed_call).to be_a(Koala::Facebook::ClientError)
567
- expect(koppel["id"]).not_to be_nil
567
+ expect(barackobama["id"]).not_to be_nil
568
568
  end
569
569
 
570
570
  it "handles different request methods" do
571
571
  result = @api.put_wall_post("Hello, world, from the test suite batch API!")
572
572
  wall_post = result["id"]
573
573
 
574
- wall_post, koppel = @api.batch do |batch_api|
574
+ wall_post, barackobama = @api.batch do |batch_api|
575
575
  batch_api.put_like(wall_post)
576
576
  batch_api.delete_object(wall_post)
577
577
  end
@@ -658,23 +658,23 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
658
658
  end
659
659
 
660
660
  it "allows you to create dependencies" do
661
- me, koppel = @api.batch do |batch_api|
661
+ me, barackobama = @api.batch do |batch_api|
662
662
  batch_api.get_object("me", {}, :batch_args => {:name => "getme"})
663
663
  batch_api.get_object(KoalaTest.user1, {}, :batch_args => {:depends_on => "getme"})
664
664
  end
665
665
 
666
666
  expect(me).to be_nil # gotcha! it's omitted because it's a successfully-executed dependency
667
- expect(koppel["id"]).not_to be_nil
667
+ expect(barackobama["id"]).not_to be_nil
668
668
  end
669
669
 
670
670
  it "properly handles dependencies that fail" do
671
- failed_call, koppel = @api.batch do |batch_api|
671
+ failed_call, barackobama = @api.batch do |batch_api|
672
672
  batch_api.get_connections("2", "invalidconnection", {}, :batch_args => {:name => "getdata"})
673
673
  batch_api.get_object(KoalaTest.user1, {}, :batch_args => {:depends_on => "getdata"})
674
674
  end
675
675
 
676
676
  expect(failed_call).to be_a(Koala::Facebook::ClientError)
677
- expect(koppel).to be_nil
677
+ expect(barackobama).to be_nil
678
678
  end
679
679
 
680
680
  it "throws an error for badly-constructed request relationships" do
@@ -9,6 +9,8 @@ describe 'Koala::Facebook::GraphAPIMethods' do
9
9
  @app_api = Koala::Facebook::API.new(@app_access_token)
10
10
  end
11
11
 
12
+ let(:dummy_response) { double("fake response", data: {}, status: 200, body: "", headers: {}) }
13
+
12
14
  describe 'post-processing for' do
13
15
  let(:result) { double("result") }
14
16
  let(:post_processing) { lambda {|arg| {"result" => result, "args" => arg} } }
@@ -17,28 +19,31 @@ describe 'Koala::Facebook::GraphAPIMethods' do
17
19
  # and the other methods which do some post-processing locally
18
20
  context '#get_object' do
19
21
  it 'returns result of block' do
20
- allow(@api).to receive(:api).and_return(double("other results"))
21
- expect(@api.get_object('koppel', &post_processing)["result"]).to eq(result)
22
+ allow(@api).to receive(:api).and_return(dummy_response)
23
+ expect(@api.get_object('barackobama', &post_processing)["result"]).to eq(result)
22
24
  end
23
25
 
24
26
  it "doesn't add token to received arguments" do
25
27
  args = {}.freeze
26
- expect(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(200, "", ""))
27
- expect(@api.get_object('koppel', args, &post_processing)["result"]).to eq(result)
28
+ expect(Koala).to receive(:make_request).and_return(dummy_response)
29
+ expect(@api.get_object('barackobama', args, &post_processing)["result"]).to eq(result)
28
30
  end
29
31
  end
30
32
 
31
33
  context '#get_picture' do
32
34
  it 'returns result of block' do
33
- allow(@api).to receive(:api).and_return({"data" => {"is_silhouette" => false, "url" => result}})
34
- expect(@api.get_picture('lukeshepard', &post_processing)["result"]).to eq(result)
35
+ result_url = "a url"
36
+ allow(@api).to receive(:api).and_return(Koala::HTTPService::Response.new(200, {"data" => {"is_silhouette" => false, "url" => result_url}}.to_json, {}))
37
+ expect(@api.get_picture('koppel', &post_processing)["result"]).to eq(result)
35
38
  end
36
39
  end
37
40
 
38
41
  context '#get_page_access_token' do
39
42
  it 'returns result of block' do
40
43
  token = Koala::MockHTTPService::APP_ACCESS_TOKEN
41
- allow(@api).to receive(:api).and_return("access_token" => token)
44
+ allow(@api).to receive(:api).and_return(
45
+ Koala::HTTPService::Response.new(200, {"access_token" => token}.to_json, {})
46
+ )
42
47
  response = @api.get_page_access_token('facebook', &post_processing)
43
48
  expect(response["args"]).to eq(token)
44
49
  expect(response["result"]).to eq(result)
@@ -52,18 +57,18 @@ describe 'Koala::Facebook::GraphAPIMethods' do
52
57
 
53
58
  it "is enabled by default if an app secret is present" do
54
59
  api = Koala::Facebook::API.new(@token, "mysecret")
55
- expect(api).to receive(:api).with(path, {}, 'get', :appsecret_proof => true)
60
+ expect(api).to receive(:api).with(path, {}, 'get', :appsecret_proof => true).and_return(dummy_response)
56
61
  api.graph_call(path)
57
62
  end
58
63
 
59
64
  it "can be disabled manually" do
60
65
  api = Koala::Facebook::API.new(@token, "mysecret")
61
- expect(api).to receive(:api).with(path, {}, 'get', hash_not_including(appsecret_proof: true))
66
+ expect(api).to receive(:api).with(path, {}, 'get', hash_not_including(appsecret_proof: true)).and_return(dummy_response)
62
67
  api.graph_call(path, {}, "get", appsecret_proof: false)
63
68
  end
64
69
 
65
70
  it "isn't included if no app secret is present" do
66
- expect(@api).to receive(:api).with(path, {}, 'get', {})
71
+ expect(@api).to receive(:api).with(path, {}, 'get', {}).and_return(dummy_response)
67
72
  @api.graph_call(path)
68
73
  end
69
74
  end
@@ -49,7 +49,7 @@ describe Koala::Facebook::API::GraphCollection do
49
49
  describe "when getting a whole page" do
50
50
  before(:each) do
51
51
  @second_page = {
52
- "data" => [:second, :page, :data],
52
+ "data" => ["second", "page", "data"],
53
53
  "paging" => {}
54
54
  }
55
55
  @base = double("base")
@@ -59,14 +59,14 @@ describe Koala::Facebook::API::GraphCollection do
59
59
 
60
60
  it "should return the previous page of results" do
61
61
  expect(@collection).to receive(:previous_page_params).and_return([@base, @args])
62
- expect(@api).to receive(:api).with(@base, @args, anything, anything).and_return(@second_page)
62
+ expect(@api).to receive(:api).with(@base, @args, anything, anything).and_return(Koala::HTTPService::Response.new(200, @second_page.to_json, {}))
63
63
  expect(Koala::Facebook::API::GraphCollection).to receive(:new).with(@second_page, @api).and_return(@page_of_results)
64
64
  expect(@collection.previous_page).to eq(@page_of_results)
65
65
  end
66
66
 
67
67
  it "should return the next page of results" do
68
68
  expect(@collection).to receive(:next_page_params).and_return([@base, @args])
69
- expect(@api).to receive(:api).with(@base, @args, anything, anything).and_return(@second_page)
69
+ expect(@api).to receive(:api).with(@base, @args, anything, anything).and_return(Koala::HTTPService::Response.new(200, @second_page.to_json, {}))
70
70
  expect(Koala::Facebook::API::GraphCollection).to receive(:new).with(@second_page, @api).and_return(@page_of_results)
71
71
 
72
72
  expect(@collection.next_page).to eq(@page_of_results)