koala 0.10.0 → 1.0.0.beta2

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 (34) hide show
  1. data/CHANGELOG +33 -7
  2. data/Manifest +8 -1
  3. data/Rakefile +4 -4
  4. data/koala.gemspec +10 -8
  5. data/lib/koala/graph_api.rb +188 -123
  6. data/lib/koala/http_services.rb +93 -17
  7. data/lib/koala/rest_api.rb +73 -6
  8. data/lib/koala/test_users.rb +18 -5
  9. data/lib/koala/uploadable_io.rb +115 -0
  10. data/lib/koala.rb +95 -72
  11. data/readme.md +18 -12
  12. data/spec/facebook_data.yml +9 -3
  13. data/spec/koala/assets/beach.jpg +0 -0
  14. data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +5 -1
  15. data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +8 -3
  16. data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +12 -61
  17. data/spec/koala/graph_api/graph_api_tests.rb +85 -0
  18. data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +167 -123
  19. data/spec/koala/http_services/http_service_tests.rb +51 -0
  20. data/spec/koala/http_services/net_http_service_tests.rb +339 -0
  21. data/spec/koala/http_services/typhoeus_service_tests.rb +162 -0
  22. data/spec/koala/live_testing_data_helper.rb +1 -1
  23. data/spec/koala/oauth/oauth_tests.rb +35 -64
  24. data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +5 -74
  25. data/spec/koala/rest_api/rest_api_tests.rb +118 -0
  26. data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +5 -3
  27. data/spec/koala/test_users/test_users_tests.rb +49 -48
  28. data/spec/koala/uploadable_io/uploadable_io_tests.rb +246 -0
  29. data/spec/koala_spec_helper.rb +30 -4
  30. data/spec/koala_spec_without_mocks.rb +3 -3
  31. data/spec/mock_facebook_responses.yml +41 -18
  32. data/spec/mock_http_service.rb +16 -3
  33. metadata +38 -8
  34. data/spec/koala/net_http_service_tests.rb +0 -186
