twitter-multi 0.9.8.1

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 (97) hide show
  1. data/History +290 -0
  2. data/License +20 -0
  3. data/Notes +33 -0
  4. data/README.rdoc +19 -0
  5. data/Rakefile +40 -0
  6. data/VERSION.yml +5 -0
  7. data/examples/connect.rb +30 -0
  8. data/examples/friendship_existence.rb +13 -0
  9. data/examples/helpers/config_store.rb +38 -0
  10. data/examples/httpauth.rb +11 -0
  11. data/examples/ids.rb +13 -0
  12. data/examples/lists.rb +11 -0
  13. data/examples/oauth.rb +27 -0
  14. data/examples/search.rb +15 -0
  15. data/examples/timeline.rb +19 -0
  16. data/examples/tumblr.rb +9 -0
  17. data/examples/unauthorized.rb +16 -0
  18. data/examples/update.rb +11 -0
  19. data/examples/user.rb +5 -0
  20. data/lib/twitter/base.rb +390 -0
  21. data/lib/twitter/geo.rb +25 -0
  22. data/lib/twitter/httpauth.rb +53 -0
  23. data/lib/twitter/local_trends.rb +30 -0
  24. data/lib/twitter/oauth.rb +64 -0
  25. data/lib/twitter/request.rb +71 -0
  26. data/lib/twitter/search.rb +163 -0
  27. data/lib/twitter/trends.rb +55 -0
  28. data/lib/twitter.rb +156 -0
  29. data/test/fixtures/blocking.json +1632 -0
  30. data/test/fixtures/firehose.json +1 -0
  31. data/test/fixtures/follower_ids.json +1 -0
  32. data/test/fixtures/followers.json +1 -0
  33. data/test/fixtures/friend_ids.json +1 -0
  34. data/test/fixtures/friends_timeline.json +1 -0
  35. data/test/fixtures/friendship.json +1 -0
  36. data/test/fixtures/friendship_exists.json +1 -0
  37. data/test/fixtures/geo_place.json +1 -0
  38. data/test/fixtures/geo_reverse_geocode.json +1 -0
  39. data/test/fixtures/geo_reverse_geocode_granularity.json +1 -0
  40. data/test/fixtures/geo_reverse_geocode_limit.json +1 -0
  41. data/test/fixtures/geo_search.json +1 -0
  42. data/test/fixtures/geo_search_ip_address.json +1 -0
  43. data/test/fixtures/geo_search_query.json +1 -0
  44. data/test/fixtures/home_timeline.json +1 -0
  45. data/test/fixtures/ids.json +1 -0
  46. data/test/fixtures/list.json +1 -0
  47. data/test/fixtures/list_statuses.json +1 -0
  48. data/test/fixtures/list_statuses_1_1.json +1 -0
  49. data/test/fixtures/list_statuses_2_1.json +1 -0
  50. data/test/fixtures/list_subscriptions.json +1 -0
  51. data/test/fixtures/list_users.json +1 -0
  52. data/test/fixtures/lists.json +1 -0
  53. data/test/fixtures/memberships.json +1 -0
  54. data/test/fixtures/mentions.json +1 -0
  55. data/test/fixtures/not_found.json +1 -0
  56. data/test/fixtures/people_search.json +39 -0
  57. data/test/fixtures/rate_limit_exceeded.json +1 -0
  58. data/test/fixtures/report_spam.json +41 -0
  59. data/test/fixtures/retweet.json +1 -0
  60. data/test/fixtures/retweeted_by_me.json +1 -0
  61. data/test/fixtures/retweeted_to_me.json +1 -0
  62. data/test/fixtures/retweeters_of_tweet.json +166 -0
  63. data/test/fixtures/retweets.json +1 -0
  64. data/test/fixtures/retweets_of_me.json +1 -0
  65. data/test/fixtures/sample-image.png +0 -0
  66. data/test/fixtures/saved_search.json +7 -0
  67. data/test/fixtures/saved_searches.json +16 -0
  68. data/test/fixtures/search.json +1 -0
  69. data/test/fixtures/search_from_jnunemaker.json +1 -0
  70. data/test/fixtures/status.json +1 -0
  71. data/test/fixtures/status_show.json +1 -0
  72. data/test/fixtures/trends_available.json +253 -0
  73. data/test/fixtures/trends_current.json +1 -0
  74. data/test/fixtures/trends_current_exclude.json +1 -0
  75. data/test/fixtures/trends_daily.json +1925 -0
  76. data/test/fixtures/trends_daily_date.json +1 -0
  77. data/test/fixtures/trends_daily_exclude.json +1 -0
  78. data/test/fixtures/trends_location.json +57 -0
  79. data/test/fixtures/trends_weekly.json +1 -0
  80. data/test/fixtures/trends_weekly_date.json +1 -0
  81. data/test/fixtures/trends_weekly_exclude.json +1 -0
  82. data/test/fixtures/unauthorized.json +1 -0
  83. data/test/fixtures/update_profile_background_image.json +1 -0
  84. data/test/fixtures/update_profile_image.json +1 -0
  85. data/test/fixtures/user.json +1 -0
  86. data/test/fixtures/user_timeline.json +710 -0
  87. data/test/fixtures/users.json +1 -0
  88. data/test/test_helper.rb +47 -0
  89. data/test/twitter/base_test.rb +426 -0
  90. data/test/twitter/geo_test.rb +79 -0
  91. data/test/twitter/httpauth_test.rb +86 -0
  92. data/test/twitter/oauth_test.rb +108 -0
  93. data/test/twitter/request_test.rb +217 -0
  94. data/test/twitter/search_test.rb +208 -0
  95. data/test/twitter/trends_test.rb +112 -0
  96. data/test/twitter_test.rb +106 -0
  97. metadata +329 -0
