stocktwits 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README +0 -0
- data/README.rdoc +17 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/app/controllers/sessions_controller.rb +68 -0
- data/app/models/stocktwits/basic_user.rb +64 -0
- data/app/models/stocktwits/generic_user.rb +123 -0
- data/app/models/stocktwits/oauth_user.rb +46 -0
- data/app/models/stocktwits/plain_user.rb +53 -0
- data/app/views/sessions/_login.html.erb +18 -0
- data/app/views/sessions/new.html.erb +5 -0
- data/config/routes.rb +6 -0
- data/generators/stocktwits/USAGE +12 -0
- data/generators/stocktwits/stocktwits_generator.rb +42 -0
- data/generators/stocktwits/templates/migration.rb +20 -0
- data/generators/stocktwits/templates/stocktwits.yml +66 -0
- data/generators/stocktwits/templates/user.rb +5 -0
- data/lib/stocktwits.rb +103 -0
- data/lib/stocktwits/controller_extensions.rb +72 -0
- data/lib/stocktwits/cryptify.rb +30 -0
- data/lib/stocktwits/dispatcher/basic.rb +46 -0
- data/lib/stocktwits/dispatcher/oauth.rb +26 -0
- data/lib/stocktwits/dispatcher/plain.rb +44 -0
- data/lib/stocktwits/dispatcher/shared.rb +42 -0
- data/rails/init.rb +6 -0
- data/spec/application.rb +1 -0
- data/spec/controllers/controller_extensions_spec.rb +162 -0
- data/spec/controllers/sessions_controller_spec.rb +221 -0
- data/spec/debug.log +397 -0
- data/spec/fixtures/config/twitter_auth.yml +17 -0
- data/spec/fixtures/factories.rb +28 -0
- data/spec/fixtures/fakeweb.rb +18 -0
- data/spec/fixtures/stocktwits.rb +5 -0
- data/spec/models/stocktwits/basic_user_spec.rb +138 -0
- data/spec/models/stocktwits/generic_user_spec.rb +146 -0
- data/spec/models/stocktwits/oauth_user_spec.rb +100 -0
- data/spec/schema.rb +25 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +107 -0
- data/spec/stocktwits/cryptify_spec.rb +51 -0
- data/spec/stocktwits/dispatcher/basic_spec.rb +83 -0
- data/spec/stocktwits/dispatcher/oauth_spec.rb +72 -0
- data/spec/stocktwits/dispatcher/shared_spec.rb +26 -0
- data/spec/stocktwits_spec.rb +173 -0
- data/stocktwits.gemspec +116 -0
- metadata +158 -0
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
TWITTER_JSON = {
|
4
|
+
:verify_credentials => "{\"profile_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/default_profile_normal.png\",\"description\":\"Saving the world for all Twitter kind.\",\"utc_offset\":null,\"favourites_count\":0,\"profile_sidebar_fill_color\":\"e0ff92\",\"screen_name\":\"twitterman\",\"statuses_count\":0,\"profile_background_tile\":false,\"profile_sidebar_border_color\":\"87bc44\",\"friends_count\":2,\"url\":null,\"name\":\"Twitter Man\",\"time_zone\":null,\"protected\":false,\"profile_background_image_url\":\"http:\\/\\/static.twitter.com\\/images\\/themes\\/theme1\\/bg.gif\",\"profile_background_color\":\"9ae4e8\",\"created_at\":\"Fri Feb 06 18:10:32 +0000 2009\",\"profile_text_color\":\"000000\",\"followers_count\":2,\"location\":null,\"id\":20256865,\"profile_link_color\":\"0000ff\"}"
|
5
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Stocktwits::BasicUser do
|
4
|
+
before do
|
5
|
+
stub_basic!
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#password=' do
|
9
|
+
before do
|
10
|
+
@user = Factory.build(:stocktwits_basic_user, :stocktwits_id => '123')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should change the value of crypted_password' do
|
14
|
+
lambda{@user.password = 'newpass'}.should change(@user, :crypted_password)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should change the value of salt' do
|
18
|
+
lambda{@user.password = 'newpass'}.should change(@user, :salt)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should not store the plaintext password' do
|
22
|
+
@user.password = 'newpass'
|
23
|
+
@user.crypted_password.should_not == 'newpass'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#password' do
|
28
|
+
before do
|
29
|
+
@user = Factory.build(:stocktwits_basic_user, :password => 'monkey')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should return the password' do
|
33
|
+
@user.password.should == 'monkey'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not be a database attribute' do
|
37
|
+
@user['password'].should_not == 'monkey'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.verify_credentials' do
|
42
|
+
before do
|
43
|
+
@user = Factory.create(:stocktwits_basic_user)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return a JSON hash of the user when successful' do
|
47
|
+
hash = User.verify_credentials('stocktwitsman','test')
|
48
|
+
hash.should be_a(Hash)
|
49
|
+
hash['screen_name'].should == 'stocktwitsman'
|
50
|
+
hash['name'].should == 'Twitter Man'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return false when a 401 unauthorized happens' do
|
54
|
+
FakeWeb.register_uri(:get, 'https://stocktwits.com:443/account/verify_credentials.json', :string => '401 "Unauthorized"', :status => ['401',' Unauthorized'])
|
55
|
+
User.verify_credentials('stocktwitsman','wrong').should be_false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.authenticate' do
|
60
|
+
before do
|
61
|
+
@user = Factory.create(:stocktwits_basic_user, :stocktwits_id => '123')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should make a call to verify_credentials' do
|
65
|
+
User.should_receive(:verify_credentials).with('stocktwitsman','test')
|
66
|
+
User.authenticate('stocktwitsman','test')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return nil if verify_credentials returns false' do
|
70
|
+
User.stub!(:verify_credentials).and_return(false)
|
71
|
+
User.authenticate('stocktwitsman','test').should be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should return the user if verify_credentials succeeds' do
|
75
|
+
User.stub!(:verify_credentials).and_return(JSON.parse("{\"profile_image_url\":\"http:\\/\\/static.stocktwits.com\\/images\\/default_profile_normal.png\",\"description\":\"Saving the world for all Twitter kind.\",\"utc_offset\":null,\"favourites_count\":0,\"profile_sidebar_fill_color\":\"e0ff92\",\"screen_name\":\"stocktwitsman\",\"statuses_count\":0,\"profile_background_tile\":false,\"profile_sidebar_border_color\":\"87bc44\",\"friends_count\":2,\"url\":null,\"name\":\"Twitter Man\",\"time_zone\":null,\"protected\":false,\"profile_background_image_url\":\"http:\\/\\/static.stocktwits.com\\/images\\/themes\\/theme1\\/bg.gif\",\"profile_background_color\":\"9ae4e8\",\"created_at\":\"Fri Feb 06 18:10:32 +0000 2009\",\"profile_text_color\":\"000000\",\"followers_count\":2,\"location\":null,\"id\":123,\"profile_link_color\":\"0000ff\"}"))
|
76
|
+
User.authenticate('stocktwitsman','test').should == @user
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '.find_or_create_by_stocktwits_hash_and_password' do
|
81
|
+
before do
|
82
|
+
@user = Factory.create(:stocktwits_basic_user, :stocktwits_id => '123')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should return the existing user if there is one' do
|
86
|
+
User.identify_or_create_from_stocktwits_hash_and_password({'id' => '123', 'screen_name' => 'stocktwitsman'},'test').should == @user
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should update the attributes from the hash' do
|
90
|
+
User.identify_or_create_from_stocktwits_hash_and_password({'id' => 123, 'screen_name' => 'stocktwitsman', 'name' => 'New Name'}, 'test').name.should == 'New Name'
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should update the password from the argument' do
|
94
|
+
User.identify_or_create_from_stocktwits_hash_and_password({'id' => '123', 'screen_name' => 'stocktwitsman', 'name' => 'New Name'}, 'test2').password.should == 'test2'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should create a user if one does not exist' do
|
98
|
+
lambda{User.identify_or_create_from_stocktwits_hash_and_password({'id' => 124, 'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')}.should change(User, :count).by(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should assign the attributes from the hash to a created user' do
|
102
|
+
user = User.identify_or_create_from_stocktwits_hash_and_password({'id' => 124, 'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')
|
103
|
+
user.stocktwits_id.should == '124'
|
104
|
+
user.login.should == 'dude'
|
105
|
+
user.name.should == 'Lebowski'
|
106
|
+
user.password.should == 'test'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#stocktwits' do
|
111
|
+
before do
|
112
|
+
@user = Factory.create(:stocktwits_basic_user, :stocktwits_id => '123')
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should be an instance of Stocktwits::Dispatcher::Basic' do
|
116
|
+
@user.stocktwits.class.should == Stocktwits::Dispatcher::Basic
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should have the correct user set' do
|
120
|
+
@user.stocktwits.user.should == @user
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'changing usernames' do
|
125
|
+
before do
|
126
|
+
@user = Factory.create(:stocktwits_basic_user, :stocktwits_id => '123')
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should not create a new record when a screen_name has changed' do
|
130
|
+
lambda{User.identify_or_create_from_stocktwits_hash_and_password({'id' => '123', 'screen_name' => 'dude'},'awesome')}.should_not change(User,:count)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should update the record with the new screen name' do
|
134
|
+
User.identify_or_create_from_stocktwits_hash_and_password({'id' => '123', 'screen_name' => 'dude'},'awesome').should == @user.reload
|
135
|
+
@user.login.should == 'dude'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Stocktwits::GenericUser do
|
4
|
+
should_validate_presence_of :login, :stocktwits_id
|
5
|
+
should_validate_format_of :login, 'some_guy', 'awesome', 'cool_man'
|
6
|
+
should_not_validate_format_of :login, 'with-dashes', 'with.periods', 'with spaces'
|
7
|
+
should_validate_length_of :login, :in => 1..15
|
8
|
+
|
9
|
+
it 'should validate uniqueness of login' do
|
10
|
+
Factory.create(:stocktwits_oauth_user)
|
11
|
+
Factory.build(:stocktwits_oauth_user).should have_at_least(1).errors_on(:login)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should validate uniqueness of remember_token' do
|
15
|
+
Factory.create(:stocktwits_oauth_user, :remember_token => 'abc')
|
16
|
+
Factory.build(:stocktwits_oauth_user, :remember_token => 'abc').should have_at_least(1).errors_on(:remember_token)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should allow capital letters in the username' do
|
20
|
+
Factory.build(:stocktwits_oauth_user, :login => 'TwitterMan').should have(:no).errors_on(:login)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should not allow the same login with different capitalization' do
|
24
|
+
Factory.create(:stocktwits_oauth_user, :login => 'stocktwitsman')
|
25
|
+
Factory.build(:stocktwits_oauth_user, :login => 'TwitterMan').should have_at_least(1).errors_on(:login)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.new_from_stocktwits_hash' do
|
29
|
+
it 'should raise an argument error if the hash does not have a screen_name attribute' do
|
30
|
+
lambda{User.new_from_stocktwits_hash({'id' => '123'})}.should raise_error(ArgumentError, 'Invalid hash: must include screen_name.')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should raise an argument error if the hash does not have an id attribute' do
|
34
|
+
lambda{User.new_from_stocktwits_hash({'screen_name' => 'abc123'})}.should raise_error(ArgumentError, 'Invalid hash: must include id.')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return a user' do
|
38
|
+
User.new_from_stocktwits_hash({'id' => '123', 'screen_name' => 'stocktwitsman'}).should be_a(User)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should assign login to the screen_name' do
|
42
|
+
User.new_from_stocktwits_hash({'id' => '123', 'screen_name' => 'stocktwitsman'}).login.should == 'stocktwitsman'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should assign stocktwits attributes that are provided' do
|
46
|
+
u = User.new_from_stocktwits_hash({'id' => '4566', 'screen_name' => 'stocktwitsman', 'name' => 'Twitter Man', 'description' => 'Saving the world for all Tweet kind.'})
|
47
|
+
u.name.should == 'Twitter Man'
|
48
|
+
u.description.should == 'Saving the world for all Tweet kind.'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#update_stocktwits_attributes' do
|
53
|
+
it 'should assign values to the user' do
|
54
|
+
user = Factory.create(:stocktwits_oauth_user, :name => "Dude", :description => "Awesome, man.")
|
55
|
+
user.update_stocktwits_attributes({'name' => 'Twitter Man', 'description' => 'Works.'})
|
56
|
+
user.reload
|
57
|
+
user.name.should == 'Twitter Man'
|
58
|
+
user.description.should == 'Works.'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should not throw an error with extraneous info' do
|
62
|
+
user = Factory.create(:stocktwits_oauth_user, :name => "Dude", :description => "Awesome, man.")
|
63
|
+
lambda{user.update_stocktwits_attributes({'name' => 'Twitter Man', 'description' => 'Works.', 'whoopsy' => 'noworks.'})}.should_not raise_error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#remember_me' do
|
68
|
+
before do
|
69
|
+
@user = Factory(:stocktwits_oauth_user)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should check for the remember_token column' do
|
73
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
74
|
+
@user.remember_me
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return nil if there is no remember_token column' do
|
78
|
+
@user.should_receive(:respond_to?).with(:remember_token).and_return(false)
|
79
|
+
@user.remember_me.should be_false
|
80
|
+
end
|
81
|
+
|
82
|
+
describe ' with proper columns' do
|
83
|
+
it 'should generate a secure random token' do
|
84
|
+
ActiveSupport::SecureRandom.should_receive(:hex).with(10).and_return('abcdef')
|
85
|
+
@user.remember_me
|
86
|
+
@user.remember_token.should == 'abcdef'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set the expiration to the current time plus the remember_for period' do
|
90
|
+
Stocktwits.stub!(:remember_for).and_return(10)
|
91
|
+
time = Time.now
|
92
|
+
Time.stub!(:now).and_return(time)
|
93
|
+
|
94
|
+
@user.remember_me
|
95
|
+
|
96
|
+
@user.remember_token_expires_at.should == Time.now + 10.days
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should return a hash with a :value and :expires key' do
|
100
|
+
result = @user.remember_me
|
101
|
+
result.should be_a(Hash)
|
102
|
+
result.key?(:value).should be_true
|
103
|
+
result.key?(:expires).should be_true
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should return a hash with appropriate values' do
|
107
|
+
Stocktwits.stub!(:remember_for).and_return(10)
|
108
|
+
time = Time.now
|
109
|
+
Time.stub!(:now).and_return(time)
|
110
|
+
ActiveSupport::SecureRandom.stub!(:hex).and_return('abcdef')
|
111
|
+
|
112
|
+
@user.remember_me.should == {:value => 'abcdef', :expires => (Time.now + 10.days)}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#forget_me' do
|
118
|
+
it 'should reset remember_token and remember_token_expires_at' do
|
119
|
+
@user = Factory(:stocktwits_oauth_user, :remember_token => "abcdef", :remember_token_expires_at => Time.now + 10.days)
|
120
|
+
@user.forget_me
|
121
|
+
@user.reload
|
122
|
+
@user.remember_token.should be_nil
|
123
|
+
@user.remember_token_expires_at.should be_nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '.from_remember_token' do
|
128
|
+
before do
|
129
|
+
@user = Factory(:stocktwits_oauth_user, :remember_token => 'abcdef', :remember_token_expires_at => (Time.now + 10.days))
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should find the user with the specified remember_token' do
|
133
|
+
User.from_remember_token('abcdef').should == @user
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should not find a user with an expired token' do
|
137
|
+
user2 = Factory(:stocktwits_oauth_user, :login => 'walker', :remember_token => 'ghijkl', :remember_token_expires_at => (Time.now - 10.days))
|
138
|
+
User.from_remember_token('ghijkl').should be_nil
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should not find a user with a nil token and an expiration' do
|
142
|
+
user = Factory(:stocktwits_oauth_user, :login => 'stranger', :remember_token => nil, :remember_token_expires_at => (Time.now + 10.days))
|
143
|
+
User.from_remember_token(nil).should be_nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Stocktwits::OauthUser do
|
4
|
+
before do
|
5
|
+
stub_oauth!
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.identify_or_create_from_access_token' do
|
9
|
+
before do
|
10
|
+
@token = OAuth::AccessToken.new(Stocktwits.consumer, 'faketoken', 'fakesecret')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should accept an OAuth::AccessToken' do
|
14
|
+
lambda{ User.identify_or_create_from_access_token(@token) }.should_not raise_error(ArgumentError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should change the login when the screen_name changes' do
|
18
|
+
@user = Factory(:stocktwits_oauth_user, :stocktwits_id => '123')
|
19
|
+
User.stub!(:handle_response).and_return({'id' => 123, 'screen_name' => 'dude'})
|
20
|
+
User.identify_or_create_from_access_token(@token).should == @user.reload
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should accept two strings' do
|
24
|
+
lambda{ User.identify_or_create_from_access_token('faketoken', 'fakesecret') }.should_not raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should not accept one string' do
|
28
|
+
lambda{ User.identify_or_create_from_access_token('faketoken') }.should raise_error(ArgumentError, 'Must authenticate with an OAuth::AccessToken or the string access token and secret.')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should make a call to verify_credentials' do
|
32
|
+
# this is in the before, just making it explicit
|
33
|
+
User.identify_or_create_from_access_token(@token)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should try to find the user with that id' do
|
37
|
+
User.should_receive(:find_by_stocktwits_id).once.with('123')
|
38
|
+
User.identify_or_create_from_access_token(@token)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return the user if he/she exists' do
|
42
|
+
user = Factory.create(:stocktwits_oauth_user, :stocktwits_id => '123', :login => 'stocktwitsman')
|
43
|
+
user.reload
|
44
|
+
User.identify_or_create_from_access_token(@token).should == user
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should update the access_token and access_secret for the user if he/she exists' do
|
48
|
+
user = Factory.create(:stocktwits_oauth_user, :stocktwits_id => '123', :login => 'stocktwitsman', :access_token => 'someothertoken', :access_secret => 'someothersecret')
|
49
|
+
User.identify_or_create_from_access_token(@token)
|
50
|
+
user.reload
|
51
|
+
user.access_token.should == @token.token
|
52
|
+
user.access_secret.should == @token.secret
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should update the user\'s attributes based on the stocktwits info' do
|
56
|
+
user = Factory.create(:stocktwits_oauth_user, :login => 'stocktwitsman', :name => 'Not Twitter Man')
|
57
|
+
User.identify_or_create_from_access_token(@token).name.should == 'Twitter Man'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should create a user if one does not exist' do
|
61
|
+
lambda{User.identify_or_create_from_access_token(@token)}.should change(User, :count).by(1)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should assign the oauth access token and secret' do
|
65
|
+
user = User.identify_or_create_from_access_token(@token)
|
66
|
+
user.access_token.should == @token.token
|
67
|
+
user.access_secret.should == @token.secret
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#token' do
|
72
|
+
before do
|
73
|
+
@user = Factory.create(:stocktwits_oauth_user, :access_token => 'token', :access_secret => 'secret')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return an AccessToken' do
|
77
|
+
@user.token.should be_a(OAuth::AccessToken)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should use the user's access_token and secret" do
|
81
|
+
@user.token.token.should == @user.access_token
|
82
|
+
@user.token.secret.should == @user.access_secret
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#stocktwits' do
|
87
|
+
before do
|
88
|
+
@user = Factory.create(:stocktwits_oauth_user, :access_token => 'token', :access_secret => 'secret')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return a Stocktwits::Dispatcher::Oauth' do
|
92
|
+
@user.stocktwits.should be_a(Stocktwits::Dispatcher::Oauth)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should use my token and secret' do
|
96
|
+
@user.stocktwits.token.should == @user.access_token
|
97
|
+
@user.stocktwits.secret.should == @user.access_secret
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
ActiveRecord::Schema.define :version => 0 do
|
2
|
+
create_table :stocktwits_users, :force => true do |t|
|
3
|
+
t.string :twitter_id
|
4
|
+
t.string :login
|
5
|
+
|
6
|
+
# OAuth fields
|
7
|
+
t.string :access_token
|
8
|
+
t.string :access_secret
|
9
|
+
|
10
|
+
# Basic fields
|
11
|
+
t.binary :crypted_password
|
12
|
+
t.string :salt
|
13
|
+
|
14
|
+
# Remember token fields
|
15
|
+
t.string :remember_token
|
16
|
+
t.datetime :remember_token_expires_at
|
17
|
+
|
18
|
+
# This information is automatically kept
|
19
|
+
# in-sync at each login of the user. You
|
20
|
+
# may remove any/all of these columns.
|
21
|
+
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# begin
|
2
|
+
# require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
|
3
|
+
# rescue LoadError
|
4
|
+
# puts "You need to install rspec in your base app"
|
5
|
+
# exit
|
6
|
+
# end
|
7
|
+
|
8
|
+
RAILS_ROOT = File.dirname(__FILE__) unless defined?(RAILS_ROOT)
|
9
|
+
|
10
|
+
|
11
|
+
module Rails
|
12
|
+
|
13
|
+
module VERSION
|
14
|
+
STRING = "2.3.5"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.env
|
18
|
+
"test"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.root
|
22
|
+
File.dirname(__FILE__)
|
23
|
+
end
|
24
|
+
end unless defined?(Rails)
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
require 'rubygems'
|
29
|
+
require 'active_record'
|
30
|
+
require 'action_controller'
|
31
|
+
require 'action_controller/test_process'
|
32
|
+
require 'spec'
|
33
|
+
require 'spec/rails'
|
34
|
+
require 'shoulda'
|
35
|
+
#require 'shoulda/rails'
|
36
|
+
|
37
|
+
#include Shoulda::Rails
|
38
|
+
|
39
|
+
ActiveRecord::Base.establish_connection(
|
40
|
+
:adapter => "sqlite3",
|
41
|
+
:database => ":memory:"
|
42
|
+
)
|
43
|
+
|
44
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
45
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
46
|
+
|
47
|
+
require 'stocktwits'
|
48
|
+
|
49
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__),'..','lib','**','*.rb'))].each {|f| require f}
|
50
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__),'..','app','**','*.rb'))].each {|f| require f}
|
51
|
+
|
52
|
+
|
53
|
+
class Stocktwits::GenericUser
|
54
|
+
def self.table_name; 'stocktwits_users' end
|
55
|
+
end
|
56
|
+
|
57
|
+
class User < Stocktwits::GenericUser; end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
require 'remarkable'
|
62
|
+
require File.dirname(__FILE__) + '/fixtures/factories'
|
63
|
+
require File.dirname(__FILE__) + '/fixtures/fakeweb'
|
64
|
+
# require File.dirname(__FILE__) + '/fixtures/stocktwits'
|
65
|
+
|
66
|
+
plugin_spec_dir = File.dirname(__FILE__)
|
67
|
+
ActiveRecord::Base.logger = Logger.new(plugin_spec_dir + "/debug.log")
|
68
|
+
|
69
|
+
load(File.dirname(__FILE__) + '/schema.rb')
|
70
|
+
|
71
|
+
def define_basic_user_class!
|
72
|
+
Stocktwits::GenericUser.send :include, Stocktwits::BasicUser
|
73
|
+
end
|
74
|
+
|
75
|
+
def define_oauth_user_class!
|
76
|
+
Stocktwits::GenericUser.send :include, Stocktwits::OauthUser
|
77
|
+
end
|
78
|
+
|
79
|
+
def define_plain_user_class!
|
80
|
+
Stocktwits::GenericUser.send :include, Stocktwits::PlainUser
|
81
|
+
end
|
82
|
+
|
83
|
+
def stub_oauth!
|
84
|
+
Stocktwits.stub!(:config).and_return({
|
85
|
+
'strategy' => 'oauth',
|
86
|
+
'oauth_consumer_key' => 'testkey',
|
87
|
+
'oauth_consumer_secret' => 'testsecret'
|
88
|
+
})
|
89
|
+
define_oauth_user_class!
|
90
|
+
end
|
91
|
+
|
92
|
+
def stub_basic!
|
93
|
+
Stocktwits.stub!(:config).and_return({
|
94
|
+
'strategy' => 'basic',
|
95
|
+
'encryption_key' => 'secretcode'
|
96
|
+
})
|
97
|
+
define_basic_user_class!
|
98
|
+
end
|
99
|
+
|
100
|
+
def stub_plain!
|
101
|
+
Stocktwits.stub!(:config).and_return({
|
102
|
+
'strategy' => 'plain'
|
103
|
+
})
|
104
|
+
define_plain_user_class!
|
105
|
+
end
|
106
|
+
|
107
|
+
define_oauth_user_class!
|