koala 1.10.1 → 1.11.0rc

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b83335264188054c217fd836a1f6508b2fcf420
4
- data.tar.gz: 43116e3f574b6c689bed8a6a47a0ff25b69f6f3f
3
+ metadata.gz: 44c50b37f43f7bc407a12420de96e89f181d7b6f
4
+ data.tar.gz: 21203b9c7703b5bbacd43711ce990d3684a9d34c
5
5
  SHA512:
6
- metadata.gz: 5982606d43ac0435e33de8b1a74e6ed32077cc515f0a52162f2ae5fe043242051e23c49a3502fcfac97ba539b7d6bcf777b383ea3bbc70db0c846d8532c04a7f
7
- data.tar.gz: abf6a0fbf049448a8d5195e353512307c0dc1d03c319fa3d61448457463ef3e994e14b9dff4b9712b846be47984c88b28225d8aec4a8e4227658807ffafd00a5
6
+ metadata.gz: 29b23719eaaedf448162e7d477525d5a999d975ad6d2847bf5a4170d08bb42efcfee924d99c9ea747aa0310b046ba38ea4804a69aa858e9b52be9097bc706d41
7
+ data.tar.gz: 89dd9133b9976792fda084c954046f0828c30e48c727a3c9f37c15a5f0905e24d6161f884c025a5ae5040b7d4cd5a0f7c3918f4ef6a70352656dae8a0749cb0b
data/.travis.yml CHANGED
@@ -3,8 +3,9 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.0
6
+ - 2.1.2
6
7
  # rbx
7
- - rbx-2
8
+ - rbx-2.4.1
8
9
  # jruby
9
10
  - jruby-19mode
10
11
  bundler_args: --without development
data/Gemfile CHANGED
@@ -13,6 +13,8 @@ end
13
13
 
14
14
  group :test do
15
15
  gem "rspec", '~> 3.0.0.beta1'
16
+ gem "vcr"
17
+ gem "webmock"
16
18
  end
17
19
 
18
20
  gem "jruby-openssl" if defined? JRUBY_VERSION
data/changelog.md CHANGED
@@ -1,3 +1,19 @@
1
+ v.1.11.0
2
+ ========
3
+
4
+ Updated features:
5
+ * OAuth now supports decoding the new JSON responses from the access token endpoints (thanks, ridiculous!)
6
+ * Batch API now accepts either symbols or strings for the access token (thanks, mattmueller!)
7
+ * Incorporate user message and title into error handling (thanks, richrines and isra17!)
8
+
9
+ Bug fixes:
10
+ * Fixed bug in GraphCollection URL versioning (thanks, deviousdodo and jankowy!)
11
+ * TestUsers#create_network now properly handles options (thanks, crx!)
12
+
13
+ Documentation improvements:
14
+ * Updated gem version (thanks, thomasklemm!)
15
+
16
+
1
17
  v.1.10.1
2
18
  ========
3
19
 
@@ -19,12 +19,15 @@ module Koala
19
19
  end
20
20
 
21
21
  def graph_call_in_batch(path, args = {}, verb = "get", options = {}, &post_processing)
22
- # for batch APIs, we queue up the call details (incl. post-processing)
22
+ # normalize options for consistency
23
+ options = Koala::Utils.symbolize_hash(options)
24
+
25
+ # for batch APIs, we queue up the call details (incl. post-processing)
23
26
  batch_calls << BatchOperation.new(
24
27
  :url => path,
25
28
  :args => args,
26
29
  :method => verb,
27
- :access_token => options['access_token'] || access_token,
30
+ :access_token => options[:access_token] || access_token,
28
31
  :http_options => options,
29
32
  :post_processing => post_processing
30
33
  )
data/lib/koala/errors.rb CHANGED
@@ -14,14 +14,14 @@ module Koala
14
14
  # http_status, then the error was detected before making a call to Facebook. (e.g. missing access token)
15
15
  class APIError < ::Koala::KoalaError
16
16
  attr_accessor :fb_error_type, :fb_error_code, :fb_error_subcode, :fb_error_message,
17
- :http_status, :response_body
17
+ :fb_error_user_message, :fb_error_user_title, :http_status, :response_body
18
18
 
19
19
  # Create a new API Error
20
20
  #
21
21
  # @param http_status [Integer] The HTTP status code of the response
22
22
  # @param response_body [String] The response body
23
23
  # @param error_info One of the following:
24
- # [Hash] The error information extracted from the request
24
+ # [Hash] The error information extracted from the request
25
25
  # ("type", "code", "error_subcode", "message")
26
26
  # [String] The error description
27
27
  # If error_info is nil or not provided, the method will attempt to extract
@@ -51,9 +51,11 @@ module Koala
51
51
  self.fb_error_code = error_info["code"]
52
52
  self.fb_error_subcode = error_info["error_subcode"]
53
53
  self.fb_error_message = error_info["message"]
