koala 1.0.0 → 1.2.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.
Files changed (54) hide show
  1. data/.autotest +12 -0
  2. data/.gitignore +3 -1
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +62 -2
  5. data/Gemfile +8 -0
  6. data/Rakefile +0 -1
  7. data/autotest/discover.rb +1 -0
  8. data/koala.gemspec +13 -14
  9. data/lib/koala/batch_operation.rb +74 -0
  10. data/lib/koala/graph_api.rb +145 -132
  11. data/lib/koala/graph_batch_api.rb +97 -0
  12. data/lib/koala/graph_collection.rb +59 -0
  13. data/lib/koala/http_service.rb +176 -0
  14. data/lib/koala/oauth.rb +191 -0
  15. data/lib/koala/realtime_updates.rb +23 -29
  16. data/lib/koala/rest_api.rb +13 -8
  17. data/lib/koala/test_users.rb +33 -17
  18. data/lib/koala/uploadable_io.rb +153 -87
  19. data/lib/koala/utils.rb +11 -0
  20. data/lib/koala/version.rb +3 -0
  21. data/lib/koala.rb +59 -217
  22. data/readme.md +92 -53
  23. data/spec/cases/{api_base_spec.rb → api_spec.rb} +31 -6
  24. data/spec/cases/error_spec.rb +32 -0
  25. data/spec/cases/graph_and_rest_api_spec.rb +12 -21
  26. data/spec/cases/graph_api_batch_spec.rb +582 -0
  27. data/spec/cases/graph_api_spec.rb +11 -14
  28. data/spec/cases/graph_collection_spec.rb +116 -0
  29. data/spec/cases/http_service_spec.rb +446 -0
  30. data/spec/cases/koala_spec.rb +54 -0
  31. data/spec/cases/oauth_spec.rb +319 -213
  32. data/spec/cases/realtime_updates_spec.rb +45 -31
  33. data/spec/cases/rest_api_spec.rb +23 -7
  34. data/spec/cases/test_users_spec.rb +123 -75
  35. data/spec/cases/uploadable_io_spec.rb +120 -37
  36. data/spec/cases/utils_spec.rb +10 -0
  37. data/spec/fixtures/cat.m4v +0 -0
  38. data/spec/fixtures/facebook_data.yml +26 -24
  39. data/spec/fixtures/mock_facebook_responses.yml +203 -78
  40. data/spec/spec_helper.rb +30 -5
  41. data/spec/support/graph_api_shared_examples.rb +149 -118
  42. data/spec/support/json_testing_fix.rb +42 -0
  43. data/spec/support/koala_test.rb +187 -0
  44. data/spec/support/mock_http_service.rb +62 -58
  45. data/spec/support/ordered_hash.rb +205 -0
  46. data/spec/support/rest_api_shared_examples.rb +139 -15
  47. data/spec/support/uploadable_io_shared_examples.rb +2 -8
  48. metadata +90 -114
  49. data/lib/koala/http_services.rb +0 -146
  50. data/spec/cases/http_services/http_service_spec.rb +0 -54
  51. data/spec/cases/http_services/net_http_service_spec.rb +0 -350
  52. data/spec/cases/http_services/typhoeus_service_spec.rb +0 -144
  53. data/spec/support/live_testing_data_helper.rb +0 -40
  54. data/spec/support/setup_mocks_or_live.rb +0 -52
@@ -3,22 +3,27 @@ require 'yaml'
3
3
 
4
4
  module Koala
5
5
  module MockHTTPService
6
- # Mocks all HTTP requests for with koala_spec_with_mocks.rb
7
- IS_MOCK = true # this lets our tests figure out if we want to stub methods
6
+ include Koala::HTTPService
7
+
8
+ # fix our specs to use ok_json, so we always get the same results from to_json
9
+ MultiJson.engine = :ok_json
8
10
 
11
+ # Mocks all HTTP requests for with koala_spec_with_mocks.rb
9
12
  # Mocked values to be included in TEST_DATA used in specs
10
13
  ACCESS_TOKEN = '*'
14
+ APP_ACCESS_TOKEN = "**"
11
15
  OAUTH_CODE = 'OAUTHCODE'
12
16
 
