palidanx-koala 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,181 @@
1
+ require 'koala/http_services'
2
+
3
+ class NetHTTPServiceTests < Test::Unit::TestCase
4
+ module Bear
5
+ include Koala::NetHTTPService
6
+ end
7
+
8
+ it "should define a make_request static module method" do
9
+ Bear.respond_to?(:make_request).should be_true
10
+ end
11
+
12
+ describe "when making a request" do
13
+ before(:each) do
14
+ # Setup stubs for make_request to execute without exceptions
15
+ @mock_http_response = stub('Net::HTTPResponse', :code => 1)
16
+ @mock_body = stub('Net::HTTPResponse body')
17
+ @http_request_result = [@mock_http_response, @mock_body]
18
+
19
+ @http_yield_mock = mock('Net::HTTP start yielded object')
20
+
21
+ @http_yield_mock.stub(:post).and_return(@http_request_result)
22
+ @http_yield_mock.stub(:get).and_return(@http_request_result)
23
+
24
+ @http_mock = stub('Net::HTTP object', 'use_ssl=' => true, 'verify_mode=' => true)
25
+ @http_mock.stub(:start).and_yield(@http_yield_mock)
26
+
27
+ Net::HTTP.stub(:new).and_return(@http_mock)
28
+ end
29
+
30
+ it "should use POST if verb is not GET" do
31
+ @http_yield_mock.should_receive(:post).and_return(@mock_http_response)
32
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
33
+
34
+ Bear.make_request('anything', {}, 'anything')
35
+ end
36
+
37
+ it "should use port 443" do
38
+ Net::HTTP.should_receive(:new).with(anything, 443).and_return(@http_mock)
39
+
40
+ Bear.make_request('anything', {}, 'anything')
41
+ end
42
+
43
+ it "should use SSL" do
44
+ @http_mock.should_receive('use_ssl=').with(true)
45
+
46
+ Bear.make_request('anything', {}, 'anything')
47
+ end
48
+
49
+ it "should use the graph server by default" do
50
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::GRAPH_SERVER, anything).and_return(@http_mock)
51
+ Bear.make_request('anything', {}, 'anything')
52
+ end
53
+
54
+ it "should use the REST server if the :rest_api option is true" do
55
+ Net::HTTP.should_receive(:new).with(Koala::Facebook::REST_SERVER, anything).and_return(@http_mock)
56
+ Bear.make_request('anything', {}, 'anything', :rest_api => true)
57
+ end
58
+
59
+ it "should turn off vertificate validaiton warnings" do
60
+ @http_mock.should_receive('verify_mode=').with(OpenSSL::SSL::VERIFY_NONE)
61
+
62
+ Bear.make_request('anything', {}, 'anything')
63
+ end
64
+
65
+ it "should start an HTTP connection" do
66
+ @http_mock.should_receive(:start).and_yield(@http_yield_mock)
67
+ Bear.make_request('anything', {}, 'anything')
68
+ end
69
+
70
+ describe "via POST" do
71
+ it "should use Net::HTTP to make a POST request" do
72
+ @http_yield_mock.should_receive(:post).and_return(@http_request_result)
73
+
74
+ Bear.make_request('anything', {}, 'post')
75
+ end
76
+
77
+ it "should go to the specified path adding a / if it doesn't exist" do
78
+ path = mock('Path')
79
+ @http_yield_mock.should_receive(:post).with(path, anything).and_return(@http_request_result)
80
+
81
+ Bear.make_request(path, {}, 'post')
82
+ end
83
+
84
+ it "should use encoded parameters" do
85
+ args = {}
86
+ params = mock('Encoded parameters')
87
+ Bear.should_receive(:encode_params).with(args).and_return(params)
88
+
89
+ @http_yield_mock.should_receive(:post).with(anything, params).and_return(@http_request_result)
90
+
91
+ Bear.make_request('anything', args, 'post')
92
+ end
93
+ end
94
+
95
+ describe "via GET" do
96
+ it "should use Net::HTTP to make a GET request" do
97
+ @http_yield_mock.should_receive(:get).and_return(@http_request_result)
98
+
99
+ Bear.make_request('anything', {}, 'get')
100
+ end
101
+
102
+ it "should use the correct path, including arguments" do
103
+ path = mock('Path')
104
+ params = mock('Encoded parameters')
105
+ args = {}
106
+
107
+ Bear.should_receive(:encode_params).with(args).and_return(params)
108
+ @http_yield_mock.should_receive(:get).with("#{path}?#{params}").and_return(@http_request_result)
109
+
110
+ Bear.make_request(path, args, 'get')
111
+ end
112
+ end
113
+
114
+ describe "the returned value" do
115
+ before(:each) do
116
+ @response = Bear.make_request('anything', {}, 'anything')
117
+ end
118
+
119
+ it "should return a Koala::Response object" do
120
+ @response.class.should == Koala::Response
121
+ end
122
+
123
+ it "should return a Koala::Response with the right status" do
124
+ @response.status.should == @mock_http_response.code
125
+ end
126
+
127
+ it "should reutrn a Koala::Response with the right body" do
128
+ @response.body.should == @mock_body
129
+ end
130
+
131
+ it "should return a Koala::Response with the Net::HTTPResponse object as headers" do
132
+ @response.headers.should == @mock_http_response
133
+ end
134
+ end # describe return value
135
+ end # describe when making a request
136
+
137
+ describe "when encoding parameters" do
138
+ it "should return an empty string if param_hash evaluates to false" do
139
+ Bear.encode_params(nil).should == ''
140
+ end
141
+
142
+ it "should convert values to JSON if the value is not a String" do
143
+ val = 'json_value'
144
+ not_a_string = 'not_a_string'
145
+ not_a_string.stub(:class).and_return('NotAString')
146
+ not_a_string.should_receive(:to_json).and_return(val)
147
+
148
+ string = "hi"
149
+
150
+ args = {
151
+ not_a_string => not_a_string,
152
+ string => string
153
+ }
154
+
155
+ result = Bear.encode_params(args)
156
+ result.split('&').find do |key_and_val|
157
+ key_and_val.match("#{not_a_string}=#{val}")
158
+ end.should be_true
159
+ end
160
+
161
+ it "should escape all values" do
162
+ args = Hash[*(1..4).map {|i| [i.to_s, "Value #{i}($"]}.flatten]
163
+
164
+ result = Bear.encode_params(args)
165
+ result.split('&').each do |key_val|
166
+ key, val = key_val.split('=')
167
+ val.should == CGI.escape(args[key])
168
+ end
169
+ end
170
+
171
+ it "should convert all keys to Strings" do
172
+ args = Hash[*(1..4).map {|i| [i, "val#{i}"]}.flatten]
173
+
174
+ result = Bear.encode_params(args)
175
+ result.split('&').each do |key_val|
176
+ key, val = key_val.split('=')
177
+ key.should == args.find{|key_val_arr| key_val_arr.last == val}.first.to_s
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,440 @@
1
+ # stub the Time class to always return a time for which the valid cookie is still valid
2
+ class Time
3
+ def self.now
4
+ self
5
+ end
6
+
7
+ def self.to_i
8
+ 1273363199
9
+ end
10
+ end
11
+
12
+ class FacebookOAuthTests < Test::Unit::TestCase
13
+ describe "Koala OAuth tests" do
14
+ before :each do
15
+ # make the relevant test data easily accessible
16
+ @oauth_data = $testing_data["oauth_test_data"]
17
+ @app_id = @oauth_data["app_id"]
18
+ @secret = @oauth_data["secret"]
19
+ @code = @oauth_data["code"]
20
+ @callback_url = @oauth_data["callback_url"]
21
+ @raw_token_string = @oauth_data["raw_token_string"]
22
+ @raw_offline_access_token_string = @oauth_data["raw_offline_access_token_string"]
23
+
24
+ # per Facebook's example:
25
+ # http://developers.facebook.com/docs/authentication/canvas
26
+ # this allows us to use Facebook's example data while running the other live data
27
+ @request_secret = @oauth_data["request_secret"] || @secret
28
+ @signed_request = @oauth_data["signed_request"]
29
+ @signed_request_result = @oauth_data["signed_request_result"]
30
+
31
+ # this should expanded to cover all variables
32
+ raise Exception, "Must supply app data to run FacebookOAuthTests!" unless @app_id && @secret && @callback_url &&
33
+ @code && @raw_token_string &&
34
+ @raw_offline_access_token_string
35
+
36
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret, @callback_url)
37
+ end
38
+
39
+ # initialization
40
+ it "should properly initialize" do
41
+ @oauth.should
42
+ end
43
+
44
+ it "should properly set attributes" do
45
+ (@oauth.app_id == @app_id &&
46
+ @oauth.app_secret == @secret &&
47
+ @oauth.oauth_callback_url == @callback_url).should be_true
48
+ end
49
+
50
+ it "should properly initialize without a callback_url" do
51
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
52
+ end
53
+
54
+ it "should properly set attributes without a callback URL" do
55
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @secret)
56
+ (@oauth.app_id == @app_id &&
57
+ @oauth.app_secret == @secret &&
58
+ @oauth.oauth_callback_url == nil).should be_true
59
+ end
60
+
61
+ describe "for cookie parsing" do
62
+ describe "get_user_info_from_cookies" do
63
+ it "should properly parse valid cookies" do
64
+ result = @oauth.get_user_info_from_cookies(@oauth_data["valid_cookies"])
65
+ result.should be_a(Hash)
66
+ end
67
+
68
+ it "should return all the cookie components from valid cookie string" do
69
+ cookie_data = @oauth_data["valid_cookies"]
70
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
71
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
72
+ parsing_results.length.should == number_of_components
73
+ end
74
+
75
+ it "should properly parse valid offline access cookies (e.g. no expiration)" do
76
+ result = @oauth.get_user_info_from_cookies(@oauth_data["offline_access_cookies"])
77
+ result["uid"].should
78
+ end
79
+
80
+ it "should return all the cookie components from offline access cookies" do
81
+ cookie_data = @oauth_data["offline_access_cookies"]
82
+ parsing_results = @oauth.get_user_info_from_cookies(cookie_data)
83
+ number_of_components = cookie_data["fbs_#{@app_id.to_s}"].scan(/\=/).length
84
+ parsing_results.length.should == number_of_components
85
+ end
86
+
87
+ it "shouldn't parse expired cookies" do
88
+ result = @oauth.get_user_info_from_cookies(@oauth_data["expired_cookies"])
89
+ result.should be_nil
90
+ end
91
+
92
+ it "shouldn't parse invalid cookies" do
93
+ # make an invalid string by replacing some values
94
+ bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
95
+ result = @oauth.get_user_info_from_cookies(bad_cookie_hash)
96
+ result.should be_nil
97
+ end
98
+ end
99
+
100
+ describe "get_user_from_cookies" do
101
+ it "should use get_user_info_from_cookies to parse the cookies" do
102
+ data = @oauth_data["valid_cookies"]
103
+ @oauth.should_receive(:get_user_info_from_cookies).with(data).and_return({})
104
+ @oauth.get_user_from_cookies(data)
105
+ end
106
+
107
+ it "should use return a string if the cookies are valid" do
108
+ result = @oauth.get_user_from_cookies(@oauth_data["valid_cookies"])
109
+ result.should be_a(String)
110
+ end
111
+
112
+ it "should return nil if the cookies are invalid" do
113
+ # make an invalid string by replacing some values
114
+ bad_cookie_hash = @oauth_data["valid_cookies"].inject({}) { |hash, value| hash[value[0]] = value[1].gsub(/[0-9]/, "3") }
115
+ result = @oauth.get_user_from_cookies(bad_cookie_hash)
116
+ result.should be_nil
117
+ end
118
+ end
119
+ end
120
+
121
+ # OAuth URLs
122
+
123
+ describe "for URL generation" do
124
+
125
+ describe "for OAuth codes" do
126
+ # url_for_oauth_code
127
+ it "should generate a properly formatted OAuth code URL with the default values" do
128
+ url = @oauth.url_for_oauth_code
129
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}"
130
+ end
131
+
132
+ it "should generate a properly formatted OAuth code URL when a callback is given" do
133
+ callback = "foo.com"
134
+ url = @oauth.url_for_oauth_code(:callback => callback)
135
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}"
136
+ end
137
+
138
+ it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
139
+ permissions = "publish_stream,read_stream"
140
+ url = @oauth.url_for_oauth_code(:permissions => permissions)
141
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions}"
142
+ end
143
+
144
+ it "should generate a properly formatted OAuth code URL when permissions are requested as a string" do
145
+ permissions = ["publish_stream", "read_stream"]
146
+ url = @oauth.url_for_oauth_code(:permissions => permissions)
147
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{@callback_url}&scope=#{permissions.join(",")}"
148
+ end
149
+
150
+ it "should generate a properly formatted OAuth code URL when both permissions and callback are provided" do
151
+ permissions = "publish_stream,read_stream"
152
+ callback = "foo.com"
153
+ url = @oauth.url_for_oauth_code(:callback => callback, :permissions => permissions)
154
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}&scope=#{permissions}"
155
+ end
156
+
157
+ it "should raise an exception if no callback is given in initialization or the call" do
158
+ oauth2 = Koala::Facebook::OAuth.new(@app_id, @secret)
159
+ lambda { oauth2.url_for_oauth_code }.should raise_error(ArgumentError)
160
+ end
161
+ end
162
+
163
+ describe "for access token URLs" do
164
+
165
+ # url_for_access_token
166
+ it "should generate a properly formatted OAuth token URL when provided a code" do
167
+ url = @oauth.url_for_access_token(@code)
168
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{@callback_url}&client_secret=#{@secret}&code=#{@code}"
169
+ end
170
+
171
+ it "should generate a properly formatted OAuth token URL when provided a callback" do
172
+ callback = "foo.com"
173
+ url = @oauth.url_for_access_token(@code, :callback => callback)
174
+ url.should == "https://#{Koala::Facebook::GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@secret}&code=#{@code}"
175
+ end
176
+ end
177
+ end
178
+
179
+ describe "for fetching access tokens" do
180
+ describe "get_access_token_info" do
181
+ it "should properly get and parse an access token token results into a hash" do
182
+ result = @oauth.get_access_token_info(@code)
183
+ result.should be_a(Hash)
184
+ end
185
+
186
+ it "should properly include the access token results" do
187
+ result = @oauth.get_access_token_info(@code)
188
+ result["access_token"].should
189
+ end
190
+
191
+ it "should raise an error when get_access_token is called with a bad code" do
192
+ lambda { @oauth.get_access_token_info("foo") }.should raise_error(Koala::Facebook::APIError)
193
+ end
194
+ end
195
+
196
+ describe "get_access_token" do
197
+ it "should use get_access_token_info to get and parse an access token token results" do
198
+ result = @oauth.get_access_token(@code)
199
+ result.should be_a(String)
200
+ end
201
+
202
+ it "should return the access token as a string" do
203
+ result = @oauth.get_access_token(@code)
204
+ original = @oauth.get_access_token_info(@code)
205
+ result.should == original["access_token"]
206
+ end
207
+
208
+ it "should raise an error when get_access_token is called with a bad code" do
209
+ lambda { @oauth.get_access_token("foo") }.should raise_error(Koala::Facebook::APIError)
210
+ end
211
+ end
212
+
213
+ describe "get_app_access_token_info" do
214
+ it "should properly get and parse an app's access token as a hash" do
215
+ result = @oauth.get_app_access_token_info
216
+ result.should be_a(Hash)
217
+ end
218
+
219
+ it "should include the access token" do
220
+ result = @oauth.get_app_access_token_info
221
+ result["access_token"].should
222
+ end
223
+ end
224
+
225
+ describe "get_app_acess_token" do
226
+ it "should use get_access_token_info to get and parse an access token token results" do
227
+ result = @oauth.get_app_access_token
228
+ result.should be_a(String)
229
+ end
230
+
231
+ it "should return the access token as a string" do
232
+ result = @oauth.get_app_access_token
233
+ original = @oauth.get_app_access_token_info
234
+ result.should == original["access_token"]
235
+ end
236
+ end
237
+
238
+ describe "protected methods" do
239
+
240
+ # protected methods
241
+ # since these are pretty fundamental and pretty testable, we want to test them
242
+
243
+ # parse_access_token
244
+ it "should properly parse access token results" do
245
+ result = @oauth.send(:parse_access_token, @raw_token_string)
246
+ has_both_parts = result["access_token"] && result["expires"]
247
+ has_both_parts.should
248
+ end
249
+
250
+ it "should properly parse offline access token results" do
251
+ result = @oauth.send(:parse_access_token, @raw_offline_access_token_string)
252
+ has_both_parts = result["access_token"] && !result["expires"]
253
+ has_both_parts.should
254
+ end
255
+
256
+ # fetch_token_string
257
+ # somewhat duplicative with the tests for get_access_token and get_app_access_token
258
+ # but no harm in thoroughness
259
+ it "should fetch a proper token string from Facebook when given a code" do
260
+ result = @oauth.send(:fetch_token_string, :code => @code, :redirect_uri => @callback_url)
261
+ result.should =~ /^access_token/
262
+ end
263
+
264
+ it "should fetch a proper token string from Facebook when asked for the app token" do
265
+ result = @oauth.send(:fetch_token_string, {:type => 'client_cred'}, true)
266
+ result.should =~ /^access_token/
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "for exchanging session keys" do
272
+ describe "with get_token_info_from_session_keys" do
273
+ it "should get an array of session keys from Facebook when passed a single key" do
274
+ result = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
275
+ result.should be_an(Array)
276
+ result.length.should == 1
277
+ end
278
+
279
+ it "should get an array of session keys from Facebook when passed multiple keys" do
280
+ result = @oauth.get_tokens_from_session_keys(@oauth_data["multiple_session_keys"])
281
+ result.should be_an(Array)
282
+ result.length.should == 2
283
+ end
284
+
285
+ it "should return the original hashes" do
286
+ result = @oauth.get_token_info_from_session_keys(@oauth_data["multiple_session_keys"])
287
+ result[0].should be_a(Hash)
288
+ end
289
+
290
+ it "should properly handle invalid session keys" do
291
+ result = @oauth.get_token_info_from_session_keys(["foo", "bar"])
292
+ #it should return nil for each of the invalid ones
293
+ result.each {|r| r.should be_nil}
294
+ end
295
+
296
+ it "should properly handle a mix of valid and invalid session keys" do
297
+ result = @oauth.get_token_info_from_session_keys(["foo"].concat(@oauth_data["multiple_session_keys"]))
298
+ # it should return nil for each of the invalid ones
299
+ result.each_with_index {|r, index| index > 0 ? r.should(be_a(Hash)) : r.should(be_nil)}
300
+ end
301
+ end
302
+
303
+ describe "with get_tokens_from_session_keys" do
304
+ it "should call get_token_info_from_session_keys" do
305
+ args = @oauth_data["multiple_session_keys"]
306
+ @oauth.should_receive(:get_token_info_from_session_keys).with(args).and_return([])
307
+ @oauth.get_tokens_from_session_keys(args)
308
+ end
309
+
310
+ it "should return an array of strings" do
311
+ args = @oauth_data["multiple_session_keys"]
312
+ result = @oauth.get_tokens_from_session_keys(args)
313
+ result.each {|r| r.should be_a(String) }
314
+ end
315
+
316
+ it "should properly handle invalid session keys" do
317
+ result = @oauth.get_tokens_from_session_keys(["foo", "bar"])
318
+ # it should return nil for each of the invalid ones
319
+ result.each {|r| r.should be_nil}
320
+ end
321
+
322
+ it "should properly handle a mix of valid and invalid session keys" do
323
+ result = @oauth.get_tokens_from_session_keys(["foo"].concat(@oauth_data["multiple_session_keys"]))
324
+ # it should return nil for each of the invalid ones
325
+ result.each_with_index {|r, index| index > 0 ? r.should(be_a(String)) : r.should(be_nil)}
326
+ end
327
+ end
328
+
329
+ describe "get_token_from_session_key" do
330
+ it "should call get_tokens_from_session_keys when the get_token_from_session_key is called" do
331
+ key = @oauth_data["session_key"]
332
+ @oauth.should_receive(:get_tokens_from_session_keys).with([key]).and_return([])
333
+ @oauth.get_token_from_session_key(key)
334
+ end
335
+
336
+ it "should get back the access token string from get_token_from_session_key" do
337
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
338
+ result.should be_a(String)
339
+ end
340
+
341
+ it "should be the first value in the array" do
342
+ result = @oauth.get_token_from_session_key(@oauth_data["session_key"])
343
+ array = @oauth.get_tokens_from_session_keys([@oauth_data["session_key"]])
344
+ result.should == array[0]
345
+ end
346
+
347
+ it "should properly handle an invalid session key" do
348
+ result = @oauth.get_token_from_session_key("foo")
349
+ result.should be_nil
350
+ end
351
+ end
352
+ end
353
+
354
+ describe "for parsing signed requests" do
355
+ before :each do
356
+ # you can test against live data by updating the YML, or you can use the default data
357
+ # which tests against Facebook's example on http://developers.facebook.com/docs/authentication/canvas
358
+ @oauth = Koala::Facebook::OAuth.new(@app_id, @request_secret || @app_secret)
359
+ end
360
+
361
+ it "should break the request into the encoded signature and the payload" do
362
+ @signed_request.should_receive(:split).with(".").and_return(["", ""])
363
+ @oauth.parse_signed_request(@signed_request)
364
+ end
365
+
366
+ it "should base64 URL decode the signed request" do
367
+ sig = ""
368
+ @signed_request.should_receive(:split).with(".").and_return([sig, "1"])
369
+ @oauth.should_receive(:base64_url_decode).with(sig).and_return("4")
370
+ @oauth.parse_signed_request(@signed_request)
371
+ end
372
+
373
+ it "should base64 URL decode the signed request" do
374
+ sig = @signed_request.split(".")[0]
375
+ @oauth.should_receive(:base64_url_decode).with(sig).and_return(nil)
376
+ @oauth.parse_signed_request(@signed_request)
377
+ end
378
+
379
+ it "should get the sha64 encoded payload using proper arguments from OpenSSL::HMAC" do
380
+ payload = ""
381
+ @signed_request.should_receive(:split).with(".").and_return(["1", payload])
382
+ OpenSSL::HMAC.should_receive(:digest).with("sha256", @request_secret, payload)
383
+ @oauth.parse_signed_request(@signed_request)
384
+ end
385
+
386
+ it "should compare the encoded payload with the signature" do
387
+ sig = "2"
388
+ @oauth.should_receive(:base64_url_decode).and_return(sig)
389
+ encoded_payload = "1"
390
+ OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return(encoded_payload)
391
+ encoded_payload.should_receive(:==).with(sig)
392
+ @oauth.parse_signed_request(@signed_request)
393
+ end
394
+
395
+ describe "if the encoded payload matches the signature" do
396
+ before :each do
397
+ # set it up so the sig will match the encoded payload
398
+ raw_sig = ""
399
+ @sig = "2"
400
+ @payload = "1"
401
+ @signed_request.should_receive(:split).and_return([raw_sig, @payload])
402
+ @oauth.should_receive(:base64_url_decode).with(raw_sig).and_return(@sig)
403
+ OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return(@sig.dup)
404
+ end
405
+
406
+ it "should base64_url_decode the payload" do
407
+ @oauth.should_receive(:base64_url_decode).with(@payload).ordered.and_return("{}")
408
+ @oauth.parse_signed_request(@signed_request)
409
+ end
410
+
411
+ it "should JSON decode the payload" do
412
+ result = "{}"
413
+ @oauth.should_receive(:base64_url_decode).with(@payload).and_return(result)
414
+ JSON.should_receive(:parse).with(result)
415
+ @oauth.parse_signed_request(@signed_request)
416
+ end
417
+ end
418
+
419
+ describe "if the encoded payload does not match the signature" do
420
+ before :each do
421
+ sig = ""
422
+ @signed_request.should_receive(:split).and_return([sig, ""])
423
+ OpenSSL::HMAC.should_receive(:digest).with(anything, anything, anything).and_return("hi")
424
+ end
425
+
426
+ it "should return nil" do
427
+ @oauth.parse_signed_request(@signed_request).should be_nil
428
+ end
429
+ end
430
+
431
+ describe "run against data" do
432
+ it "should work" do
433
+ @oauth.parse_signed_request(@signed_request).should == @signed_request_result
434
+ end
435
+ end
436
+ end
437
+
438
+ end # describe
439
+
440
+ end #class