54
+ self.fb_error_user_message = error_info["error_user_message"]
55
+ self.fb_error_user_title = error_info["error_user_title"]
54
56
 
55
57
  error_array = []
56
- %w(type code error_subcode message).each do |key|
58
+ %w(type code error_subcode message error_user_title error_user_message).each do |key|
57
59
  error_array << "#{key}: #{error_info[key]}" if error_info[key]
58
60
  end
59
61
 
@@ -78,7 +80,7 @@ module Koala
78
80
  # Any error with a 5xx HTTP status code
79
81
  class ServerError < APIError; end
80
82
 
81
- # Any error with a 4xx HTTP status code
83
+ # Any error with a 4xx HTTP status code
82
84
  class ClientError < APIError; end
83
85
 
84
86
  # All graph API authentication failures.
@@ -88,8 +88,10 @@ module Koala
88
88
  ssl[:verify] = true unless ssl.has_key?(:verify)
89
89
  end
90
90
 
91
- # if an api_version is specified, prepend it to the path
92
- if api_version = request_options[:api_version] || Koala.config.api_version
91
+ # if an api_version is specified and the path does not already contain
92
+ # one, prepend it to the path
93
+ api_version = request_options[:api_version] || Koala.config.api_version
94
+ if api_version && !path_contains_api_version?(path)
93
95
  begins_with_slash = path[0] == "/"
94
96
  divider = begins_with_slash ? "" : "/"
95
97
  path = "/#{api_version}#{divider}#{path}"
@@ -123,6 +125,16 @@ module Koala
123
125
  end).join("&")
124
126
  end
125
127
 
128
+ # Determines whether a given path already contains an API version.
129
+ #
130
+ # @param path the URL path.
131
+ #
132
+ # @return true or false accordingly.
133
+ def self.path_contains_api_version?(path)
134
+ match = /^\/?(v\d+(?:\.\d+)?)\//.match(path)
135
+ !!(match && match[1])
136
+ end
137
+
126
138
  # deprecations
127
139
  # not elegant or compact code, but temporary
128
140
 
data/lib/koala/oauth.rb CHANGED
@@ -316,11 +316,12 @@ module Koala
316
316
  end
317
317
 
318
318
  def parse_access_token(response_text)
319
- components = response_text.split("&").inject({}) do |hash, bit|
319
+ MultiJson.load(response_text)
320
+ rescue MultiJson::ParseError
321
+ response_text.split("&").inject({}) do |hash, bit|
320
322
  key, value = bit.split("=")
321
323
  hash.merge!(key => value)
322
324
  end
323
- components
324
325
  end
325
326
 
326
327
  def parse_unsigned_cookie(fb_cookie)
@@ -166,7 +166,7 @@ module Koala
166
166
  #
167
167
  # @return the list of users created
168
168
  def create_network(network_size, installed = true, permissions = '', options = {})
169
- users = (0...network_size).collect { create(installed, permissions, options) }
169
+ users = (0...network_size).collect { create(installed, permissions, {}, options) }
170
170
  friends = users.clone
171
171
  users.each do |user|
172
172
  # Remove this user from list of friends
data/lib/koala/utils.rb CHANGED
@@ -29,5 +29,13 @@ module Koala
29
29
  @posted_deprecations << message
30
30
  end
31
31
  end
32
+
33
+ # Ensures that a hash uses symbols as opposed to strings
34
+ # Useful for allowing either syntax for end users
35
+ def symbolize_hash(hash)
36
+ return hash unless hash.is_a?(Hash)
37
+
38
+ hash.inject({}){ |memo,(key,value)| memo[key.to_sym] = symbolize_hash(value); memo }
39
+ end
32
40
  end
33
41
  end
data/lib/koala/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Koala
2
- VERSION = "1.10.1"
2
+ VERSION = "1.11.0rc"
3
3
  end
data/readme.md CHANGED
@@ -15,7 +15,7 @@ Installation
15
15
 
16
16
  In Bundler:
17
17
  ```ruby
18
- gem "koala", "~> 1.10.0rc"
18
+ gem "koala", "~> 1.10.1"
19
19
  ```
20
20
 
21
21
  Otherwise:
@@ -5,7 +5,7 @@ describe Koala::Facebook::APIError do
5
5
  expect(Koala::Facebook::APIError.new(nil, nil)).to be_a(Koala::KoalaError)
6
6
  end
7
7
 
8
- [:fb_error_type, :fb_error_code, :fb_error_subcode, :fb_error_message, :http_status, :response_body].each do |accessor|
8
+ [:fb_error_type, :fb_error_code, :fb_error_subcode, :fb_error_message, :fb_error_user_message, :fb_error_user_title, :http_status, :response_body].each do |accessor|
9
9
  it "has an accessor for #{accessor}" do
10
10
  expect(Koala::Facebook::APIError.instance_methods.map(&:to_sym)).to include(accessor)
