secobarbital-twitter 0.9.2.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 (84) hide show
  1. data/History +271 -0
  2. data/License +20 -0
  3. data/Notes +33 -0
  4. data/README.rdoc +19 -0
  5. data/Rakefile +39 -0
  6. data/VERSION.yml +5 -0
  7. data/examples/connect.rb +30 -0
  8. data/examples/friendship_existance.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 +371 -0
  21. data/lib/twitter/httpauth.rb +39 -0
  22. data/lib/twitter/local_trends.rb +15 -0
  23. data/lib/twitter/oauth.rb +58 -0
  24. data/lib/twitter/request.rb +71 -0
  25. data/lib/twitter/search.rb +157 -0
  26. data/lib/twitter/trends.rb +41 -0
  27. data/lib/twitter.rb +148 -0
  28. data/test/fixtures/blocking.json +1632 -0
  29. data/test/fixtures/firehose.json +1 -0
  30. data/test/fixtures/follower_ids.json +1 -0
  31. data/test/fixtures/followers.json +1 -0
  32. data/test/fixtures/friend_ids.json +1 -0
  33. data/test/fixtures/friends_timeline.json +1 -0
  34. data/test/fixtures/friendship.json +1 -0
  35. data/test/fixtures/home_timeline.json +1 -0
  36. data/test/fixtures/ids.json +1 -0
  37. data/test/fixtures/list.json +1 -0
  38. data/test/fixtures/list_statuses.json +1 -0
  39. data/test/fixtures/list_statuses_1_1.json +1 -0
  40. data/test/fixtures/list_statuses_2_1.json +1 -0
  41. data/test/fixtures/list_subscriptions.json +1 -0
  42. data/test/fixtures/list_users.json +1 -0
  43. data/test/fixtures/lists.json +1 -0
  44. data/test/fixtures/memberships.json +1 -0
  45. data/test/fixtures/mentions.json +1 -0
  46. data/test/fixtures/not_found.json +1 -0
  47. data/test/fixtures/people_search.json +39 -0
  48. data/test/fixtures/rate_limit_exceeded.json +1 -0
  49. data/test/fixtures/retweet.json +1 -0
  50. data/test/fixtures/retweeted_by_me.json +1 -0
  51. data/test/fixtures/retweeted_to_me.json +1 -0
  52. data/test/fixtures/retweeters_of_tweet.json +166 -0
  53. data/test/fixtures/retweets.json +1 -0
  54. data/test/fixtures/retweets_of_me.json +1 -0
  55. data/test/fixtures/sample-image.png +0 -0
  56. data/test/fixtures/search.json +1 -0
  57. data/test/fixtures/search_from_jnunemaker.json +1 -0
  58. data/test/fixtures/status.json +1 -0
  59. data/test/fixtures/status_show.json +1 -0
  60. data/test/fixtures/trends_available.json +253 -0
  61. data/test/fixtures/trends_current.json +1 -0
  62. data/test/fixtures/trends_current_exclude.json +1 -0
  63. data/test/fixtures/trends_daily.json +1925 -0
  64. data/test/fixtures/trends_daily_date.json +1 -0
  65. data/test/fixtures/trends_daily_exclude.json +1 -0
  66. data/test/fixtures/trends_location.json +57 -0
  67. data/test/fixtures/trends_weekly.json +1 -0
  68. data/test/fixtures/trends_weekly_date.json +1 -0
  69. data/test/fixtures/trends_weekly_exclude.json +1 -0
  70. data/test/fixtures/unauthorized.json +1 -0
  71. data/test/fixtures/update_profile_background_image.json +1 -0
  72. data/test/fixtures/update_profile_image.json +1 -0
  73. data/test/fixtures/user.json +1 -0
  74. data/test/fixtures/user_timeline.json +710 -0
  75. data/test/fixtures/users.json +1 -0
  76. data/test/test_helper.rb +46 -0
  77. data/test/twitter/base_test.rb +364 -0
  78. data/test/twitter/httpauth_test.rb +76 -0
  79. data/test/twitter/oauth_test.rb +108 -0
  80. data/test/twitter/request_test.rb +217 -0
  81. data/test/twitter/search_test.rb +208 -0
  82. data/test/twitter/trends_test.rb +112 -0
  83. data/test/twitter_test.rb +106 -0
  84. metadata +280 -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,46 @@
