tweetable 0.1.10
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/Gemfile +8 -0
- data/History.txt +4 -0
- data/Manifest.txt +33 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +37 -0
- data/Rakefile +19 -0
- data/VERSION +1 -0
- data/lib/tweetable/authorization.rb +21 -0
- data/lib/tweetable/collection.rb +54 -0
- data/lib/tweetable/link.rb +30 -0
- data/lib/tweetable/message.rb +119 -0
- data/lib/tweetable/persistable.rb +32 -0
- data/lib/tweetable/photo.rb +6 -0
- data/lib/tweetable/queue.rb +121 -0
- data/lib/tweetable/search.rb +77 -0
- data/lib/tweetable/twitter_client.rb +36 -0
- data/lib/tweetable/twitter_streaming_client.rb +67 -0
- data/lib/tweetable/url.rb +39 -0
- data/lib/tweetable/user.rb +104 -0
- data/lib/tweetable.rb +82 -0
- data/pkg/tweetable-0.1.7.gem +0 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/collection_spec.rb +55 -0
- data/spec/fixtures/blank.json +1 -0
- data/spec/fixtures/flippyhead.json +1 -0
- data/spec/fixtures/follower_ids.json +1 -0
- data/spec/fixtures/friend_ids.json +1 -0
- data/spec/fixtures/friends_timeline.json +1 -0
- data/spec/fixtures/link_blank.json +1 -0
- data/spec/fixtures/link_exists.json +1 -0
- data/spec/fixtures/rate_limit_status.json +1 -0
- data/spec/fixtures/search.json +1 -0
- data/spec/fixtures/user_timeline.json +1 -0
- data/spec/fixtures/verify_credentials.json +1 -0
- data/spec/link_spec.rb +35 -0
- data/spec/message_spec.rb +148 -0
- data/spec/persistable_spec.rb +53 -0
- data/spec/queue_spec.rb +29 -0
- data/spec/search_spec.rb +60 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/tweetable_spec.rb +19 -0
- data/spec/twitter_client_spec.rb +41 -0
- data/spec/twitter_streaming_client_spec.rb +18 -0
- data/spec/user_spec.rb +143 -0
- data/tweetable.gemspec +106 -0
- metadata +165 -0
@@ -0,0 +1 @@
|
|
1
|
+
{"created_at":"Wed Feb 20 04:05:51 +0000 2008","description":"Haha made ya read!","profile_background_tile":false,"profile_link_color":"FF0000","status":{"created_at":"Sun Apr 04","in_reply_to_status_id":null,"favorited":false,"source":"<a href=\"http://gettwidget.com/\" rel=\"nofollow\">Twidget</a>","in_reply_to_user_id":null,"truncated":false,"in_reply_to_screen_name":null,"id":11572672967,"text":"http://iamawesome.com/"},"following":false,"followers_count":229,"statuses_count":247,"profile_sidebar_fill_color":"FFF7CC","url":"http://wagglelabs.com","notifications":false,"friends_count":339,"profile_image_url":"http://a3.twimg.com/profile_images/74792235/screen-capture-2_normal.png","contributors_enabled":false,"time_zone":"Pacific Time (US & Canada)","profile_sidebar_border_color":"F2E195","location":"Capitol Hill, Washington","favourites_count":2,"screen_name":"Flippyhead","protected":false,"geo_enabled":true,"profile_background_color":"BADFCD","name":"Peter T. Brown","id":13705052,"lang":"en","verified":false,"profile_background_image_url":"http://s.twimg.com/a/1269553143/images/themes/theme12/bg.gif","utc_offset":-28800,"profile_text_color":"0C3E53"}
|
data/spec/link_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
attrs = {:url => 'http://someurl.com', :created_at => Time.now.utc.to_s, :screen_name => 'somename'}
|
4
|
+
|
5
|
+
describe Tweetable::Link, 'when doing CRUD' do
|
6
|
+
before do
|
7
|
+
RedisSpecHelper.reset
|
8
|
+
@link = Tweetable::Link.create(:url => attrs[:url], :created_at => attrs[:created_at])
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should find link by URL" do
|
12
|
+
link = Tweetable::Link.find(:url => attrs[:url]).first
|
13
|
+
link.url.should == attrs[:url]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Tweetable::Link, 'when counting' do
|
18
|
+
before do
|
19
|
+
RedisSpecHelper.reset
|
20
|
+
@link = Tweetable::Link.create(:url => attrs[:url], :created_at => attrs[:created_at])
|
21
|
+
@user = Tweetable::User.create(:screen_name => attrs[:screen_name])
|
22
|
+
@link.users.add(@user)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not increment count for users already in set" do
|
26
|
+
@link.should_not_receive(:incr).with(:count)
|
27
|
+
@link.increment_usage_count(@user)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should increment count for users already in set" do
|
31
|
+
user = Tweetable::User.create(:screen_name => attrs[:screen_name] + '_other')
|
32
|
+
@link.should_receive(:incr).with(:count)
|
33
|
+
@link.increment_usage_count(user)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
attrs = {:short_url => 'http://bit.ly/k1n4M', :long_url => 'http://pathable.com', :from_screen_name => 'somename'}
|
4
|
+
|
5
|
+
describe Tweetable::Message do
|
6
|
+
before do
|
7
|
+
RedisSpecHelper.reset
|
8
|
+
stub_get('http://www.longurlplease.com/api/v1.1?q=http%3A%2F%2Fwww.thisisalink.com%2Fwith-a-path%2Fand-so_forth.xml', 'link_blank.json')
|
9
|
+
stub_get('http://www.longurlplease.com/api/v1.1?q=http%3A%2F%2Fbit.ly%2Fk1n4M', 'link_exists.json')
|
10
|
+
|
11
|
+
@user = Tweetable::User.create(:screen_name => attrs[:from_screen_name])
|
12
|
+
@message = Tweetable::Message.create(
|
13
|
+
:message_id => '1234',
|
14
|
+
:text => "here a link http://www.thisisalink.com/with-a-path/and-so_forth.xml there a link #{attrs[:short_url]}",
|
15
|
+
:links_parsed => "0",
|
16
|
+
:photos_parsed => "0",
|
17
|
+
:from_screen_name => attrs[:from_screen_name],
|
18
|
+
:created_at => Time.now
|
19
|
+
)
|
20
|
+
@message.parse_links
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when doing CRUD" do
|
24
|
+
it "shuould find from_user" do
|
25
|
+
@message.from_user.should == @user
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should consider two objects with same id ==" do
|
29
|
+
copy = @message.dup
|
30
|
+
(copy == @message).should be_true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when purging" do
|
35
|
+
it "should get all" do
|
36
|
+
Tweetable::Message.should_receive(:all).and_return(mock("AllMessages", :sort => []))
|
37
|
+
Tweetable::Message.purge
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should delete message if block returns true" do
|
41
|
+
mock_message = mock(Tweetable::Message)
|
42
|
+
mock_message.should_receive(:delete).once
|
43
|
+
|
44
|
+
Tweetable::Message.should_receive(:all).and_return(mock("AllMessages", :sort => [mock_message]))
|
45
|
+
Tweetable::Message.purge do
|
46
|
+
true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not delete message if block returns false" do
|
51
|
+
mock_message = mock(Tweetable::Message)
|
52
|
+
mock_message.should_receive(:delete).never
|
53
|
+
|
54
|
+
Tweetable::Message.should_receive(:all).and_return(mock("AllMessages", :sort => [mock_message]))
|
55
|
+
Tweetable::Message.purge do
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when parsing links" do
|
62
|
+
it "should should add of Link type" do
|
63
|
+
@message.links.first.should be_instance_of Tweetable::Link
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should add with correct URL" do
|
67
|
+
@message.links.first.url.should == 'http://www.thisisalink.com/with-a-path/and-so_forth.xml'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should extract multiple" do
|
71
|
+
@message.links.size.should == 2
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should initialize counter at 1" do
|
75
|
+
@message.links.first.count.should == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should flag message as parsed" do
|
79
|
+
@message.links_parsed.should == "1"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not parse already parsed" do
|
83
|
+
@message.text.should_not_receive(:scan)
|
84
|
+
@message.parse_links
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should be able to find parsed links" do
|
88
|
+
@message.parse_links
|
89
|
+
link = Tweetable::Link.find(:url => attrs[:short_url]).first
|
90
|
+
link.should_not be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should search messages for non parsed links" do
|
94
|
+
Tweetable::Message.find(:links_parsed => "0") do |results|
|
95
|
+
results.each do |message|
|
96
|
+
links = message.parse_links
|
97
|
+
links.size.should == 1
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should get long url for short urls" do
|
103
|
+
@message.links.all[1].long_url.should == attrs[:long_url]
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should increment links count on other messages with link" do
|
107
|
+
Tweetable::User.create(:screen_name => attrs[:from_screen_name] + '_other')
|
108
|
+
|
109
|
+
message = Tweetable::Message.create(
|
110
|
+
:message_id => '5678',
|
111
|
+
:text => "xxx #{attrs[:short_url]} rrr",
|
112
|
+
:created_at => Time.now.utc.to_s,
|
113
|
+
:from_screen_name => attrs[:from_screen_name] + '_other',
|
114
|
+
:links_parsed => "0",
|
115
|
+
:photos_parsed => "0")
|
116
|
+
|
117
|
+
message.parse_links
|
118
|
+
message.links.first.count.should == 2
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not increment links count on other messages from same user" do
|
122
|
+
message = Tweetable::Message.create(
|
123
|
+
:message_id => '5678',
|
124
|
+
:text => "xxx #{attrs[:short_url]} rrr",
|
125
|
+
:links_parsed => "0",
|
126
|
+
:photos_parsed => "0",
|
127
|
+
:from_screen_name => attrs[:from_screen_name],
|
128
|
+
:created_at => Time.now)
|
129
|
+
|
130
|
+
message.parse_links
|
131
|
+
message.links.first.count.should == 1
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should not try to create already existing link" do
|
135
|
+
message = Tweetable::Message.create(:message_id => '5678', :text => "xxx #{attrs[:short_url]}", :created_at => Time.now, :links_parsed => "0", :photos_parsed => "0")
|
136
|
+
Tweetable::Link.should_not_receive(:create)
|
137
|
+
message.parse_links
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'when posting status updates' do
|
142
|
+
it "should return new messages" do
|
143
|
+
# Tweetable::Message.should_receive(:create_from_timeline).once
|
144
|
+
# Tweetable::Message.create_from_status('a status update')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
attrs = {:now => Time.new.to_s, :then => 'Sat Sep 26 13:32:22 -0700 2009'}
|
4
|
+
|
5
|
+
describe Tweetable::Persistable do
|
6
|
+
before do
|
7
|
+
RedisSpecHelper.reset
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'when building' do
|
11
|
+
before do
|
12
|
+
Tweetable.login('l', 'p')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have a twitter client" do
|
16
|
+
item = Tweetable::Persistable.create(:created_at => attrs[:now], :updated_at => attrs[:now])
|
17
|
+
item.send(:client).class.should == Tweetable::TwitterClient
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should store a persistable item with dates" do
|
21
|
+
item = Tweetable::Persistable.create(:created_at => attrs[:now], :updated_at => attrs[:now])
|
22
|
+
item.should be_valid
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should find or create new" do
|
26
|
+
item = Tweetable::User.find_or_create(:screen_name, 'Flippyhead')
|
27
|
+
item.should be_valid
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should find or create existing" do
|
31
|
+
existing = Tweetable::User.create(:screen_name => 'Flippyhead', :created_at => Time.now.utc.to_s)
|
32
|
+
item = Tweetable::User.find_or_create(:screen_name, 'Flippyhead')
|
33
|
+
existing.id.to_s.should == item.id.to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when needs update' do
|
38
|
+
it "should not need_update when new" do
|
39
|
+
item = Tweetable::Persistable.create(:updated_at => attrs[:now])
|
40
|
+
item.should_not be_needs_update
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should need_update when old enough" do
|
44
|
+
item = Tweetable::Persistable.create(:updated_at => attrs[:then])
|
45
|
+
item.should be_needs_update
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should need_update when forced" do
|
49
|
+
item = Tweetable::Persistable.create(:updated_at => attrs[:now])
|
50
|
+
item.should be_needs_update(true)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/queue_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
#
|
3
|
+
# search_attrs ={:name => 'test-search_queue', :queries => ['google','pathable']}
|
4
|
+
#
|
5
|
+
# describe Tweetable::Queue, 'when adding to search queue' do
|
6
|
+
# before do
|
7
|
+
# RedisSpecHelper.reset
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# it "should create search queue" do
|
11
|
+
# Tweetable::Queue.add_to_search_queue(search_attrs[:name], search_attrs[:queries])
|
12
|
+
# queue = Tweetable::SearchCollection.find(:name, search_attrs[:name]).first
|
13
|
+
# queue.should_not be_nil
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# it "should add queries to queue collection" do
|
17
|
+
# Tweetable::Queue.add_to_search_queue(search_attrs[:name], search_attrs[:queries])
|
18
|
+
# queue = Tweetable::SearchCollection.find(:name, search_attrs[:name]).first
|
19
|
+
# queue.searches.size.should == 2
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# it "should process things passed to block" do
|
23
|
+
# Tweetable::Queue.add_to_search_queue(search_attrs[:name], search_attrs[:queries]) do |search|
|
24
|
+
# search.update(:query => 'xxx')
|
25
|
+
# end
|
26
|
+
# queue = Tweetable::SearchCollection.find(:name, search_attrs[:name]).first
|
27
|
+
# queue.searches.collect{|s| s.query}.should include('xxx')
|
28
|
+
# end
|
29
|
+
# end
|
data/spec/search_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
attrs = {:valid_query => 'google'}
|
4
|
+
|
5
|
+
describe Tweetable::Search, 'when searching' do
|
6
|
+
before do
|
7
|
+
RedisSpecHelper.reset
|
8
|
+
@search = Tweetable::Search.create(:query => attrs[:valid_query], :created_at => DateTime.now)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when searching' do
|
12
|
+
before do
|
13
|
+
14.times do |page|
|
14
|
+
stub_get("http://search.twitter.com/search.json?rpp=100&page=#{page}&since_id=0&q=google", 'search.json')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find messages for valid search" do
|
19
|
+
@search.update_messages(1)
|
20
|
+
@search.messages.first.should be_instance_of Tweetable::Message
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should store messages after search" do
|
24
|
+
@search.update_messages(1)
|
25
|
+
search = Tweetable::Search.find(:query => 'google').first
|
26
|
+
search.messages.first.should be_instance_of Tweetable::Message
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should create users associated with messages" do
|
30
|
+
@search.update_messages(1)
|
31
|
+
search = Tweetable::Search.find(:query => 'google').first
|
32
|
+
search.messages.first.from_user.should be_instance_of Tweetable::User
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should update existing messages but not duplicate in messages list" do
|
36
|
+
stub_get("http://search.twitter.com/search.json?q=google&rpp=100&since_id=11674745688&page=1", 'search.json') # since_id is last id in search.json
|
37
|
+
|
38
|
+
@search.update_messages(1)
|
39
|
+
search = Tweetable::Search.find(:query => 'google').first
|
40
|
+
search.messages.size.should == 100
|
41
|
+
|
42
|
+
@search.update_messages(1)
|
43
|
+
search.messages.size.should == 100 # not adding duplicates to messages list
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should get multiple pages" do
|
47
|
+
array = Array.new
|
48
|
+
array.stub!(:size => 100)
|
49
|
+
@search.should_receive(:search).exactly(3).times.and_return(mock('search', :results => array))
|
50
|
+
@search.update_messages(3)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when doing CRUD' do
|
55
|
+
it "should have validations errors with invald data" do
|
56
|
+
item = Tweetable::Search.create(:created_at => DateTime.now)
|
57
|
+
item.errors.should == [[:query, :not_present]]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
gem 'rspec'
|
6
|
+
require 'spec'
|
7
|
+
end
|
8
|
+
|
9
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
10
|
+
require 'rubygems'
|
11
|
+
require 'ohm'
|
12
|
+
require 'redis'
|
13
|
+
require 'tweetable'
|
14
|
+
require 'fakeweb'
|
15
|
+
|
16
|
+
FakeWeb.allow_net_connect = false
|
17
|
+
|
18
|
+
def twitter_url(path, login=nil, password=nil)
|
19
|
+
if path =~ /^http/
|
20
|
+
path
|
21
|
+
else
|
22
|
+
login || pass ? "http://#{login}:#{password}@api.twitter.com#{path}" : path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def fixture_file(filename)
|
27
|
+
return '' if filename == ''
|
28
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
|
29
|
+
File.read(file_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def stub_get(url, filename, options = {})
|
33
|
+
fwoptions = {:body => fixture_file(filename)}
|
34
|
+
fwoptions.merge!({:status => options[:status]}) unless options[:status].nil?
|
35
|
+
FakeWeb.register_uri(:get, twitter_url(url, options[:login], options[:password]), fwoptions)
|
36
|
+
end
|
37
|
+
|
38
|
+
def stub_post(url, filename)
|
39
|
+
FakeWeb.register_uri(:post, twitter_url(url), :body => fixture_file(filename))
|
40
|
+
end
|
41
|
+
|
42
|
+
def stub_put(url, filename)
|
43
|
+
FakeWeb.register_uri(:put, twitter_url(url), :body => fixture_file(filename))
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
class RedisSpecHelper
|
48
|
+
TEST_OPTIONS = {:db => 11}
|
49
|
+
|
50
|
+
def self.reset
|
51
|
+
Ohm.connect(TEST_OPTIONS)
|
52
|
+
Ohm.flush
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Tweetable do
|
4
|
+
before do
|
5
|
+
Tweetable.config({:max_message_count=>10})
|
6
|
+
RedisSpecHelper.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'when configuring' do
|
10
|
+
it "should use default config values" do
|
11
|
+
Tweetable.config.should == Tweetable::DEFAULT_CONFIG
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should update the config" do
|
15
|
+
Tweetable.config({:max_message_count=>101})
|
16
|
+
Tweetable.config[:max_message_count].should == 101
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Tweetable::TwitterClient do
|
4
|
+
before do
|
5
|
+
RedisSpecHelper.reset
|
6
|
+
stub_get('/1/account/rate_limit_status.json', 'rate_limit_status.json', {:login => 'l', :password => 'p'})
|
7
|
+
stub_get('/1/account/verify_credentials.json', 'verify_credentials.json', {:login => 'l', :password => 'p'})
|
8
|
+
|
9
|
+
@twitter = Tweetable::TwitterClient.new
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when not logged in' do
|
13
|
+
it "should require login" do
|
14
|
+
expect {
|
15
|
+
@twitter.verify_credentials
|
16
|
+
}.should raise_exception(Tweetable::TweetableAuthError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise exception with nil authorization" do
|
20
|
+
expect {
|
21
|
+
@twitter.authorize(nil, nil, nil)
|
22
|
+
}.should raise_exception(Tweetable::TweetableAuthError)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when logged in' do
|
28
|
+
before do
|
29
|
+
@twitter.login('l', 'p')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should verify credentials of valid user" do
|
33
|
+
info = @twitter.verify_credentials
|
34
|
+
info.name.should == 'Peter T. Brown'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should get rate limit status" do
|
38
|
+
@twitter.status.should include(:hourly_limit)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Tweetable::TwitterStreamingClient, 'when streaming' do
|
4
|
+
before do
|
5
|
+
RedisSpecHelper.reset
|
6
|
+
@twitter = Tweetable::TwitterStreamingClient.new('flippyhead', 'apple2406')
|
7
|
+
end
|
8
|
+
|
9
|
+
# it "should stream sample" do
|
10
|
+
# message = nil
|
11
|
+
# @twitter.sample do |m|
|
12
|
+
# message = m
|
13
|
+
# break
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# message.should include(:text)
|
17
|
+
# end
|
18
|
+
end
|
data/spec/user_spec.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
attrs = {:screen_name => 'flippyhead', :user_id => '13705052', :created_at => Time.now.utc.to_s, :updated_at => Time.now.utc.to_s}
|
4
|
+
|
5
|
+
describe Tweetable::User do
|
6
|
+
before do
|
7
|
+
RedisSpecHelper.reset
|
8
|
+
@user = Tweetable::User.create(attrs)
|
9
|
+
|
10
|
+
Tweetable.login('l', 'p')
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when building and saving" do
|
14
|
+
it "should store a user item with screen_name, user_id, and created_at attributes" do
|
15
|
+
@user.should be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should save user info after modification" do
|
19
|
+
@user.user_id = 12345
|
20
|
+
@user.save
|
21
|
+
Tweetable::User.find(:screen_name => attrs[:screen_name]).first.user_id.should == '12345'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set created_at" do
|
25
|
+
Tweetable::User.find(:screen_name => attrs[:screen_name]).first.created_at.should == attrs[:created_at]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not save user info without calling save" do
|
29
|
+
@user.user_id = '12345'
|
30
|
+
Tweetable::User.find(:screen_name => attrs[:screen_name]).first.user_id.should == attrs[:user_id]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should find stored user by screen_name" do
|
34
|
+
Tweetable::User.find(:screen_name => attrs[:screen_name]).first.screen_name.should == attrs[:screen_name]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when updating info" do
|
40
|
+
before do
|
41
|
+
stub_get('/1/users/show/flippyhead.json', 'flippyhead.json', {:login => 'l', :password => 'p'})
|
42
|
+
stub_get('/1/users/show/13705052.json', 'flippyhead.json', {:login => 'l', :password => 'p'})
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should get using just screen_name" do
|
46
|
+
@user.update_info
|
47
|
+
@user.user_id.should == 13705052
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should save after fetching" do
|
51
|
+
@user.should_receive(:save)
|
52
|
+
@user.update_info
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should get user_id" do
|
56
|
+
@user.update_info
|
57
|
+
Tweetable::User.find(:screen_name => attrs[:screen_name]).first.user_id.should == attrs[:user_id]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get friend count" do
|
61
|
+
@user.update_info
|
62
|
+
@user.friends_count.should > 0
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should get profile image url" do
|
66
|
+
@user.update_info
|
67
|
+
@user.profile_image_url.should == 'http://a3.twimg.com/profile_images/74792235/screen-capture-2_normal.png'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should get follower counts" do
|
71
|
+
@user.update_info
|
72
|
+
@user.friends_count.should > 0
|
73
|
+
end
|
74
|
+
|
75
|
+
# it "should find stored user by screen_name regardless of case" do
|
76
|
+
# user = Tweetable::User.create(:screen_name => attrs[:screen_name].upcase)
|
77
|
+
# user.update_info
|
78
|
+
# users = Tweetable::User.find(:screen_name => attrs[:screen_name].downcase)
|
79
|
+
# users.first.screen_name.should == attrs[:screen_name]
|
80
|
+
# end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when updating friends and followers' do
|
84
|
+
before do
|
85
|
+
stub_get('/1/followers/ids.json?screen_name=flippyhead&page=1', 'follower_ids.json', {:login => 'l', :password => 'p'})
|
86
|
+
stub_get('/1/friends/ids.json?screen_name=flippyhead&page=1', 'friend_ids.json', {:login => 'l', :password => 'p'})
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should update friend_ids" do
|
90
|
+
@user.update_friend_ids
|
91
|
+
@user.friend_ids.size.should > 0
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should update follower_ids" do
|
95
|
+
@user.update_follower_ids
|
96
|
+
@user.follower_ids.size.should > 0
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when updating messages' do
|
101
|
+
before do
|
102
|
+
stub_get('/1/statuses/friends_timeline.json?screen_name=flippyhead&count=10', 'friends_timeline.json', {:login => 'l', :password => 'p'})
|
103
|
+
stub_get('/1/statuses/user_timeline.json?screen_name=flippyhead&count=10', 'user_timeline.json', {:login => 'l', :password => 'p'})
|
104
|
+
stub_get('/1/statuses/user_timeline.json?screen_name=flippyhead&count=10&since_id=11572672967', 'blank.json', {:login => 'l', :password => 'p'})
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should return new messages" do
|
108
|
+
@user.update_messages.size.should > 0
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should store created_at date" do
|
112
|
+
@user.update_messages
|
113
|
+
@user.messages.first.created_at.should_not be_nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should build message objects" do
|
117
|
+
@user.update_messages
|
118
|
+
@user.messages.first.should be_instance_of Tweetable::Message
|
119
|
+
@user.messages.first.text.should_not be_blank
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should only get created since last message" do
|
123
|
+
@user.update_messages.size.should > 0
|
124
|
+
@user.update_messages.size.should == 0
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not duplicate messages" do
|
128
|
+
@user.update_messages.size.should > 0
|
129
|
+
@user.update_messages.size.should == 0
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should build friend message objects" do
|
133
|
+
@user.update_friend_messages
|
134
|
+
@user.friend_messages.first.should be_instance_of Tweetable::Message
|
135
|
+
@user.friend_messages.first.text.should_not be_blank
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should create associated users for friend messages" do
|
139
|
+
@user.update_friend_messages
|
140
|
+
@user.friend_messages.first.from_user.should_not be_nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|