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