13
17
  # Loads testing data
14
18
  TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'fixtures', 'facebook_data.yml'))
15
19
  TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
16
20
  TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
17
-
21
+ TEST_DATA['search_time'] = (Time.now - 3600).to_s
22
+
18
23
  # Useful in mock_facebook_responses.yml
19
24
  OAUTH_DATA = TEST_DATA['oauth_test_data']
20
25
  OAUTH_DATA.merge!({
21
- 'app_access_token' => Koala::MockHTTPService::ACCESS_TOKEN,
26
+ 'app_access_token' => APP_ACCESS_TOKEN,
22
27
  'session_key' => "session_key",
23
28
  'multiple_session_keys' => ["session_key", "session_key_2"]
24
29
  })
@@ -30,66 +35,65 @@ module Koala
30
35
  mock_response_file_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'mock_facebook_responses.yml')
31
36
  RESPONSES = YAML.load(ERB.new(IO.read(mock_response_file_path)).result(binding))
32
37
 
33
- def self.included(base)
34
- base.class_eval do
35
-
36
- include Koala::HTTPService
37
-
38
- def self.make_request(path, args, verb, options = {})
39
- path = 'root' if path == '' || path == '/'
40
- verb ||= 'get'
41
- server = options[:rest_api] ? 'rest_api' : 'graph_api'
42
- with_token = args.delete('access_token') == ACCESS_TOKEN ? 'with_token' : 'no_token'
38
+ def self.make_request(path, args, verb, options = {})
39
+ path = 'root' if path == '' || path == '/'
40
+ verb ||= 'get'
41
+ server = options[:rest_api] ? 'rest_api' : 'graph_api'
42
+ token = args.delete('access_token')
43
+ with_token = (token == ACCESS_TOKEN || token == APP_ACCESS_TOKEN) ? 'with_token' : 'no_token'
43
44
 
44
- # Assume format is always JSON
45
- args.delete('format')
45
+ # Assume format is always JSON
46
+ args.delete('format')
46
47
 
47
- # Create a hash key for the arguments
48
- args = create_params_key(args)
48
+ # Create a hash key for the arguments
49
+ args = create_params_key(args)
49
50
 
50
- begin
51
- response = RESPONSES[server][path][args][verb][with_token]
52
-
53
- # Raises an error of with_token/no_token key is missing
54
- raise NoMethodError unless response
55
-
56
- # create response class object
57
- response_object = if response.is_a? String
58
- Koala::Response.new(200, response, {})
59
- else
60
- Koala::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
61
- end
62
-
63
- rescue NoMethodError
64
- # Raises an error message with the place in the data YML
65
- # to place a mock as well as a URL to request from
66
- # Facebook's servers for the actual data
67
- # (Don't forget to replace ACCESS_TOKEN with a real access token)
68
- data_trace = [server, path, args, verb, with_token] * ': '
69
-
70
- args = args == 'no_args' ? '' : "#{args}&"
71
- args += 'format=json'
72
- args += "&access_token=#{ACCESS_TOKEN}" if with_token
73
-
74
- raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[path, args].join('?')}"
75
- end
51
+ begin
52
+ response = RESPONSES[server][path][args][verb][with_token]
76
53
 
77
- response_object
78
- end
54
+ # Raises an error of with_token/no_token key is missing
55
+ raise NoMethodError unless response
79
56
 
80
- protected
81
- def self.create_params_key(params_hash)
82
- if params_hash.empty?
83
- 'no_args'
57
+ # create response class object
58
+ response_object = if response.is_a? String
59
+ Koala::Response.new(200, response, {})
84
60
  else
85
- params_hash.sort{ |a,b| a[0].to_s <=> b[0].to_s}.map do |arr|
86
- arr[1] = '[FILE]' if arr[1].kind_of?(Koala::UploadableIO)
87
- arr.join('=')
88
- end.join('&')
61
+ Koala::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
89
62
  end
90
- end
91
63
 