@@ -0,0 +1 @@
1
+ [{"created_at":"Mon Jul 16 12:59:01 +0000 2007","friends_count":50,"description":"Captain","statuses_count":1948,"profile_text_color":"333333","screen_name":"sferik","status":{"created_at":"Thu Mar 18 18:13:19 +0000 2010","truncated":false,"in_reply_to_status_id":null,"source":"<a href=\"http://www.atebits.com/\" rel=\"nofollow\">Tweetie</a>","in_reply_to_screen_name":null,"favorited":false,"in_reply_to_user_id":null,"id":10682865729,"text":"If the earth was square, what shape would web browser icons be? #rhetorical"},"following":false,"profile_background_image_url":"http://a3.twimg.com/profile_background_images/58220609/gem.png","favourites_count":494,"contributors_enabled":false,"profile_link_color":"BF1238","url":null,"geo_enabled":true,"profile_background_tile":false,"profile_background_color":"000000","location":"California","verified":false,"profile_sidebar_fill_color":"EFEFEF","protected":true,"name":"Erik Michaels-Ober","notifications":false,"time_zone":"Pacific Time (US & Canada)","profile_sidebar_border_color":"FFFFFF","followers_count":799,"id":7505382,"lang":"en","utc_offset":-28800,"profile_image_url":"http://a1.twimg.com/profile_images/323331048/me_normal.jpg"},{"created_at":"Tue Dec 12 06:39:24 +0000 2006","friends_count":39,"description":"Full-time inventor.\r\nI don't do drugs. I AM drugs.","statuses_count":2157,"profile_text_color":"333333","screen_name":"jm3","status":{"created_at":"Thu Mar 18 21:32:31 +0000 2010","in_reply_to_status_id":null,"truncated":false,"source":"<a href=\"http://foursquare.com\" rel=\"nofollow\">foursquare</a>","in_reply_to_screen_name":null,"in_reply_to_user_id":null,"id":10690325085,"favorited":false,"text":"\"Social media is the new porn.\" Not sure I agree. (@ OMMA Global SF w/ 21 others) http://4sq.com/aURoO4"},"following":true,"profile_background_image_url":"http://a1.twimg.com/profile_background_images/67143062/drucker.jpg","favourites_count":4179,"contributors_enabled":false,"profile_link_color":"038543","url":"http://jm3.net","geo_enabled":true,"profile_background_tile":true,"profile_background_color":"ACDED6","location":"SF Yay Area","verified":false,"profile_sidebar_fill_color":"F6F6F6","protected":false,"name":"John Manoogian III","notifications":true,"time_zone":"Pacific Time (US & Canada)","profile_sidebar_border_color":"EEEEEE","followers_count":477,"id":59593,"lang":"en","utc_offset":-28800,"profile_image_url":"http://a3.twimg.com/profile_images/689856229/jm3-stripes_normal.jpg"},{"created_at":"Thu Feb 15 16:28:04 +0000 2007","friends_count":223,"description":"Internet researcher & open source hacker. I created Know Your Meme and taught the Internet Famous class","contributors_enabled":false,"profile_text_color":"000000","screen_name":"jamiew","status":{"created_at":"Tue Mar 16 02:00:21 +0000 2010","favorited":false,"in_reply_to_user_id":null,"in_reply_to_status_id":null,"source":"web","in_reply_to_screen_name":null,"id":10547290021,"truncated":false,"text":"Chat Roulette Piano Improv http://www.youtube.com/watch?v=32vpgNiAH60 A++, I'm in love"},"following":true,"profile_background_image_url":"http://a1.twimg.com/profile_background_images/83556904/fat_NBC_diagram_cooper_40.jpg","favourites_count":496,"profile_link_color":"061e6f","url":"http://jamiedubs.com","geo_enabled":false,"profile_background_tile":true,"profile_background_color":"ffffff","location":"San Francisco","verified":false,"profile_sidebar_fill_color":"ededed","protected":false,"name":"Jamie Wilkinson","notifications":false,"time_zone":"Pacific Time (US & Canada)","profile_sidebar_border_color":"e3c4c9","followers_count":1135,"id":774010,"lang":"en","statuses_count":918,"utc_offset":-28800,"profile_image_url":"http://a1.twimg.com/profile_images/698063756/jamie_beards-big_normal.jpg"}]
@@ -0,0 +1,47 @@
1
+ require "test/unit"
2
+ require "pathname"
3
+ require "shoulda"
4
+ require "matchy"
5
+ require "mocha"
6
+ require "fakeweb"
7
+ require "redgreen"
8
+
9
+ FakeWeb.allow_net_connect = false
10
+
11
+ dir = (Pathname(__FILE__).dirname + "../lib").expand_path
12
+ require dir + "twitter"
13
+
14
+ class Test::Unit::TestCase
15
+ end
16
+
17
+ def sample_image(filename)
18
+ File.expand_path(File.dirname(__FILE__) + "/fixtures/" + filename)
19
+ end
20
+
21
+ def fixture_file(filename)
22
+ return "" if filename == ""
23
+ file_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/" + filename)
24
+ File.read(file_path)
25
+ end
26
+
27
+ def twitter_url(url)
28
+ url =~ /^http/ ? url : "http://api.twitter.com:80#{url}"
29
+ end
30
+
31
+ def stub_get(url, filename, status=nil)
32
+ options = {:body => fixture_file(filename)}
33
+ options.merge!({:status => status}) unless status.nil?
34
+ FakeWeb.register_uri(:get, twitter_url(url), options)
35
+ end
36
+
37
+ def stub_post(url, filename)
38
+ FakeWeb.register_uri(:post, twitter_url(url), :body => fixture_file(filename))
39
+ end
40
+
41
+ def stub_put(url, filename)
42
+ FakeWeb.register_uri(:put, twitter_url(url), :body => fixture_file(filename))
43
+ end
44
+
45
+ def stub_delete(url, filename)
46
+ FakeWeb.register_uri(:delete, twitter_url(url), :body => fixture_file(filename))
47
+ end
@@ -0,0 +1,426 @@
1
+ require "test_helper"
2
+
3
+ class BaseTest < Test::Unit::TestCase
4
+ context "base" do
5
+ setup do
6
+ oauth = Twitter::OAuth.new("token", "secret")
7
+ @access_token = OAuth::AccessToken.new(oauth.consumer, "atoken", "asecret")
8
+ oauth.stubs(:access_token).returns(@access_token)
9
+ @twitter = Twitter::Base.new(oauth)
10
+ end
11
+
12
+ context "initialize" do
13
+ should "require a client" do
14
+ @twitter.client.should respond_to(:get)
15
+ @twitter.client.should respond_to(:post)
16
+ end
17
+ end
18
+
19
+ should "delegate get to the client" do
20
+ @access_token.expects(:get).with("/foo").returns(nil)
21
+ @twitter.get("/foo")
22
+ end
23
+
24
+ should "delegate post to the client" do
25
+ @access_token.expects(:post).with("/foo", {:bar => "baz"}).returns(nil)
26
+ @twitter.post("/foo", {:bar => "baz"})
27
+ end
28
+
29
+ context "hitting the api" do
30
+ should "be able to get home timeline" do
31
+ stub_get("/statuses/home_timeline.json", "home_timeline.json")
32
+ timeline = @twitter.home_timeline
33
+ timeline.size.should == 20
34
+ first = timeline.first
35
+ first.source.should == '<a href="http://www.atebits.com/software/tweetie/">Tweetie</a>'
36
+ first.user.name.should == "John Nunemaker"
37
+ first.user.url.should == "http://railstips.org/about"
38
+ first.id.should == 1441588944
39
+ first.favorited.should be(false)
40
+ end
41
+
42
+ should "be able to get friends timeline" do
43
+ stub_get("/statuses/friends_timeline.json", "friends_timeline.json")
44
+ timeline = @twitter.friends_timeline
45
+ timeline.size.should == 20
46
+ first = timeline.first
47
+ first.source.should == '<a href="http://www.atebits.com/software/tweetie/">Tweetie</a>'
48
+ first.user.name.should == "John Nunemaker"
49
+ first.user.url.should == "http://railstips.org/about"
50
+ first.id.should == 1441588944
51
+ first.favorited.should be(false)
52
+ end
53
+
54
+ should "be able to get user timeline" do
55
+ stub_get("/statuses/user_timeline.json", "user_timeline.json")
56
+ timeline = @twitter.user_timeline
57
+ timeline.size.should == 20
58
+ first = timeline.first
59
+ first.text.should == "Colder out today than expected. Headed to the Beanery for some morning wakeup drink. Latte or coffee...hmmm..."
60
+ first.user.name.should == "John Nunemaker"
61
+ end
62
+
63
+ should "be able to get a status" do
64
+ stub_get("/statuses/show/1441588944.json", "status.json")
65
+ status = @twitter.status(1441588944)
66
+ status.user.name.should == "John Nunemaker"
67
+ status.id.should == 1441588944
68
+ end
69
+
70
+ should "be able to update status" do
71
+ stub_post("/statuses/update.json", "status.json")
72
+ status = @twitter.update("Rob Dyrdek is the funniest man alive. That is all.")
73
+ status.user.name.should == "John Nunemaker"
74
+ status.text.should == "Rob Dyrdek is the funniest man alive. That is all."
75
+ end
76
+
77
+ should "be able to retweet a status" do
78
+ stub_post("/statuses/retweet/6235127466.json", "retweet.json")
79
+ status = @twitter.retweet(6235127466)
80
+ status.user.name.should == "Michael D. Ivey"
81
+ status.text.should == "RT @jstetser: I'm not actually awake. My mind's on autopilot for food and I managed to take a detour along the way."
82
+ status.retweeted_status.user.screen_name.should == "jstetser"
83
+ status.retweeted_status.text.should == "I'm not actually awake. My mind's on autopilot for food and I managed to take a detour along the way."
84
+ end
85
+
86
+ should "be able to get retweets of a status" do
87
+ stub_get("/statuses/retweets/6192831130.json", "retweets.json")
88
+ retweets = @twitter.retweets(6192831130)
89
+ retweets.size.should == 6
90
+ first = retweets.first
91
+ first.user.name.should == "josephholsten"
92
+ first.text.should == "RT @Moltz: Personally, I won't be satisfied until a Buddhist monk lights himself on fire for web standards."
93
+ end
94
+
95
+ should "be able to get mentions" do
96
+ stub_get("/statuses/mentions.json", "mentions.json")
97
+ mentions = @twitter.mentions
98
+ mentions.size.should == 19
99
+ first = mentions.first
100
+ first.user.name.should == "-oAk-"
101
+ first.text.should == "@jnunemaker cold out today. cold yesterday. even colder today."
102
+ end
103
+
104
+ should "be able to get retweets by me" do
105
+ stub_get("/statuses/retweeted_by_me.json", "retweeted_by_me.json")
106
+ retweeted_by_me = @twitter.retweeted_by_me
107
+ retweeted_by_me.size.should == 20
108
+ first = retweeted_by_me.first.retweeted_status
109
+ first.user.name.should == "Troy Davis"
110
+ first.text.should == "I'm the mayor of win a free MacBook Pro with promo code Cyber Monday RT for a good time"
111
+ end
112
+
113
+ should "be able to get retweets to me" do
114
+ stub_get("/statuses/retweeted_to_me.json", "retweeted_to_me.json")
115
+ retweeted_to_me = @twitter.retweeted_to_me
116
+ retweeted_to_me.size.should == 20
117
+ first = retweeted_to_me.first.retweeted_status
118
+ first.user.name.should == "Cloudvox"
119
+ first.text.should == "Testing counts with voice apps too:\n\"the voice told residents to dial 'nine hundred eleven' rather than '9-1-1'\" \342\200\224 http://j.mp/7mqe2B"
120
+ end
121
+
122
+ should "be able to get retweets of me" do
123
+ stub_get("/statuses/retweets_of_me.json", "retweets_of_me.json")
124
+ retweets_of_me = @twitter.retweets_of_me
125
+ retweets_of_me.size.should == 11
126
+ first = retweets_of_me.first
127
+ first.user.name.should == "Michael D. Ivey"
128
+ first.text.should == "Trying out geotweets in Birdfeed. No \"new RT\" support, though. Any iPhone client with RTs yet?"
129
+ end
130
+
131
+ should "be able to get users who retweeted a tweet" do
132
+ stub_get("/statuses/9021932472/retweeted_by.json", "retweeters_of_tweet.json")
133
+ retweeters = @twitter.retweeters_of("9021932472")
134
+ retweeters.size.should == 4
135
+ first = retweeters.first
136
+ first.screen_name.should == "bryanl"
137
+ end
138
+
139
+ should "be able to get ids of users who retweeted a tweet" do
140
+ stub_get("/statuses/9021932472/retweeted_by/ids.json", "ids.json")
141
+ retweeters = @twitter.retweeters_of("9021932472", :ids_only => true)
142
+ retweeters.first.should == 61940910
143
+ end
144
+
145
+ should "be able to get follower ids" do
146
+ stub_get("/followers/ids.json", "follower_ids.json")
147
+ follower_ids = @twitter.follower_ids
148
+ follower_ids.size.should == 1252
149
+ follower_ids.first.should == 613
150
+ end
151
+
152
+ should "be able to get friend ids" do
153
+ stub_get("/friends/ids.json", "friend_ids.json")
154
+ friend_ids = @twitter.friend_ids
155
+ friend_ids.size.should == 161
156
+ friend_ids.first.should == 15323
157
+ end
158
+
159
+ should "correctly hash statuses" do
160
+ stub_get("/statuses/friends_timeline.json", "friends_timeline.json")
161
+ hashes = @twitter.friends_timeline.map{ |s| s.hash }
162
+ hashes.should == @twitter.friends_timeline.map{ |s| s.hash }
163
+ end
164
+
165
+ should "be able to test whether a friendship exists" do
166
+ stub_get("/friendships/exists.json?user_a=pengwynn&user_b=sferik", "friendship_exists.json")
167
+ @twitter.friendship_exists?("pengwynn", "sferik").should == true
168
+ end
169
+
170
+ should "be able to get a friendship" do
171
+ stub_get("/friendships/show.json?source_screen_name=dcrec1&target_screen_name=pengwynn", "friendship.json")
172
+ @twitter.friendship_show(:source_screen_name => "dcrec1", :target_screen_name => "pengwynn").relationship.target.followed_by == false
173
+ end
174
+
175
+ should "be able to lookup a user" do
176
+ stub_get("/users/show/4243.json", "user.json")
177
+ user = @twitter.user(4243)
178
+ user.screen_name.should == "jnunemaker"
179
+ end
180
+
181
+ should "be able to lookup users in bulk" do
182
+ stub_get("/users/lookup.json?screen_name=sferik&user_id=59593,774010", "users.json")
183
+ users = @twitter.users("sferik", 59593, 774010)
184
+ users.first.screen_name.should == "sferik"
185
+ end
186
+
187
+ should "be able to search people" do
188
+ stub_get("/users/search.json?q=Wynn%20Netherland", "people_search.json")
189
+ people = @twitter.user_search("Wynn Netherland")
190
+ people.first.screen_name.should == "pengwynn"
191
+ end
192
+
193
+ should "be able to get followers' stauses" do
194
+ stub_get("/statuses/followers.json", "followers.json")
195
+ followers = @twitter.followers
196
+ followers.should == @twitter.followers
197
+ end
198
+
199
+ should "be able to get blocked users' IDs" do
200
+ stub_get("/blocks/blocking/ids.json", "ids.json")
201
+ blocked = @twitter.blocked_ids
202
+ blocked.should == @twitter.blocked_ids
203
+ end
204
+
205
+ should "be able to get an array of blocked users" do
206
+ stub_get("/blocks/blocking.json", "blocking.json")
207
+ blocked = @twitter.blocking
208
+ blocked.last.screen_name.should == "euciavkvyplx"
209
+ end
210
+
211
+ should "report a spammer" do
212
+ stub_post("/report_spam.json", "report_spam.json")
213
+ spammer = @twitter.report_spam(:screen_name => 'lucaasvaz00')
214
+ spammer.screen_name.should == "lucaasvaz00"
215
+ end
216
+
217
+ should "upload a profile image" do
218
+ stub_post("/account/update_profile_image.json", "update_profile_image.json")
219
+ user = @twitter.update_profile_image(File.new(sample_image("sample-image.png")))
220
+ user.name.should == "John Nunemaker" # update_profile_image responds with the user
221
+ end
222
+
223
+ should "upload a background image" do
224
+ stub_post("/account/update_profile_background_image.json", "update_profile_background_image.json")
225
+ user = @twitter.update_profile_background(File.new(sample_image("sample-image.png")))
226
+ user.name.should == "John Nunemaker" # update_profile_background responds with the user
227
+ end
228
+ end
229
+
230
+ context "when using saved searches" do
231
+ should "be able to retrieve my saved searches" do
232
+ stub_get('/saved_searches.json', 'saved_searches.json')
233
+ searches = @twitter.saved_searches
234
+ searches[0].query.should == "great danes"
235
+ searches[1].query.should == "rubyconf OR railsconf"
236
+ end
237
+
238
+ should "be able to retrieve a saved search by id" do
239
+ stub_get('/saved_searches/show/7095598.json', 'saved_search.json')
240
+ search = @twitter.saved_search(7095598)
241
+ search.query.should == "great danes"
242
+ end
243
+
244
+ should "be able to create a saved search" do
245
+ stub_post('/saved_searches/create.json', 'saved_search.json')
246
+ search = @twitter.saved_search_create('great danes')
247
+ search.query.should == "great danes"
248
+ end
249
+
250
+ should "be able to delete a saved search" do
251
+ stub_delete('/saved_searches/destroy/7095598.json', 'saved_search.json')
252
+ search = @twitter.saved_search_destroy(7095598)
253
+ search.query.should == "great danes"
254
+ end
255
+ end
256
+
257
+ context "when using lists" do
258
+
259
+ should "be able to create a new list" do
260
+ stub_post("/pengwynn/lists.json", "list.json")
261
+ list = @twitter.list_create("pengwynn", {:name => "Rubyists"})
262
+ list.name.should == "Rubyists"
263
+ list.slug.should == "rubyists"
264
+ list.mode.should == "public"
265
+ end
266
+
267
+ should "be able to update a list" do
268
+ stub_put("/pengwynn/lists/rubyists.json", "list.json")
269
+ list = @twitter.list_update("pengwynn", "rubyists", {:name => "Rubyists"})
270
+ list.name.should == "Rubyists"
271
+ list.slug.should == "rubyists"
272
+ list.mode.should == "public"
273
+ end
274
+
275
+ should "be able to delete a list" do
276
+ stub_delete("/pengwynn/lists/rubyists.json", "list.json")
277
+ list = @twitter.list_delete("pengwynn", "rubyists")
278
+ list.name.should == "Rubyists"
279
+ list.slug.should == "rubyists"
280
+ list.mode.should == "public"
281
+ end
282
+
283
+ should "be able to view lists to which a user belongs" do
284
+ stub_get("/pengwynn/lists/memberships.json", "memberships.json")
285
+ lists = @twitter.memberships("pengwynn").lists
286
+ lists.size.should == 16
287
+ lists.first.name.should == "web-dev"
288
+ lists.first.member_count.should == 38
289
+ end
290
+
291
+ should "be able to view lists for the authenticated user" do
292
+ stub_get("/pengwynn/lists.json", "lists.json")
293
+ lists = @twitter.lists("pengwynn").lists
294
+ lists.size.should == 1
295
+ lists.first.name.should == "Rubyists"
296
+ lists.first.slug.should == "rubyists"
297
+ end
298
+
299
+ should "be able to view the user owned lists without passing the username" do
300
+ stub_get('/lists.json', 'lists.json')
301
+ lists = @twitter.lists().lists
302
+ lists.size.should == 1
303
+ lists.first.name.should == 'Rubyists'
304
+ lists.first.slug.should == 'rubyists'
305
+ end
306
+
307
+ should "be able to view lists for the authenticated user by passing in a cursor" do
308
+ stub_get('/pengwynn/lists.json?cursor=-1', 'lists.json')
309
+ lists = @twitter.lists('pengwynn', :cursor => -1).lists
310
+ lists.size.should == 1
311
+ lists.first.name.should == 'Rubyists'
312
+ lists.first.slug.should == 'rubyists'
313
+ end
314
+
315
+ should "be able to view the user owned lists without passing the username and passing in a cursor" do
316
+ stub_get('/lists.json?cursor=-1', 'lists.json')
317
+ lists = @twitter.lists(:cursor => -1).lists
318
+ lists.size.should == 1
319
+ lists.first.name.should == 'Rubyists'
320
+ lists.first.slug.should == 'rubyists'
321
+ end
322
+
323
+ should "be able to view list details" do
324
+ stub_get("/pengwynn/lists/rubyists.json", "list.json")
325
+ list = @twitter.list("pengwynn", "rubyists")
326
+ list.name.should == "Rubyists"
327
+ list.subscriber_count.should == 0
328
+ end
329
+
330
+ should "be able to view list timeline" do
331
+ stub_get("/pengwynn/lists/rubyists/statuses.json", "list_statuses.json")
332
+ tweets = @twitter.list_timeline("pengwynn", "rubyists")
333
+ tweets.size.should == 20
334
+ tweets.first.id.should == 5272535583
335
+ tweets.first.user.name.should == "John Nunemaker"
336
+ end
337
+
338
+ should "be able to limit number of tweets in list timeline" do
339
+ stub_get("/pengwynn/lists/rubyists/statuses.json?per_page=1", "list_statuses_1_1.json")
340
+ tweets = @twitter.list_timeline("pengwynn", "rubyists", :per_page => 1)
341
+ tweets.size.should == 1
342
+ tweets.first.id.should == 5272535583
343
+ tweets.first.user.name.should == "John Nunemaker"
344
+ end
345
+
346
+ should "be able to paginate through the timeline" do
347
+ stub_get("/pengwynn/lists/rubyists/statuses.json?page=1&per_page=1", "list_statuses_1_1.json")
348
+ stub_get("/pengwynn/lists/rubyists/statuses.json?page=2&per_page=1", "list_statuses_2_1.json")
349
+ tweets = @twitter.list_timeline("pengwynn", "rubyists", { :page => 1, :per_page => 1 })
350
+ tweets.size.should == 1
351
+ tweets.first.id.should == 5272535583
352
+ tweets.first.user.name.should == "John Nunemaker"
353
+ tweets = @twitter.list_timeline("pengwynn", "rubyists", { :page => 2, :per_page => 1 })
354
+ tweets.size.should == 1
355
+ tweets.first.id.should == 5264324712
356
+ tweets.first.user.name.should == "John Nunemaker"
357
+ end
358
+
359
+ should "be able to view list members" do
360
+ stub_get("/pengwynn/rubyists/members.json", "list_users.json")
361
+ members = @twitter.list_members("pengwynn", "rubyists").users
362
+ members.size.should == 2
363
+ members.first.name.should == "John Nunemaker"
364
+ members.first.screen_name.should == "jnunemaker"
365
+ end
366
+
367
+ should "be able to add a member to a list" do
368
+ stub_post("/pengwynn/rubyists/members.json", "user.json")
369
+ user = @twitter.list_add_member("pengwynn", "rubyists", 4243)
370
+ user.screen_name.should == "jnunemaker"
371
+ end
372
+
373
+ should "be able to remove a member from a list" do
374
+ stub_delete("/pengwynn/rubyists/members.json?id=4243", "user.json")
375
+ user = @twitter.list_remove_member("pengwynn", "rubyists", 4243)
376
+ user.screen_name.should == "jnunemaker"
377
+ end
378
+
379
+ should "be able to check if a user is member of a list" do
380
+ stub_get("/pengwynn/rubyists/members/4243.json", "user.json")
381
+ @twitter.is_list_member?("pengwynn", "rubyists", 4243).should == true
382
+ end
383
+
384
+ should "be able to view list subscribers" do
385
+ stub_get("/pengwynn/rubyists/subscribers.json", "list_users.json")
386
+ subscribers = @twitter.list_subscribers("pengwynn", "rubyists").users
387
+ subscribers.size.should == 2
388
+ subscribers.first.name.should == "John Nunemaker"
389
+ subscribers.first.screen_name.should == "jnunemaker"
390
+ end
391
+
392
+ should "be able to subscribe to a list" do
393
+ stub_post("/pengwynn/rubyists/subscribers.json", "user.json")
394
+ user = @twitter.list_subscribe("pengwynn", "rubyists")
395
+ user.screen_name.should == "jnunemaker"
396
+ end
397
+
398
+ should "be able to unsubscribe from a list" do
399
+ stub_delete("/pengwynn/rubyists/subscribers.json", "user.json")
400
+ user = @twitter.list_unsubscribe("pengwynn", "rubyists")
401
+ user.screen_name.should == "jnunemaker"
402
+ end
403
+
404
+ should "be able to view a members list subscriptions" do
405
+ stub_get('/pengwynn/lists/subscriptions.json', 'list_subscriptions.json')
406
+ subscriptions = @twitter.subscriptions('pengwynn').lists
407
+ subscriptions.size.should == 1
408
+ subscriptions.first.full_name.should == "@chriseppstein/sass-users"
409
+ subscriptions.first.slug.should == "sass-users"
410
+ end
411
+
412
+ end
413
+ end
414
+
415
+ context "when using a non-twitter service" do
416
+ setup do
417
+ @twitter = Twitter::Base.new(Twitter::HTTPAuth.new("wynn@example.com", "mypass", :api_endpoint => "tumblr.com"))
418
+ end
419
+
420
+ should "get the home timeline" do
421
+ stub_get("http://wynn%40example.com:mypass@tumblr.com/1/statuses/home_timeline.json", "home_timeline.json")
422
+ timeline = @twitter.home_timeline
423
+ timeline.size.should == 20
424
+ end
425
+ end
426
+ end
@@ -0,0 +1,79 @@
1
+ require 'test_helper'
2
+
3
+ class GeoTest < Test::Unit::TestCase
4
+ include Twitter
5
+
6
+ context "Geographic place lookup" do
7
+
8
+ should "work" do
9
+ stub_get 'http://api.twitter.com/1/geo/id/ea76a36c5bc2bdff.json', 'geo_place.json'
10
+ place = Geo.place('ea76a36c5bc2bdff')
11
+ place.country.should == 'The United States of America'
12
+ place.full_name.should == 'Ballantyne West, Charlotte'
13
+ place.geometry.coordinates.should be_kind_of(Array)
14
+ end
15
+
16
+ end
17
+
18
+ context "Geographic search" do
19
+
20
+ should "work" do
21
+ stub_get 'http://api.twitter.com:80/1/geo/search.json?lat=35.061161&long=-80.854568', 'geo_search.json'
22
+ places = Geo.search(:lat => 35.061161, :long => -80.854568)
23
+ places.size.should == 3
24
+ places[0].full_name.should eql('Ballantyne West, Charlotte')
25
+ places[0].name.should eql('Ballantyne West')
26
+ end
27
+
28
+ should "be able to search with free form text" do
29
+ stub_get 'http://api.twitter.com/1/geo/search.json?query=princeton%20record%20exchange', 'geo_search_query.json'
30
+ places = Geo.search(:query => 'princeton record exchange')
31
+ places.size.should == 1
32
+ places[0].name.should eql('Princeton Record Exchange')
33
+ places[0].place_type.should eql('poi')
34
+ places[0].attributes.street_address.should eql('20 S Tulane St')
35
+ end
36
+
37
+ should "be able to search by ip address" do
38
+ stub_get 'http://api.twitter.com/1/geo/search.json?ip=74.125.19.104', 'geo_search_ip_address.json'
39
+ places = Geo.search(:ip => '74.125.19.104')
40
+ places.size.should == 4
41
+ places[0].full_name.should eql("Mountain View, CA")
42
+ places[0].name.should eql("Mountain View")
43
+ places[1].full_name.should eql("Sunnyvale, CA")
44
+ places[1].name.should eql('Sunnyvale')
45
+ end
46
+
47
+ end
48
+
49
+ context "Geographic reverse_geocode" do
50
+
51
+ should "work" do
52
+ stub_get 'http://api.twitter.com:80/1/geo/reverse_geocode.json?lat=35.061161&long=-80.854568', 'geo_reverse_geocode.json'
53
+ places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568)
54
+ places.size.should == 4
55
+ places[0].full_name.should eql('Ballantyne West, Charlotte')
56
+ places[0].name.should eql('Ballantyne West')
57
+ end
58
+
59
+ should "be able to limit the number of results returned" do
60
+ stub_get 'http://api.twitter.com/1/geo/reverse_geocode.json?lat=35.061161&max_results=2&long=-80.854568', 'geo_reverse_geocode_limit.json'
61
+ places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568, :max_results => 2)
62
+ places.size.should == 2
63
+ places[0].full_name.should eql('Ballantyne West, Charlotte')
64
+ places[0].name.should eql('Ballantyne West')
65
+ end
66
+
67
+ should "be able to lookup with granularity" do
68
+ stub_get 'http://api.twitter.com/1/geo/reverse_geocode.json?lat=35.061161&long=-80.854568&granularity=city', 'geo_reverse_geocode_granularity.json'
69
+ places = Geo.reverse_geocode(:lat => 35.061161, :long => -80.854568, :granularity => 'city')
70
+ places.size.should == 3
71
+ places[0].full_name.should eql('Charlotte, NC')
72
+ places[0].name.should eql('Charlotte')
73
+ places[1].full_name.should eql('North Carolina, US')
74
+ places[1].name.should eql('North Carolina')
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,86 @@
1
+ require 'test_helper'
2
+
3
+ class HTTPAuthTest < Test::Unit::TestCase
4
+ context "Creating new instance" do
5
+ should "should take user and password" do
6
+ twitter = Twitter::HTTPAuth.new('username', 'password')
7
+ twitter.username.should == 'username'
8
+ twitter.password.should == 'password'
9
+ end
10
+
11
+ should "accept options" do
12
+ twitter = Twitter::HTTPAuth.new('username', 'password', :ssl => true)
13
+ twitter.options.should == {:ssl => true}
14
+ end
15
+
16
+ should "default ssl to false" do
17
+ twitter = Twitter::HTTPAuth.new('username', 'password')
18
+ twitter.options[:ssl].should be(false)
19
+ end
20
+
21
+ should "use https if ssl is true" do
22
+ Twitter::HTTPAuth.expects(:base_uri).with('https://api.twitter.com/' + Twitter::API_VERSION)
23
+ twitter = Twitter::HTTPAuth.new('username', 'password', :ssl => true)
24
+ end
25
+
26
+ should "use http if ssl is false" do
27
+ Twitter::HTTPAuth.expects(:base_uri).with('http://api.twitter.com/' + Twitter::API_VERSION)
28
+ twitter = Twitter::HTTPAuth.new('username', 'password', :ssl => false)
29
+ end
30
+
31
+ should "use api version if provided" do
32
+ Twitter::HTTPAuth.expects(:base_uri).with('http://api.twitter.com/2')
33
+ twitter = Twitter::HTTPAuth.new('username', 'password', {:ssl => false, :api_version => 2})
34
+ end
35
+
36
+ should "not use api versioning if api_version is false " do
37
+ Twitter::HTTPAuth.expects(:base_uri).with('http://api.twitter.com')
38
+ twitter = Twitter::HTTPAuth.new('username', 'password', {:ssl => false, :api_version => false})
39
+ end
40
+ end
41
+
42
+ context "Client methods" do
43
+ setup do
44
+ @twitter = Twitter::HTTPAuth.new('username', 'password')
45
+ end
46
+
47
+ should "not throw error when accessing response message" do
48
+ stub_get('http://api.twitter.com:80/1/statuses/user_timeline.json', 'user_timeline.json')
49
+ response = @twitter.get('/statuses/user_timeline.json')
50
+ response.message.should == 'OK'
51
+ end
52
+
53
+ should "be able to get" do
54
+ stub_get('http://username:password@api.twitter.com:80/1/statuses/user_timeline.json', 'user_timeline.json')
55
+ response = @twitter.get('/statuses/user_timeline.json')
56
+ response.should == fixture_file('user_timeline.json')
57
+ end
58
+
59
+ should "be able to get with headers" do
60
+ @twitter.class.expects(:get).with(
61
+ '/statuses/user_timeline.json', {
62
+ :basic_auth => {:username => 'username', :password => 'password'},
63
+ :headers => {'Foo' => 'Bar'}
64
+ }
65
+ ).returns(fixture_file('user_timeline.json'))
66
+ @twitter.get('/statuses/user_timeline.json', {'Foo' => 'Bar'})
67
+ end
68
+
69
+ should "be able to post" do
70
+ stub_post('http://username:password@api.twitter.com:80/1/statuses/update.json', 'status.json')
71
+ response = @twitter.post('/statuses/update.json', :text => 'My update.')
72
+ response.should == fixture_file('status.json')
73
+ end
74
+
75
+ should "be able to post with headers" do
76
+ @twitter.class.expects(:post).with(
77
+ '/statuses/update.json', {
78
+ :headers => {'Foo' => 'Bar'},
79
+ :body => {:text => 'My update.'},
80
+ :basic_auth => {:username => 'username', :password => 'password'}
81
+ }
82
+ ).returns(fixture_file('status.json'))
83
+ @twitter.post('/statuses/update.json', {:text => 'My update.'}, {'Foo' => 'Bar'})
84
+ end
85
+ end
86
+ end