koala 0.9.0 → 1.0.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 (66) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +47 -7
  3. data/Gemfile +3 -0
  4. data/LICENSE +1 -1
  5. data/Manifest +10 -15
  6. data/Rakefile +13 -13
  7. data/koala.gemspec +36 -16
  8. data/lib/koala/graph_api.rb +188 -123
  9. data/lib/koala/http_services.rb +93 -18
  10. data/lib/koala/rest_api.rb +73 -6
  11. data/lib/koala/test_users.rb +85 -0
  12. data/lib/koala/uploadable_io.rb +115 -0
  13. data/lib/koala.rb +114 -116
  14. data/readme.md +32 -18
  15. data/spec/cases/api_base_spec.rb +101 -0
  16. data/spec/cases/graph_and_rest_api_spec.rb +31 -0
  17. data/spec/cases/graph_api_spec.rb +25 -0
  18. data/spec/cases/http_services/http_service_spec.rb +54 -0
  19. data/spec/cases/http_services/net_http_service_spec.rb +350 -0
  20. data/spec/cases/http_services/typhoeus_service_spec.rb +144 -0
  21. data/spec/cases/oauth_spec.rb +409 -0
  22. data/spec/cases/realtime_updates_spec.rb +184 -0
  23. data/spec/cases/rest_api_spec.rb +25 -0
  24. data/spec/cases/test_users_spec.rb +221 -0
  25. data/spec/cases/uploadable_io_spec.rb +151 -0
  26. data/spec/fixtures/beach.jpg +0 -0
  27. data/spec/{facebook_data.yml → fixtures/facebook_data.yml} +18 -14
  28. data/spec/{mock_facebook_responses.yml → fixtures/mock_facebook_responses.yml} +314 -241
  29. data/spec/spec_helper.rb +18 -0
  30. data/spec/support/graph_api_shared_examples.rb +424 -0
  31. data/spec/support/live_testing_data_helper.rb +40 -0
  32. data/spec/{mock_http_service.rb → support/mock_http_service.rb} +94 -80
  33. data/spec/support/rest_api_shared_examples.rb +161 -0
  34. data/spec/support/setup_mocks_or_live.rb +52 -0
  35. data/spec/support/uploadable_io_shared_examples.rb +76 -0
  36. metadata +140 -55
  37. data/examples/oauth_playground/Capfile +0 -2
  38. data/examples/oauth_playground/LICENSE +0 -22
  39. data/examples/oauth_playground/Rakefile +0 -4
  40. data/examples/oauth_playground/config/deploy.rb +0 -39
  41. data/examples/oauth_playground/config/facebook.yml +0 -13
  42. data/examples/oauth_playground/config.ru +0 -27
  43. data/examples/oauth_playground/lib/load_facebook.rb +0 -3
  44. data/examples/oauth_playground/lib/oauth_playground.rb +0 -187
  45. data/examples/oauth_playground/readme.md +0 -8
  46. data/examples/oauth_playground/spec/oauth_playground_spec.rb +0 -35
  47. data/examples/oauth_playground/spec/spec_helper.rb +0 -36
  48. data/examples/oauth_playground/tmp/restart.txt +0 -0
  49. data/examples/oauth_playground/views/index.erb +0 -206
  50. data/examples/oauth_playground/views/layout.erb +0 -39
  51. data/init.rb +0 -2
  52. data/spec/koala/api_base_tests.rb +0 -95
  53. data/spec/koala/graph_and_rest_api/graph_and_rest_api_no_token_tests.rb +0 -10
  54. data/spec/koala/graph_and_rest_api/graph_and_rest_api_with_token_tests.rb +0 -11
  55. data/spec/koala/graph_api/graph_api_no_access_token_tests.rb +0 -114
  56. data/spec/koala/graph_api/graph_api_with_access_token_tests.rb +0 -150
  57. data/spec/koala/graph_api/graph_collection_tests.rb +0 -104
  58. data/spec/koala/live_testing_data_helper.rb +0 -15
  59. data/spec/koala/net_http_service_tests.rb +0 -181
  60. data/spec/koala/oauth/oauth_tests.rb +0 -440
  61. data/spec/koala/realtime_updates/realtime_updates_tests.rb +0 -187
  62. data/spec/koala/rest_api/rest_api_no_access_token_tests.rb +0 -94
  63. data/spec/koala/rest_api/rest_api_with_access_token_tests.rb +0 -36
  64. data/spec/koala_spec.rb +0 -18
  65. data/spec/koala_spec_helper.rb +0 -31
  66. data/spec/koala_spec_without_mocks.rb +0 -19
