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.
- data/History +271 -0
- data/License +20 -0
- data/Notes +33 -0
- data/README.rdoc +19 -0
- data/Rakefile +39 -0
- data/VERSION.yml +5 -0
- data/examples/connect.rb +30 -0
- data/examples/friendship_existance.rb +13 -0
- data/examples/helpers/config_store.rb +38 -0
- data/examples/httpauth.rb +11 -0
- data/examples/ids.rb +13 -0
- data/examples/lists.rb +11 -0
- data/examples/oauth.rb +27 -0
- data/examples/search.rb +15 -0
- data/examples/timeline.rb +19 -0
- data/examples/tumblr.rb +9 -0
- data/examples/unauthorized.rb +16 -0
- data/examples/update.rb +11 -0
- data/examples/user.rb +5 -0
- data/lib/twitter/base.rb +371 -0
- data/lib/twitter/httpauth.rb +39 -0
- data/lib/twitter/local_trends.rb +15 -0
- data/lib/twitter/oauth.rb +58 -0
- data/lib/twitter/request.rb +71 -0
- data/lib/twitter/search.rb +157 -0
- data/lib/twitter/trends.rb +41 -0
- data/lib/twitter.rb +148 -0
- data/test/fixtures/blocking.json +1632 -0
- data/test/fixtures/firehose.json +1 -0
- data/test/fixtures/follower_ids.json +1 -0
- data/test/fixtures/followers.json +1 -0
- data/test/fixtures/friend_ids.json +1 -0
- data/test/fixtures/friends_timeline.json +1 -0
- data/test/fixtures/friendship.json +1 -0
- data/test/fixtures/home_timeline.json +1 -0
- data/test/fixtures/ids.json +1 -0
- data/test/fixtures/list.json +1 -0
- data/test/fixtures/list_statuses.json +1 -0
- data/test/fixtures/list_statuses_1_1.json +1 -0
- data/test/fixtures/list_statuses_2_1.json +1 -0
- data/test/fixtures/list_subscriptions.json +1 -0
- data/test/fixtures/list_users.json +1 -0
- data/test/fixtures/lists.json +1 -0
- data/test/fixtures/memberships.json +1 -0
- data/test/fixtures/mentions.json +1 -0
- data/test/fixtures/not_found.json +1 -0
- data/test/fixtures/people_search.json +39 -0
- data/test/fixtures/rate_limit_exceeded.json +1 -0
- data/test/fixtures/retweet.json +1 -0
- data/test/fixtures/retweeted_by_me.json +1 -0
- data/test/fixtures/retweeted_to_me.json +1 -0
- data/test/fixtures/retweeters_of_tweet.json +166 -0
- data/test/fixtures/retweets.json +1 -0
- data/test/fixtures/retweets_of_me.json +1 -0
- data/test/fixtures/sample-image.png +0 -0
- data/test/fixtures/search.json +1 -0
- data/test/fixtures/search_from_jnunemaker.json +1 -0
- data/test/fixtures/status.json +1 -0
- data/test/fixtures/status_show.json +1 -0
- data/test/fixtures/trends_available.json +253 -0
- data/test/fixtures/trends_current.json +1 -0
- data/test/fixtures/trends_current_exclude.json +1 -0
- data/test/fixtures/trends_daily.json +1925 -0
- data/test/fixtures/trends_daily_date.json +1 -0
- data/test/fixtures/trends_daily_exclude.json +1 -0
- data/test/fixtures/trends_location.json +57 -0
- data/test/fixtures/trends_weekly.json +1 -0
- data/test/fixtures/trends_weekly_date.json +1 -0
- data/test/fixtures/trends_weekly_exclude.json +1 -0
- data/test/fixtures/unauthorized.json +1 -0
- data/test/fixtures/update_profile_background_image.json +1 -0
- data/test/fixtures/update_profile_image.json +1 -0
- data/test/fixtures/user.json +1 -0
- data/test/fixtures/user_timeline.json +710 -0
- data/test/fixtures/users.json +1 -0
- data/test/test_helper.rb +46 -0
- data/test/twitter/base_test.rb +364 -0
- data/test/twitter/httpauth_test.rb +76 -0
- data/test/twitter/oauth_test.rb +108 -0
- data/test/twitter/request_test.rb +217 -0
- data/test/twitter/search_test.rb +208 -0
- data/test/twitter/trends_test.rb +112 -0
- data/test/twitter_test.rb +106 -0
- 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"}]
|
data/test/test_helper.rb
ADDED
@@ -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
|