92
- end # class_eval
93
- end # included
64
+ rescue NoMethodError
65
+ # Raises an error message with the place in the data YML
66
+ # to place a mock as well as a URL to request from
67
+ # Facebook's servers for the actual data
68
+ # (Don't forget to replace ACCESS_TOKEN with a real access token)
69
+ data_trace = [server, path, args, verb, with_token] * ': '
70
+
71
+ args = args == 'no_args' ? '' : "#{args}&"
72
+ args += 'format=json'
73
+ args += "&access_token=#{ACCESS_TOKEN}" if with_token
74
+
75
+ raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[path, args].join('?')}"
76
+ end
77
+
78
+ response_object
79
+ end
80
+
81
+ def self.encode_params(*args)
82
+ # use HTTPService's encode_params
83
+ HTTPService.encode_params(*args)
84
+ end
85
+
86
+ protected
87
+
88
+ def self.create_params_key(params_hash)
89
+ if params_hash.empty?
90
+ 'no_args'
91
+ else
92
+ params_hash.sort{ |a,b| a[0].to_s <=> b[0].to_s}.map do |arr|
93
+ arr[1] = '[FILE]' if arr[1].kind_of?(Koala::UploadableIO)
94
+ arr.join('=')
95
+ end.join('&')
96
+ end
97
+ end
94
98
  end
95
- end
99
+ end
@@ -0,0 +1,205 @@
1
+ module KoalaTest
2
+ # directly taken from Rails 3.1's OrderedHash
3
+ # see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/ordered_hash.rb
4
+
5
+ # The order of iteration over hashes in Ruby 1.8 is undefined. For example, you do not know the
6
+ # order in which +keys+ will return keys, or +each+ yield pairs. <tt>ActiveSupport::OrderedHash</tt>
7
+ # implements a hash that preserves insertion order, as in Ruby 1.9:
8
+ #
9
+ # oh = ActiveSupport::OrderedHash.new
10
+ # oh[:a] = 1
11
+ # oh[:b] = 2
12
+ # oh.keys # => [:a, :b], this order is guaranteed
13
+ #
14
+ # <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts with other implementations.
15
+ class OrderedHash < ::Hash #:nodoc:
16
+ def to_yaml_type
17
+ "!tag:yaml.org,2002:omap"
18
+ end
19
+
20
+ def encode_with(coder)
21
+ coder.represent_seq '!omap', map { |k,v| { k => v } }
22
+ end
23
+
24
+ def to_yaml(opts = {})
25
+ if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?
26
+ return super
27
+ end
28
+
29
+ YAML.quick_emit(self, opts) do |out|
30
+ out.seq(taguri) do |seq|
31
+ each do |k, v|
32
+ seq.add(k => v)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def nested_under_indifferent_access
39
+ self
40
+ end
41
+
42
+ # Hash is ordered in Ruby 1.9!
43
+ if RUBY_VERSION < '1.9'
44
+
45
+ # In MRI the Hash class is core and written in C. In particular, methods are
46
+ # programmed with explicit C function calls and polymorphism is not honored.
47
+ #
48
+ # For example, []= is crucial in this implementation to maintain the @keys
49
+ # array but hash.c invokes rb_hash_aset() originally. This prevents method
50
+ # reuse through inheritance and forces us to reimplement stuff.
51
+ #
52
+ # For instance, we cannot use the inherited #merge! because albeit the algorithm
53
+ # itself would work, our []= is not being called at all by the C code.
54
+
55
+ def initialize(*args, &block)
56
+ super
57
+ @keys = []
58
+ end
59
+
60
+ def self.[](*args)
61
+ ordered_hash = new
62
+
63
+ if (args.length == 1 && args.first.is_a?(Array))
64
+ args.first.each do |key_value_pair|
65
+ next unless (key_value_pair.is_a?(Array))
66
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
67
+ end
68
+
69
+ return ordered_hash
70
+ end
71
+
72
+ unless (args.size % 2 == 0)
73
+ raise ArgumentError.new("odd number of arguments for Hash")
74
+ end
75
+
76
+ args.each_with_index do |val, ind|
77
+ next if (ind % 2 != 0)
78
+ ordered_hash[val] = args[ind + 1]
79
+ end
80
+
81
+ ordered_hash
82
+ end
83
+
84
+ def initialize_copy(other)
85
+ super
86
+ # make a deep copy of keys
87
+ @keys = other.keys
88
+ end
89
+
90
+ def []=(key, value)
91
+ @keys << key unless has_key?(key)
92
+ super
93
+ end
94
+
95
+ def delete(key)
96
+ if has_key? key
97
+ index = @keys.index(key)
98
+ @keys.delete_at index
99
+ end
100
+ super
101
+ end
102
+
103
+ def delete_if
104
+ super
105
+ sync_keys!
106
+ self
107
+ end
108
+
109
+ def reject!
110
+ super
111
+ sync_keys!
112
+ self
113
+ end
114
+
115
+ def reject(&block)
116
+ dup.reject!(&block)
117
+ end
118
+
119
+ def keys
120
+ @keys.dup
121
+ end
122
+
123
+ def values
124
+ @keys.collect { |key| self[key] }
125
+ end
126
+
127
+ def to_hash
128
+ self
129
+ end
130
+
131
+ def to_a
132
+ @keys.map { |key| [ key, self[key] ] }
133
+ end
134
+
135
+ def each_key
136
+ return to_enum(:each_key) unless block_given?
137
+ @keys.each { |key| yield key }
138
+ self
139
+ end
140
+
141
+ def each_value
142
+ return to_enum(:each_value) unless block_given?
143
+ @keys.each { |key| yield self[key]}
144
+ self
145
+ end
146
+
147
+ def each
148
+ return to_enum(:each) unless block_given?
149
+ @keys.each {|key| yield [key, self[key]]}
150
+ self
151
+ end
152
+
153
+ alias_method :each_pair, :each
154
+
155
+ alias_method :select, :find_all
156
+
157
+ def clear
158
+ super
159
+ @keys.clear
160
+ self
161
+ end
162
+
163
+ def shift
164
+ k = @keys.first
165
+ v = delete(k)
166
+ [k, v]
167
+ end
168
+
169
+ def merge!(other_hash)
170
+ if block_given?
171
+ other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
172
+ else
173
+ other_hash.each { |k, v| self[k] = v }
174
+ end
175
+ self
176
+ end
177
+
178
+ alias_method :update, :merge!
179
+
180
+ def merge(other_hash, &block)
181
+ dup.merge!(other_hash, &block)
182
+ end
183
+
184
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
185
+ def replace(other)
186
+ super
187
+ @keys = other.keys
188
+ self
189
+ end
190
+
191
+ def invert
192
+ OrderedHash[self.to_a.map!{|key_value_pair| key_value_pair.reverse}]
193
+ end
194
+
195
+ def inspect
196
+ "#<OrderedHash #{super}>"
197
+ end
198
+
199
+ private
200
+ def sync_keys!
201
+ @keys.delete_if {|k| !has_key?(k)}
202
+ end
203
+ end
204
+ end
205
+ end
@@ -88,6 +88,29 @@ shared_examples_for "Koala RestAPI" do
88
88
  @api.rest_call('anything', {}, options)