1
+ require "test/unit"
2
+ require "pathname"
3
+ require "shoulda"
4
+ require "matchy"
5
+ require "mocha"
6
+ require "fakeweb"
7
+
8
+ FakeWeb.allow_net_connect = false
9
+
10
+ dir = (Pathname(__FILE__).dirname + "../lib").expand_path
11
+ require dir + "twitter"
12
+
13
+ class Test::Unit::TestCase
14
+ end
15
+
16
+ def sample_image(filename)
17
+ File.expand_path(File.dirname(__FILE__) + "/fixtures/" + filename)
18
+ end
19
+
20
+ def fixture_file(filename)
21
+ return "" if filename == ""
22
+ file_path = File.expand_path(File.dirname(__FILE__) + "/fixtures/" + filename)
23
+ File.read(file_path)
24
+ end
25
+
26
+ def twitter_url(url)
27
+ url =~ /^http/ ? url : "http://api.twitter.com:80#{url}"
28
+ end
29
+
30
+ def stub_get(url, filename, status=nil)
31
+ options = {:body => fixture_file(filename)}
32
+ options.merge!({:status => status}) unless status.nil?
33
+ FakeWeb.register_uri(:get, twitter_url(url), options)
34
+ end
35
+
36
+ def stub_post(url, filename)
37
+ FakeWeb.register_uri(:post, twitter_url(url), :body => fixture_file(filename))
38
+ end
39
+
40
+ def stub_put(url, filename)
41
+ FakeWeb.register_uri(:put, twitter_url(url), :body => fixture_file(filename))
42
+ end
43
+
44
+ def stub_delete(url, filename)
45
+ FakeWeb.register_uri(:delete, twitter_url(url), :body => fixture_file(filename))
46
+ end
@@ -0,0 +1,364 @@
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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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('/1/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 get a friendship" do
166
+ stub_get("/1/friendships/show.json?source_screen_name=dcrec1&target_screen_name=pengwynn", 'friendship.json')
167
+ @twitter.friendship_show(:source_screen_name => 'dcrec1', :target_screen_name => 'pengwynn').relationship.target.followed_by == false
168
+ end
169
+
170
+ should "be able to lookup a user" do
171
+ stub_get("/1/users/show/4243.json", "user.json")
172
+ user = @twitter.user(4243)
173
+ user.screen_name.should == "jnunemaker"
174
+ end
175
+
176
+ should "be able to lookup users in bulk" do
177
+ stub_get("/1/users/lookup.json?screen_name=sferik&user_id=59593,774010", "users.json")
178
+ users = @twitter.users("sferik", 59593, 774010)
179
+ users.first.screen_name.should == "sferik"
180
+ end
181
+
182
+ should "be able to search people" do
183
+ stub_get("/1/users/search.json?q=Wynn%20Netherland", 'people_search.json')
184
+ people = @twitter.user_search('Wynn Netherland')
185
+ people.first.screen_name.should == 'pengwynn'
186
+ end
187
+
188
+ should "be able to get followers' stauses" do
189
+ stub_get('/1/statuses/followers.json', 'followers.json')
190
+ followers = @twitter.followers
191
+ followers.should == @twitter.followers
192
+ end
193
+
194
+ should "be able to get blocked users' IDs" do
195
+ stub_get('/1/blocks/blocking/ids.json', 'ids.json')
196
+ blocked = @twitter.blocked_ids
197
+ blocked.should == @twitter.blocked_ids
198
+ end
199
+
200
+ should "be able to get an array of blocked users" do
201
+ stub_get('/1/blocks/blocking.json', 'blocking.json')
202
+ blocked = @twitter.blocking
203
+ blocked.last.screen_name.should == "euciavkvyplx"
204
+ end
205
+
206
+ should "upload a profile image" do
207
+ stub_post('/1/account/update_profile_image.json', 'update_profile_image.json')
208
+ user = @twitter.update_profile_image(File.new(sample_image('sample-image.png')))
209
+ user.name.should == 'John Nunemaker' # update_profile_image responds with the user
210
+ end
211
+
212
+ should "upload a background image" do
213
+ stub_post('/1/account/update_profile_background_image.json', 'update_profile_background_image.json')
214
+ user = @twitter.update_profile_background(File.new(sample_image('sample-image.png')))
215
+ user.name.should == 'John Nunemaker' # update_profile_background responds with the user
216
+ end
217
+ end
218
+
219
+ context "when using lists" do
220
+
221
+ should "be able to create a new list" do
222
+ stub_post('/1/pengwynn/lists.json', 'list.json')
223
+ list = @twitter.list_create('pengwynn', {:name => 'Rubyists'})
224
+ list.name.should == 'Rubyists'
225
+ list.slug.should == 'rubyists'
226
+ list.mode.should == 'public'
227
+ end
228
+
229
+ should "be able to update a list" do
230
+ stub_put('/1/pengwynn/lists/rubyists.json', 'list.json')
231
+ list = @twitter.list_update('pengwynn', 'rubyists', {:name => 'Rubyists'})
232
+ list.name.should == 'Rubyists'
233
+ list.slug.should == 'rubyists'
234
+ list.mode.should == 'public'
235
+ end
236
+
237
+ should "be able to delete a list" do
238
+ stub_delete('/1/pengwynn/lists/rubyists.json', 'list.json')
239
+ list = @twitter.list_delete('pengwynn', 'rubyists')
240
+ list.name.should == 'Rubyists'
241
+ list.slug.should == 'rubyists'
242
+ list.mode.should == 'public'
243
+ end
244
+
245
+ should "be able to view lists to which a user belongs" do
246
+ stub_get('/1/pengwynn/lists/memberships.json', 'memberships.json')
247
+ lists = @twitter.memberships('pengwynn').lists
248
+ lists.size.should == 16
249
+ lists.first.name.should == 'web-dev'
250
+ lists.first.member_count.should == 38
251
+ end
252
+
253
+ should "be able to view lists for the authenticated user" do
254
+ stub_get('/1/pengwynn/lists.json', 'lists.json')
255
+ lists = @twitter.lists('pengwynn').lists
256
+ lists.size.should == 1
257
+ lists.first.name.should == 'Rubyists'
258
+ lists.first.slug.should == 'rubyists'
259
+ end
260
+
261
+ should "be able to view list details" do
262
+ stub_get('/1/pengwynn/lists/rubyists.json', 'list.json')
263
+ list = @twitter.list('pengwynn', 'rubyists')
264
+ list.name.should == 'Rubyists'
265
+ list.subscriber_count.should == 0
266
+ end
267
+
268
+ should "be able to view list timeline" do
269
+ stub_get('/1/pengwynn/lists/rubyists/statuses.json', 'list_statuses.json')
270
+ tweets = @twitter.list_timeline('pengwynn', 'rubyists')
271
+ tweets.size.should == 20
272
+ tweets.first.id.should == 5272535583
273
+ tweets.first.user.name.should == 'John Nunemaker'
274
+ end
275
+
276
+ should "be able to limit number of tweets in list timeline" do
277
+ stub_get('/1/pengwynn/lists/rubyists/statuses.json?per_page=1', 'list_statuses_1_1.json')
278
+ tweets = @twitter.list_timeline('pengwynn', 'rubyists', :per_page => 1)
279
+ tweets.size.should == 1
280
+ tweets.first.id.should == 5272535583
281
+ tweets.first.user.name.should == 'John Nunemaker'
282
+ end
283
+
284
+ should "be able to paginate through the timeline" do
285
+ stub_get('/1/pengwynn/lists/rubyists/statuses.json?page=1&per_page=1', 'list_statuses_1_1.json')
286
+ stub_get('/1/pengwynn/lists/rubyists/statuses.json?page=2&per_page=1', 'list_statuses_2_1.json')
287
+ tweets = @twitter.list_timeline('pengwynn', 'rubyists', { :page => 1, :per_page => 1 })
288
+ tweets.size.should == 1
289
+ tweets.first.id.should == 5272535583
290
+ tweets.first.user.name.should == 'John Nunemaker'
291
+ tweets = @twitter.list_timeline('pengwynn', 'rubyists', { :page => 2, :per_page => 1 })
292
+ tweets.size.should == 1
293
+ tweets.first.id.should == 5264324712
294
+ tweets.first.user.name.should == 'John Nunemaker'
295
+ end
296
+
297
+ should "be able to view list members" do
298
+ stub_get('/1/pengwynn/rubyists/members.json', 'list_users.json')
299
+ members = @twitter.list_members('pengwynn', 'rubyists').users
300
+ members.size.should == 2
301
+ members.first.name.should == 'John Nunemaker'
302
+ members.first.screen_name.should == 'jnunemaker'
303
+ end
304
+
305
+ should "be able to add a member to a list" do
306
+ stub_post('/1/pengwynn/rubyists/members.json', 'user.json')
307
+ user = @twitter.list_add_member('pengwynn', 'rubyists', 4243)
308
+ user.screen_name.should == 'jnunemaker'
309
+ end
310
+
311
+ should "be able to remove a member from a list" do
312
+ stub_delete('/1/pengwynn/rubyists/members.json?id=4243', 'user.json')
313
+ user = @twitter.list_remove_member('pengwynn', 'rubyists', 4243)
314
+ user.screen_name.should == 'jnunemaker'
315
+ end
316
+
317
+ should "be able to check if a user is member of a list" do
318
+ stub_get('/1/pengwynn/rubyists/members/4243.json', 'user.json')
319
+ @twitter.is_list_member?('pengwynn', 'rubyists', 4243).should == true
320
+ end
321
+
322
+ should "be able to view list subscribers" do
323
+ stub_get('/1/pengwynn/rubyists/subscribers.json', 'list_users.json')
324
+ subscribers = @twitter.list_subscribers('pengwynn', 'rubyists').users
325
+ subscribers.size.should == 2
326
+ subscribers.first.name.should == 'John Nunemaker'
327
+ subscribers.first.screen_name.should == 'jnunemaker'
328
+ end
329
+
330
+ should "be able to subscribe to a list" do
331
+ stub_post('/1/pengwynn/rubyists/subscribers.json', 'user.json')
332
+ user = @twitter.list_subscribe('pengwynn', 'rubyists')
333
+ user.screen_name.should == 'jnunemaker'
334
+ end
335
+
336
+ should "be able to unsubscribe from a list" do
337
+ stub_delete('/1/pengwynn/rubyists/subscribers.json', 'user.json')
338
+ user = @twitter.list_unsubscribe('pengwynn', 'rubyists')
339
+ user.screen_name.should == 'jnunemaker'
340
+ end
341
+
342
+ should "be able to view a members list subscriptions" do
343
+ stub_get('/1/pengwynn/lists/subscriptions.json', 'list_subscriptions.json')
344
+ subscriptions = @twitter.list_subscriptions('pengwynn').lists
345
+ subscriptions.size.should == 1
346
+ subscriptions.first.full_name.should == '@chriseppstein/sass-users'
347
+ subscriptions.first.slug.should == 'sass-users'
348
+ end
349
+
350
+ end
351
+ end
352
+
353
+ context "when using a non-twitter service" do
354
+ setup do
355
+ @twitter = Twitter::Base.new(Twitter::HTTPAuth.new('wynn@example.com', 'mypass', :api_endpoint => 'tumblr.com'))
356
+ end
357
+
358
+ should "get the home timeline" do
359
+ stub_get('http://wynn%40example.com:mypass@tumblr.com/1/statuses/home_timeline.json', 'home_timeline.json')
360
+ timeline = @twitter.home_timeline
361
+ timeline.size.should == 20
362
+ end
363
+ end
364
+ end
@@ -0,0 +1,76 @@
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')
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')
28
+ twitter = Twitter::HTTPAuth.new('username', 'password', :ssl => false)
29
+ end
30
+ end
31
+
32
+ context "Client methods" do
33
+ setup do
34
+ @twitter = Twitter::HTTPAuth.new('username', 'password')
35
+ end
36
+
37
+ should "not throw error when accessing response message" do
38
+ stub_get('http://api.twitter.com:80/1/statuses/user_timeline.json', 'user_timeline.json')
39
+ response = @twitter.get('/1/statuses/user_timeline.json')
40
+ response.message.should == 'OK'
41
+ end
42
+
43
+ should "be able to get" do
44
+ stub_get('http://username:password@api.twitter.com:80/1/statuses/user_timeline.json', 'user_timeline.json')
45
+ response = @twitter.get('/1/statuses/user_timeline.json')
46
+ response.should == fixture_file('user_timeline.json')
47
+ end
48
+
49
+ should "be able to get with headers" do
50
+ @twitter.class.expects(:get).with(
51
+ '/1/statuses/user_timeline.json', {
52
+ :basic_auth => {:username => 'username', :password => 'password'},
53
+ :headers => {'Foo' => 'Bar'}
54
+ }
55
+ ).returns(fixture_file('user_timeline.json'))
56
+ @twitter.get('/1/statuses/user_timeline.json', {'Foo' => 'Bar'})
57
+ end
58
+
59
+ should "be able to post" do
60
+ stub_post('http://username:password@api.twitter.com:80/1/statuses/update.json', 'status.json')
61
+ response = @twitter.post('/1/statuses/update.json', :text => 'My update.')
62
+ response.should == fixture_file('status.json')
63
+ end
64
+
65
+ should "be able to post with headers" do
66
+ @twitter.class.expects(:post).with(
67
+ '/1/statuses/update.json', {
68
+ :headers => {'Foo' => 'Bar'},
69
+ :body => {:text => 'My update.'},
70
+ :basic_auth => {:username => 'username', :password => 'password'}
71
+ }
72
+ ).returns(fixture_file('status.json'))
73
+ @twitter.post('/1/statuses/update.json', {:text => 'My update.'}, {'Foo' => 'Bar'})
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,108 @@
1
+ require 'test_helper'
2
+
3
+ class OAuthTest < Test::Unit::TestCase
4
+ should "initialize with consumer token and secret" do
5
+ twitter = Twitter::OAuth.new('token', 'secret')
6
+
7
+ twitter.ctoken.should == 'token'
8
+ twitter.csecret.should == 'secret'
9
+ end
10
+
11
+ should "set autorization path to '/oauth/authorize' by default" do
12
+ twitter = Twitter::OAuth.new('token', 'secret')
13
+ twitter.consumer.options[:authorize_path].should == '/oauth/authorize'
14
+ end
15
+
16
+ should "set autorization path to '/oauth/authenticate' if sign_in_with_twitter" do
17
+ twitter = Twitter::OAuth.new('token', 'secret', :sign_in => true)
18
+ twitter.consumer.options[:authorize_path].should == '/oauth/authenticate'
19
+ end
20
+
21
+ should "have a consumer" do
22
+ consumer = mock('oauth consumer')
23
+ OAuth::Consumer.expects(:new).with('token', 'secret', {:site => 'http://api.twitter.com'}).returns(consumer)
24
+ twitter = Twitter::OAuth.new('token', 'secret')
25
+
26
+ twitter.consumer.should == consumer
27
+ end
28
+
29
+ should "have a request token from the consumer" do
30
+ consumer = mock('oauth consumer')
31
+ request_token = mock('request token')
32
+ consumer.expects(:get_request_token).returns(request_token)
33
+ OAuth::Consumer.expects(:new).with('token', 'secret', {:site => 'http://api.twitter.com'}).returns(consumer)
34
+ twitter = Twitter::OAuth.new('token', 'secret')
35
+
36
+ twitter.request_token.should == request_token
37
+ end
38
+
39
+ context "set_callback_url" do
40
+ should "clear request token and set the callback url" do
41
+ consumer = mock('oauth consumer')
42
+ request_token = mock('request token')
43
+
44
+ OAuth::Consumer.
45
+ expects(:new).
46
+ with('token', 'secret', {:site => 'http://api.twitter.com'}).
47
+ returns(consumer)
48
+
49
+ twitter = Twitter::OAuth.new('token', 'secret')
50
+
51
+ consumer.
52
+ expects(:get_request_token).
53
+ with({:oauth_callback => 'http://myapp.com/oauth_callback'})
54
+
55
+ twitter.set_callback_url('http://myapp.com/oauth_callback')
56
+ end
57
+ end
58
+
59
+ should "be able to create access token from request token, request secret and verifier" do
60
+ twitter = Twitter::OAuth.new('token', 'secret')
61
+ consumer = OAuth::Consumer.new('token', 'secret', {:site => 'http://api.twitter.com'})
62
+ twitter.stubs(:consumer).returns(consumer)
63
+
64
+ access_token = mock('access token', :token => 'atoken', :secret => 'asecret')
65
+ request_token = mock('request token')
66
+ request_token.
67
+ expects(:get_access_token).
68
+ with(:oauth_verifier => 'verifier').
69
+ returns(access_token)
70
+
71
+ OAuth::RequestToken.
72
+ expects(:new).
73
+ with(consumer, 'rtoken', 'rsecret').
74
+ returns(request_token)
75
+
76
+ twitter.authorize_from_request('rtoken', 'rsecret', 'verifier')
77
+ twitter.access_token.class.should be(OAuth::AccessToken)
78
+ twitter.access_token.token.should == 'atoken'
79
+ twitter.access_token.secret.should == 'asecret'
80
+ end
81
+
82
+ should "be able to create access token from access token and secret" do
83
+ twitter = Twitter::OAuth.new('token', 'secret')
84
+ consumer = OAuth::Consumer.new('token', 'secret', {:site => 'http://api.twitter.com'})
85
+ twitter.stubs(:consumer).returns(consumer)
86
+
87
+ twitter.authorize_from_access('atoken', 'asecret')
88
+ twitter.access_token.class.should be(OAuth::AccessToken)
89
+ twitter.access_token.token.should == 'atoken'
90
+ twitter.access_token.secret.should == 'asecret'
91
+ end
92
+
93
+ should "delegate get to access token" do
94
+ access_token = mock('access token')
95
+ twitter = Twitter::OAuth.new('token', 'secret')
96
+ twitter.stubs(:access_token).returns(access_token)
97
+ access_token.expects(:get).returns(nil)
98
+ twitter.get('/foo')
99
+ end
100
+
101
+ should "delegate post to access token" do
102
+ access_token = mock('access token')
103
+ twitter = Twitter::OAuth.new('token', 'secret')
104
+ twitter.stubs(:access_token).returns(access_token)
105
+ access_token.expects(:post).returns(nil)
106
+ twitter.post('/foo')
107
+ end
108
+ end