11
11
  expect(Koala::Facebook::APIError.instance_methods.map(&:to_sym)).to include(:"#{accessor}=")
@@ -22,12 +22,14 @@ describe Koala::Facebook::APIError do
22
22
  end
23
23
 
24
24
  context "with an error_info hash" do
25
- let(:error) {
25
+ let(:error) {
26
26
  error_info = {
27
27
  'type' => 'type',
28
28
  'message' => 'message',
29
29
  'code' => 1,
30
- 'error_subcode' => 'subcode'
30
+ 'error_subcode' => 'subcode',
31
+ 'error_user_message' => 'error user message',
32
+ 'error_user_title' => 'error user title'
31
33
  }
32
34
  Koala::Facebook::APIError.new(400, '', error_info)
33
35
  }
@@ -36,15 +38,17 @@ describe Koala::Facebook::APIError do
36
38
  :fb_error_type => 'type',
37
39
  :fb_error_message => 'message',
38
40
  :fb_error_code => 1,
39
- :fb_error_subcode => 'subcode'
41
+ :fb_error_subcode => 'subcode',
42
+ :fb_error_user_message => 'error user message',
43
+ :fb_error_user_title => 'error user title'
40
44
  }.each_pair do |accessor, value|
41
45
  it "sets #{accessor} to #{value}" do
42
46
  expect(error.send(accessor)).to eq(value)
43
47
  end
44
48
  end
45
49
 
46
- it "sets the error message \"type: error_info['type'], code: error_info['code'], error_subcode: error_info['error_subcode'], message: error_info['message'] [HTTP http_status]\"" do
47
- expect(error.message).to eq("type: type, code: 1, error_subcode: subcode, message: message [HTTP 400]")
50
+ it "sets the error message appropriately" do
51
+ expect(error.message).to eq("type: type, code: 1, error_subcode: subcode, message: message, error_user_title: error user title, error_user_message: error user message [HTTP 400]")
48
52
  end
49
53
  end
50
54
 
@@ -58,13 +62,15 @@ describe Koala::Facebook::APIError do
58
62
 
59
63
  context "with no error_info and a response_body containing error JSON" do
60
64
  it "should extract the error info from the response body" do
61
- response_body = '{ "error": { "type": "type", "message": "message", "code": 1, "error_subcode": "subcode" } }'
65
+ response_body = '{ "error": { "type": "type", "message": "message", "code": 1, "error_subcode": "subcode", "error_user_message": "error user message", "error_user_title": "error user title" } }'
62
66
  error = Koala::Facebook::APIError.new(400, response_body)
63
67
  {
64
68
  :fb_error_type => 'type',
65
69
  :fb_error_message => 'message',
66
70
  :fb_error_code => 1,
67
- :fb_error_subcode => 'subcode'
71
+ :fb_error_subcode => 'subcode',
72
+ :fb_error_user_message => 'error user message',
73
+ :fb_error_user_title => 'error user title'
68
74
  }.each_pair do |accessor, value|
69
75
  expect(error.send(accessor)).to eq(value)
70
76
  end
@@ -519,6 +519,15 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
519
519
  expect(insights).to be_an(Koala::Facebook::GraphCollection)
520
520
  end
521
521
 
522
+ it "handles requests passing the access token option as a symbol instead of a string" do
523
+ me, insights = @api.batch do |batch_api|
524
+ batch_api.get_object('me')
525
+ batch_api.get_connections(@app_id, 'insights', {}, {:access_token => @app_api.access_token})
526
+ end
527
+ expect(me['id']).not_to be_nil
528
+ expect(insights).to be_an(Koala::Facebook::GraphCollection)
529
+ end
530
+
522
531
  it "preserves batch-op specific access tokens in GraphCollection returned from batch" do
523
532
  # Provide an alternate token for a batch operation
524
533
  @other_access_token_args = { 'access_token' => @app_api.access_token }
@@ -145,15 +145,15 @@ describe Koala::Facebook::GraphCollection do
145
145
  end
146
146
 
147
147
  describe "#next_page" do
148
- let(:paging){ {"next" => "http://example.com/?a=2&b=3"} }
148
+ let(:paging){ {"next" => "http://example.com/abc?a=2&b=3"} }
149
149
 
150
150
  it "should get next page" do
151
- expect(@api).to receive(:get_page).with(["", {"a" => "2", "b" => "3"}])
151
+ expect(@api).to receive(:get_page).with(["abc", {"a" => "2", "b" => "3"}])
152
152
  @collection.next_page
153
153
  end
154
154
 
155
155
  it "should get next page with extra parameters" do
156
- expect(@api).to receive(:get_page).with(["", {"a" => "2", "b" => "3", "c" => "4"}])
156
+ expect(@api).to receive(:get_page).with(["abc", {"a" => "2", "b" => "3", "c" => "4"}])
157
157
  @collection.next_page("c" => "4")
158
158
  end