@@ -0,0 +1,424 @@
1
+ shared_examples_for "Koala GraphAPI" do
2
+ # all Graph API instances should pass these tests, regardless of configuration
3
+
4
+ # API
5
+ it "should never use the rest api server" do
6
+ Koala.should_receive(:make_request).with(
7
+ anything,
8
+ anything,
9
+ anything,
10
+ hash_not_including(:rest_api => true)
11
+ ).and_return(Koala::Response.new(200, "", {}))
12
+
13
+ @api.api("anything")
14
+ end
15
+
16
+ # GRAPH CALL
17
+ describe "graph_call" do
18
+ it "should pass all arguments to the api method" do
19
+ args = ["koppel", {}, "get", {:a => :b}]
20
+
21
+ @api.should_receive(:api).with(*args)
22
+
23
+ @api.graph_call(*args)
24
+ end
25
+
26
+ it "should throw an APIError if the result hash has an error key" do
27
+ Koala.stub(:make_request).and_return(Koala::Response.new(500, {"error" => "An error occurred!"}, {}))
28
+ lambda { @api.graph_call("koppel", {}) }.should raise_exception(Koala::Facebook::APIError)
29
+ end
30
+ end
31
+
32
+ # SEARCH
33
+ it "should be able to search" do
34
+ result = @api.search("facebook")
35
+ result.length.should be_an(Integer)
36
+ end
37
+
38
+ # DATA
39
+ # access public info
40
+
41
+ # get_object
42
+ it "should get public data about a user" do
43
+ result = @api.get_object("koppel")
44
+ # the results should have an ID and a name, among other things
45
+ (result["id"] && result["name"]).should_not be_nil
46
+ end
47
+
48
+ it "should get public data about a Page" do
49
+ result = @api.get_object("contextoptional")
50
+ # the results should have an ID and a name, among other things
51
+ (result["id"] && result["name"]).should
52
+ end
53
+
54
+ it "should be able to get multiple objects" do
55
+ results = @api.get_objects(["contextoptional", "naitik"])
56
+ results.length.should == 2
57
+ end
58
+
59
+ it "should be able to access a user's picture" do
60
+ @api.get_picture("chris.baclig").should =~ /http[s]*\:\/\//
61
+ end
62
+
63
+ it "should be able to access a user's picture, given a picture type" do
64
+ @api.get_picture("lukeshepard", {:type => 'large'}).should =~ /^http[s]*\:\/\//
65
+ end
66
+
67
+ it "should be able to access connections from public Pages" do
68
+ result = @api.get_connections("contextoptional", "photos")
69
+ result.should be_a(Array)
70
+ end
71
+
72
+ # SEARCH
73
+ it "should be able to search" do
74
+ result = @api.search("facebook")
75
+ result.length.should be_an(Integer)
76
+ end
77
+
78
+ # PAGING THROUGH COLLECTIONS
79
+ # see also graph_collection_tests
80
+ it "should make a request for a page when provided a specific set of page params" do
81
+ query = [1, 2]
82
+ @api.should_receive(:graph_call).with(*query)
83
+ @api.get_page(query)
84
+ end
85
+ end
86
+
87
+
88
+ shared_examples_for "Koala GraphAPI with an access token" do
89
+
90
+ it "should get private data about a user" do
91
+ result = @api.get_object("koppel")
92
+ # updated_time should be a pretty fixed test case
93
+ result["updated_time"].should_not be_nil
94
+ end
95
+
96
+ it "should get data about 'me'" do
97
+ result = @api.get_object("me")
98
+ result["updated_time"].should
99
+ end
100
+
101
+ it "should be able to get multiple objects" do
102
+ result = @api.get_objects(["contextoptional", "naitik"])
103
+ result.length.should == 2
104
+ end
105
+ it "should be able to access connections from users" do
106
+ result = @api.get_connections("lukeshepard", "likes")
107
+ result.length.should > 0
108
+ end
109
+
110
+ # PUT
111
+ it "should be able to write an object to the graph" do
112
+ result = @api.put_wall_post("Hello, world, from the test suite!")
113
+ @temporary_object_id = result["id"]
114
+ @temporary_object_id.should_not be_nil
115
+ end
116
+
117
+ # DELETE
118
+ it "should be able to delete posts" do
119
+ result = @api.put_wall_post("Hello, world, from the test suite delete method!")
120
+ object_id_to_delete = result["id"]
121
+ delete_result = @api.delete_object(object_id_to_delete)
122
+ delete_result.should == true
123
+ end
124
+
125
+ it "should be able to delete likes" do
126
+ result = @api.put_wall_post("Hello, world, from the test suite delete method!")
127
+ @temporary_object_id = result["id"]
128
+ @api.put_like(@temporary_object_id)
129
+ delete_like_result = @api.delete_like(@temporary_object_id)
130
+ delete_like_result.should == true
131
+ end
132
+
133
+ # additional put tests
134
+ it "should be able to verify messages posted to a wall" do
135
+ message = "the cats are asleep"
136
+ put_result = @api.put_wall_post(message)
137
+ @temporary_object_id = put_result["id"]
138
+ get_result = @api.get_object(@temporary_object_id)
139
+
140
+ # make sure the message we sent is the message that got posted
141
+ get_result["message"].should == message
142
+ end
143
+
144
+ it "should be able to post a message with an attachment to a feed" do
145
+ result = @api.put_wall_post("Hello, world, from the test suite again!", {:name => "OAuth Playground", :link => "http://oauth.twoalex.com/"})
146
+ @temporary_object_id = result["id"]
147
+ @temporary_object_id.should_not be_nil
148
+ end
149
+
150
+ it "should be able to post photos to the user's wall with an open file object" do
151
+ content_type = "image/jpg"
152
+ file = File.open(File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg"))
153
+
154
+ result = @api.put_picture(file, content_type)
155
+ @temporary_object_id = result["id"]
156
+ @temporary_object_id.should_not be_nil
157
+ end
158
+
159
+ it "should be able to post photos to the user's wall without an open file object" do
160
+ content_type = "image/jpg",
161
+ file_path = File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg")
162
+
163
+ result = @api.put_picture(file_path, content_type)
164
+ @temporary_object_id = result["id"]
165
+ @temporary_object_id.should_not be_nil
166
+ end
167
+
168
+ it "should be able to verify a photo posted to a user's wall" do
169
+ content_type = "image/jpg",
170
+ file_path = File.join(File.dirname(__FILE__), "..", "fixtures", "beach.jpg")
171
+
172
+ expected_message = "This is the test message"
173
+
174
+ result = @api.put_picture(file_path, content_type, :message => expected_message)
175
+ @temporary_object_id = result["id"]
176
+ @temporary_object_id.should_not be_nil
177
+
178
+ get_result = @api.get_object(@temporary_object_id)
179
+ get_result["name"].should == expected_message
180
+ end
181
+
182
+ it "should be able to verify a message with an attachment posted to a feed" do
183
+ attachment = {"name" => "OAuth Playground", "link" => "http://oauth.twoalex.com/"}
184
+ result = @api.put_wall_post("Hello, world, from the test suite again!", attachment)
185
+ @temporary_object_id = result["id"]
186
+ get_result = @api.get_object(@temporary_object_id)
187
+
188
+ # make sure the result we fetch includes all the parameters we sent
189
+ it_matches = attachment.inject(true) {|valid, param| valid && (get_result[param[0]] == attachment[param[0]])}
190
+ it_matches.should == true
191
+ end
192
+
193
+ it "should be able to comment on an object" do
194
+ result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
195
+ @temporary_object_id = result["id"]
196
+
197
+ # this will be deleted when the post gets deleted
198
+ comment_result = @api.put_comment(@temporary_object_id, "it's my comment!")
199
+ comment_result.should_not be_nil
200
+ end
201
+
202
+ it "should be able to verify a comment posted about an object" do
203
+ message_text = "Hello, world, from the test suite, testing comments!"
204
+ result = @api.put_wall_post(message_text)
205
+ @temporary_object_id = result["id"]
206
+
207
+ # this will be deleted when the post gets deleted
208
+ comment_text = "it's my comment!"
209
+ comment_result = @api.put_comment(@temporary_object_id, comment_text)
210
+ get_result = @api.get_object(comment_result["id"])
211
+
212
+ # make sure the text of the comment matches what we sent
213
+ get_result["message"].should == comment_text
214
+ end
215
+
216
+ it "should be able to like an object" do
217
+ result = @api.put_wall_post("Hello, world, from the test suite, testing comments!")
218
+ @temporary_object_id = result["id"]
219
+ like_result = @api.put_like(@temporary_object_id)
220
+ like_result.should be_true
221
+ end
222
+
223
+
224
+ # test all methods to make sure they pass data through to the API
225
+ # we run the tests here (rather than in the common shared example group)
226
+ # since some require access tokens
227
+ describe "HTTP options" do
228
+ # Each of the below methods should take an options hash as their last argument
229
+ # ideally we'd use introspection to determine how many arguments a method has
230
+ # but some methods require specially formatted arguments for processing
231
+ # (and anyway, Ruby 1.8's arity method fails (for this) for methods w/ 2+ optional arguments)
232
+ # (Ruby 1.9's parameters method is perfect, but only in 1.9)
233
+ # so we have to double-document
234
+ {
235
+ :get_object => 3, :put_object => 4, :delete_object => 2,
236
+ :get_connections => 4, :put_connections => 4, :delete_connections => 4,
237
+ :put_wall_post => 4,
238
+ :put_comment => 3,
239
+ :put_like => 2, :delete_like => 2,
240
+ :search => 3,
241
+ # methods that have special arguments
242
+ :put_picture => ["x.jpg", "image/jpg", {}, "me"],
243
+ :get_objects => [["x"], {}]
244
+ }.each_pair do |method_name, params|
245
+ it "should pass http options through for #{method_name}" do
246
+ options = {:a => 2}
247
+ # graph call should ultimately receive options as the fourth argument
248
+ @api.should_receive(:graph_call).with(anything, anything, anything, options)
249
+
250
+ # if we supply args, use them (since some methods process params)
251
+ # the method should receive as args n-1 anythings and then options
252
+ args = (params.is_a?(Integer) ? ([{}] * (params - 1)) : params) + [options]
253
+
254
+ @api.send(method_name, *args)
255
+ end
256
+ end
257
+
258
+ # also test get_picture, which merges a parameter into options
259
+ it "should pass http options through for get_picture" do
260
+ options = {:a => 2}
261
+ # graph call should ultimately receive options as the fourth argument
262
+ @api.should_receive(:graph_call).with(anything, anything, anything, hash_including(options)).and_return({})
263
+ @api.send(:get_picture, "x", {}, options)
264
+ end
265
+ end
266
+ end
267
+
268
+
269
+ # GraphCollection
270
+ shared_examples_for "Koala GraphAPI with GraphCollection" do
271
+
272
+ it "should create an array-like object" do
273
+ call = @api.graph_call("contextoptional/photos")
274
+ Koala::Facebook::GraphCollection.new(call, @api).should be_an(Array)
275
+ end
276
+
277
+ describe "when getting a collection" do
278
+ # GraphCollection methods
279
+ it "should get a GraphCollection when getting connections" do
280
+ @result = @api.get_connections("contextoptional", "photos")
281
+ @result.should be_a(Koala::Facebook::GraphCollection)
282
+ end
283
+
284
+ it "should return nil if the get_collections call fails with nil" do
285
+ # this happens sometimes
286
+ @api.should_receive(:graph_call).and_return(nil)
287
+ @api.get_connections("contextoptional", "photos").should be_nil
288
+ end
289
+
290
+ it "should get a GraphCollection when searching" do
291
+ result = @api.search("facebook")
292
+ result.should be_a(Koala::Facebook::GraphCollection)
293
+ end
294
+
295
+ it "should return nil if the search call fails with nil" do
296
+ # this happens sometimes
297
+ @api.should_receive(:graph_call).and_return(nil)
298
+ @api.search("facebook").should be_nil
299
+ end
300
+
301
+ it "should get a GraphCollection when paging through results" do
302
+ @results = @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=>"2010-09-23T21:17:33+0000"}])
303
+ @results.should be_a(Koala::Facebook::GraphCollection)
304
+ end
305
+
306
+ it "should return nil if the page call fails with nil" do
307
+ # this happens sometimes
308
+ @api.should_receive(:graph_call).and_return(nil)
309
+ @api.get_page(["search", {"q"=>"facebook", "limit"=>"25", "until"=>"2010-09-23T21:17:33+0000"}]).should be_nil
310
+ end
311
+
312
+ # GraphCollection attributes
313
+ describe "the GraphCollection" do
314
+ before(:each) do
315
+ @result = @api.get_connections("contextoptional", "photos")
316
+ end
317
+
318
+ it "should have a read-only paging attribute" do
319
+ lambda { @result.paging }.should_not raise_error
320
+ lambda { @result.paging = "paging" }.should raise_error(NoMethodError)
321
+ end
322
+
323
+ describe "when getting a whole page" do
324
+ before(:each) do
325
+ @second_page = stub("page of Fb graph results")
326
+ @base = stub("base")
327
+ @args = stub("args")
328
+ @page_of_results = stub("page of results")
329
+ end
330
+
331
+ it "should return the previous page of results" do
332
+ @result.should_receive(:previous_page_params).and_return([@base, @args])
333
+ @api.should_receive(:graph_call).with(@base, @args).and_return(@second_page)
334
+ Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
335
+
336
+ @result.previous_page.should == @page_of_results
337
+ end
338
+
339
+ it "should return the next page of results" do
340
+ @result.should_receive(:next_page_params).and_return([@base, @args])
341
+ @api.should_receive(:graph_call).with(@base, @args).and_return(@second_page)
342
+ Koala::Facebook::GraphCollection.should_receive(:new).with(@second_page, @api).and_return(@page_of_results)
343
+
344
+ @result.next_page.should == @page_of_results
345
+ end
346
+
347
+ it "should return nil it there are no other pages" do
348
+ %w{next previous}.each do |this|
349
+ @result.should_receive("#{this}_page_params".to_sym).and_return(nil)
350
+ @result.send("#{this}_page").should == nil
351
+ end
352
+ end
353
+ end
354
+
355
+ describe "when parsing page paramters" do
356
+ before(:each) do
357
+ @graph_collection = Koala::Facebook::GraphCollection.new({"data" => []}, Koala::Facebook::GraphAPI.new)
358
+ end
359
+
360
+ it "should return the base as the first array entry" do
361
+ base = "url_path"
362
+ @graph_collection.parse_page_url("anything.com/#{base}?anything").first.should == base
363
+ end
364
+
365
+ it "should return the arguments as a hash as the last array entry" do
366
+ args_hash = {"one" => "val_one", "two" => "val_two"}
367
+ @graph_collection.parse_page_url("anything.com/anything?#{args_hash.map {|k,v| "#{k}=#{v}" }.join("&")}").last.should == args_hash
368
+ end
369
+ end
370
+ end
371
+ end
372
+ end
373
+
374
+
375
+ shared_examples_for "Koala GraphAPI without an access token" do
376
+
377
+ it "should not get private data about a user" do
378
+ result = @api.get_object("koppel")
379
+ # updated_time should be a pretty fixed test case
380
+ result["updated_time"].should be_nil
381
+ end
382
+
383
+ it "should not be able to get data about 'me'" do
384
+ lambda { @api.get_object("me") }.should raise_error(Koala::Facebook::APIError)
385
+ end
386
+
387
+ it "shouldn't be able to access connections from users" do
388
+ lambda { @api.get_connections("lukeshepard", "likes") }.should raise_error(Koala::Facebook::APIError)
389
+ end
390
+
391
+ it "should not be able to put an object" do
392
+ lambda { @result = @api.put_object("lukeshepard", "feed", :message => "Hello, world") }.should raise_error(Koala::Facebook::APIError)
393
+ puts "Error! Object #{@result.inspect} somehow put onto Luke Shepard's wall!" if @result
394
+ end
395
+
396
+ # these are not strictly necessary as the other put methods resolve to put_object, but are here for completeness
397
+ it "should not be able to post to a feed" do
398
+ (lambda do
399
+ attachment = {:name => "OAuth Playground", :link => "http://oauth.twoalex.com/"}
400
+ @result = @api.put_wall_post("Hello, world", attachment, "contextoptional")
401
+ end).should raise_error(Koala::Facebook::APIError)
402
+ puts "Error! Object #{@result.inspect} somehow put onto Context Optional's wall!" if @result
403
+ end
404
+
405
+ it "should not be able to comment on an object" do
406
+ # random public post on the ContextOptional wall
407
+ lambda { @result = @api.put_comment("7204941866_119776748033392", "The hackathon was great!") }.should raise_error(Koala::Facebook::APIError)
408
+ puts "Error! Object #{@result.inspect} somehow commented on post 7204941866_119776748033392!" if @result
409
+ end
410
+
411
+ it "should not be able to like an object" do
412
+ lambda { @api.put_like("7204941866_119776748033392") }.should raise_error(Koala::Facebook::APIError)
413
+ end
414
+
415
+ # DELETE
416
+ it "should not be able to delete posts" do
417
+ # test post on the Ruby SDK Test application
418
+ lambda { @result = @api.delete_object("115349521819193_113815981982767") }.should raise_error(Koala::Facebook::APIError)
419
+ end
420
+
421
+ it "should not be able to delete a like" do
422
+ lambda { @api.delete_like("7204941866_119776748033392") }.should raise_error(Koala::Facebook::APIError)
423
+ end
424
+ end
@@ -0,0 +1,40 @@
1
+ module LiveTestingDataHelper
2
+ # in RSpec 2, included example groups no longer share any hooks or state with outside examples
3
+ # even if in the same block
4
+ # so we have to use a module to provide setup and teardown hooks for live testing
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ before :each do
9
+ @token = $testing_data["oauth_token"]
10
+ raise Exception, "Must supply access token to run FacebookWithAccessTokenTests!" unless @token
11
+ # track temporary objects created
12
+ @temporary_object_ids = []
13
+ end
14
+
15
+ after :each do
16
+ # clean up any temporary objects
17
+ @temporary_object_ids << @temporary_object_id if @temporary_object_id
18
+ count = @temporary_object_ids.length
19
+ errors = []
20
+
21
+ if count > 0
22
+ @temporary_object_ids.each do |id|
23
+ # get our API
24
+ api = @api || (@test_users ? @test_users.graph_api : nil)
25
+ raise "Unable to locate API when passed temporary object to delete!" unless api
26
+
27
+ # delete the object
28
+ result = (api.delete_object(id) rescue false)
29
+ # if we errored out or Facebook returned false, track that
30
+ errors << id unless result
31
+ end
32
+
33
+ unless errors.length == 0
34
+ puts "cleaned up #{count - errors.length} objects, but errored out on the following:\n #{errors.join(", ")}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,81 +1,95 @@
1
- require 'erb'
2
- require 'yaml'
3
-
4
- module Koala
5
- module MockHTTPService
6
- # Mocks all HTTP requests for with koala_spec_with_mocks.rb
7
-
8
- # Mocked values to be included in TEST_DATA used in specs
9
- ACCESS_TOKEN = '*'
10
- OAUTH_CODE = 'OAUTHCODE'
11
-
12
- # Loads testing data
13
- TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), 'facebook_data.yml'))
14
- TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
15
- TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
16
-
17
- # Useful in mock_facebook_responses.yml
18
- OAUTH_DATA = TEST_DATA['oauth_test_data']
19
- OAUTH_DATA.merge!({
20
- 'app_access_token' => Koala::MockHTTPService::ACCESS_TOKEN,
21
- 'session_key' => "session_key",
22
- 'multiple_session_keys' => ["session_key", "session_key_2"]
23
- })
24
- APP_ID = OAUTH_DATA['app_id']
25
- SECRET = OAUTH_DATA['secret']
26
- SUBSCRIPTION_DATA = TEST_DATA["subscription_test_data"]
27
-
28
- # Loads the mock response data via ERB to substitue values for TEST_DATA (see oauth/access_token)
29
- mock_response_file_path = File.join(File.dirname(__FILE__), 'mock_facebook_responses.yml')
30
- RESPONSES = YAML.load(ERB.new(IO.read(mock_response_file_path)).result(binding))
31
-
32
- def self.included(base)
33
- base.class_eval do
34
-
35
- def self.make_request(path, args, verb, options = {})
36
- path = 'root' if path == '' || path == '/'
37
- verb ||= 'get'
38
- server = options[:rest_api] ? 'rest_api' : 'graph_api'
39
- with_token = args.delete('access_token') == ACCESS_TOKEN ? 'with_token' : 'no_token'
40
-
41
- # Assume format is always JSON
42
- args.delete('format')
43
-
44
- # Create a hash key for the arguments
45
- args = args.empty? ? 'no_args' : args.sort{|a,b| a[0].to_s <=> b[0].to_s }.map{|arr| arr.join('=')}.join('&')
46
-
47
- begin
48
- response = RESPONSES[server][path][args][verb][with_token]
49
-
50
- # Raises an error of with_token/no_token key is missing
51
- raise NoMethodError unless response
52
-
53
- # create response class object
54
- response_object = if response.is_a? String
55
- Koala::Response.new(200, response, {})
56
- else
57
- Koala::Response.new(response["code"] || 200, response["body"] || "", response["headers"] || {})
58
- end
59
-
60
- rescue NoMethodError
61
- # Raises an error message with the place in the data YML
62
- # to place a mock as well as a URL to request from
63
- # Facebook's servers for the actual data
64
- # (Don't forget to replace ACCESS_TOKEN with a real access token)
65
-
66
- data_trace = [server, path, args, verb, with_token] * ': '
67
-
68
- args = args == 'no_args' ? '' : "#{args}&"
69
- args += 'format=json'
70
- args += "&access_token=#{ACCESS_TOKEN}" if with_token
71
-
72
- raise "Missing a mock response for #{data_trace}\nAPI PATH: #{[path, args].join('?')}"
73
- end
74
-
75
- response_object
76
- end
77
-
78
- end # class_eval
79
- end # included
80
- end
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ module Koala
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
8
+
9
+ # Mocked values to be included in TEST_DATA used in specs
10
+ ACCESS_TOKEN = '*'
11
+ OAUTH_CODE = 'OAUTHCODE'
12
+
13
+ # Loads testing data
14
+ TEST_DATA = YAML.load_file(File.join(File.dirname(__FILE__), '..', 'fixtures', 'facebook_data.yml'))
15
+ TEST_DATA.merge!('oauth_token' => Koala::MockHTTPService::ACCESS_TOKEN)
16
+ TEST_DATA['oauth_test_data'].merge!('code' => Koala::MockHTTPService::OAUTH_CODE)
17
+
18
+ # Useful in mock_facebook_responses.yml
19
+ OAUTH_DATA = TEST_DATA['oauth_test_data']
20
+ OAUTH_DATA.merge!({
21
+ 'app_access_token' => Koala::MockHTTPService::ACCESS_TOKEN,
22
+ 'session_key' => "session_key",
23
+ 'multiple_session_keys' => ["session_key", "session_key_2"]
24
+ })
25
+ APP_ID = OAUTH_DATA['app_id']
26
+ SECRET = OAUTH_DATA['secret']
27
+ SUBSCRIPTION_DATA = TEST_DATA["subscription_test_data"]
28
+
29
+ # Loads the mock response data via ERB to substitue values for TEST_DATA (see oauth/access_token)
30
+ mock_response_file_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'mock_facebook_responses.yml')
31
+ RESPONSES = YAML.load(ERB.new(IO.read(mock_response_file_path)).result(binding))
32
+
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'
43
+
44
+ # Assume format is always JSON
45
+ args.delete('format')
46
+
47
+ # Create a hash key for the arguments
48
+ args = create_params_key(args)
49
+
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
76
+
77
+ response_object
78
+ end
79
+
80
+ protected
81
+ def self.create_params_key(params_hash)
82
+ if params_hash.empty?
83
+ 'no_args'
84
+ 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('&')
89
+ end
90
+ end
91
+
92
+ end # class_eval
93
+ end # included
94
+ end
81
95
  end