@@ -0,0 +1,339 @@
1
+ require 'koala/http_services'
2
+ class NetHTTPServiceTests < Test::Unit::TestCase
3
+ module Bear
4
+ include Koala::NetHTTPService
5
+ end
6
+
7
+ describe "NetHTTPService module holder class Bear" do
8
+ before :each do
9
+ # reset the always_use_ssl parameter
10
+ Bear.always_use_ssl = nil
11
+ end
12
+
13
+ it "should define a make_request static module method" do
14
+ Bear.respond_to?(:make_request).should be_true
15
+ end
16
+
17
+ it "should include the Koala::HTTPService module defining common features" do
18
+ Bear.included_modules.include?(Koala::HTTPService).should be_true
19
+ end
20
+
21
+ describe "when making a request" do
22
+ before(:each) do
23
+ # Setup stubs for make_request to execute without exceptions
24
+ @mock_http_response = stub('Net::HTTPResponse', :code => 1)
25
+ @mock_body = stub('Net::HTTPResponse body')
26
+ @http_request_result = [@mock_http_response, @mock_body]
27
+
28
+ # to_ary is called in Ruby 1.9 to provide backwards compatibility
29
+ # with the response, body = http.get() syntax we use
30
+ @mock_http_response.stub!(:to_ary).and_return(@http_request_result)
31
+
32
+ @http_yield_mock = mock('Net::HTTP start yielded object')
33
+
34
+ @http_yield_mock.stub(:post).and_return(@http_request_result)
35
+ @http_yield_mock.stub(:get).and_return(@http_request_result)
36
+
37
+ @http_mock = stub('Net::HTTP object', 'use_ssl=' => true, 'verify_mode=' => true)
38
+ @http_mock.stub(:start).and_yield(@http_yield_mock)
39
+
40
+ Net::HTTP.stub(:new).and_return(@http_mock)
41
+ end
42
+
43
+ describe "the connection" do
44
+ it "should use POST if verb is not GET" do
45
+ @http_yield_mock.should_receive(:post).and_return(@mock_http_response)
46
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
47
+
48
+ Bear.make_request('anything', {}, 'anything')
49
+ end
50
+
51
+ it "should use GET if that verb is specified" do
52
+ @http_yield_mock.should_receive(:get).and_return(@mock_http_response)
53
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
54
+
55
+ Bear.make_request('anything', {}, 'get')
56
+ end
57
+
58
+ it "should add the method to the arguments if it's not get or post" do
59
+ args = {}
60
+ method = "telekenesis"
61
+ # since the arguments get encoded later, we'll test for merge!
62
+ # even though that's somewhat testing internal implementation
63
+ args.should_receive(:merge!).with(:method => method)
64
+
65
+ Bear.make_request('anything', args, method)
66
+ end
67
+ end
68
+
69
+ describe "if the request has an access token" do
70
+ before :each do
71
+ @args = {"access_token" => "123"}
72
+ end
73
+
74
+ it "should use SSL" do
75
+ @http_mock.should_receive('use_ssl=').with(true)
76
+
77
+ Bear.make_request('anything', @args, 'anything')
78
+ end
79
+
80
+ it "should set the port to 443" do
81
+ Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
82
+
83
+ Bear.make_request('anything', @args, 'anything')
84
+ end
85
+ end
86
+
87
+ describe "if always_use_ssl is true" do
88
+ before :each do
89
+ Bear.always_use_ssl = true
90
+ end
91
+
92
+ it "should use SSL" do
93
+ @http_mock.should_receive('use_ssl=').with(true)
94
+
95
+ Bear.make_request('anything', {}, 'anything')
96
+ end
97
+
98
+ it "should set the port to 443" do
99
+ Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
100
+
101
+ Bear.make_request('anything', {}, 'anything')
102
+ end
103
+ end
104
+
105
+ describe "if the use_ssl option is provided" do
106
+ it "should use SSL" do
107
+ @http_mock.should_receive('use_ssl=').with(true)
108
+
109
+ Bear.make_request('anything', {}, 'anything', :use_ssl => true)
110
+ end
111
+
112
+ it "should set the port to 443" do
113
+ Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
114
+
115
+ Bear.make_request('anything', {}, 'anything', :use_ssl => true)
116
+ end
117
+ end
118
+
119
+ describe "if there's no token and always_use_ssl isn't true" do
120
+ it "should not use SSL" do
121
+ @http_mock.should_not_receive('use_ssl=')
122
+ Bear.make_request('anything', {}, 'anything')
123
+ end
124
+
125
+ it "should not set the port" do
126
+ Net::HTTP.should_receive(:new).with(anything, nil).and_return(@http_mock)
127
+ Bear.make_request('anything', {}, 'anything')
128
+ end
129
+ end
130
+
131
+ it "should use the graph server by default" do
132
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::GRAPH_SERVER, anything).and_return(@http_mock)
133
+ Bear.make_request('anything', {}, 'anything')
134
+ end
135
+
136
+ it "should use the REST server if the :rest_api option is true" do
137
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::REST_SERVER, anything).and_return(@http_mock)
138
+ Bear.make_request('anything', {}, 'anything', :rest_api => true)
139
+ end
140
+
141
+ it "should turn off vertificate validaiton warnings" do
142
+ @http_mock.should_receive('verify_mode=').with(OpenSSL::SSL::VERIFY_NONE)
143
+
144
+ Bear.make_request('anything', {}, 'anything')
145
+ end
146
+
147
+ it "should start an HTTP connection" do
148
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
149
+ Bear.make_request('anything', {}, 'anything')
150
+ end
151
+
152
+ describe "via POST" do
153
+ it "should use Net::HTTP to make a POST request" do
154
+ @http_yield_mock.should_receive(:post).and_return(@http_request_result)
155
+
156
+ Bear.make_request('anything', {}, 'post')
157
+ end
158
+
159
+ it "should go to the specified path adding a / if it doesn't exist" do
160
+ path = mock('Path')
161
+ @http_yield_mock.should_receive(:post).with(path, anything).and_return(@http_request_result)
162
+
163
+ Bear.make_request(path, {}, 'post')
164
+ end
165
+
166
+ it "should use encoded parameters" do
167
+ args = {}
168
+ params = mock('Encoded parameters')
169
+ Bear.should_receive(:encode_params).with(args).and_return(params)
170
+
171
+ @http_yield_mock.should_receive(:post).with(anything, params).and_return(@http_request_result)
172
+
173
+ Bear.make_request('anything', args, 'post')
174
+ end
175
+
176
+ describe "with multipart/form-data" do
177
+ before(:each) do
178
+ Bear.stub(:encode_multipart_params)
179
+ Bear.stub("params_require_multipart?").and_return(true)
180
+
181
+ @multipart_request_stub = stub('Stub Multipart Request')
182
+ Net::HTTP::Post::Multipart.stub(:new).and_return(@multipart_request_stub)
183
+
184
+ @file_stub = stub('fake File', "kind_of?" => true, "path" => 'anypath.jpg')
185
+
186
+ @http_yield_mock.stub(:request).with(@multipart_request_stub).and_return(@http_request_result)
187
+ end
188
+
189
+ it "should use multipart/form-data if any parameter is a valid file hash" do
190
+ @http_yield_mock.should_receive(:request).with(@multipart_request_stub).and_return(@http_request_result)
191
+
192
+ Bear.make_request('anything', {}, 'post')
193
+ end
194
+
195
+ it "should use the given request path for the request" do
196
+ args = {"file" => @file_stub}
197
+ expected_path = 'expected/path'
198
+
199
+ Net::HTTP::Post::Multipart.should_receive(:new).with(expected_path, anything).and_return(@multipart_request_stub)
200
+
201
+ Bear.make_request(expected_path, {}, 'post')
202
+ end
203
+
204
+ it "should use multipart encoded arguments for the request" do
205
+ args = {"file" => @file_stub}
206
+ expected_params = stub('Stub Multipart Params')
207
+
208
+ Bear.should_receive(:encode_multipart_params).with(args).and_return(expected_params)
209
+ Net::HTTP::Post::Multipart.should_receive(:new).with(anything, expected_params).and_return(@multipart_request_stub)
210
+
211
+ Bear.make_request('anything', args, 'post')
212
+ end
213
+ end
214
+ end
215
+
216
+ describe "via GET" do
217
+ it "should use Net::HTTP to make a GET request" do
218
+ @http_yield_mock.should_receive(:get).and_return(@http_request_result)
219
+
220
+ Bear.make_request('anything', {}, 'get')
221
+ end
222
+
223
+ it "should use the correct path, including arguments" do
224
+ path = mock('Path')
225
+ params = mock('Encoded parameters')
226
+ args = {}
227
+
228
+ Bear.should_receive(:encode_params).with(args).and_return(params)
229
+ @http_yield_mock.should_receive(:get).with("#{path}?#{params}").and_return(@http_request_result)
230
+
231
+ Bear.make_request(path, args, 'get')
232
+ end
233
+ end
234
+
235
+ describe "the returned value" do
236
+ before(:each) do
237
+ @response = Bear.make_request('anything', {}, 'anything')
238
+ end
239
+
240
+ it "should return a Koala::Response object" do
241
+ @response.class.should == Koala::Response
242
+ end
243
+
244
+ it "should return a Koala::Response with the right status" do
245
+ @response.status.should == @mock_http_response.code
246
+ end
247
+
248
+ it "should reutrn a Koala::Response with the right body" do
249
+ @response.body.should == @mock_body
250
+ end
251
+
252
+ it "should return a Koala::Response with the Net::HTTPResponse object as headers" do
253
+ @response.headers.should == @mock_http_response
254
+ end
255
+ end # describe return value
256
+ end # describe when making a request
257
+
258
+ describe "when encoding parameters" do
259
+ it "should return an empty string if param_hash evaluates to false" do
260
+ Bear.encode_params(nil).should == ''
261
+ end
262
+
263
+ it "should convert values to JSON if the value is not a String" do
264
+ val = 'json_value'
265
+ not_a_string = 'not_a_string'
266
+ not_a_string.stub(:class).and_return('NotAString')
267
+ not_a_string.should_receive(:to_json).and_return(val)
268
+
269
+ string = "hi"
270
+
271
+ args = {
272
+ not_a_string => not_a_string,
273
+ string => string
274
+ }
275
+
276
+ result = Bear.encode_params(args)
277
+ result.split('&').find do |key_and_val|
278
+ key_and_val.match("#{not_a_string}=#{val}")
279
+ end.should be_true
280
+ end
281
+
282
+ it "should escape all values" do
283
+ args = Hash[*(1..4).map {|i| [i.to_s, "Value #{i}($"]}.flatten]
284
+
285
+ result = Bear.encode_params(args)
286
+ result.split('&').each do |key_val|
287
+ key, val = key_val.split('=')
288
+ val.should == CGI.escape(args[key])
289
+ end
290
+ end
291
+
292
+ it "should convert all keys to Strings" do
293
+ args = Hash[*(1..4).map {|i| [i, "val#{i}"]}.flatten]
294
+
295
+ result = Bear.encode_params(args)
296
+ result.split('&').each do |key_val|
297
+ key, val = key_val.split('=')
298
+ key.should == args.find{|key_val_arr| key_val_arr.last == val}.first.to_s
299
+ end
300
+ end
301
+ end
302
+
303
+ describe "when detecting if multipart posting is needed" do
304
+ it "should be true if any parameter value requires multipart post" do
305
+ koala_io = mock("Koala::IO")
306
+ koala_io.should_receive(:kind_of?).with(Koala::UploadableIO).and_return(true)
307
+
308
+ args = {
309
+ "key1" => "val",
310
+ "key2" => "val",
311
+ "key3" => koala_io,
312
+ "key4" => "val"
313
+ }
314
+
315
+ Bear.params_require_multipart?(args).should be_true
316
+ end
317
+
318
+ describe "when encoding multipart/form-data params" do
319
+ it "should replace Koala::UploadableIO values with UploadIO values" do
320
+ upload_io = UploadIO.new(__FILE__, "fake type")
321
+
322
+ uploadable_io = stub('Koala::UploadableIO')
323
+ uploadable_io.should_receive(:kind_of?).with(Koala::UploadableIO).and_return(true)
324
+ uploadable_io.should_receive(:to_upload_io).and_return(upload_io)
325
+ args = {
326
+ "not_a_file" => "not a file",
327
+ "file" => uploadable_io
328
+ }
329
+
330
+ result = Bear.encode_multipart_params(args)
331
+
332
+ result["not_a_file"] == args["not_a_file"]
333
+ result["file"] == upload_io
334
+ end
335
+ end
336
+
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,162 @@
1
+ require 'koala/http_services'
2
+ class TyphoeusServiceTests < Test::Unit::TestCase
3
+ module Bear
4
+ include Koala::TyphoeusService
5
+ end
6
+
7
+ describe "TyphoeusService module holder class Bear" do
8
+ before :each do
9
+ # reset the always_use_ssl parameter
10
+ Bear.always_use_ssl = nil
11
+ end
12
+
13
+ it "should define a make_request static module method" do
14
+ Bear.respond_to?(:make_request).should be_true
15
+ end
16
+
17
+ it "should include the Koala::HTTPService module defining common features" do
18
+ Bear.included_modules.include?(Koala::HTTPService).should be_true
19
+ end
20
+
21
+ describe "when making a request" do
22
+ before(:each) do
23
+ # Setup stubs for make_request to execute without exceptions
24
+ @mock_body = stub('Typhoeus response body')
25
+ @mock_headers_hash = stub({:value => "headers hash"})
26
+ @mock_http_response = stub(Typhoeus::Response, :code => 1, :headers_hash => @mock_headers_hash, :body => @mock_body)
27
+
28
+ # Typhoeus is an included module, so we stub methods on Bear itself
29
+ Bear.stub(:post).and_return(@mock_http_response)
30
+ Bear.stub(:get).and_return(@mock_http_response)
31
+ end
32
+
33
+ it "should use POST if verb is not GET" do
34
+ Bear.should_receive(:post).and_return(@mock_http_response)
35
+ Bear.make_request('anything', {}, 'anything')
36
+ end
37
+
38
+ it "should use GET if that verb is specified" do
39
+ Bear.should_receive(:get).and_return(@mock_http_response)
40
+ Bear.make_request('anything', {}, 'get')
41
+ end
42
+
43
+ describe "the connection" do
44
+ it "should use SSL if the request has an access token" do
45
+ Bear.should_receive(:post).with(/https\:/, anything)
46
+
47
+ Bear.make_request('anything', {"access_token" => "123"}, 'anything')
48
+ end
49
+
50
+ it "should use SSL if always_use_ssl is true, even if there's no token" do
51
+ Bear.should_receive(:post).with(/https\:/, anything)
52
+
53
+ Bear.always_use_ssl = true
54
+ Bear.make_request('anything', {}, 'anything')
55
+ end
56
+
57
+ it "should use SSL if the :use_ssl option is provided, even if there's no token" do
58
+ Bear.should_receive(:post).with(/https\:/, anything)
59
+
60
+ Bear.always_use_ssl = true
61
+ Bear.make_request('anything', {}, 'anything', :use_ssl => true)
62
+ end
63
+
64
+ it "should not use SSL if always_use_ssl is false and there's no token" do
65
+ Bear.should_receive(:post).with(/http\:/, anything)
66
+
67
+ Bear.make_request('anything', {}, 'anything')
68
+ end
69
+
70
+ it "should use the graph server by default" do
71
+ Bear.should_receive(:post).with(Regexp.new(Koala::Facebook::GRAPH_SERVER), anything)
72
+
73
+ Bear.make_request('anything', {}, 'anything')
74
+ end
75
+
76
+ it "should use the REST server if the :rest_api option is true" do
77
+ Bear.should_receive(:post).with(Regexp.new(Koala::Facebook::REST_SERVER), anything)
78
+
79
+ Bear.make_request('anything', {}, 'anything', :rest_api => true)
80
+ end
81
+ end
82
+
83
+ it "should pass the arguments to Typhoeus under the :params key" do
84
+ args = {:a => 2}
85
+ Bear.should_receive(:post).with(anything, hash_including(:params => args))
86
+
87
+ Bear.make_request('anything', args, "post")
88
+ end
89
+
90
+ it "should add the method to the arguments if the method isn't get or post" do
91
+ method = "telekenesis"
92
+ Bear.should_receive(:post).with(anything, hash_including(:params => {:method => method}))
93
+
94
+ Bear.make_request('anything', {}, method)
95
+ end
96
+
97
+ it "should pass :typhoeus_options to Typhoeus if provided" do
98
+ t_options = {:a => :b}
99
+ Bear.should_receive(:post).with(anything, hash_including(t_options))
100
+
101
+ Bear.make_request("anything", {}, "post", :typhoeus_options => t_options)
102
+ end
103
+
104
+ it "should include the path in the request" do
105
+ path = "/a/b/c/1"
106
+ Bear.should_receive(:post).with(Regexp.new(path), anything)
107
+
108
+ Bear.make_request(path, {}, "post")
109
+ end
110
+
111
+ describe "the returned value" do
112
+ before(:each) do
113
+ @response = Bear.make_request('anything', {}, 'anything')
114
+ end
115
+
116
+ it "should return a Koala::Response object" do
117
+ @response.class.should == Koala::Response
118
+ end
119
+
120
+ it "should return a Koala::Response with the right status" do
121
+ @response.status.should == @mock_http_response.code
122
+ end
123
+
124
+ it "should reutrn a Koala::Response with the right body" do
125
+ @response.body.should == @mock_body
126
+ end
127
+
128
+ it "should return a Koala::Response with the Net::HTTPResponse object as headers" do
129
+ @response.headers.should == @mock_headers_hash
130
+ end
131
+ end # describe return value
132
+ end
133
+
134
+ describe "with file upload" do
135
+ it "should include an interface to NetHTTPService called NetHTTPInterface" do
136
+ # we should be able to access it
137
+ lambda { Koala::TyphoeusService::NetHTTPInterface }.should_not raise_exception(Exception)
138
+ Koala::TyphoeusService::NetHTTPInterface.included_modules.include?(Koala::NetHTTPService).should be_true
139
+ end
140
+
141
+ it "should call the NetHTTPInterface if multipart is required" do
142
+ method = "any_method"
143
+ args = {}
144
+ verb = "get"
145
+ options = {}
146
+
147
+ Bear.stub(:params_require_multipart?).and_return(true)
148
+ Koala::TyphoeusService::NetHTTPInterface.should_receive(:make_request).with(method, args, verb, options)
149
+
150
+ Bear.make_request(method, args, verb, options)
151
+ end
152
+
153
+ # Typhoeus file uploads currently don't work
154
+ # for live tests, run the Graph API tests with Typhoues, which will run file uploads
155
+ # it "should pass any files directly on to Typhoues" do
156
+ # args = {:file => File.new(__FILE__, "r")}
157
+ # Bear.should_receive(:post).with(anything, hash_including(:params => args)).and_return(Typhoeus::Response.new)
158
+ # Bear.make_request("anything", args, :post)
159
+ # end
160
+ end
161
+ end
162
+ end
@@ -19,7 +19,7 @@ module LiveTestingDataHelper
19
19
  errors = []