159
159
  end
@@ -171,4 +171,4 @@ describe Koala::Facebook::GraphCollection do
171
171
  @collection.previous_page("c" => "4")
172
172
  end
173
173
  end
174
- end
174
+ end
@@ -296,6 +296,12 @@ describe Koala::HTTPService do
296
296
  expect(@mock_connection).to receive(:get).with("/v12/anything", anything)
297
297
  Koala::HTTPService.make_request("/anything", {}, "get")
298
298
  end
299
+
300
+ it "doesn't add a version if the path already contains one" do
301
+ expect(Koala.config).to receive(:api_version).and_return("v11")
302
+ expect(@mock_connection).to receive(:get).with("/v12/anything", anything)
303
+ Koala::HTTPService.make_request("/v12/anything", {}, "get")
304
+ end
299
305
  end
300
306
 
301
307
  it "makes a POST request if the verb isn't get" do
@@ -378,6 +384,24 @@ describe Koala::HTTPService do
378
384
  end
379
385
  end
380
386
 
387
+ describe ".path_contains_api_version?" do
388
+ it "works when the path is prefixed by a slash" do
389
+ expect(Koala::HTTPService.path_contains_api_version?('/v2.1/anything')).to be true
390
+ end
391
+
392
+ it "works when the path is not prefixed by a slash" do
393
+ expect(Koala::HTTPService.path_contains_api_version?('v2.1/anything')).to be true
394
+ end
395
+
396
+ it "works with versions without a ." do
397
+ expect(Koala::HTTPService.path_contains_api_version?('v21/anything')).to be true
398
+ end
399
+
400
+ it "returns nil for paths without a version" do
401
+ expect(Koala::HTTPService.path_contains_api_version?('/anything')).to be false
402
+ end
403
+ end
404
+
381
405
  describe "deprecated options" do
382
406
  before :each do
383
407
  allow(Koala::HTTPService).to receive(:http_options).and_return({})
@@ -449,6 +449,34 @@ describe "Koala::Facebook::OAuth" do
449
449
  @oauth.get_access_token_info(@code)
450
450
  end
451
451
 
452
+ it "properly decodes JSON results" do
453
+ result = {
454
+ "access_token" => "foo",
455
+ "expires_in" => "baz",
456
+ "machine_id" => "bar"
457
+ }
458
+ allow(Koala).to receive(:make_request).and_return(
459
+ Koala::HTTPService::Response.new(
460
+ 200,
461
+ MultiJson.dump(result),
462
+ {}
463
+ )
464
+ )
465
+ expect(@oauth.get_access_token_info(@code)).to eq(result)
466
+ end
467
+
468
+ it "falls back to URL-style parsing " do
469
+ result = "access_token=foo&expires_in=baz&machine_id=bar"
470
+ allow(Koala).to receive(:make_request).and_return(
471
+ Koala::HTTPService::Response.new(200, result, {})
472
+ )
473
+ expect(@oauth.get_access_token_info(@code)).to eq({
474
+ "access_token" => "foo",
475
+ "expires_in" => "baz",
476
+ "machine_id" => "bar"
477
+ })
478
+ end
479
+
452
480
  if KoalaTest.code
453
481
  it "properly gets and parses an access token token results into a hash" do
454
482
  result = @oauth.get_access_token_info(@code)
@@ -328,7 +328,7 @@ describe "Koala::Facebook::TestUsers" do
328
328
  perms = ["read_stream", "offline_access"]
329
329
  installed = false
330
330
  count = 25
331
- expect(@test_users).to receive(:create).exactly(count).times.with(installed, perms, anything)
331
+ expect(@test_users).to receive(:create).exactly(count).times.with(installed, perms, anything, anything)
332
332
  allow(@test_users).to receive(:befriend)
333
333
  @test_users.create_network(count, installed, perms)
334
334
  end
@@ -336,7 +336,7 @@ describe "Koala::Facebook::TestUsers" do
336
336
  it "accepts http options that are passed to both the create and befriend calls" do
337
337
  count = 25
338
338
  options = {:some_http_option => true}
339
- expect(@test_users).to receive(:create).exactly(count).times.with(anything, anything, options).and_return({})
339
+ expect(@test_users).to receive(:create).exactly(count).times.with(anything, anything, anything, options).and_return({})
340
340
  # there are more befriends than creates, but we don't need to do the extra work to calculate out the exact #
341
341
  expect(@test_users).to receive(:befriend).at_least(count).times.with(anything, anything, options)
342
342
  @test_users.create_network(count, true, "", options)
@@ -59,4 +59,7 @@ subscription_test_data:
59
59
  challenge_data:
60
60
  "hub.challenge": "1290024882"
61
61
  "hub.verify_token": "myverificationtoken|1f54545d5f722733e17faae15377928f"