89
89
  end
90
90
 
91
+ it "uses get by default" do
92
+ @api.should_receive(:api).with(
93
+ anything,
94
+ anything,
95
+ "get",
96
+ anything
97
+ )
98
+
99
+ @api.rest_call('anything')
100
+ end
101
+
102
+ it "allows you to specify other http methods as the last argument" do
103
+ method = 'bar'
104
+ @api.should_receive(:api).with(
105
+ anything,
106
+ anything,
107
+ method,
108
+ anything
109
+ )
110
+
111
+ @api.rest_call('anything', {}, {}, method)
112
+ end
113
+
91
114
  it "should throw an APIError if the result hash has an error key" do
92
115
  Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error_code" => "An error occurred!"}, {}))
93
116
  lambda { @api.rest_call("koppel", {}) }.should raise_exception(Koala::Facebook::APIError)
@@ -96,8 +119,7 @@ shared_examples_for "Koala RestAPI" do
96
119
  describe "when making a FQL request" do
97
120
  it "should call fql.query method" do
98
121
  @api.should_receive(:rest_call).with(
99
- "fql.query",
100
- anything
122
+ "fql.query", anything, anything
101
123
  ).and_return(Koala::Response.new(200, "2", {}))
102
124
 
103
125
  @api.fql_query stub('query string')
