koala 1.10.1 → 1.11.0rc

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 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