62
- "hub.mode": "subscribe"
62
+ "hub.mode": "subscribe"
63
+
64
+ vcr_data:
65
+ oauth_token: CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD
@@ -0,0 +1,121 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://graph.facebook.com/v2.2/me/friends?access_token=CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.0
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Facebook-Api-Version:
22
+ - v2.2
23
+ Etag:
24
+ - "\"405645cb180f38f9c1e373a1fe301c47c2a763db\""
25
+ Content-Type:
26
+ - application/json; charset=UTF-8
27
+ Pragma:
28
+ - no-cache
29
+ Access-Control-Allow-Origin:
30
+ - "*"
31
+ X-Fb-Rev:
32
+ - '1543964'
33
+ Cache-Control:
34
+ - private, no-cache, no-store, must-revalidate
35
+ Expires:
36
+ - Sat, 01 Jan 2000 00:00:00 GMT
37
+ X-Fb-Debug:
38
+ - sR8XVZI7FA7B7iZBo18REPDIaoeLkIbkg06WTYKMmJ/wzV/Gr5wYOYE47wIIgvnLBMgTe2D3RKvGo668AMWYXw==
39
+ Date:
40
+ - Fri, 26 Dec 2014 14:54:14 GMT
41
+ Connection:
42
+ - keep-alive
43
+ Content-Length:
44
+ - '834'
45
+ body:
46
+ encoding: UTF-8
47
+ string: "{\"data\":[{\"name\":\"Brian Rosenthal\",\"id\":\"6580\"},{\"name\":\"Waynn
48
+ Lue\",\"id\":\"202035\"},{\"name\":\"Chris Baclig\",\"id\":\"216743\"},{\"name\":\"Scott
49
+ Kleper\",\"id\":\"219493\"},{\"name\":\"Nick Elser\",\"id\":\"429772\"},{\"name\":\"Ian
50
+ Spivey\",\"id\":\"700103\"},{\"name\":\"Hong Dave\",\"id\":\"1215057\"},{\"name\":\"Trek
51
+ Glowacki\",\"id\":\"2203865\"},{\"name\":\"Tung Bach Ly\",\"id\":\"2803850\"},{\"name\":\"Isaac
52
+ Wolkerstorfer\",\"id\":\"2900100\"},{\"name\":\"Avishai Weiss\",\"id\":\"2900461\"},{\"name\":\"Harold
53
+ Liss\",\"id\":\"2900570\"},{\"name\":\"Ryo Chijiiwa\",\"id\":\"2901026\"},{\"name\":\"Luke
54
+ Shepard\",\"id\":\"2901279\"},{\"name\":\"Daniela Wellisz\",\"id\":\"2903998\"},{\"name\":\"Daniel
55
+ Hirschberg\",\"id\":\"2904437\"},{\"name\":\"Borja Sotomayor\",\"id\":\"2905626\"},{\"name\":\"David
56
+ Underwood\",\"id\":\"2906370\"},{\"name\":\"Avi Schwab\",\"id\":\"2908086\"},{\"name\":\"Kathleen
57
+ Burnett\",\"id\":\"6827168\"},{\"name\":\"Solomon Hursey\",\"id\":\"6857763\"},{\"name\":\"Sarah
58
+ Allen\",\"id\":\"10100146\"},{\"name\":\"Zach Wolfenbarger\",\"id\":\"10115065\"},{\"name\":\"JT
59
+ Archie\",\"id\":\"10603565\"},{\"name\":\"Colin McCloskey\",\"id\":\"11308679\"}],\"paging\":{\"next\":\"https:\\/\\/graph.facebook.com\\/v2.2\\/2905623\\/friends?access_token=CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD&limit=25&offset=25&__after_id=enc_Aez9Lwck5wLvRR_mHYNCzYNGmnYunJfnA3Z8hYXQ0xOluJfy4KVv4YYD1I4Im036hrA\"},\"summary\":{\"total_count\":821}}"
60
+ http_version:
61
+ recorded_at: Fri, 26 Dec 2014 14:54:14 GMT
62
+ - request:
63
+ method: get
64
+ uri: https://graph.facebook.com/v2.2/2905623/friends?__after_id=enc_Aez9Lwck5wLvRR_mHYNCzYNGmnYunJfnA3Z8hYXQ0xOluJfy4KVv4YYD1I4Im036hrA&access_token=CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD&limit=25&offset=25
65
+ body:
66
+ encoding: US-ASCII
67
+ string: ''
68
+ headers:
69
+ User-Agent:
70
+ - Faraday v0.9.0
71
+ Accept-Encoding:
72
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
73
+ Accept:
74
+ - "*/*"
75
+ response:
76
+ status:
77
+ code: 200
78
+ message: OK
79
+ headers:
80
+ Facebook-Api-Version:
81
+ - v2.2
82
+ Etag:
83
+ - "\"ad597c7482d414a109407197c49d9c102b245fec\""
84
+ Content-Type:
85
+ - application/json; charset=UTF-8
86
+ Pragma:
87
+ - no-cache
88
+ Access-Control-Allow-Origin:
89
+ - "*"
90
+ X-Fb-Rev:
91
+ - '1543964'
92
+ Cache-Control:
93
+ - private, no-cache, no-store, must-revalidate
94
+ Expires:
95
+ - Sat, 01 Jan 2000 00:00:00 GMT
96
+ X-Fb-Debug:
97
+ - 4rfPGqFD0OuxktinjEn9le7gO3aRg+E1a6367E4h3cFk3O/vsYMACfGJFCAgsLakTiOMJaaNj4ep+CkgFPnFiw==
98
+ Date:
99
+ - Fri, 26 Dec 2014 14:54:15 GMT
100
+ Connection:
101
+ - keep-alive
102
+ Content-Length:
103
+ - '972'
104
+ body:
105
+ encoding: UTF-8
106
+ string: "{\"data\":[{\"name\":\"Andrew Kane\",\"id\":\"12460925\"},{\"name\":\"Robin
107
+ Greenwood\",\"id\":\"34602916\"},{\"name\":\"Tom Elliott\",\"id\":\"36902548\"},{\"name\":\"Brian
108
+ Maula\",\"id\":\"77800072\"},{\"name\":\"Brian Wis\",\"id\":\"78500422\"},{\"name\":\"Ryan
109
+ Merket\",\"id\":\"136300045\"},{\"name\":\"Alex Coles\",\"id\":\"202905335\"},{\"name\":\"Chris
110
+ Vincent\",\"id\":\"205300220\"},{\"name\":\"Craig Stoe\",\"id\":\"500388531\"},{\"name\":\"Alex
111
+ Neill\",\"id\":\"504120418\"},{\"name\":\"Riste\\u00e1rd Br\\u00e9anainn\",\"id\":\"10152350043011181\"},{\"name\":\"Rafi
112
+ Jacoby\",\"id\":\"518938454\"},{\"name\":\"Marc Blinder\",\"id\":\"519467425\"},{\"name\":\"Erik
113
+ Ogan\",\"id\":\"542404932\"},{\"name\":\"Nigel Benito Griffin\",\"id\":\"566130340\"},{\"name\":\"Karla
114
+ Geci\",\"id\":\"569882615\"},{\"name\":\"Dennis Schneider\",\"id\":\"582757122\"},{\"name\":\"Chad
115
+ Krsek\",\"id\":\"605431196\"},{\"name\":\"Simon Cross\",\"id\":\"605665581\"},{\"name\":\"Matt
116
+ Patterson\",\"id\":\"629514342\"},{\"name\":\"Adeel Ahmad\",\"id\":\"630665156\"},{\"name\":\"Nicholas
117
+ Solter\",\"id\":\"647473136\"},{\"name\":\"David Morcillo Mu\\u00f1oz\",\"id\":\"674832191\"},{\"name\":\"Ana
118
+ Luisa Santos\",\"id\":\"685010072\"},{\"name\":\"Matthias Wiemann\",\"id\":\"693274202\"}],\"paging\":{\"next\":\"https:\\/\\/graph.facebook.com\\/v2.2\\/2905623\\/friends?limit=25&offset=50&access_token=CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD&__after_id=enc_Aez79XsNc6mXAfVDW2zvCkfHWTRTl_YprQ2VgrtLMqPa71dSOCoC34H-6YHCCNonr-w\",\"previous\":\"https:\\/\\/graph.facebook.com\\/v2.2\\/2905623\\/friends?limit=25&offset=0&access_token=CAACEdEose0cBAKuiUM40KZBEsq2l0iggaMGZBPI74svGQRMmZCPXb7eZCYPhNUbVXnnYZCjXKFKIc7HgYllr4RDIKrANHm6kKncOx0Y3UpDqLliRGZAnSEUypyFworUnBMOQJBlAuB1wlwYJZB7LIZCobCcnT2q9QwrZBpK3qAZB3u7ZAJaZAdsMZBsyALkAXatoj75leWXhgXfT1QiJHZBGoRlz07Q85z1dZBReK4ZD&__before_id=enc_Aey0OlxZalVBlh623QavOqlYyEOlclWjZMQ_7Hv2x4BHFV_JzG9H2j-_nOikaW5PsyY\"},\"summary\":{\"total_count\":821}}"
119
+ http_version:
120
+ recorded_at: Fri, 26 Dec 2014 14:54:15 GMT
121
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Koala
4
+ RSpec.describe "requests using GraphCollections" do
5
+ let(:api) { Facebook::API.new(KoalaTest.vcr_oauth_token) }
6
+
7
+ before :each do
8
+ # use the right version of the API as of the writing of this test
9
+ Koala.config.api_version = "v2.2"
10
+ end
11
+
12
+ it "can access the next page of a friend list" do
13
+ KoalaTest.with_vcr_unless_live("friend_list_next_page") do
14
+ result = api.get_connection("me", "friends")
15
+ expect(result).not_to be_empty
16
+ expect(result.next_page).not_to be_empty
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -5,6 +5,7 @@ module KoalaTest
5
5
  attr_accessor :oauth_token, :app_id, :secret, :app_access_token, :code, :session_key