@@ -107,23 +129,94 @@ shared_examples_for "Koala RestAPI" do
107
129
  query = stub('query string')
108
130
 
109
131
  @api.should_receive(:rest_call).with(
110
- anything,
111
- hash_including("query" => query)
132
+ anything, hash_including(:query => query), anything
112
133
  )
113
134
 
114
135
  @api.fql_query(query)
115
136
  end
137
+
138
+ it "should pass on any other arguments provided" do
139
+ args = {:a => 2}
140
+ @api.should_receive(:rest_call).with(anything, hash_including(args), anything)
141
+ @api.fql_query("a query", args)
142
+ end
143
+
144
+ it "should pass on any http options provided" do
145
+ opts = {:a => 2}
146
+ @api.should_receive(:rest_call).with(anything, anything, hash_including(opts))
147
+ @api.fql_query("a query", {}, opts)
148
+ end
149
+ end
150
+
151
+ describe "when making a FQL-multiquery request" do
152
+ it "should call fql.multiquery method" do
153
+ @api.should_receive(:rest_call).with(
154
+ "fql.multiquery", anything, anything
155
+ ).and_return({})
156
+
157
+ @api.fql_multiquery 'query string'
158
+ end
159
+
160
+ it "should pass a queries argument" do
161
+ queries = stub('query string')
162
+ queries_json = "some JSON"
163
+ MultiJson.stub(:encode).with(queries).and_return(queries_json)
164
+
165
+ @api.should_receive(:rest_call).with(
166
+ anything,
167
+ hash_including(:queries => queries_json),
168
+ anything
169
+ )
170
+
171
+ @api.fql_multiquery(queries)
172
+ end
173
+
174
+ it "simplifies the response format" do
175
+ raw_results = [
176
+ {"name" => "query1", "fql_result_set" => [1, 2, 3]},
177
+ {"name" => "query2", "fql_result_set" => [:a, :b, :c]}
178
+ ]
179
+ expected_results = {
180
+ "query1" => [1, 2, 3],
181
+ "query2" => [:a, :b, :c]
182
+ }
183
+
184
+ @api.stub(:rest_call).and_return(raw_results)
185
+ results = @api.fql_multiquery({:query => true})
186
+ results.should == expected_results
187
+ end
188
+
189
+ it "should pass on any other arguments provided" do
190
+ args = {:a => 2}
191
+ @api.should_receive(:rest_call).with(anything, hash_including(args), anything)
192
+ @api.fql_multiquery("a query", args)
193
+ end
194
+
195
+ it "should pass on any http options provided" do
196
+ opts = {:a => 2}
197
+ @api.should_receive(:rest_call).with(anything, anything, hash_including(opts))
198
+ @api.fql_multiquery("a query", {}, opts)
199
+ end
116
200
  end
117
201
  end
118
202
  end
119
203
 
120
-
121
204
  shared_examples_for "Koala RestAPI with an access token" do
122
205
  # FQL
123
206
  it "should be able to access public information via FQL" do
124
- result = @api.fql_query('select first_name from user where uid = 216743')
207
+ result = @api.fql_query("select first_name from user where uid = #{KoalaTest.user2_id}")
125
208
  result.size.should == 1
126
- result.first['first_name'].should == 'Chris'
209
+ result.first['first_name'].should == KoalaTest.user2_name
210
+ end
211
+
212
+ it "should be able to access public information via FQL.multiquery" do
213
+ result = @api.fql_multiquery(
214
+ :query1 => "select first_name from user where uid = #{KoalaTest.user2_id}",
215
+ :query2 => "select first_name from user where uid = #{KoalaTest.user1_id}"
216
+ )
217
+ result.size.should == 2
218
+ result["query1"].first['first_name'].should == KoalaTest.user2_name
219
+ result["query2"].first['first_name'].should == KoalaTest.user1_name
127
220
  end
128
221
 
129
222
  it "should be able to access protected information via FQL" do
@@ -131,17 +224,28 @@ shared_examples_for "Koala RestAPI with an access token" do
131
224
 
132
225
  # get the current user's ID
133
226
  # we're sneakily using the Graph API, which should be okay since it has its own tests