20
20
 
21
21
  if count > 0
22
- print "\nCleaning up #{count} temporary #{count > 1 ? "objects" : "object"}..."
22
+ print "\nCleaning up #{count} temporary #{count > 1 ? "objects" : "object (#{@temporary_object_ids.first})"}..."
23
23
  @temporary_object_ids.each do |id|
24
24
  # get our API
25
25
  api = @api || (@test_users ? @test_users.graph_api : nil)
@@ -16,6 +16,10 @@ class FacebookOAuthTests < Test::Unit::TestCase
16
16
  @request_secret = @oauth_data["request_secret"] || @secret
17
17
  @signed_request = @oauth_data["signed_request"]
18
18
  @signed_request_result = @oauth_data["signed_request_result"]
19
+ # for signed requests (http://developers.facebook.com/docs/authentication/canvas/encryption_proposal)
20
+ @signed_params_secret = @oauth_data["signed_params_secret"] || @secret
21
+ @signed_params = @oauth_data["signed_params"]
22
+ @signed_params_result = @oauth_data["signed_params_result"]
19
23
 
20
24
  # this should expanded to cover all variables
21
25
  raise Exception, "Must supply app data to run FacebookOAuthTests!" unless @app_id && @secret && @callback_url &&
@@ -24,9 +28,9 @@ class FacebookOAuthTests < Test::Unit::TestCase
24
28
 
25
29
  @oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
26
30
 
27
- time = Time.now
28
- Time.stub!(:now).and_return(time)
29
- time.stub!(:to_i).and_return(1273363199)
31
+ @time = Time.now
32
+ Time.stub!(:now).and_return(@time)
33
+ @time.stub!(:to_i).and_return(1273363199)
30
34
  end
31
35
 
32
36
  # initialization
@@ -356,81 +360,48 @@ class FacebookOAuthTests < Test::Unit::TestCase
356
360
  @oauth = Koala::Facebook::OAuth.new(@app_id, @request_secret || @app_secret)
357
361
  end
358
362
 
359
- it "should break the request into the encoded signature and the payload" do
360
- @signed_request.should_receive(:split).with(".").and_return(["", ""])
361
- @oauth.parse_signed_request(@signed_request)
363
+ # the signed request code comes directly from Facebook
364
+ # so we only need to test at a high level that it works
365
+ # signed params refers to http://developers.facebook.com/docs/authentication/canvas
366
+ # signed request refers to http://developers.facebook.com/docs/authentication/canvas/encryption_proposal
367
+ it "should throw an error if the algorithm is unsupported" do
368
+ JSON.stub!(:parse).and_return("algorithm" => "my fun algorithm")
369
+ lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
362
370
  end
363
371
 
364
- it "should base64 URL decode the signed request" do
365
- sig = ""
366
- @signed_request.should_receive(:split).with(".").and_return([sig, "1"])
367
- @oauth.should_receive(:base64_url_decode).with(sig).and_return("4")
368
- @oauth.parse_signed_request(@signed_request)
372
+ it "should throw an error if the signature is invalid" do
373
+ OpenSSL::HMAC.stub!(:hexdigest).and_return("i'm an invalid signature")
374
+ lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
369
375
  end
370
376
 
371
- it "should base64 URL decode the signed request" do
372
- sig = @signed_request.split(".")[0]
373
- @oauth.should_receive(:base64_url_decode).with(sig).and_return(nil)
374
- @oauth.parse_signed_request(@signed_request)
375
- end
376
-
377
- it "should get the sha64 encoded payload using proper arguments from OpenSSL::HMAC" do
378
- payload = ""
379
- @signed_request.should_receive(:split).with(".").and_return(["1", payload])
380
- OpenSSL::HMAC.should_receive(:digest).with("sha256", @request_secret, payload)
381
- @oauth.parse_signed_request(@signed_request)
377
+ describe "for signed params" do
378
+ it "should work" do
379
+ @oauth.parse_signed_request(@signed_request).should == @signed_request_result
380
+ end
382
381
  end
383
382
 
384
- it "should compare the encoded payload with the signature" do
385
- sig = "2"
386
- @oauth.should_receive(:base64_url_decode).and_return(sig)
387
- encoded_payload = "1"
388
- OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return(encoded_payload)
389
- encoded_payload.should_receive(:==).with(sig)
390
- @oauth.parse_signed_request(@signed_request)
391
- end
392
-
393
- describe "if the encoded payload matches the signature" do
394
- before :each do
395
- # set it up so the sig will match the encoded payload
396
- raw_sig = ""
397
- @sig = "2"
398
- @payload = "1"
399
- @signed_request.should_receive(:split).and_return([raw_sig, @payload])
400
- @oauth.should_receive(:base64_url_decode).with(raw_sig).and_return(@sig)
401
- OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return(@sig.dup)
383
+ describe "for signed requests" do
384
+ it "should work" do
385
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
386
+ @oauth.parse_signed_request(@signed_params).should == @signed_params_result
402
387
  end
403
388
 
404
- it "should base64_url_decode the payload" do
405
- @oauth.should_receive(:base64_url_decode).with(@payload).ordered.and_return("{}")
406
- @oauth.parse_signed_request(@signed_request)
389
+ it "should throw an error if the params are too old" do
390
+ @time.stub!(:to_i).and_return(1287601988 + 4000)
391
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
392
+
393
+ lambda { @oauth.parse_signed_request(@signed_params) }.should raise_error
407
394
  end
408
395
 
409
- it "should JSON decode the payload" do
410
- result = "{}"
411
- @oauth.should_receive(:base64_url_decode).with(@payload).and_return(result)
412
- JSON.should_receive(:parse).with(result)
413
- @oauth.parse_signed_request(@signed_request)
414
- end
415
- end
416
-
417
- describe "if the encoded payload does not match the signature" do
418
- before :each do
419
- sig = ""
420
- @signed_request.should_receive(:split).and_return([sig, ""])
421
- OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return("hi")
396
+ it "should let you specify the max age for a request" do
397
+ @time.stub!(:to_i).and_return(1287601988 + 4000)
398
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @signed_params_secret || @app_secret)
399
+
400
+ lambda { @oauth.parse_signed_request(@signed_params, 4001) }.should_not raise_error
422
401
  end
423
402
 
424
- it "should return nil" do
425
- @oauth.parse_signed_request(@signed_request).should be_nil
426
- end
427
403
  end
428
404
 
429
- describe "run against data" do
430
- it "should work" do
431
- @oauth.parse_signed_request(@signed_request).should == @signed_request_result
432
- end
433
- end
434
405
  end
435
406
 
436
407
  end # describe