secobarbital-twitter 0.9.2.1

Sign up to get free protection for your applications and to get access to all the features.
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