koala 2.2.0 → 2.3.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/Gemfile +1 -1
- data/changelog.md +21 -0
- data/code_of_conduct.md +22 -0
- data/lib/koala/api/graph_api.rb +27 -44
- data/lib/koala/api/graph_batch_api.rb +9 -3
- data/lib/koala/api/graph_error_checker.rb +71 -0
- data/lib/koala/errors.rb +16 -3
- data/lib/koala/oauth.rb +1 -1
- data/lib/koala/version.rb +1 -1
- data/readme.md +39 -11
- data/spec/cases/error_spec.rb +10 -4
- data/spec/cases/graph_api_batch_spec.rb +1 -24
- data/spec/cases/graph_api_spec.rb +1 -1
- data/spec/cases/graph_error_checker_spec.rb +116 -0
- data/spec/cases/oauth_spec.rb +4 -4
- data/spec/cases/realtime_updates_spec.rb +0 -16
- data/spec/cases/test_users_spec.rb +0 -4
- data/spec/fixtures/mock_facebook_responses.yml +16 -4
- data/spec/spec_helper.rb +10 -0
- data/spec/support/graph_api_shared_examples.rb +20 -5
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76e59769142ebe10d76554dfdf8c33e1f61cadc6
|
4
|
+
data.tar.gz: 57b9b65c9fd36ff249bc75dac3bab8f795a352db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6ff1b2181cdbab58b6b2a010349492102b6e598d7021d6bb7bce7949cc327259d37e4a16b51c609323fe410b87fbbfa835bfed377353d2e71a1a3c9f6125f79
|
7
|
+
data.tar.gz: 85c0c8dcf1a629043970be2a6c3eb9f6504ad5c1ca041189b3fe13e63aa70a3b90e68ca98e7cbbb042f8f616c59eac26600627ee20f0fed39419ba49b42a03da
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/changelog.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
v2.3.0
|
2
|
+
======
|
3
|
+
|
4
|
+
Updated features:
|
5
|
+
|
6
|
+
* API#get_user_picture_data is now API#get_picture_data. The old method and API#get_picture both
|
7
|
+
remain with deprecation warnings. (Thanks noahsilas for earlier work on this!)
|
8
|
+
* Koala::Facebook::APIError now includes [debug and trace
|
9
|
+
info](https://github.com/arsduo/koala/blob/master/lib/koala/errors.rb) provided by Facebook in the headers
|
10
|
+
(thanks, @elhu!)
|
11
|
+
|
12
|
+
Internal Improvements:
|
13
|
+
|
14
|
+
* Graph API error handling is now done via the GraphErrorChecker class
|
15
|
+
|
16
|
+
Testing improvements:
|
17
|
+
|
18
|
+
* Upgraded RSpec to 3.3.0
|
19
|
+
* Removed pended specs that were no longer relevant
|
20
|
+
* Improved https regex in test suite (thanks, lucaskds!)
|
21
|
+
|
1
22
|
v2.2.0
|
2
23
|
======
|
3
24
|
|
data/code_of_conduct.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include:
|
8
|
+
|
9
|
+
* The use of sexualized language or imagery
|
10
|
+
* Personal attacks
|
11
|
+
* Trolling or insulting/derogatory comments
|
12
|
+
* Public or private harassment
|
13
|
+
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
14
|
+
* Other unethical or unprofessional conduct.
|
15
|
+
|
16
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
17
|
+
|
18
|
+
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
19
|
+
|
20
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
21
|
+
|
22
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
data/lib/koala/api/graph_api.rb
CHANGED
@@ -2,6 +2,7 @@ require 'addressable/uri'
|
|
2
2
|
|
3
3
|
require 'koala/api/graph_collection'
|
4
4
|
require 'koala/http_service/uploadable_io'
|
5
|
+
require 'koala/api/graph_error_checker'
|
5
6
|
|
6
7
|
module Koala
|
7
8
|
module Facebook
|
@@ -164,9 +165,10 @@ module Koala
|
|
164
165
|
graph_call("#{id}/#{connection_name}", args, "delete", options, &block)
|
165
166
|
end
|
166
167
|
|
167
|
-
# Fetches a photo.
|
168
|
-
#
|
169
|
-
#
|
168
|
+
# Fetches a photo url.
|
169
|
+
# Note that this method returns the picture url, not the full API
|
170
|
+
# response. For the hash containing the full metadata for the photo, use
|
171
|
+
# #get_user_picture_data instead.
|
170
172
|
#
|
171
173
|
# @param options options for Facebook (see #get_object).
|
172
174
|
# To get a different size photo, pass :type => size (small, normal, large, square).
|
@@ -176,22 +178,34 @@ module Koala
|
|
176
178
|
#
|
177
179
|
# @return the URL to the image
|
178
180
|
def get_picture(object, args = {}, options = {}, &block)
|
179
|
-
#
|
180
|
-
|
181
|
-
|
182
|
-
|
181
|
+
Koala::Utils.deprecate("API#get_picture will be removed in a future version. Please use API#get_picture_data, which returns a hash including the url.")
|
182
|
+
|
183
|
+
get_user_picture_data(object, args, options) do |result|
|
184
|
+
# Try to extract the URL
|
185
|
+
result = result.fetch('data', {})['url'] if result.respond_to?(:fetch)
|
186
|
+
block ? block.call(result) : result
|
183
187
|
end
|
184
188
|
end
|
185
189
|
|
186
|
-
# Fetches a photo data.
|
190
|
+
# Fetches a photo data hash.
|
187
191
|
#
|
188
192
|
# @param args (see #get_object)
|
189
193
|
# @param options (see Koala::Facebook::API#api)
|
190
194
|
# @param block (see Koala::Facebook::API#api)
|
191
195
|
#
|
192
196
|
# @return a hash of object data
|
193
|
-
def
|
194
|
-
|
197
|
+
def get_picture_data(object, args = {}, options = {}, &block)
|
198
|
+
# The default response for a Graph API query like GET /me/picture is to
|
199
|
+
# return a 302 redirect. This is a surprising difference from the
|
200
|
+
# common return type, so we add the `redirect: false` parameter to get
|
201
|
+
# a RESTful API response instead.
|
202
|
+
args = args.merge(:redirect => false)
|
203
|
+
graph_call("#{object}/picture", args, "get", options, &block)
|
204
|
+
end
|
205
|
+
|
206
|
+
def get_user_picture_data(*args, &block)
|
207
|
+
Koala::Utils.deprecate("API#get_user_picture_data is deprecated and will be removed in a future version. Please use API#get_picture_data, which has the same signature.")
|
208
|
+
get_picture_data(*args, &block)
|
195
209
|
end
|
196
210
|
|
197
211
|
# Upload a photo.
|
@@ -511,7 +525,7 @@ module Koala
|
|
511
525
|
# enable appsecret_proof by default
|
512
526
|
options = {:appsecret_proof => true}.merge(options) if @app_secret
|
513
527
|
result = api(path, args, verb, options) do |response|
|
514
|
-
error = check_response(response.status, response.body)
|
528
|
+
error = check_response(response.status, response.body, response.headers)
|
515
529
|
raise error if error
|
516
530
|
end
|
517
531
|
|
@@ -524,39 +538,8 @@ module Koala
|
|
524
538
|
|
525
539
|
private
|
526
540
|
|
527
|
-
def check_response(http_status,
|
528
|
-
|
529
|
-
# which is immediately raised (non-batch) or added to the list of batch results (batch)
|
530
|
-
http_status = http_status.to_i
|
531
|
-
|
532
|
-
if http_status >= 400
|
533
|
-
begin
|
534
|
-
response_hash = MultiJson.load(response_body)
|
535
|
-
rescue MultiJson::DecodeError
|
536
|
-
response_hash = {}
|
537
|
-
end
|
538
|
-
|
539
|
-
if response_hash['error_code']
|
540
|
-
# Old batch api error format. This can be removed on July 5, 2012.
|
541
|
-
# See https://developers.facebook.com/roadmap/#graph-batch-api-exception-format
|
542
|
-
error_info = {
|
543
|
-
'code' => response_hash['error_code'],
|
544
|
-
'message' => response_hash['error_description']
|
545
|
-
}
|
546
|
-
else
|
547
|
-
error_info = response_hash['error'] || {}
|
548
|
-
end
|
549
|
-
|
550
|
-
if error_info['type'] == 'OAuthException' &&
|
551
|
-
( !error_info['code'] || [102, 190, 450, 452, 2500].include?(error_info['code'].to_i))
|
552
|
-
|
553
|
-
# See: https://developers.facebook.com/docs/authentication/access-token-expiration/
|
554
|
-
# https://developers.facebook.com/bugs/319643234746794?browse=search_4fa075c0bd9117b20604672
|
555
|
-
AuthenticationError.new(http_status, response_body, error_info)
|
556
|
-
else
|
557
|
-
ClientError.new(http_status, response_body, error_info)
|
558
|
-
end
|
559
|
-
end
|
541
|
+
def check_response(http_status, body, headers)
|
542
|
+
GraphErrorChecker.new(http_status, body, headers).error_if_appropriate
|
560
543
|
end
|
561
544
|
|
562
545
|
def parse_media_args(media_args, method)
|
@@ -22,7 +22,7 @@ module Koala
|
|
22
22
|
# normalize options for consistency
|
23
23
|
options = Koala::Utils.symbolize_hash(options)
|
24
24
|
|
25
|
-
# for batch APIs, we queue up the call details (incl. post-processing)
|
25
|
+
# for batch APIs, we queue up the call details (incl. post-processing)
|
26
26
|
batch_calls << BatchOperation.new(
|
27
27
|
:url => path,
|
28
28
|
:args => args,
|
@@ -65,7 +65,13 @@ module Koala
|
|
65
65
|
|
66
66
|
raw_result = nil
|
67
67
|
if call_result
|
68
|
-
|
68
|
+
parsed_headers = if call_result.has_key?('headers')
|
69
|
+
call_result['headers'].inject({}) { |headers, h| headers[h['name']] = h['value']; headers}
|
70
|
+
else
|
71
|
+
{}
|
72
|
+
end
|
73
|
+
|
74
|
+
if (error = check_response(call_result['code'], call_result['body'].to_s, parsed_headers))
|
69
75
|
raw_result = error
|
70
76
|
else
|
71
77
|
# (see note in regular api method about JSON parsing)
|
@@ -77,7 +83,7 @@ module Koala
|
|
77
83
|
call_result["code"].to_i
|
78
84
|
when :headers
|
79
85
|
# facebook returns the headers as an array of k/v pairs, but we want a regular hash
|
80
|
-
|
86
|
+
parsed_headers
|
81
87
|
else
|
82
88
|
body
|
83
89
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Koala
|
2
|
+
module Facebook
|
3
|
+
# This class, given a Koala::HTTPService::Response object, will check for Graph API-specific
|
4
|
+
# errors. This returns an error of the appropriate type which can be immediately raised
|
5
|
+
# (non-batch) or added to the list of batch results (batch)
|
6
|
+
class GraphErrorChecker
|
7
|
+
attr_reader :http_status, :body, :headers
|
8
|
+
def initialize(http_status, body, headers)
|
9
|
+
@http_status = http_status.to_i
|
10
|
+
@body = body
|
11
|
+
@headers = headers
|
12
|
+
end
|
13
|
+
|
14
|
+
# Facebook has a set of standardized error codes, some of which represent problems with the
|
15
|
+
# token.
|
16
|
+
AUTHENTICATION_ERROR_CODES = [102, 190, 450, 452, 2500]
|
17
|
+
|
18
|
+
# Facebook can return debug information in the response headers -- see
|
19
|
+
# https://developers.facebook.com/docs/graph-api/using-graph-api#bugdebug
|
20
|
+
DEBUG_HEADERS = ["x-fb-debug", "x-fb-rev", "x-fb-trace-id"]
|
21
|
+
|
22
|
+
def error_if_appropriate
|
23
|
+
if http_status >= 400
|
24
|
+
error_class.new(http_status, body, error_info)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def error_class
|
31
|
+
if auth_error?
|
32
|
+
# See: https://developers.facebook.com/docs/authentication/access-token-expiration/
|
33
|
+
# https://developers.facebook.com/bugs/319643234746794?browse=search_4fa075c0bd9117b20604672
|
34
|
+
AuthenticationError
|
35
|
+
else
|
36
|
+
ClientError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def auth_error?
|
41
|
+
# tbh, I'm not sure why we restrict Facebook-reported OAuthExceptions to only those without
|
42
|
+
# codes or whose codes match the list above -- let's investigate changing this later.
|
43
|
+
error_info['type'] == 'OAuthException' &&
|
44
|
+
(!error_info['code'] || AUTHENTICATION_ERROR_CODES.include?(error_info['code'].to_i))
|
45
|
+
end
|
46
|
+
|
47
|
+
def error_info
|
48
|
+
# Build up the complete error info from whatever Facebook gives us plus the header
|
49
|
+
# information
|
50
|
+
@error_info ||= DEBUG_HEADERS.inject(base_error_info) do |hash, error_key|
|
51
|
+
hash[error_key] = headers[error_key] if headers[error_key]
|
52
|
+
hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def base_error_info
|
57
|
+
response_hash['error'] || {}
|
58
|
+
end
|
59
|
+
|
60
|
+
def response_hash
|
61
|
+
# Normally, we start with the response body. If it isn't valid JSON, we start with an empty
|
62
|
+
# hash and fill it with error data.
|
63
|
+
@response_hash ||= begin
|
64
|
+
MultiJson.load(body)
|
65
|
+
rescue MultiJson::DecodeError
|
66
|
+
{}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/koala/errors.rb
CHANGED
@@ -13,8 +13,17 @@ module Koala
|
|
13
13
|
# Facebook responded with an error to an API request. If the exception contains a nil
|
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
|
-
attr_accessor :
|
17
|
-
:
|
16
|
+
attr_accessor :http_status,
|
17
|
+
:response_body,
|
18
|
+
:fb_error_type,
|
19
|
+
:fb_error_code,
|
20
|
+
:fb_error_subcode,
|
21
|
+
:fb_error_message,
|
22
|
+
:fb_error_user_msg,
|
23
|
+
:fb_error_user_title,
|
24
|
+
:fb_error_trace_id,
|
25
|
+
:fb_error_debug,
|
26
|
+
:fb_error_rev
|
18
27
|
|
19
28
|
# Create a new API Error
|
20
29
|
#
|
@@ -54,8 +63,12 @@ module Koala
|
|
54
63
|
self.fb_error_user_msg = error_info["error_user_msg"]
|
55
64
|
self.fb_error_user_title = error_info["error_user_title"]
|
56
65
|
|
66
|
+
self.fb_error_trace_id = error_info["x-fb-trace-id"]
|
67
|
+
self.fb_error_debug = error_info["x-fb-debug"]
|
68
|
+
self.fb_error_rev = error_info["x-fb-rev"]
|
69
|
+
|
57
70
|
error_array = []
|
58
|
-
%w(type code error_subcode message error_user_title error_user_msg).each do |key|
|
71
|
+
%w(type code error_subcode message error_user_title error_user_msg x-fb-trace-id).each do |key|
|
59
72
|
error_array << "#{key}: #{error_info[key]}" if error_info[key]
|
60
73
|
end
|
61
74
|
|
data/lib/koala/oauth.rb
CHANGED
data/lib/koala/version.rb
CHANGED
data/readme.md
CHANGED
@@ -7,12 +7,14 @@ Koala [![Version](https://img.shields.io/gem/v/koala.svg)](https://rubygems.org/
|
|
7
7
|
* Flexible: Koala should be useful to everyone, regardless of their current configuration. We support JRuby, Rubinius, and REE as well as vanilla Ruby (1.8.7, 1.9.2, 1.9.3, and 2.0.0), and use the Faraday library to provide complete flexibility over how HTTP requests are made.
|
8
8
|
* Tested: Koala should have complete test coverage, so you can rely on it. Our test coverage is complete and can be run against either mocked responses or the live Facebook servers; we're also on [Travis CI](http://travis-ci.org/arsduo/koala/).
|
9
9
|
|
10
|
+
**Found a bug? Interested in contributing?** Check out the Maintenance section below!
|
11
|
+
|
10
12
|
Installation
|
11
|
-
|
13
|
+
------------
|
12
14
|
|
13
15
|
In Bundler:
|
14
16
|
```ruby
|
15
|
-
gem "koala", "~> 2.
|
17
|
+
gem "koala", "~> 2.2"
|
16
18
|
```
|
17
19
|
|
18
20
|
Otherwise:
|
@@ -20,8 +22,8 @@ Otherwise:
|
|
20
22
|
[sudo|rvm] gem install koala
|
21
23
|
```
|
22
24
|
|
23
|
-
Upgrading to 2.0
|
24
|
-
|
25
|
+
Upgrading to 2.0+
|
26
|
+
-----------------
|
25
27
|
|
26
28
|
Koala 2.0 is not a major refactor, but rather a set of small, mostly internal
|
27
29
|
refactors, which should not require significant changes by users. See changelog.md for more
|
@@ -112,7 +114,8 @@ the results apart from a long list of array entries:
|
|
112
114
|
Check out the wiki for more details and examples.
|
113
115
|
|
114
116
|
The REST API
|
115
|
-
|
117
|
+
------------
|
118
|
+
|
116
119
|
Where the Graph API and the old REST API overlap, you should choose the Graph API. Unfortunately, that overlap is far from complete, and there are many important API calls that can't yet be done via the Graph.
|
117
120
|
|
118
121
|
Fortunately, Koala supports the REST API using the very same interface; to use this, instantiate an API:
|
@@ -132,7 +135,8 @@ fql = @api.fql_query(my_fql_query)
|
|
132
135
|
```
|
133
136
|
|
134
137
|
Configuration
|
135
|
-
|
138
|
+
-------------
|
139
|
+
|
136
140
|
You can change the host that koala makes requests to (point to a mock server, apigee, runscope etc..)
|
137
141
|
```ruby
|
138
142
|
# config/initializers/koala.rb
|
@@ -150,6 +154,7 @@ tier and video upload matching and replacement strings.
|
|
150
154
|
|
151
155
|
OAuth
|
152
156
|
-----
|
157
|
+
|
153
158
|
You can use the Graph and REST APIs without an OAuth access token, but the real magic happens when you provide Facebook an OAuth token to prove you're authenticated. Koala provides an OAuth class to make that process easy:
|
154
159
|
```ruby
|
155
160
|
@oauth = Koala::Facebook::OAuth.new(app_id, app_secret, callback_url)
|
@@ -189,7 +194,8 @@ Or, if for some horrible reason, you're still using session keys, despair not!
|
|
189
194
|
That's it! It's pretty simple once you get the hang of it. If you're new to OAuth, though, check out the wiki and the OAuth Playground example site (see below).
|
190
195
|
|
191
196
|
Real-time Updates
|
192
|
-
|
197
|
+
-----------------
|
198
|
+
|
193
199
|
Sometimes, reaching out to Facebook is a pain -- let it reach out to you instead. The Graph API allows your application to subscribe to real-time updates for certain objects in the graph; check the [official Facebook documentation](http://developers.facebook.com/docs/api/realtime) for more details on what objects you can subscribe to and what limitations may apply.
|
194
200
|
|
195
201
|
Koala makes it easy to interact with your applications using the RealtimeUpdates class:
|
@@ -215,7 +221,7 @@ Koala::Facebook::RealtimeUpdates.meet_challenge(params, your_verify_token)
|
|
215
221
|
For more information about meet_challenge and the RealtimeUpdates class, check out the Real-Time Updates page on the wiki.
|
216
222
|
|
217
223
|
Test Users
|
218
|
-
|
224
|
+
----------
|
219
225
|
|
220
226
|
We also support the test users API, allowing you to conjure up fake users and command them to do your bidding using the Graph or REST API:
|
221
227
|
```ruby
|
@@ -226,7 +232,7 @@ user_graph_api = Koala::Facebook::API.new(user["access_token"])
|
|
226
232
|
@test_users.create_network(network_size, is_app_installed, common_permissions)
|
227
233
|
```
|
228
234
|
Talking to Facebook
|
229
|
-
|
235
|
+
-------------------
|
230
236
|
|
231
237
|
Koala uses Faraday to make HTTP requests, which means you have complete control over how your app makes HTTP requests to Facebook. You can set Faraday options globally or pass them in on a per-request (or both):
|
232
238
|
```ruby
|
@@ -240,7 +246,7 @@ Koala.http_service.http_options = {
|
|
240
246
|
The <a href="https://github.com/arsduo/koala/wiki/HTTP-Services">HTTP Services wiki page</a> has more information on what options are available, as well as on how to configure your own Faraday middleware stack (for instance, to implement request logging).
|
241
247
|
|
242
248
|
See examples, ask questions
|
243
|
-
|
249
|
+
---------------------------
|
244
250
|
|
245
251
|
Some resources to help you as you play with Koala and the Graph API:
|
246
252
|
|
@@ -257,7 +263,7 @@ issues filed about how to use the Facebook API may be closed with a reference
|
|
257
263
|
to the Facebook Stack Overflow page.
|
258
264
|
|
259
265
|
Testing
|
260
|
-
|
266
|
+
-------
|
261
267
|
|
262
268
|
Unit tests are provided for all of Koala's methods. By default, these tests run against mock responses and hence are ready out of the box:
|
263
269
|
```bash
|
@@ -273,3 +279,25 @@ LIVE=true bundle exec rake spec
|
|
273
279
|
LIVE=true BETA=true bundle exec rake spec
|
274
280
|
```
|
275
281
|
By default, the live tests are run against test users, so you can run them as frequently as you want. If you want to run them against a real user, however, you can fill in the OAuth token, code, and access\_token values in spec/fixtures/facebook_data.yml. See the wiki for more details.
|
282
|
+
|
283
|
+
Maintenance
|
284
|
+
-----------
|
285
|
+
|
286
|
+
_Pull requests_: Koala exists as it does thanks to the amazing support and work of community members of all
|
287
|
+
backgrounds and levels of experience. Pull requests are very welcome! If you have any questions,
|
288
|
+
just open an issue.
|
289
|
+
|
290
|
+
Please note that this project is released with a Contributor Code of Conduct. By participating in
|
291
|
+
this project you agree to abide by its terms. See
|
292
|
+
[code_of_conduct.md](https://github.com/arsduo/koala/blob/master/code_of_conduct.md) for more information.
|
293
|
+
|
294
|
+
_Schedule_: In order to keep Koala moving forward on a regular and predictable schedule, I will
|
295
|
+
address issues and pull requests at least three times a year: late July/early August, late
|
296
|
+
December/early January, and late March/early April. I may respond to issues in between maintenance
|
297
|
+
periods, but it'll depend on other life/work goings-on.
|
298
|
+
|
299
|
+
Breaking/new Facebook changes and other urgent issues obviously will get addressed much more
|
300
|
+
quickly. (We've never had a security issue, but obviously that would be priority 0.)
|
301
|
+
|
302
|
+
Have questions? Found a breaking bug or urgent issue? [Tweet at me](http://twitter.com/arsduo) --
|
303
|
+
I'm always happy to respond.
|
data/spec/cases/error_spec.rb
CHANGED
@@ -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, :fb_error_user_msg, :fb_error_user_title, :http_status, :response_body].each do |accessor|
|
8
|
+
[: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|
|
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}=")
|
@@ -29,7 +29,10 @@ describe Koala::Facebook::APIError do
|
|
29
29
|
'code' => 1,
|
30
30
|
'error_subcode' => 'subcode',
|
31
31
|
'error_user_msg' => 'error user message',
|
32
|
-
'error_user_title' => 'error user title'
|
32
|
+
'error_user_title' => 'error user title',
|
33
|
+
'x-fb-trace-id' => 'fb trace id',
|
34
|
+
'x-fb-debug' => 'fb debug token',
|
35
|
+
'x-fb-rev' => 'fb revision'
|
33
36
|
}
|
34
37
|
Koala::Facebook::APIError.new(400, '', error_info)
|
35
38
|
}
|
@@ -40,7 +43,10 @@ describe Koala::Facebook::APIError do
|
|
40
43
|
:fb_error_code => 1,
|
41
44
|
:fb_error_subcode => 'subcode',
|
42
45
|
:fb_error_user_msg => 'error user message',
|
43
|
-
:fb_error_user_title => 'error user title'
|
46
|
+
:fb_error_user_title => 'error user title',
|
47
|
+
:fb_error_trace_id => 'fb trace id',
|
48
|
+
:fb_error_debug => 'fb debug token',
|
49
|
+
:fb_error_rev => 'fb revision'
|
44
50
|
}.each_pair do |accessor, value|
|
45
51
|
it "sets #{accessor} to #{value}" do
|
46
52
|
expect(error.send(accessor)).to eq(value)
|
@@ -48,7 +54,7 @@ describe Koala::Facebook::APIError do
|
|
48
54
|
end
|
49
55
|
|
50
56
|
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_msg: error user message [HTTP 400]")
|
57
|
+
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, x-fb-trace-id: fb trace id [HTTP 400]")
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
@@ -401,30 +401,7 @@ describe "Koala::Facebook::GraphAPI in batch mode" do
|
|
401
401
|
}.to raise_exception(Koala::Facebook::BadFacebookResponse)
|
402
402
|
end
|
403
403
|
|
404
|
-
context "with
|
405
|
-
before :each do
|
406
|
-
allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(400, '{"error_code":190,"error_description":"Error validating access token."}', {}))
|
407
|
-
end
|
408
|
-
|
409
|
-
it "throws an error" do
|
410
|
-
expect {
|
411
|
-
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
412
|
-
}.to raise_exception(Koala::Facebook::APIError)
|
413
|
-
end
|
414
|
-
|
415
|
-
it "passes all the error details" do
|
416
|
-
begin
|
417
|
-
Koala::Facebook::API.new("foo").batch {|batch_api| batch_api.get_object('me') }
|
418
|
-
rescue Koala::Facebook::APIError => err
|
419
|
-
expect(err.fb_error_code).to eq(190)
|
420
|
-
expect(err.fb_error_message).to eq("Error validating access token.")
|
421
|
-
err.http_status == 400
|
422
|
-
err.response_body == '{"error_code":190,"error_description":"Error validating access token."}'
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
context "with the new style" do
|
404
|
+
context "with error info" do
|
428
405
|
before :each do
|
429
406
|
allow(Koala).to receive(:make_request).and_return(Koala::HTTPService::Response.new(400, '{"error":{"message":"Request 0 cannot depend on an unresolved request with name f. Requests can only depend on preceding requests","type":"GraphBatchException"}}', {}))
|
430
407
|
end
|
@@ -30,7 +30,7 @@ describe 'Koala::Facebook::GraphAPIMethods' do
|
|
30
30
|
|
31
31
|
context '#get_picture' do
|
32
32
|
it 'returns result of block' do
|
33
|
-
allow(@api).to receive(:api).and_return("
|
33
|
+
allow(@api).to receive(:api).and_return({"data" => {"is_silhouette" => false, "url" => result}})
|
34
34
|
expect(@api.get_picture('lukeshepard', &post_processing)["result"]).to eq(result)
|
35
35
|
end
|
36
36
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Koala
|
4
|
+
module Facebook
|
5
|
+
RSpec.describe GraphErrorChecker do
|
6
|
+
it "defines a set of AUTHENTICATION_ERROR_CODES" do
|
7
|
+
expect(GraphErrorChecker::AUTHENTICATION_ERROR_CODES).to match_array([102, 190, 450, 452, 2500])
|
8
|
+
end
|
9
|
+
|
10
|
+
it "defines a set of DEBUG_HEADERS" do
|
11
|
+
expect(GraphErrorChecker::DEBUG_HEADERS).to match_array([
|
12
|
+
"x-fb-rev",
|
13
|
+
"x-fb-debug",
|
14
|
+
"x-fb-trace-id"
|
15
|
+
])
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#error_if_appropriate" do
|
19
|
+
shared_examples_for :returning_no_error do |status|
|
20
|
+
it "returns no error" do
|
21
|
+
expect(GraphErrorChecker.new(status, "{}", {}).error_if_appropriate).to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "ignores error data even if present" do
|
25
|
+
checker = GraphErrorChecker.new(
|
26
|
+
status,
|
27
|
+
{"error" => {"some" => "error"}},
|
28
|
+
{"x-fb-rev" => "data"}
|
29
|
+
)
|
30
|
+
expect(checker.error_if_appropriate).to be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "if the status is 2xx" do
|
35
|
+
it_should_behave_like :returning_no_error, 202
|
36
|
+
end
|
37
|
+
|
38
|
+
context "if the status is 3xx" do
|
39
|
+
it_should_behave_like :returning_no_error, 302
|
40
|
+
end
|
41
|
+
|
42
|
+
shared_examples_for :returns_an_error do |status|
|
43
|
+
let(:body) { "{}" }
|
44
|
+
let(:headers) { {} }
|
45
|
+
let(:error) { GraphErrorChecker.new(status, body, headers).error_if_appropriate }
|
46
|
+
it "returns a ClientError for a generic error" do
|
47
|
+
expect(error).to be_a(ClientError)
|
48
|
+
expect(error.response_body).to eq(body)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns a ClientError even if the body can't be parsed as JSON" do
|
52
|
+
body.replace("hello from Chicago")
|
53
|
+
expect(error).to be_a(ClientError)
|
54
|
+
expect(error.response_body).to eq(body)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "adds error data from the body" do
|
58
|
+
error_data = {
|
59
|
+
"type" => "FB error type",
|
60
|
+
"code" => "FB error code",
|
61
|
+
"error_subcode" => "FB error subcode",
|
62
|
+
"message" => "An error occurred!",
|
63
|
+
"error_user_msg" => "A user msg",
|
64
|
+
"error_user_title" => "usr title"
|
65
|
+
}
|
66
|
+
body.replace({"error" => error_data}.to_json)
|
67
|
+
|
68
|
+
expect(error.fb_error_type).to eq(error_data["type"])
|
69
|
+
expect(error.fb_error_code).to eq(error_data["code"])
|
70
|
+
expect(error.fb_error_subcode).to eq(error_data["error_subcode"])
|
71
|
+
expect(error.fb_error_message).to eq(error_data["message"])
|
72
|
+
expect(error.fb_error_user_msg).to eq(error_data["error_user_msg"])
|
73
|
+
expect(error.fb_error_user_title).to eq(error_data["error_user_title"])
|
74
|
+
end
|
75
|
+
|
76
|
+
it "adds the FB debug headers to the errors" do
|
77
|
+
headers.merge!(
|
78
|
+
"x-fb-debug" => double("fb debug"),
|
79
|
+
"x-fb-rev" => double("fb rev"),
|
80
|
+
"x-fb-trace-id" => double("fb trace id"),
|
81
|
+
)
|
82
|
+
expect(error.fb_error_trace_id).to eq(headers["x-fb-trace-id"])
|
83
|
+
expect(error.fb_error_debug).to eq(headers["x-fb-debug"])
|
84
|
+
expect(error.fb_error_rev).to eq(headers["x-fb-rev"])
|
85
|
+
end
|
86
|
+
|
87
|
+
context "it returns an AuthenticationError" do
|
88
|
+
it "if FB says it's an OAuthException and it has no code" do
|
89
|
+
body.replace({"error" => {"type" => "OAuthException"}}.to_json)
|
90
|
+
expect(error).to be_an(AuthenticationError)
|
91
|
+
end
|
92
|
+
|
93
|
+
GraphErrorChecker::AUTHENTICATION_ERROR_CODES.each do |error_code|
|
94
|
+
it "if FB says it's an OAuthException and it has code #{error_code}" do
|
95
|
+
body.replace({"error" => {"type" => "OAuthException", "code" => error_code}}.to_json)
|
96
|
+
expect(error).to be_an(AuthenticationError)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Note: I'm not sure why this behavior was implemented, it may be incorrect. To
|
102
|
+
# investigate.
|
103
|
+
it "doesn't return an AuthenticationError if FB says it's an OAuthException but the code doesn't match" do
|
104
|
+
body.replace({"error" => {"type" => "OAuthException", "code" => 2499}}.to_json)
|
105
|
+
expect(error).to be_an(ClientError)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "if the status is 4xx" do
|
110
|
+
it_should_behave_like :returns_an_error, 400
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
data/spec/cases/oauth_spec.rb
CHANGED
@@ -585,18 +585,18 @@ describe "Koala::Facebook::OAuth" do
|
|
585
585
|
# so we only need to test at a high level that it works
|
586
586
|
it "throws an error if the algorithm is unsupported" do
|
587
587
|
allow(MultiJson).to receive(:load).and_return("algorithm" => "my fun algorithm")
|
588
|
-
expect { @oauth.parse_signed_request(@
|
588
|
+
expect { @oauth.parse_signed_request(@signed_params) }.to raise_error(Koala::Facebook::OAuthSignatureError)
|
589
589
|
end
|
590
590
|
|
591
591
|
it "throws an error if the signature is invalid" do
|
592
592
|
allow(OpenSSL::HMAC).to receive(:hexdigest).and_return("i'm an invalid signature")
|
593
|
-
expect { @oauth.parse_signed_request(@
|
593
|
+
expect { @oauth.parse_signed_request(@signed_params) }.to raise_error(Koala::Facebook::OAuthSignatureError)
|
594
594
|
end
|
595
595
|
|
596
596
|
it "throws an error if the signature string is empty" do
|
597
597
|
# this occasionally happens due to Facebook error
|
598
|
-
expect { @oauth.parse_signed_request("") }.to raise_error
|
599
|
-
expect { @oauth.parse_signed_request("abc-def") }.to raise_error
|
598
|
+
expect { @oauth.parse_signed_request("") }.to raise_error(Koala::Facebook::OAuthSignatureError)
|
599
|
+
expect { @oauth.parse_signed_request("abc-def") }.to raise_error(Koala::Facebook::OAuthSignatureError)
|
600
600
|
end
|
601
601
|
|
602
602
|
it "properly parses requests" do
|
@@ -106,18 +106,6 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
106
106
|
@updates.subscribe("user", "name", @subscription_path, @verify_token)
|
107
107
|
end
|
108
108
|
|
109
|
-
pending "doesn't require a verify_token" do
|
110
|
-
# see https://github.com/arsduo/koala/issues/150
|
111
|
-
obj = "user"
|
112
|
-
fields = "name"
|
113
|
-
expect(@updates.api).not_to receive(:graph_call).with(anything, hash_including(:verify_token => anything), anything, anything)
|
114
|
-
@updates.subscribe("user", "name", @subscription_path)
|
115
|
-
end
|
116
|
-
|
117
|
-
it "requires verify_token" do
|
118
|
-
expect { @updates.subscribe("user", "name", @subscription_path) }.to raise_exception
|
119
|
-
end
|
120
|
-
|
121
109
|
it "accepts an options hash" do
|
122
110
|
options = {:a => 2, :b => "c"}
|
123
111
|
expect(@updates.api).to receive(:graph_call).with(anything, anything, anything, hash_including(options))
|
@@ -129,10 +117,6 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
129
117
|
expect { @updates.subscribe("user", "name", @subscription_path, @verify_token) }.to_not raise_error
|
130
118
|
end
|
131
119
|
|
132
|
-
pending "sends a subscription request without a verify token" do
|
133
|
-
expect { @updates.subscribe("user", "name", @subscription_path) }.to_not raise_error
|
134
|
-
end
|
135
|
-
|
136
120
|
it "fails if you try to hit an invalid path on your valid server" do
|
137
121
|
expect { result = @updates.subscribe("user", "name", @subscription_path + "foo", @verify_token) }.to raise_exception(Koala::Facebook::APIError)
|
138
122
|
end
|
@@ -261,10 +261,6 @@ describe "Koala::Facebook::TestUsers" do
|
|
261
261
|
expect(result).to be_truthy
|
262
262
|
end
|
263
263
|
|
264
|
-
it "does not accept user IDs anymore" do
|
265
|
-
expect { @test_users.befriend(@user1["id"], @user2["id"]) }.to raise_exception
|
266
|
-
end
|
267
|
-
|
268
264
|
it "accepts http options passed to both calls" do
|
269
265
|
options = {:some_http_option => true}
|
270
266
|
# should come twice, once for each user
|
@@ -79,7 +79,10 @@ graph_api:
|
|
79
79
|
with_token: '[{"code": 200, "body":"{\"id\":\"123\"}"}, {"code": 200, "body":"{\"id\":\"456\"}"}]'
|
80
80
|
batch=<%= MultiJson.dump([{"method" => "get", "relative_url" => "me/picture"}]) %>:
|
81
81
|
post:
|
82
|
-
with_token: '[{"code":
|
82
|
+
with_token: '[{"code": 302, "headers":[{"name":"Location","value":"http://google.com"}]}]'
|
83
|
+
batch=<%= MultiJson.dump([{"method" => "get", "relative_url" => "me/picture?redirect=false"}]) %>:
|
84
|
+
post:
|
85
|
+
with_token: '[{"code": 200, "body":"{\"data\":{\"is_silhouette\":false,\"url\":\"http:\/\/google.com\"}}"}]'
|
83
86
|
batch=<%= MultiJson.dump([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "me/friends"}]) %>:
|
84
87
|
post:
|
85
88
|
with_token: '[{"code": 200, "body":"{\"id\":\"koppel\"}"}, {"code": 200, "body":"{\"data\":[{\"id\":\"lukeshepard\"}],\"paging\":{}}"}]'
|
@@ -167,6 +170,11 @@ graph_api:
|
|
167
170
|
post:
|
168
171
|
with_token: '{"id": "FEED_ITEM_DICTIONARY"}'
|
169
172
|
|
173
|
+
/me/picture:
|
174
|
+
redirect=false:
|
175
|
+
no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
|
176
|
+
with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
|
177
|
+
|
170
178
|
/me/photos:
|
171
179
|
source=[FILE]:
|
172
180
|
post:
|
@@ -248,11 +256,15 @@ graph_api:
|
|
248
256
|
code: 302
|
249
257
|
headers:
|
250
258
|
Location: https://facebook.com/large
|
251
|
-
|
252
259
|
redirect=false:
|
253
260
|
get:
|
254
|
-
no_token: '{"is_silhouette": true, "url": "https://facebook.com
|
255
|
-
with_token: '{"is_silhouette": true, "url": "https://facebook.com
|
261
|
+
no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
|
262
|
+
with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com" } }'
|
263
|
+
redirect=false&type=large:
|
264
|
+
get:
|
265
|
+
no_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com/large" } }'
|
266
|
+
with_token: '{ "data": { "is_silhouette": true, "url": "https://facebook.com/large" } }'
|
267
|
+
|
256
268
|
/comments:
|
257
269
|
ids=http://developers.facebook.com/blog/post/472:
|
258
270
|
get:
|
data/spec/spec_helper.rb
CHANGED
@@ -13,3 +13,13 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
13
13
|
KoalaTest.setup_test_environment!
|
14
14
|
|
15
15
|
BEACH_BALL_PATH = File.join(File.dirname(__FILE__), "fixtures", "beach.jpg")
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.mock_with :rspec do |mocks|
|
19
|
+
# This option should be set when all dependencies are being loaded
|
20
|
+
# before a spec run, as is the case in a typical spec helper. It will
|
21
|
+
# cause any verifying double instantiation for a class that does not
|
22
|
+
# exist to raise, protecting against incorrectly spelt names.
|
23
|
+
mocks.verify_doubled_constant_names = true
|
24
|
+
end
|
25
|
+
end
|
@@ -90,11 +90,11 @@ shared_examples_for "Koala GraphAPI" do
|
|
90
90
|
|
91
91
|
describe "#get_picture" do
|
92
92
|
it "can access a user's picture" do
|
93
|
-
expect(@api.get_picture(KoalaTest.user2)).to match(/
|
93
|
+
expect(@api.get_picture(KoalaTest.user2)).to match(/https?\:\/\//)
|
94
94
|
end
|
95
95
|
|
96
96
|
it "can access a user's picture, given a picture type" do
|
97
|
-
expect(@api.get_picture(KoalaTest.user2, {:type => 'large'})).to match(/^
|
97
|
+
expect(@api.get_picture(KoalaTest.user2, {:type => 'large'})).to match(/^https?\:\/\//)
|
98
98
|
end
|
99
99
|
|
100
100
|
it "works even if Facebook returns nil" do
|
@@ -103,9 +103,24 @@ shared_examples_for "Koala GraphAPI" do
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
describe "#get_picture_data" do
|
107
|
+
it "can access a user's picture data" do
|
108
|
+
result = @api.get_picture_data(KoalaTest.user2)
|
109
|
+
expect(result).to be_kind_of(Hash)
|
110
|
+
expect(result["data"]).to be_kind_of(Hash)
|
111
|
+
expect(result['data']).to be_truthy
|
112
|
+
expect(result['data'].keys).to include('is_silhouette', 'url')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#get_user_picture_data" do
|
117
|
+
it "can access a user's picture data" do
|
118
|
+
result = @api.get_picture_data(KoalaTest.user2)
|
119
|
+
expect(result).to be_kind_of(Hash)
|
120
|
+
expect(result["data"]).to be_kind_of(Hash)
|
121
|
+
expect(result['data']).to be_truthy
|
122
|
+
expect(result['data'].keys).to include('is_silhouette', 'url')
|
123
|
+
end
|
109
124
|
end
|
110
125
|
|
111
126
|
it "can access connections from public Pages" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: koala
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Koppel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- Rakefile
|
77
77
|
- autotest/discover.rb
|
78
78
|
- changelog.md
|
79
|
+
- code_of_conduct.md
|
79
80
|
- koala.gemspec
|
80
81
|
- lib/koala.rb
|
81
82
|
- lib/koala/api.rb
|
@@ -83,6 +84,7 @@ files:
|
|
83
84
|
- lib/koala/api/graph_api.rb
|
84
85
|
- lib/koala/api/graph_batch_api.rb
|
85
86
|
- lib/koala/api/graph_collection.rb
|
87
|
+
- lib/koala/api/graph_error_checker.rb
|
86
88
|
- lib/koala/api/rest_api.rb
|
87
89
|
- lib/koala/errors.rb
|
88
90
|
- lib/koala/http_service.rb
|
@@ -100,6 +102,7 @@ files:
|
|
100
102
|
- spec/cases/graph_api_batch_spec.rb
|
101
103
|
- spec/cases/graph_api_spec.rb
|
102
104
|
- spec/cases/graph_collection_spec.rb
|
105
|
+
- spec/cases/graph_error_checker_spec.rb
|
103
106
|
- spec/cases/http_service_spec.rb
|
104
107
|
- spec/cases/koala_spec.rb
|
105
108
|
- spec/cases/koala_test_spec.rb
|
@@ -141,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
144
|
version: '0'
|
142
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
146
|
requirements:
|
144
|
-
- - "
|
147
|
+
- - ">"
|
145
148
|
- !ruby/object:Gem::Version
|
146
|
-
version:
|
149
|
+
version: 1.3.1
|
147
150
|
requirements: []
|
148
151
|
rubyforge_project:
|
149
152
|
rubygems_version: 2.4.6
|
@@ -157,6 +160,7 @@ test_files:
|
|
157
160
|
- spec/cases/graph_api_batch_spec.rb
|
158
161
|
- spec/cases/graph_api_spec.rb
|
159
162
|
- spec/cases/graph_collection_spec.rb
|
163
|
+
- spec/cases/graph_error_checker_spec.rb
|
160
164
|
- spec/cases/http_service_spec.rb
|
161
165
|
- spec/cases/koala_spec.rb
|
162
166
|
- spec/cases/koala_test_spec.rb
|