6
6
  attr_accessor :oauth_test_data, :subscription_test_data, :search_time
7
7
  attr_accessor :test_user_api
8
+ attr_accessor :vcr_oauth_token
8
9
  end
9
10
 
10
11
  # Test setup
@@ -12,31 +13,13 @@ module KoalaTest
12
13
  def self.setup_test_environment!
13
14
  setup_rspec
14
15
 
15
- unless ENV['LIVE']
16
- # By default the Koala specs are run using stubs for HTTP requests,
17
- # so they won't fail due to Facebook-imposed rate limits or server timeouts.
18
- #
19
- # However as a result they are more brittle since
20
- # we are not testing the latest responses from the Facebook servers.
21
- # To be certain all specs pass with the current Facebook services,
22
- # run LIVE=true bundle exec rake spec.
23
- Koala.http_service = Koala::MockHTTPService
24
- KoalaTest.setup_test_data(Koala::MockHTTPService::TEST_DATA)
25
- else
16
+ if live?
26
17
  # Runs Koala specs through the Facebook servers
27
18
  # using data for a real app
28
19
  live_data = YAML.load_file(File.join(File.dirname(__FILE__), '../fixtures/facebook_data.yml'))
29
20
  KoalaTest.setup_test_data(live_data)
30
21
 
31
- # allow live tests with different adapters
32
- adapter = ENV['ADAPTER'] || "typhoeus" # use Typhoeus by default if available
33
- begin
34
- require adapter
35
- require 'typhoeus/adapters/faraday' if adapter.to_s == "typhoeus"
36
- Faraday.default_adapter = adapter.to_sym
37
- rescue LoadError
38
- puts "Unable to load adapter #{adapter}, using Net::HTTP."
39
- end
22
+ activate_adapter!
40
23
 