134
- g = Koala::Facebook::GraphAPI.new(@token)
227
+ g = Koala::Facebook::API.new(@token)
135
228
  id = g.get_object("me", :fields => "id")["id"]
136
229
 
137
230
  # now send a query about your permissions
138
231
  result = @api.fql_query("select read_stream from permissions where uid = #{id}")
139
232
 
140
233
  result.size.should == 1
141
- # we assume that you have read_stream permissions, so we can test against that
142
- # (should we keep this?)
234
+ # we've verified that you have read_stream permissions, so we can test against that
143
235
  result.first["read_stream"].should == 1
144
236
  end
237
+
238
+
239
+ it "should be able to access protected information via FQL.multiquery" do
240
+ result = @api.fql_multiquery(
241
+ :query1 => "select post_id from stream where source_id = me()",
242
+ :query2 => "select fromid from comment where post_id in (select post_id from #query1)",
243
+ :query3 => "select uid, name from user where uid in (select fromid from #query2)"
244
+ )
245
+ result.size.should == 3
246
+ result.keys.should include("query1", "query2", "query3")
247
+ end
248
+
145
249
  end
146
250
 
147
251
 
@@ -149,13 +253,33 @@ shared_examples_for "Koala RestAPI without an access token" do
149
253
  # FQL_QUERY
150
254
  describe "when making a FQL request" do
151
255
  it "should be able to access public information via FQL" do
152
- @result = @api.fql_query("select first_name from user where uid = 216743")
153
- @result.size.should == 1
154
- @result.first["first_name"].should == "Chris"
256
+ result = @api.fql_query("select first_name from user where uid = #{KoalaTest.user2_id}")
257
+ result.size.should == 1
258
+ result.first['first_name'].should == KoalaTest.user2_name
259
+ end
260
+
261
+ it "should be able to access public information via FQL.multiquery" do
262
+ result = @api.fql_multiquery(
263
+ :query1 => "select first_name from user where uid = #{KoalaTest.user2_id}",
264
+ :query2 => "select first_name from user where uid = #{KoalaTest.user1_id}"
265
+ )
266
+ result.size.should == 2
267
+ result["query1"].first['first_name'].should == KoalaTest.user2_name
268
+ result["query2"].first['first_name'].should == KoalaTest.user1_name
155
269
  end
156
270
 
157
271
  it "should not be able to access protected information via FQL" do
158
- lambda { @api.fql_query("select read_stream from permissions where uid = 216743") }.should raise_error(Koala::Facebook::APIError)
272
+ lambda { @api.fql_query("select read_stream from permissions where uid = #{KoalaTest.user2_id}") }.should raise_error(Koala::Facebook::APIError)
273
+ end
274
+
275
+ it "should not be able to access protected information via FQL.multiquery" do
276
+ lambda {
277
+ @api.fql_multiquery(
278
+ :query1 => "select post_id from stream where source_id = me()",
279
+ :query2 => "select fromid from comment where post_id in (select post_id from #query1)",
280
+ :query3 => "select uid, name from user where uid in (select fromid from #query2)"
281
+ )
282
+ }.should raise_error(Koala::Facebook::APIError)
159
283
  end
160
284
  end
161
- end
285
+ end
@@ -36,15 +36,9 @@ shared_examples_for "MIME::Types can't return results" do
36
36
  end
37
37
  end
38
38
 
39
- it "should throw an exception if the MIME type can't be determined and the HTTP service requires content type" do
40
- Koala.stub!(:multipart_requires_content_type?).and_return(true)
39
+ it "should throw an exception" do
41
40
  lambda { Koala::UploadableIO.new(*@koala_io_params) }.should raise_exception(Koala::KoalaError)
42
41
  end
43
-
44
- it "should just have @content_type == nil if the HTTP service doesn't require content type" do
45
- Koala.stub!(:multipart_requires_content_type?).and_return(false)
46
- Koala::UploadableIO.new(*@koala_io_params).content_type.should be_nil
47
- end
48
42
  end
49
43
  end
50
44
 
@@ -73,4 +67,4 @@ shared_examples_for "determining a mime type" do
73
67
 
74
68
  it_should_behave_like "MIME::Types can't return results"
75
69
  end
76
- end
70
+ end