mwilliams-facebooker 1.0.40

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/.autotest +15 -0
  2. data/CHANGELOG.rdoc +24 -0
  3. data/COPYING.rdoc +19 -0
  4. data/Manifest.txt +133 -0
  5. data/README.rdoc +113 -0
  6. data/Rakefile +85 -0
  7. data/TODO.rdoc +4 -0
  8. data/examples/desktop_login.rb +14 -0
  9. data/facebooker.gemspec +38 -0
  10. data/generators/facebook/facebook_generator.rb +14 -0
  11. data/generators/facebook/templates/config/facebooker.yml +49 -0
  12. data/generators/facebook/templates/public/javascripts/facebooker.js +93 -0
  13. data/generators/facebook_controller/USAGE +33 -0
  14. data/generators/facebook_controller/facebook_controller_generator.rb +40 -0
  15. data/generators/facebook_controller/templates/controller.rb +7 -0
  16. data/generators/facebook_controller/templates/functional_test.rb +11 -0
  17. data/generators/facebook_controller/templates/helper.rb +2 -0
  18. data/generators/facebook_controller/templates/view.fbml.erb +2 -0
  19. data/generators/facebook_controller/templates/view.html.erb +2 -0
  20. data/generators/facebook_publisher/facebook_publisher_generator.rb +14 -0
  21. data/generators/facebook_publisher/templates/create_facebook_templates.rb +15 -0
  22. data/generators/facebook_publisher/templates/publisher.rb +3 -0
  23. data/generators/facebook_scaffold/USAGE +27 -0
  24. data/generators/facebook_scaffold/facebook_scaffold_generator.rb +118 -0
  25. data/generators/facebook_scaffold/templates/controller.rb +93 -0
  26. data/generators/facebook_scaffold/templates/facebook_style.css +2579 -0
  27. data/generators/facebook_scaffold/templates/functional_test.rb +89 -0
  28. data/generators/facebook_scaffold/templates/helper.rb +2 -0
  29. data/generators/facebook_scaffold/templates/layout.fbml.erb +6 -0
  30. data/generators/facebook_scaffold/templates/layout.html.erb +17 -0
  31. data/generators/facebook_scaffold/templates/style.css +74 -0
  32. data/generators/facebook_scaffold/templates/view_edit.fbml.erb +13 -0
  33. data/generators/facebook_scaffold/templates/view_edit.html.erb +18 -0
  34. data/generators/facebook_scaffold/templates/view_index.fbml.erb +24 -0
  35. data/generators/facebook_scaffold/templates/view_index.html.erb +24 -0
  36. data/generators/facebook_scaffold/templates/view_new.fbml.erb +12 -0
  37. data/generators/facebook_scaffold/templates/view_new.html.erb +17 -0
  38. data/generators/facebook_scaffold/templates/view_show.fbml.erb +10 -0
  39. data/generators/facebook_scaffold/templates/view_show.html.erb +10 -0
  40. data/generators/publisher/publisher_generator.rb +14 -0
  41. data/generators/xd_receiver/templates/xd_receiver.html +10 -0
  42. data/generators/xd_receiver/xd_receiver_generator.rb +10 -0
  43. data/init.rb +26 -0
  44. data/install.rb +12 -0
  45. data/lib/facebooker.rb +216 -0
  46. data/lib/facebooker/adapters/adapter_base.rb +91 -0
  47. data/lib/facebooker/adapters/bebo_adapter.rb +77 -0
  48. data/lib/facebooker/adapters/facebook_adapter.rb +52 -0
  49. data/lib/facebooker/admin.rb +42 -0
  50. data/lib/facebooker/batch_request.rb +45 -0
  51. data/lib/facebooker/data.rb +57 -0
  52. data/lib/facebooker/feed.rb +78 -0
  53. data/lib/facebooker/logging.rb +44 -0
  54. data/lib/facebooker/mobile.rb +20 -0
  55. data/lib/facebooker/mock/service.rb +50 -0
  56. data/lib/facebooker/mock/session.rb +18 -0
  57. data/lib/facebooker/model.rb +139 -0
  58. data/lib/facebooker/models/affiliation.rb +10 -0
  59. data/lib/facebooker/models/album.rb +11 -0
  60. data/lib/facebooker/models/applicationproperties.rb +39 -0
  61. data/lib/facebooker/models/applicationrestrictions.rb +10 -0
  62. data/lib/facebooker/models/cookie.rb +10 -0
  63. data/lib/facebooker/models/education_info.rb +11 -0
  64. data/lib/facebooker/models/event.rb +28 -0
  65. data/lib/facebooker/models/friend_list.rb +16 -0
  66. data/lib/facebooker/models/group.rb +36 -0
  67. data/lib/facebooker/models/info_item.rb +10 -0
  68. data/lib/facebooker/models/info_section.rb +10 -0
  69. data/lib/facebooker/models/location.rb +8 -0
  70. data/lib/facebooker/models/notifications.rb +17 -0
  71. data/lib/facebooker/models/page.rb +28 -0
  72. data/lib/facebooker/models/photo.rb +19 -0
  73. data/lib/facebooker/models/tag.rb +12 -0
  74. data/lib/facebooker/models/user.rb +516 -0
  75. data/lib/facebooker/models/video.rb +9 -0
  76. data/lib/facebooker/models/work_info.rb +10 -0
  77. data/lib/facebooker/parser.rb +674 -0
  78. data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
  79. data/lib/facebooker/rails/controller.rb +356 -0
  80. data/lib/facebooker/rails/cucumber.rb +28 -0
  81. data/lib/facebooker/rails/cucumber/world.rb +46 -0
  82. data/lib/facebooker/rails/extensions/action_controller.rb +48 -0
  83. data/lib/facebooker/rails/extensions/rack_setup.rb +6 -0
  84. data/lib/facebooker/rails/extensions/routing.rb +15 -0
  85. data/lib/facebooker/rails/facebook_form_builder.rb +112 -0
  86. data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
  87. data/lib/facebooker/rails/facebook_request_fix.rb +28 -0
  88. data/lib/facebooker/rails/facebook_request_fix_2-3.rb +31 -0
  89. data/lib/facebooker/rails/facebook_session_handling.rb +68 -0
  90. data/lib/facebooker/rails/facebook_url_helper.rb +192 -0
  91. data/lib/facebooker/rails/facebook_url_rewriting.rb +60 -0
  92. data/lib/facebooker/rails/helpers.rb +804 -0
  93. data/lib/facebooker/rails/helpers/fb_connect.rb +118 -0
  94. data/lib/facebooker/rails/integration_session.rb +38 -0
  95. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  96. data/lib/facebooker/rails/publisher.rb +550 -0
  97. data/lib/facebooker/rails/routing.rb +49 -0
  98. data/lib/facebooker/rails/test_helpers.rb +68 -0
  99. data/lib/facebooker/rails/utilities.rb +22 -0
  100. data/lib/facebooker/server_cache.rb +24 -0
  101. data/lib/facebooker/service.rb +102 -0
  102. data/lib/facebooker/session.rb +636 -0
  103. data/lib/facebooker/version.rb +9 -0
  104. data/lib/net/http_multipart_post.rb +123 -0
  105. data/lib/rack/facebook.rb +82 -0
  106. data/lib/tasks/facebooker.rake +18 -0
  107. data/lib/tasks/tunnel.rake +46 -0
  108. data/rails/init.rb +1 -0
  109. data/setup.rb +1585 -0
  110. data/templates/layout.erb +24 -0
  111. data/test/facebooker/adapters_test.rb +174 -0
  112. data/test/facebooker/admin_test.rb +102 -0
  113. data/test/facebooker/batch_request_test.rb +83 -0
  114. data/test/facebooker/data_test.rb +86 -0
  115. data/test/facebooker/logging_test.rb +43 -0
  116. data/test/facebooker/mobile_test.rb +45 -0
  117. data/test/facebooker/model_test.rb +133 -0
  118. data/test/facebooker/models/event_test.rb +15 -0
  119. data/test/facebooker/models/photo_test.rb +16 -0
  120. data/test/facebooker/models/user_test.rb +361 -0
  121. data/test/facebooker/rails/facebook_request_fix_2-3_test.rb +25 -0
  122. data/test/facebooker/rails/facebook_url_rewriting_test.rb +39 -0
  123. data/test/facebooker/rails/publisher_test.rb +481 -0
  124. data/test/facebooker/rails_integration_test.rb +1434 -0
  125. data/test/facebooker/server_cache_test.rb +44 -0
  126. data/test/facebooker/session_test.rb +652 -0
  127. data/test/facebooker_test.rb +951 -0
  128. data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
  129. data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
  130. data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
  131. data/test/net/http_multipart_post_test.rb +52 -0
  132. data/test/rack/facebook_test.rb +61 -0
  133. data/test/rails_test_helper.rb +27 -0
  134. data/test/test_helper.rb +74 -0
  135. metadata +232 -0
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class FacebookCacheTest < Test::Unit::TestCase
4
+ def setup
5
+ @session = Facebooker::Session.create('apikey', 'secretkey')
6
+ Facebooker.use_curl=false
7
+ end
8
+
9
+ def test_can_ask_facebook_to_store_fbml_in_a_named_reference
10
+ expect_http_posts_with_responses(example_set_ref_handle_xml)
11
+ assert(@session.server_cache.set_ref_handle('a_handle_name', '<h2>Some FBML</h2>'))
12
+ end
13
+
14
+ def test_can_ask_facebook_to_recache_content_stored_from_a_given_url
15
+ expect_http_posts_with_responses(example_refresh_ref_url_xml)
16
+ assert(@session.server_cache.refresh_ref_url('http://localhost/roflmao'))
17
+ end
18
+
19
+ def test_can_ask_facebook_to_recache_an_img
20
+ expect_http_posts_with_responses(example_refresh_img_xml)
21
+ assert(@session.server_cache.refresh_img_src('http://localhost/roflmao.jpg'))
22
+ end
23
+
24
+ private
25
+ def example_set_ref_handle_xml
26
+ <<-XML
27
+ <?xml version="1.0" encoding="UTF-8"?>
28
+ <fbml_setRefHandle_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">1</fbml_setRefHandle_response>
29
+ XML
30
+ end
31
+
32
+ def example_refresh_ref_url_xml
33
+ <<-XML
34
+ <?xml version="1.0" encoding="UTF-8"?>
35
+ <fbml_refreshRefUrl_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">1</fbml_refreshRefUrl_response>
36
+ XML
37
+ end
38
+ def example_refresh_img_xml
39
+ <<-XML
40
+ <?xml version="1.0" encoding="UTF-8"?>
41
+ <fbml_refreshImgSrc_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">1</fbml_refreshImgSrc_response>
42
+ XML
43
+ end
44
+ end
@@ -0,0 +1,652 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require 'active_support'
3
+
4
+ class Facebooker::SessionTest < Test::Unit::TestCase
5
+
6
+
7
+ def setup
8
+ ENV['FACEBOOK_API_KEY'] = '1234567'
9
+ ENV['FACEBOOK_SECRET_KEY'] = '7654321'
10
+ Facebooker.current_adapter = nil
11
+ @session = Facebooker::Session.create('whatever', 'doesnotmatterintest')
12
+ Facebooker.use_curl=false
13
+ end
14
+
15
+ def teardown
16
+ Facebooker::Session.configuration_file_path = nil
17
+ super
18
+ end
19
+
20
+ def test_install_url_escapes_optional_next_parameter
21
+ session = Facebooker::CanvasSession.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
22
+ assert_equal("http://www.facebook.com/install.php?api_key=1234567&v=1.0&next=next_url%3Fa%3D1%26b%3D2", session.install_url(:next => "next_url?a=1&b=2"))
23
+ end
24
+
25
+ def test_can_get_api_and_secret_key_from_environment
26
+ assert_equal('1234567', Facebooker::Session.api_key)
27
+ assert_equal('7654321', Facebooker::Session.secret_key)
28
+ end
29
+
30
+ def test_if_keys_are_not_available_via_environment_then_they_are_gotten_from_a_file
31
+ ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'] = nil
32
+ Facebooker.instance_variable_set('@facebooker_configuration', nil)
33
+ flexmock(File).should_receive(:read).with(File.expand_path("~/.facebookerrc")).once.and_return('{:api => "foo"}')
34
+ assert_equal('foo', Facebooker::Session.api_key)
35
+ end
36
+
37
+ def test_if_environment_and_file_fail_to_match_then_an_exception_is_raised
38
+ ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'] = nil
39
+ Facebooker.instance_variable_set('@facebooker_configuration', nil)
40
+ flexmock(File).should_receive(:read).with(File.expand_path("~/.facebookerrc")).once.and_return {raise Errno::ENOENT, "No such file"}
41
+ assert_raises(Facebooker::Session::ConfigurationMissing) {
42
+ Facebooker::Session.api_key
43
+ }
44
+ end
45
+
46
+ def test_marshal_stores_api_key
47
+ data = Marshal.dump(@session)
48
+ loaded_session = Marshal.load(data)
49
+ assert_equal 'whatever', loaded_session.instance_variable_get("@api_key")
50
+ end
51
+
52
+ def test_marshal_stores_secret_key
53
+ data = Marshal.dump(@session)
54
+ loaded_session = Marshal.load(data)
55
+ assert_equal 'doesnotmatterintest', loaded_session.instance_variable_get("@secret_key")
56
+ end
57
+
58
+ def test_configuration_file_path_can_be_set_explicitly
59
+ Facebooker::Session.configuration_file_path = '/tmp/foo'
60
+ assert_equal('/tmp/foo', Facebooker::Session.configuration_file_path)
61
+ end
62
+
63
+ def test_session_can_be_secured_with_existing_values
64
+ session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
65
+ session.secure_with!("a session key", "123456", Time.now.to_i + 60)
66
+ assert(session.secured?)
67
+ assert_equal 'a session key', session.session_key
68
+ assert_equal 123456, session.user.to_i
69
+ end
70
+
71
+ def test_session_can_be_secured_with_existing_values_and_a_nil_uid
72
+ flexmock(session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY']))
73
+ session.should_receive(:post).with('facebook.users.getLoggedInUser', :session_key => 'a session key').returns(321)
74
+ session.secure_with!("a session key", nil, Time.now.to_i + 60)
75
+ assert(session.secured?)
76
+ assert_equal 'a session key', session.session_key
77
+ assert_equal 321, session.user.to_i
78
+ end
79
+
80
+ # The Facebook API for this is hideous. Oh well.
81
+ def test_can_ask_session_to_check_friendship_between_pairs_of_users
82
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
83
+ mock_http = establish_session
84
+ mock_http.should_receive(:post_form).and_return(example_check_friendship_xml).once.ordered(:posts)
85
+ assert_equal({[222332, 222333] => true, [1240077, 1240079] => false}, @session.check_friendship([[222332, 222333], [1240077, 1240079]]))
86
+ end
87
+
88
+ def test_facebook_can_claim_ignorance_as_to_friend_relationships
89
+ mock_http = establish_session
90
+ mock_http.should_receive(:post_form).and_return(example_check_friendship_with_unknown_result).once.ordered(:posts)
91
+ assert_equal({[1240077, 1240079] => nil}, @session.check_friendship([[1240077, 1240079]]))
92
+ end
93
+
94
+ def test_can_query_with_fql
95
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
96
+ expect_http_posts_with_responses(example_fql_for_multiple_photos_xml)
97
+ response = @session.fql_query('Lets be frank. We are not testing the query here')
98
+ assert_kind_of(Facebooker::Photo, response.first)
99
+ end
100
+
101
+ def test_anonymous_fql_results_get_put_in_a_positioned_array_on_the_model
102
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
103
+ expect_http_posts_with_responses(example_fql_for_multiple_photos_with_anon_xml)
104
+ response = @session.fql_query('Lets be frank. We are not testing the query here')
105
+ assert_kind_of(Facebooker::Photo, response.first)
106
+ response.each do |photo|
107
+ assert_equal(['first', 'second'], photo.anonymous_fields)
108
+ end
109
+ end
110
+ def test_no_results_returns_empty_array
111
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
112
+ expect_http_posts_with_responses(no_results_fql)
113
+ response = @session.fql_query('Lets be frank. We are not testing the query here')
114
+ assert_equal [],response
115
+ end
116
+
117
+ def test_can_fql_query_for_event_members
118
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
119
+ expect_http_posts_with_responses(example_fql_query_event_members_xml)
120
+ response = @session.fql_query("DOES NOT REALLY MATTER FOR TEST")
121
+ assert_kind_of(Facebooker::Event::Attendance, response.first)
122
+ assert_equal('attending', response.first.rsvp_status)
123
+ end
124
+
125
+ def test_can_query_for_event_members
126
+ expect_http_posts_with_responses(example_event_members_xml)
127
+ event_attendances = @session.event_members(69)
128
+ assert_equal Facebooker::Event::Attendance, event_attendances.first.class
129
+ assert_equal 'attending', event_attendances.first.rsvp_status
130
+ assert_equal(["1240077", "222332", "222333", "222335", "222336"], event_attendances.map{|ea| ea.uid}.sort)
131
+ assert_equal 5, event_attendances.size
132
+ end
133
+
134
+ def test_can_query_for_events
135
+ expect_http_posts_with_responses(example_events_get_xml)
136
+ events = @session.events
137
+ assert_equal 'Technology Tasting', events.first.name
138
+ end
139
+
140
+ def test_can_query_for_groups
141
+ expect_http_posts_with_responses(example_groups_get_xml)
142
+ groups = @session.user.groups
143
+ assert_equal 'Donald Knuth Is My Homeboy', groups.first.name
144
+ end
145
+
146
+ def test_can_query_for_group_memberships
147
+ expect_http_posts_with_responses(example_group_members_xml)
148
+ example_group = Facebooker::Group.new({:gid => 123, :session => @session})
149
+ group_memberships = example_group.memberships
150
+ assert_equal('officers', group_memberships.last.position)
151
+ assert_equal(123, group_memberships.last.gid)
152
+ assert_equal(1240078, example_group.members.last.id)
153
+ end
154
+
155
+ def test_can_fql_query_for_users_and_pictures
156
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
157
+ mock_http = establish_session
158
+ mock_http.should_receive(:post_form).and_return(example_fql_for_multiple_users_and_pics).once.ordered(:posts)
159
+ response = @session.fql_query('SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660')
160
+ assert_kind_of Array, response
161
+ assert_kind_of Facebooker::User, response.first
162
+ assert_equal "Ari Steinberg", response.first.name
163
+ end
164
+
165
+ def test_can_fql_multiquery_for_users_and_pictures
166
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
167
+ mock_http = establish_session
168
+ mock_http.should_receive(:post_form).and_return(example_fql_multiquery_xml).once.ordered(:posts)
169
+ response = @session.fql_multiquery({:query => 'SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660'})
170
+ assert_kind_of Array, response["query1"]
171
+ assert_kind_of Facebooker::User, response["query1"].first
172
+ assert_equal "Ari Steinberg", response["query1"].first.name
173
+ end
174
+
175
+ def test_can_send_notification_with_object
176
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
177
+ @session.expects(:post).with('facebook.notifications.send',{:to_ids=>"1",:notification=>"a",:type=>"user_to_user"},true)
178
+ @session.send(:instance_variable_set,"@uid",3)
179
+ user=flexmock("user")
180
+ user.should_receive(:facebook_id).and_return("1").once
181
+ @session.send_notification([user],"a")
182
+ end
183
+ def test_can_send_notification_with_string
184
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
185
+ @session.send(:instance_variable_set,"@uid",3)
186
+ @session.expects(:post).with('facebook.notifications.send',{:to_ids=>"1",:notification=>"a", :type=>"user_to_user"},true)
187
+ @session.send_notification(["1"],"a")
188
+ end
189
+
190
+ def test_can_send_announcement_notification
191
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
192
+ @session.expects(:post).with('facebook.notifications.send',{:to_ids=>"1",:notification=>"a", :type=>"app_to_user"},false)
193
+ @session.send_notification(["1"],"a")
194
+ end
195
+
196
+ def test_can_register_template_bundle
197
+ expect_http_posts_with_responses(example_register_template_bundle_return_xml)
198
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
199
+ assert_equal 17876842716, @session.register_template_bundle("{*actor*} did something")
200
+ end
201
+
202
+ def test_can_register_template_bundle_with_action_links
203
+ expect_http_posts_with_responses(example_register_template_bundle_return_xml)
204
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
205
+ assert_equal 17876842716, @session.register_template_bundle("{*actor*} did something",nil,nil,[{:text=>"text",:href=>"href"}])
206
+ end
207
+ def test_can_publish_user_action
208
+ expect_http_posts_with_responses(publish_user_action_return_xml)
209
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
210
+ assert @session.publish_user_action(17876842716,{})
211
+ end
212
+
213
+ def test_logs_api_calls
214
+ call_name = 'sample.api.call'
215
+ params = { :param1 => true, :param2 => 'value' }
216
+ flexmock(Facebooker::Logging, :Logging).should_receive(:log_fb_api).once.with(
217
+ call_name, params, Proc)
218
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
219
+ @session.post(call_name, params)
220
+ end
221
+
222
+ def test_requests_inside_batch_are_added_to_batch
223
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
224
+ @session.send(:service).expects(:post).once
225
+ @session.batch do
226
+ @session.send_notification(["1"],"a")
227
+ @session.send_notification(["1"],"a")
228
+ end
229
+
230
+ end
231
+
232
+ def test_parses_batch_response
233
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
234
+ expect_http_posts_with_responses(example_batch_run_xml)
235
+ @session.batch do
236
+ @fql_response = @session.fql_query('SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660')
237
+ end
238
+ assert_kind_of(Facebooker::Event::Attendance, @fql_response.first)
239
+ assert_equal('attending', @fql_response.first.rsvp_status)
240
+ end
241
+ def test_parses_batch_response_sets_exception
242
+ @session = Facebooker::Session.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
243
+ expect_http_posts_with_responses(example_batch_run_xml)
244
+ Facebooker::FqlQuery.expects(:process).raises(NoMethodError.new)
245
+
246
+ @session.batch do
247
+ @fql_response = @session.fql_query('SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660')
248
+ end
249
+ assert_raises(NoMethodError) {
250
+ @fql_response.first
251
+ }
252
+ end
253
+
254
+ def test_can_set_and_get_current_batch
255
+ Facebooker::BatchRun.current_batch=4
256
+ assert_equal 4,Facebooker::BatchRun.current_batch
257
+ end
258
+
259
+ def test_can_get_stanard_info
260
+ expect_http_posts_with_responses(standard_info_xml)
261
+ result = @session.users_standard([4])
262
+ assert_equal "Mike Mangino",result.first.name
263
+ end
264
+
265
+ def test_can_query_for_pages
266
+ expect_http_posts_with_responses(example_pages_xml)
267
+ example_page = Facebooker::Page.new(
268
+ :page_id => 4846711747,
269
+ :name => "Kronos Quartet",
270
+ :website => "http://www.kronosquartet.org",
271
+ :company_overview => "",
272
+ :session => @session)
273
+ pages = @session.pages(:fields => %w[ page_id name website company_overview ])
274
+
275
+ assert_equal 1, pages.size
276
+
277
+ page = pages.first
278
+ assert_equal "4846711747", page.page_id
279
+ assert_equal "Kronos Quartet", page.name
280
+ assert_equal "http://www.kronosquartet.org", page.website
281
+
282
+ # TODO we really need a way to differentiate between hash/list and text attributes
283
+ # assert_equal({}, page.company_overview)
284
+
285
+ # sakkaoui : as a fix to the parser, I replace empty text node by "" instead of {}
286
+ # we have child.attributes['list'] == 'true' that let us know that we have a hash/list.
287
+ assert_equal("", page.company_overview)
288
+
289
+ genre = page.genre
290
+ assert_equal false, genre.dance
291
+ assert_equal true, genre.party
292
+ end
293
+
294
+ private
295
+
296
+ def example_fql_multiquery_xml
297
+ <<-XML
298
+ <?xml version="1.0" encoding="UTF-8"?>
299
+ <fql_multiquery_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
300
+ <fql_result>
301
+ <name>query1</name>
302
+ <results list="true">
303
+ <user>
304
+ <name>Ari Steinberg</name>
305
+ <uid>46903192</uid>
306
+ <rsvp_status xsi:nil="true"/>
307
+ </user>
308
+ </results>
309
+ </fql_result>
310
+ <fql_result>
311
+ <name>query2</name>
312
+ <results list="true">
313
+ <user>
314
+ <name>Lisa Petrovskaia</name>
315
+ <pic xsi:nil="true"/>
316
+ </user>
317
+ </results>
318
+ </fql_result>
319
+ </fql_multiquery_response>
320
+ XML
321
+ end
322
+
323
+ def example_groups_get_xml
324
+ <<-XML
325
+ <?xml version="1.0" encoding="UTF-8"?>
326
+ <groups_get_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
327
+ <group>
328
+ <gid>2206609142</gid>
329
+ <name>Donald Knuth Is My Homeboy</name>
330
+ <nid>0</nid>
331
+ <description>Donald Ervin Knuth (born January 10, 1938) is a renowned computer scientist and professor emeritus at Stanford University.
332
+
333
+ Knuth is best known as the author of the multi-volume The Art of Computer Programming, one of the most highly respected references in the computer science field. He practically created the field of rigorous analysis of algorithms, and made many seminal contributions to several branches of theoretical computer science. He is also the creator of the TeX typesetting system and of the METAFONT font design system, and pioneered the concept of literate programming.
334
+
335
+ That's how he ROLLS, y0.</description>
336
+ <group_type>Just for Fun</group_type>
337
+ <group_subtype>Fan Clubs</group_subtype>
338
+ <recent_news/>
339
+ <pic>http://photos-142.facebook.com/ip006/object/543/95/s2206609142_32530.jpg</pic>
340
+ <pic_big>http://photos-142.facebook.com/ip006/object/543/95/n2206609142_32530.jpg</pic_big>
341
+ <pic_small>http://photos-142.facebook.com/ip006/object/543/95/t2206609142_32530.jpg</pic_small>
342
+ <creator>1240077</creator>
343
+ <update_time>1156543965</update_time>
344
+ <office/>
345
+ <website/>
346
+ <venue>
347
+ <street/>
348
+ <city/>
349
+ <state>CA</state>
350
+ <country>United States</country>
351
+ </venue>
352
+ </group>
353
+ </groups_get_response>
354
+ XML
355
+ end
356
+
357
+ def example_events_get_xml
358
+ <<-XML
359
+ <?xml version="1.0" encoding="UTF-8"?>
360
+ <events_get_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
361
+ <event>
362
+ <eid>1037629024</eid>
363
+ <name>Technology Tasting</name>
364
+ <tagline>Who said Engineering can't be delicious?</tagline>
365
+ <nid>12409987</nid>
366
+ <pic>http://photos-628.facebook.com/ip006/object/1345/48/s1037629024_30775.jpg</pic>
367
+ <pic_big>http://photos-628.facebook.com/ip006/object/1345/48/n1037629024_30775.jpg</pic_big>
368
+ <pic_small>http://photos-628.facebook.com/ip006/object/1345/48/t1037629024_30775.jpg</pic_small>
369
+ <host>Facebook</host>
370
+ <description>Facebook will be hosting technology thought leaders and avid software engineers for a social evening of technology tasting. We invite you to connect with some of our newest technologies and innovative people over hors d'oeuvres and wine. Come share ideas, ask questions, and challenge existing technology paradigms in the spirit of the open source community.</description>
371
+ <event_type>Party</event_type>
372
+ <event_subtype>Cocktail Party</event_subtype>
373
+ <start_time>1172107800</start_time>
374
+ <end_time>1172115000</end_time>
375
+ <creator>1078</creator>
376
+ <update_time>1170096157</update_time>
377
+ <location>Facebook's New Office</location>
378
+ <venue>
379
+ <city>Palo Alto</city>
380
+ <state>CA</state>
381
+ <country>United States</country>
382
+ </venue>
383
+ </event>
384
+ </events_get_response>
385
+ XML
386
+ end
387
+
388
+ def example_fql_query_event_members_xml
389
+ <<-XML
390
+ <?xml version="1.0" encoding="UTF-8"?>
391
+ <fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
392
+ <event_member>
393
+ <uid>517961878</uid>
394
+ <eid>2454827764</eid>
395
+ <rsvp_status>attending</rsvp_status>
396
+ </event_member>
397
+ <event_member>
398
+ <uid>744961110</uid>
399
+ <eid>2454827764</eid>
400
+ <rsvp_status>declined</rsvp_status>
401
+ </event_member>
402
+ </fql_query_response>
403
+ XML
404
+ end
405
+ def example_check_friendship_xml
406
+ <<-XML
407
+ <?xml version="1.0" encoding="UTF-8"?>
408
+ <friends_areFriends_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
409
+ <friend_info>
410
+ <uid1>222332</uid1>
411
+ <uid2>222333</uid2>
412
+ <are_friends>1</are_friends>
413
+ </friend_info>
414
+ <friend_info>
415
+ <uid1>1240077</uid1>
416
+ <uid2>1240079</uid2>
417
+ <are_friends>0</are_friends>
418
+ </friend_info>
419
+ </friends_areFriends_response>
420
+ XML
421
+ end
422
+
423
+ def example_check_friendship_with_unknown_result
424
+ <<-XML
425
+ <?xml version="1.0" encoding="UTF-8"?>
426
+ <friends_areFriends_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
427
+ <friend_info>
428
+ <uid1>1240077</uid1>
429
+ <uid2>1240079</uid2>
430
+ <are_friends xsi:nil="true"/>
431
+ </friend_info>
432
+ </friends_areFriends_response>
433
+ XML
434
+ end
435
+
436
+ def example_fql_for_multiple_users_and_pics
437
+ <<-XML
438
+ <?xml version="1.0" encoding="UTF-8"?>
439
+ <fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
440
+ <user>
441
+ <name>Ari Steinberg</name>
442
+ <pic>http://profile.ak.facebook.com/profile2/1805/47/s211031_26434.jpg</pic>
443
+ </user>
444
+ <user>
445
+ <name>Ruchi Sanghvi</name>
446
+ <pic>http://profile.ak.facebook.com/v52/870/125/s4801660_2498.jpg</pic>
447
+ </user>
448
+ </fql_query_response>
449
+ XML
450
+ end
451
+
452
+ def example_fql_for_multiple_photos_xml
453
+ <<-XML
454
+ <?xml version="1.0" encoding="UTF-8"?>
455
+ <fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
456
+ <photo>
457
+ <src>http://photos-c.ak.facebook.com/photos-ak-sf2p/v108/212/118/22700225/s22700225_30345986_2713.jpg</src>
458
+ <caption>Nottttt. get ready for some museumz</caption>
459
+ <caption>Nottttt. get ready for some museumz</caption>
460
+ </photo>
461
+ <photo>
462
+ <src>http://photos-c.ak.facebook.com/photos-ak-sf2p/v77/74/112/22701786/s22701786_30324934_7816.jpg</src>
463
+ <caption>Rooftop barbecues make me act funny</caption>
464
+ <caption>Rooftop barbecues make me act funny</caption>
465
+ </photo>
466
+ <photo>
467
+ <src>http://photos-c.ak.facebook.com/photos-ak-sctm/v96/154/56/22700188/s22700188_30321538_17.jpg</src>
468
+ <caption>An epic shot of Patrick getting ready for a run to second.</caption>
469
+ <caption>An epic shot of Patrick getting ready for a run to second.</caption>
470
+ </photo>
471
+ </fql_query_response>
472
+ XML
473
+ end
474
+
475
+ def example_fql_for_multiple_photos_with_anon_xml
476
+ <<-XML
477
+ <?xml version="1.0" encoding="UTF-8"?>
478
+ <fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
479
+ <photo>
480
+ <src>http://photos-c.ak.facebook.com/photos-ak-sf2p/v108/212/118/22700225/s22700225_30345986_2713.jpg</src>
481
+ <caption>Nottttt. get ready for some museumz</caption>
482
+ <caption>Nottttt. get ready for some museumz</caption>
483
+ <anon>first</anon>
484
+ <anon>second</anon>
485
+ </photo>
486
+ <photo>
487
+ <src>http://photos-c.ak.facebook.com/photos-ak-sf2p/v77/74/112/22701786/s22701786_30324934_7816.jpg</src>
488
+ <caption>Rooftop barbecues make me act funny</caption>
489
+ <caption>Rooftop barbecues make me act funny</caption>
490
+ <anon>first</anon>
491
+ <anon>second</anon>
492
+ </photo>
493
+ <photo>
494
+ <src>http://photos-c.ak.facebook.com/photos-ak-sctm/v96/154/56/22700188/s22700188_30321538_17.jpg</src>
495
+ <caption>An epic shot of Patrick getting ready for a run to second.</caption>
496
+ <caption>An epic shot of Patrick getting ready for a run to second.</caption>
497
+ <anon>first</anon>
498
+ <anon>second</anon>
499
+ </photo>
500
+ </fql_query_response>
501
+ XML
502
+ end
503
+
504
+ def no_results_fql
505
+ <<-XML
506
+ <?xml version="1.0" encoding="UTF-8"?>
507
+ <fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
508
+ </fql_query_response>
509
+ XML
510
+
511
+ end
512
+
513
+ def example_group_members_xml
514
+ <<-XML
515
+ <?xml version="1.0" encoding="UTF-8"?>
516
+ <groups_getMembers_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
517
+ <members list="true">
518
+ <uid>1240077</uid>
519
+ <uid>1240078</uid>
520
+ <uid>222332</uid>
521
+ <uid>222333</uid>
522
+ </members>
523
+ <admins list="true">
524
+ <uid>1240077</uid>
525
+ <uid>222333</uid>
526
+ </admins>
527
+ <officers list="true">
528
+ <uid>1240078</uid>
529
+ </officers>
530
+ <not_replied list="true"/>
531
+ </groups_getMembers_response>
532
+ XML
533
+ end
534
+
535
+ def example_batch_run_xml
536
+ <<-XML
537
+ <?xml version="1.0" encoding="UTF-8"?>
538
+ <batch_run_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
539
+ <batch_run_response_elt>
540
+ #{CGI.escapeHTML(example_fql_query_event_members_xml)}
541
+ </batch_run_response_elt>
542
+ </batch_run_response>
543
+ XML
544
+ end
545
+
546
+ def example_event_members_xml
547
+ <<-XML
548
+ <?xml version="1.0" encoding="UTF-8"?>
549
+ <events_getMembers_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
550
+ <attending list="true">
551
+ <uid>222332</uid>
552
+ <uid>222333</uid>
553
+ </attending>
554
+ <unsure list="true">
555
+ <uid>1240077</uid>
556
+ </unsure>
557
+ <declined list="true"/>
558
+ <not_replied list="true">
559
+ <uid>222335</uid>
560
+ <uid>222336</uid>
561
+ </not_replied>
562
+ </events_getMembers_response>
563
+ XML
564
+ end
565
+
566
+ def example_register_template_bundle_return_xml
567
+ <<-XML
568
+ <?xml version="1.0" encoding="UTF-8"?>
569
+ <feed_registerTemplateBundle_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/">
570
+ 17876842716
571
+ </feed_registerTemplateBundle_response>
572
+ XML
573
+ end
574
+
575
+ def example_pages_xml
576
+ <<-XML
577
+ <?xml version="1.0" encoding="UTF-8"?>
578
+ <pages_getInfo_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
579
+ <page>
580
+ <page_id>4846711747</page_id>
581
+ <name>Kronos Quartet</name>
582
+ <website>http://www.kronosquartet.org</website>
583
+ <company_overview/>
584
+ <genre>
585
+ <dance>0</dance>
586
+ <party>1</party>
587
+ </genre>
588
+ </page>
589
+ </pages_getInfo_response>
590
+ XML
591
+ end
592
+
593
+ def publish_user_action_return_xml
594
+ <<-XML
595
+ <?xml version="1.0" encoding="UTF-8"?>
596
+ <feed_publishUserAction_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
597
+ <feed_publishUserAction_response_elt>1</feed_publishUserAction_response_elt>
598
+ </feed_publishUserAction_response>
599
+ XML
600
+ end
601
+
602
+ def standard_info_xml
603
+ <<-XML
604
+ <?xml version="1.0" encoding="UTF-8"?>
605
+ <?xml version="1.0" encoding="UTF-8"?>
606
+
607
+ <users_getStandardInfo_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
608
+ <standard_user_info>
609
+ <uid>12451752</uid>
610
+ <name>Mike Mangino</name>
611
+ </standard_user_info>
612
+ </users_getStandardInfo_response>
613
+ XML
614
+ end
615
+ end
616
+
617
+ class PostMethodTest < Test::Unit::TestCase
618
+
619
+ def setup
620
+ Facebooker.use_curl = true
621
+ Facebooker::Parser.stubs(:parse)
622
+ @uri = URI.parse("http://api.facebook.com/api")
623
+ @service = Facebooker::Service.new("a","b","c")
624
+ @service.stubs("url").returns(@uri)
625
+ end
626
+
627
+ def teardown
628
+ Facebooker.use_curl = false
629
+ end
630
+
631
+ def test_use_curl_makes_post_with_curl
632
+ @service.expects(:post_form_with_curl).with(@uri,{:method=>"a"})
633
+ @service.post(:method=>"a")
634
+ end
635
+
636
+ def test_use_curl_makes_post_file_use_curl_with_multipart
637
+ @service.expects(:post_form_with_curl).with(@uri,{:method=>"a"},true)
638
+ @service.post_file(:method=>"a")
639
+ end
640
+ end
641
+
642
+ class CanvasSessionTest < Test::Unit::TestCase
643
+ def setup
644
+ ENV['FACEBOOK_API_KEY'] = '1234567'
645
+ ENV['FACEBOOK_SECRET_KEY'] = '7654321'
646
+ end
647
+
648
+ def test_login_url_will_display_callback_url_in_canvas
649
+ session = Facebooker::CanvasSession.create(ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'])
650
+ assert_equal("http://www.facebook.com/login.php?api_key=1234567&v=1.0&canvas=true", session.login_url)
651
+ end
652
+ end