41
24
  Koala.http_service.http_options[:beta] = true if ENV["beta"] || ENV["BETA"]
42
25
 
@@ -46,6 +29,17 @@ module KoalaTest
46
29
  else
47
30
  KoalaTest.validate_user_info(token)
48
31
  end
32
+ else
33
+ # By default the Koala specs are run using stubs for HTTP requests,
34
+ # so they won't fail due to Facebook-imposed rate limits or server timeouts.
35
+ #
36
+ # However as a result they are more brittle since
37
+ # we are not testing the latest responses from the Facebook servers.
38
+ # To be certain all specs pass with the current Facebook services,
39
+ # run LIVE=true bundle exec rake spec.
40
+ activate_vcr!
41
+ Koala.http_service = Koala::MockHTTPService
42
+ KoalaTest.setup_test_data(Koala::MockHTTPService::TEST_DATA)
49
43
  end
50
44
  end
51
45
 
@@ -79,6 +73,28 @@ module KoalaTest
79
73
  end
80
74
  end
81
75
 
76
+ # If we're running live tests against the Facebook API, don't use the VCR
77
+ # fixtures. (Another alternative would be to rerecord those fixtures, but we
78
+ # don't necessarily want to do that.
79
+ def self.with_vcr_unless_live(name)
80
+ if live?
81
+ yield
82
+ else
83
+ begin
84
+ # if we're using VCR, we don't want to use the mock service, which was
85
+ # an early implementation of the same type of tool
86
+ old_adapter = Koala.http_service
87
+ Koala.http_service = Koala::HTTPService
88
+ activate_adapter!
89
+ VCR.use_cassette(name) do
90
+ yield
91
+ end
92
+ ensure
93
+ Koala.http_service = old_adapter
94
+ end
95
+ end
96
+ end
97
+
82
98
  def self.setup_test_data(data)
83
99
  # make data accessible to all our tests
84
100
  self.oauth_test_data = data["oauth_test_data"]
@@ -90,12 +106,14 @@ module KoalaTest
90
106
  self.code = data["oauth_test_data"]["code"]
91
107
  self.session_key = data["oauth_test_data"]["session_key"]
92
108
 
109
+ self.vcr_oauth_token = data["vcr_data"]["oauth_token"]
110
+
93
111
  # fix the search time so it can be used in the mock responses
94
112
  self.search_time = data["search_time"] || (Time.now - 3600).to_s
95
113
  end
96
114
 
97
115
  def self.testing_permissions
98
- "read_stream, publish_stream, user_photos, user_videos, read_insights"
116
+ "read_stream, publish_actions, user_photos, user_videos, read_insights"
99
117
  end
100
118
 
101
119
  def self.setup_test_users
@@ -143,7 +161,7 @@ module KoalaTest
143
161
  perms.each_pair do |perm, value|
