koala 0.4 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +32 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.yardopts +3 -0
- data/Gemfile +25 -0
- data/ISSUE_TEMPLATE +25 -0
- data/LICENSE +22 -0
- data/Manifest +32 -5
- data/PULL_REQUEST_TEMPLATE +11 -0
- data/Rakefile +12 -12
- data/changelog.md +781 -0
- data/code_of_conduct.md +74 -0
- data/koala.gemspec +28 -24
- data/lib/koala/api/batch_operation.rb +86 -0
- data/lib/koala/api/graph_api_methods.rb +504 -0
- data/lib/koala/api/graph_batch_api.rb +167 -0
- data/lib/koala/api/graph_collection.rb +129 -0
- data/lib/koala/api/graph_error_checker.rb +72 -0
- data/lib/koala/api.rb +159 -0
- data/lib/koala/configuration.rb +56 -0
- data/lib/koala/errors.rb +126 -0
- data/lib/koala/http_service/request.rb +133 -0
- data/lib/koala/http_service/response.rb +20 -0
- data/lib/koala/http_service/uploadable_io.rb +183 -0
- data/lib/koala/http_service.rb +108 -0
- data/lib/koala/oauth.rb +342 -0
- data/lib/koala/realtime_updates.rb +151 -0
- data/lib/koala/test_users.rb +189 -0
- data/lib/koala/utils.rb +41 -0
- data/lib/koala/version.rb +3 -0
- data/lib/koala.rb +51 -291
- data/readme.md +269 -21
- data/spec/cases/api_spec.rb +362 -0
- data/spec/cases/configuration_spec.rb +11 -0
- data/spec/cases/error_spec.rb +143 -0
- data/spec/cases/graph_api_batch_spec.rb +788 -0
- data/spec/cases/graph_api_spec.rb +76 -0
- data/spec/cases/graph_collection_spec.rb +192 -0
- data/spec/cases/graph_error_checker_spec.rb +147 -0
- data/spec/cases/http_service/request_spec.rb +250 -0
- data/spec/cases/http_service/response_spec.rb +24 -0
- data/spec/cases/http_service_spec.rb +280 -0
- data/spec/cases/koala_spec.rb +57 -0
- data/spec/cases/koala_test_spec.rb +5 -0
- data/spec/cases/oauth_spec.rb +647 -0
- data/spec/cases/realtime_updates_spec.rb +327 -0
- data/spec/cases/test_users_spec.rb +383 -0
- data/spec/cases/uploadable_io_spec.rb +266 -0
- data/spec/cases/utils_spec.rb +55 -0
- data/spec/fixtures/beach.jpg +0 -0
- data/spec/fixtures/cat.m4v +0 -0
- data/spec/fixtures/facebook_data.yml +63 -0
- data/spec/fixtures/mock_facebook_responses.yml +483 -0
- data/spec/fixtures/vcr_cassettes/app_test_accounts.yml +97 -0
- data/spec/fixtures/vcr_cassettes/friend_list_next_page.yml +121 -0
- data/spec/integration/graph_collection_spec.rb +24 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/custom_matchers.rb +28 -0
- data/spec/support/graph_api_shared_examples.rb +534 -0
- data/spec/support/koala_test.rb +251 -0
- data/spec/support/mock_http_service.rb +140 -0
- data/spec/support/uploadable_io_shared_examples.rb +70 -0
- metadata +206 -62
- data/CHANGELOG +0 -24
- data/init.rb +0 -2
- data/lib/http_services.rb +0 -60
- data/test/facebook_data.yml +0 -5
- data/test/koala/facebook_no_access_token_tests.rb +0 -119
- data/test/koala/facebook_with_access_token_tests.rb +0 -106
- data/test/koala_tests.rb +0 -30
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# small helper method for live testing
|
|
2
|
+
module KoalaTest
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
attr_accessor :oauth_token, :app_id, :secret, :app_access_token, :code, :session_key
|
|
6
|
+
attr_accessor :oauth_test_data, :subscription_test_data, :search_time
|
|
7
|
+
attr_accessor :test_user_api
|
|
8
|
+
attr_accessor :vcr_oauth_token
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Test setup
|
|
12
|
+
|
|
13
|
+
def self.setup_test_environment!
|
|
14
|
+
setup_rspec
|
|
15
|
+
|
|
16
|
+
if live?
|
|
17
|
+
# Runs Koala specs through the Facebook servers
|
|
18
|
+
# using data for a real app
|
|
19
|
+
live_data = YAML.load_file(File.join(File.dirname(__FILE__), '../fixtures/facebook_data.yml'))
|
|
20
|
+
KoalaTest.setup_test_data(live_data)
|
|
21
|
+
|
|
22
|
+
activate_adapter!
|
|
23
|
+
|
|
24
|
+
Koala.http_service.http_options[:beta] = true if ENV["beta"] || ENV["BETA"]
|
|
25
|
+
|
|
26
|
+
# use a test user unless the developer wants to test against a real profile
|
|
27
|
+
unless token = KoalaTest.oauth_token
|
|
28
|
+
KoalaTest.setup_test_users
|
|
29
|
+
else
|
|
30
|
+
KoalaTest.validate_user_info(token)
|
|
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)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.setup_rspec
|
|
47
|
+
# set up a global before block to set the token for tests
|
|
48
|
+
# set the token up for
|
|
49
|
+
RSpec.configure do |config|
|
|
50
|
+
config.before :each do
|
|
51
|
+
@token = KoalaTest.oauth_token
|
|
52
|
+
allow(Koala::Utils).to receive(:deprecate) # never fire deprecation warnings
|
|
53
|
+
# Clean up Koala config
|
|
54
|
+
Koala.reset_config
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
config.after :each do
|
|
58
|
+
# if we're working with a real user, clean up any objects posted to Facebook
|
|
59
|
+
# no need to do so for test users, since they get deleted at the end
|
|
60
|
+
if @temporary_object_id && KoalaTest.real_user?
|
|
61
|
+
raise "Unable to locate API when passed temporary object to delete!" unless @api
|
|
62
|
+
|
|
63
|
+
# wait 10ms to allow Facebook to propagate data so we can delete it
|
|
64
|
+
sleep(0.01)
|
|
65
|
+
|
|
66
|
+
# clean up any objects we've posted
|
|
67
|
+
result = (@api.delete_object(@temporary_object_id) rescue false)
|
|
68
|
+
# if we errored out or Facebook returned false, track that
|
|
69
|
+
puts "Unable to delete #{@temporary_object_id}: #{result} (probably a photo or video, which can't be deleted through the API)" unless result
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
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
|
+
|
|
98
|
+
def self.setup_test_data(data)
|
|
99
|
+
# make data accessible to all our tests
|
|
100
|
+
self.oauth_test_data = data["oauth_test_data"]
|
|
101
|
+
self.subscription_test_data = data["subscription_test_data"]
|
|
102
|
+
self.oauth_token = data["oauth_token"]
|
|
103
|
+
self.app_id = data["oauth_test_data"]["app_id"].to_s
|
|
104
|
+
self.app_access_token = data["oauth_test_data"]["app_access_token"]
|
|
105
|
+
self.secret = data["oauth_test_data"]["secret"]
|
|
106
|
+
self.code = data["oauth_test_data"]["code"]
|
|
107
|
+
self.session_key = data["oauth_test_data"]["session_key"]
|
|
108
|
+
|
|
109
|
+
# fix the search time so it can be used in the mock responses
|
|
110
|
+
self.search_time = data["search_time"] || (Time.now - 3600).to_s
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.testing_permissions
|
|
114
|
+
"read_stream, publish_actions, user_photos, user_videos, read_insights"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.setup_test_users
|
|
118
|
+
print "Setting up test users..."
|
|
119
|
+
@test_user_api = Koala::Facebook::TestUsers.new(:app_id => self.app_id, :secret => self.secret)
|
|
120
|
+
|
|
121
|
+
RSpec.configure do |config|
|
|
122
|
+
config.before :suite do
|
|
123
|
+
# before each test module, create two test users with specific names and befriend them
|
|
124
|
+
KoalaTest.create_test_users
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
config.after :suite do
|
|
128
|
+
# after each test module, delete the test users to avoid cluttering up the application
|
|
129
|
+
KoalaTest.destroy_test_users
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
puts "done."
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.create_test_users
|
|
137
|
+
begin
|
|
138
|
+
@live_testing_user = @test_user_api.create(true, KoalaTest.testing_permissions, :name => KoalaTest.user1_name)
|
|
139
|
+
@live_testing_friend = @test_user_api.create(true, KoalaTest.testing_permissions, :name => KoalaTest.user2_name)
|
|
140
|
+
@test_user_api.befriend(@live_testing_user, @live_testing_friend)
|
|
141
|
+
self.oauth_token = @live_testing_user["access_token"]
|
|
142
|
+
rescue Exception => e
|
|
143
|
+
Kernel.warn("Problem creating test users! #{e.message}")
|
|
144
|
+
raise
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.destroy_test_users
|
|
149
|
+
[@live_testing_user, @live_testing_friend].each do |u|
|
|
150
|
+
puts "Unable to delete test user #{u.inspect}" if u && !(@test_user_api.delete(u) rescue false)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def self.validate_user_info(token)
|
|
155
|
+
print "Validating permissions for live testing..."
|
|
156
|
+
# make sure we have the necessary permissions
|
|
157
|
+
api = Koala::Facebook::API.new(token)
|
|
158
|
+
perms = api.get_connect("me", "permissions")["data"]
|
|
159
|
+
|
|
160
|
+
# live testing depends on insights calls failing
|
|
161
|
+
if perms.keys.include?("read_insights") || (perms.keys & testing_permissions) != testing_permissions
|
|
162
|
+
puts "failed!\n" # put a new line after the print above
|
|
163
|
+
raise ArgumentError, "Your access token must have #{testing_permissions.join(", ")}, and lack read_insights. You have: #{perms.inspect}"
|
|
164
|
+
end
|
|
165
|
+
puts "done!"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Info about the testing environment
|
|
169
|
+
def self.real_user?
|
|
170
|
+
!(mock_interface? || @test_user_api)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.test_user?
|
|
174
|
+
!!@test_user_api
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.mock_interface?
|
|
178
|
+
Koala.http_service == Koala::MockHTTPService
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Data for testing
|
|
182
|
+
def self.user1
|
|
183
|
+
# user ID, either numeric or username
|
|
184
|
+
test_user? ? @live_testing_user["id"] : "barackobama"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def self.user1_id
|
|
188
|
+
# numerical ID, used for FQL
|
|
189
|
+
# (otherwise the two IDs are interchangeable)
|
|
190
|
+
test_user? ? @live_testing_user["id"] : 2905623
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def self.user1_name
|
|
194
|
+
"Alex"
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def self.user2
|
|
198
|
+
# see notes for user1
|
|
199
|
+
test_user? ? @live_testing_friend["id"] : "koppel"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def self.user2_id
|
|
203
|
+
# see notes for user1
|
|
204
|
+
test_user? ? @live_testing_friend["id"] : 2901279
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def self.user2_name
|
|
208
|
+
"Luke"
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def self.page
|
|
212
|
+
"facebook"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def self.app_properties
|
|
216
|
+
mock_interface? ? {"desktop" => 0} : {"description" => "A test framework for Koala and its users. (#{rand(10000).to_i})"}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def self.live?
|
|
220
|
+
ENV['LIVE']
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def self.activate_vcr!
|
|
224
|
+
require 'vcr'
|
|
225
|
+
|
|
226
|
+
VCR.configure do |c|
|
|
227
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
|
228
|
+
c.hook_into :webmock # or :fakeweb
|
|
229
|
+
c.ignore_hosts 'codeclimate.com' # Allow test coverage to be reported
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def self.activate_adapter!
|
|
234
|
+
unless @adapter_activation_attempted
|
|
235
|
+
# allow live tests with different adapters
|
|
236
|
+
adapter = ENV['ADAPTER'] || "typhoeus" # use Typhoeus by default if available
|
|
237
|
+
begin
|
|
238
|
+
# JRuby doesn't support typhoeus on Travis
|
|
239
|
+
unless defined? JRUBY_VERSION
|
|
240
|
+
require adapter
|
|
241
|
+
require "faraday/#{adapter}"
|
|
242
|
+
Faraday.default_adapter = adapter.to_sym
|
|
243
|
+
end
|
|
244
|
+
rescue => e
|
|
245
|
+
puts "Unable to load adapter #{adapter}, using Net::HTTP. #{e.class} #{e.message}"
|
|
246
|
+
ensure
|
|
247
|
+
@adapter_activation_attempted = true
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
module Koala
|
|
5
|
+
module MockHTTPService
|
|
6
|
+
include Koala::HTTPService
|
|
7
|
+
|
|
8
|
+
# Mocks all HTTP requests for with koala_spec_with_mocks.rb
|
|
9
|
+
# Mocked values to be included in TEST_DATA used in specs
|
|
10
|
+
ACCESS_TOKEN = '*'
|
|
11
|
+
APP_ACCESS_TOKEN = "********************"
|
|
12
|
+
OAUTH_CODE = 'OAUTHCODE'
|
|
13
|
+
|
|
14
|
+
# Loads testing data
|
|
15
|
+
TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'fixtures', 'facebook_data.yml'))
|
|
16
|
+
TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
|
|
17
|
+
TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
|
|
18
|
+
TEST_DATA['search_time'] = (Time.now - 3600).to_s
|
|
19
|
+
|
|
20
|
+
# Useful in mock_facebook_responses.yml
|
|
21
|
+
OAUTH_DATA = TEST_DATA['oauth_test_data']
|
|
22
|
+
OAUTH_DATA.merge!({
|
|
23
|
+
'app_access_token' => APP_ACCESS_TOKEN,
|
|
24
|
+
'session_key' => "session_key",
|
|
25
|
+
'multiple_session_keys' => ["session_key", "session_key_2"]
|
|
26
|
+
})
|
|
27
|
+
APP_ID = OAUTH_DATA['app_id']
|
|
28
|
+
SECRET = OAUTH_DATA['secret']
|
|
29
|
+
SUBSCRIPTION_DATA = TEST_DATA["subscription_test_data"]
|
|
30
|
+
|
|
31
|
+
# Loads the mock response data via ERB to substitue values for TEST_DATA (see oauth/access_token)
|
|
32
|
+
mock_response_file_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'mock_facebook_responses.yml')
|
|
33
|
+
RESPONSES = YAML.safe_load(ERB.new(IO.read(mock_response_file_path)).result(binding), [], [], true)
|
|
34
|
+
|
|
35
|
+
def self.make_request(request)
|
|
36
|
+
if response = match_response(request.raw_path, request.raw_args, request.raw_verb, request.raw_options)
|
|
37
|
+
# create response class object
|
|
38
|
+
response_object = if response.is_a? String
|
|
39
|
+
Koala::HTTPService::Response.new(200, response, {})
|
|
40
|
+
else
|
|
41
|
+
Koala::HTTPService::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
# Raises an error message with the place in the data YML
|
|
45
|
+
# to place a mock as well as a URL to request from
|
|
46
|
+
# Facebook's servers for the actual data
|
|
47
|
+
# (Don't forget to replace ACCESS_TOKEN with a real access token)
|
|
48
|
+
data_trace = [request.raw_path, request.raw_args, request.raw_verb, request.raw_options] * ': '
|
|
49
|
+
|
|
50
|
+
args = request.raw_args == 'no_args' ? '' : "#{request.raw_args}&"
|
|
51
|
+
args += 'format=json'
|
|
52
|
+
|
|
53
|
+
raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[request.path, request.raw_args].join('?')}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
response_object
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.encode_params(*args)
|
|
60
|
+
# use HTTPService's encode_params
|
|
61
|
+
HTTPService.encode_params(*args)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
protected
|
|
65
|
+
|
|
66
|
+
# For a given query, see if our mock responses YAML has a resopnse for it.
|
|
67
|
+
def self.match_response(path, args, verb, options = {})
|
|
68
|
+
server = 'graph_api'
|
|
69
|
+
path = 'root' if path == '' || path == '/'
|
|
70
|
+
verb = (verb || 'get').to_s
|
|
71
|
+
token = args.delete('access_token')
|
|
72
|
+
with_token = (token == ACCESS_TOKEN || token == APP_ACCESS_TOKEN) ? 'with_token' : 'no_token'
|
|
73
|
+
|
|
74
|
+
if endpoint = RESPONSES[server][path]
|
|
75
|
+
# see if we have a match for the arguments
|
|
76
|
+
if arg_match = endpoint.find {|query, v| decode_query(query) == massage_args(args)}
|
|
77
|
+
# we have a match for the server/path/arguments
|
|
78
|
+
# so if it's the right verb and authentication, we're good
|
|
79
|
+
# arg_match will be [query, hash_response]
|
|
80
|
+
arg_match.last[verb][with_token]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Since we're comparing the arguments with data in a yaml file, we need to
|
|
86
|
+
# massage them slightly to get to the format we expect.
|
|
87
|
+
def self.massage_args(arguments)
|
|
88
|
+
args = arguments.inject({}) do |hash, (k, v)|
|
|
89
|
+
# ensure our args are all stringified
|
|
90
|
+
value = if v.is_a?(String)
|
|
91
|
+
should_json_decode?(v) ? JSON.parse(v) : v
|
|
92
|
+
elsif v.is_a?(Koala::HTTPService::UploadableIO)
|
|
93
|
+
# obviously there are no files in the yaml
|
|
94
|
+
"[FILE]"
|
|
95
|
+
else
|
|
96
|
+
v
|
|
97
|
+
end
|
|
98
|
+
# make sure all keys are strings
|
|
99
|
+
hash.merge(k.to_s => value)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Assume format is always JSON
|
|
103
|
+
args.delete('format')
|
|
104
|
+
|
|
105
|
+
# if there are no args, return the special keyword no_args
|
|
106
|
+
args.empty? ? "no_args" : args
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Facebook sometimes requires us to encode JSON values in an HTTP query
|
|
110
|
+
# param. This complicates test matches, since we get into JSON-encoding
|
|
111
|
+
# issues (what order keys are written into). To avoid string comparisons
|
|
112
|
+
# and the hacks required to make it work, we decode the query into a
|
|
113
|
+
# Ruby object.
|
|
114
|
+
def self.decode_query(string)
|
|
115
|
+
if string == "no_args"
|
|
116
|
+
string
|
|
117
|
+
else
|
|
118
|
+
# we can't use Faraday's decode_query because that CGI-unencodes, which
|
|
119
|
+
# will remove +'s in restriction strings
|
|
120
|
+
string.split("&").reduce({}) do |hash, component|
|
|
121
|
+
k, v = component.split("=", 2) # we only care about the first =
|
|
122
|
+
value = should_json_decode?(v) ? JSON.parse(v) : v.to_s rescue v.to_s
|
|
123
|
+
# some special-casing, unfortunate but acceptable in this testing
|
|
124
|
+
# environment
|
|
125
|
+
value = nil if value.empty?
|
|
126
|
+
value = true if value == "true"
|
|
127
|
+
value = false if value == "false"
|
|
128
|
+
hash.merge(k => value)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# We want to decode JSON because it may not be encoded in the same order
|
|
134
|
+
# all the time -- different Rubies may create a strings with equivalent
|
|
135
|
+
# content but different order. We want to compare the objects.
|
|
136
|
+
def self.should_json_decode?(v)
|
|
137
|
+
v.match(/^[\[\{]/)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
shared_examples_for "MIME::Types can't return results" do
|
|
2
|
+
{
|
|
3
|
+
"jpg" => "image/jpeg",
|
|
4
|
+
"jpeg" => "image/jpeg",
|
|
5
|
+
"png" => "image/png",
|
|
6
|
+
"gif" => "image/gif"
|
|
7
|
+
}.each_pair do |extension, mime_type|
|
|
8
|
+
it "should properly get content types for #{extension} using basic analysis" do
|
|
9
|
+
path = "filename.#{extension}"
|
|
10
|
+
if @koala_io_params[0].is_a?(File)
|
|
11
|
+
allow(@koala_io_params[0]).to receive(:path).and_return(path)
|
|
12
|
+
else
|
|
13
|
+
@koala_io_params[0] = path
|
|
14
|
+
end
|
|
15
|
+
expect(Koala::HTTPService::UploadableIO.new(*@koala_io_params).content_type).to eq(mime_type)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should get content types for #{extension} using basic analysis with file names with more than one dot" do
|
|
19
|
+
path = "file.name.#{extension}"
|
|
20
|
+
if @koala_io_params[0].is_a?(File)
|
|
21
|
+
allow(@koala_io_params[0]).to receive(:path).and_return(path)
|
|
22
|
+
else
|
|
23
|
+
@koala_io_params[0] = path
|
|
24
|
+
end
|
|
25
|
+
expect(Koala::HTTPService::UploadableIO.new(*@koala_io_params).content_type).to eq(mime_type)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "if the MIME type can't be determined" do
|
|
30
|
+
before :each do
|
|
31
|
+
path = "badfile.badextension"
|
|
32
|
+
if @koala_io_params[0].is_a?(File)
|
|
33
|
+
allow(@koala_io_params[0]).to receive(:path).and_return(path)
|
|
34
|
+
else
|
|
35
|
+
@koala_io_params[0] = path
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should throw an exception" do
|
|
40
|
+
expect { Koala::HTTPService::UploadableIO.new(*@koala_io_params) }.to raise_exception(Koala::KoalaError)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
shared_examples_for "determining a mime type" do
|
|
46
|
+
describe "if MIME::Types is available" do
|
|
47
|
+
it "should return an UploadIO with MIME::Types-determined type if the type exists" do
|
|
48
|
+
type_result = ["type"]
|
|
49
|
+
allow(Koala::MIME::Types).to receive(:type_for).and_return(type_result)
|
|
50
|
+
expect(Koala::HTTPService::UploadableIO.new(*@koala_io_params).content_type).to eq(type_result.first)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "if MIME::Types is unavailable" do
|
|
55
|
+
before :each do
|
|
56
|
+
# fake that MIME::Types doesn't exist
|
|
57
|
+
allow(Koala::MIME::Types).to receive(:type_for).and_raise(NameError)
|
|
58
|
+
end
|
|
59
|
+
it_should_behave_like "MIME::Types can't return results"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "if MIME::Types can't find the result" do
|
|
63
|
+
before :each do
|
|
64
|
+
# fake that MIME::Types doesn't exist
|
|
65
|
+
allow(Koala::MIME::Types).to receive(:type_for).and_return([])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it_should_behave_like "MIME::Types can't return results"
|
|
69
|
+
end
|
|
70
|
+
end
|