144
162
  if value == (perm == "read_insights" ? 1 : 0) # live testing depends on insights calls failing
145
163
  puts "failed!\n" # put a new line after the print above
146
- raise ArgumentError, "Your access token must have the read_stream, publish_stream, and user_photos permissions, and lack read_insights. You have: #{perms.inspect}"
164
+ raise ArgumentError, "Your access token must have #{testing_permissions.join(", ")}, and lack read_insights. You have: #{perms.inspect}"
147
165
  end
148
166
  end
149
167
  puts "done!"
@@ -199,4 +217,36 @@ module KoalaTest
199
217
  def self.app_properties
200
218
  mock_interface? ? {"desktop" => 0} : {"description" => "A test framework for Koala and its users. (#{rand(10000).to_i})"}
201
219
  end
220
+
221
+ def self.live?
222
+ ENV['LIVE']
223
+ end
224
+
225
+ def self.activate_vcr!
226
+ require 'vcr'
227
+
228
+ VCR.configure do |c|
229
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
230
+ c.hook_into :webmock # or :fakeweb
231
+ end
232
+ end
233
+
234
+ def self.activate_adapter!
235
+ unless @adapter_activation_attempted
236
+ # allow live tests with different adapters
237
+ adapter = ENV['ADAPTER'] || "typhoeus" # use Typhoeus by default if available
238
+ begin
239
+ # JRuby doesn't support typhoeus on Travis
240
+ unless defined? JRUBY_VERSION
241
+ require adapter
242
+ require 'typhoeus/adapters/faraday' if adapter.to_s == "typhoeus"
243
+ Faraday.default_adapter = adapter.to_sym
244
+ end
245
+ rescue LoadError
246
+ puts "Unable to load adapter #{adapter}, using Net::HTTP."
247
+ ensure
248
+ @adapter_activation_attempted = true
249
+ end
250
+ end
251
+ end
202
252
  end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: koala
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.1
4
+ version: 1.11.0rc
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Koppel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-03 00:00:00.000000000 Z
11
+ date: 2014-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: faraday
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: addressable
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  description: Koala is a lightweight, flexible Ruby SDK for Facebook. It allows read/write
@@ -64,11 +64,11 @@ extra_rdoc_files:
64
64
  - readme.md
65
65
  - changelog.md
66
66
  files:
67
- - ".autotest"
68
- - ".gitignore"
69
- - ".rspec"
70
- - ".travis.yml"
71
- - ".yardopts"
67
+ - .autotest
68
+ - .gitignore
69
+ - .rspec
70
+ - .travis.yml
71
+ - .yardopts
72
72
  - Gemfile
73
73
  - Guardfile
74
74
  - LICENSE
@@ -115,6 +115,8 @@ files:
115
115
  - spec/fixtures/cat.m4v
116
116
  - spec/fixtures/facebook_data.yml
117
117
  - spec/fixtures/mock_facebook_responses.yml
118
+ - spec/fixtures/vcr_cassettes/friend_list_next_page.yml
119
+ - spec/integration/graph_collection_spec.rb
118
120
  - spec/spec_helper.rb
119
121
  - spec/support/custom_matchers.rb
120
122
  - spec/support/graph_api_shared_examples.rb
@@ -128,25 +130,25 @@ licenses:
128
130
  metadata: {}
129
131
  post_install_message:
130
132
  rdoc_options:
131
- - "--line-numbers"
132
- - "--inline-source"
133
- - "--title"
133
+ - --line-numbers
134
+ - --inline-source
135
+ - --title
134
136
  - Koala
135
137
  require_paths:
136
138
  - lib
137
139
  required_ruby_version: !ruby/object:Gem::Requirement
138
140
  requirements:
139
- - - ">="
141
+ - - '>='
140
142
  - !ruby/object:Gem::Version
141
143
  version: '0'
142
144
  required_rubygems_version: !ruby/object:Gem::Requirement
143
145
  requirements:
144
- - - ">="
146
+ - - '>'
145
147
  - !ruby/object:Gem::Version
146
- version: '0'
148
+ version: 1.3.1
147
149
  requirements: []
148
150
  rubyforge_project:
149
- rubygems_version: 2.2.1
151
+ rubygems_version: 2.2.2
150
152
  signing_key:
151
153
  specification_version: 4
152
154
  summary: A lightweight, flexible library for Facebook with support for the Graph API,
@@ -171,6 +173,8 @@ test_files:
171
173
  - spec/fixtures/cat.m4v
172
174
  - spec/fixtures/facebook_data.yml
173
175
  - spec/fixtures/mock_facebook_responses.yml
176
+ - spec/fixtures/vcr_cassettes/friend_list_next_page.yml
177
+ - spec/integration/graph_collection_spec.rb
174
178
  - spec/spec_helper.rb
175
179
  - spec/support/custom_matchers.rb
176
180
  - spec/support/graph_api_shared_examples.rb