millsb-twitter-auth 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/README.markdown +96 -0
  2. data/Rakefile +31 -0
  3. data/VERSION.yml +4 -0
  4. data/app/controllers/sessions_controller.rb +64 -0
  5. data/app/models/twitter_auth/basic_user.rb +63 -0
  6. data/app/models/twitter_auth/generic_user.rb +93 -0
  7. data/app/models/twitter_auth/oauth_user.rb +43 -0
  8. data/app/views/sessions/_login_form.html.erb +17 -0
  9. data/app/views/sessions/new.html.erb +5 -0
  10. data/config/routes.rb +6 -0
  11. data/generators/twitter_auth/USAGE +12 -0
  12. data/generators/twitter_auth/templates/migration.rb +48 -0
  13. data/generators/twitter_auth/templates/twitter_auth.yml +44 -0
  14. data/generators/twitter_auth/templates/user.rb +5 -0
  15. data/generators/twitter_auth/twitter_auth_generator.rb +34 -0
  16. data/lib/twitter_auth.rb +87 -0
  17. data/lib/twitter_auth/controller_extensions.rb +65 -0
  18. data/lib/twitter_auth/cryptify.rb +30 -0
  19. data/lib/twitter_auth/dispatcher/basic.rb +46 -0
  20. data/lib/twitter_auth/dispatcher/oauth.rb +26 -0
  21. data/lib/twitter_auth/dispatcher/shared.rb +40 -0
  22. data/rails/init.rb +8 -0
  23. data/spec/controllers/controller_extensions_spec.rb +162 -0
  24. data/spec/controllers/sessions_controller_spec.rb +221 -0
  25. data/spec/fixtures/config/twitter_auth.yml +17 -0
  26. data/spec/fixtures/factories.rb +18 -0
  27. data/spec/fixtures/fakeweb.rb +18 -0
  28. data/spec/fixtures/twitter.rb +5 -0
  29. data/spec/models/twitter_auth/basic_user_spec.rb +122 -0
  30. data/spec/models/twitter_auth/generic_user_spec.rb +142 -0
  31. data/spec/models/twitter_auth/oauth_user_spec.rb +94 -0
  32. data/spec/schema.rb +41 -0
  33. data/spec/spec.opts +1 -0
  34. data/spec/spec_helper.rb +51 -0
  35. data/spec/twitter_auth/cryptify_spec.rb +51 -0
  36. data/spec/twitter_auth/dispatcher/basic_spec.rb +83 -0
  37. data/spec/twitter_auth/dispatcher/oauth_spec.rb +72 -0
  38. data/spec/twitter_auth/dispatcher/shared_spec.rb +26 -0
  39. data/spec/twitter_auth_spec.rb +154 -0
  40. metadata +127 -0
@@ -0,0 +1,162 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ ActionController::Routing::Routes.draw do |map|
4
+ map.connect ':controller/:action/:id'
5
+ end
6
+
7
+ class TwitterAuthTestController < ApplicationController
8
+ before_filter :login_required, :only => [:login_required_action]
9
+
10
+ def login_required_action
11
+ render :text => "You are logged in!"
12
+ end
13
+
14
+ def fail_auth
15
+ authentication_failed('Auth FAIL.')
16
+ end
17
+
18
+ def pass_auth
19
+ if params[:message]
20
+ authentication_succeeded(params[:message])
21
+ else
22
+ authentication_succeeded
23
+ end
24
+ end
25
+
26
+ def access_denied_action
27
+ access_denied
28
+ end
29
+
30
+ def redirect_back_action
31
+ redirect_back_or_default(params[:to] || '/')
32
+ end
33
+
34
+ def logout_keeping_session_action
35
+ logout_keeping_session!
36
+ redirect_back_or_default('/')
37
+ end
38
+
39
+ def current_user_action
40
+ @user = current_user
41
+ render :nothing => true
42
+ end
43
+ end
44
+
45
+ describe TwitterAuthTestController do
46
+ before do
47
+ controller.stub!(:cookies).and_return({})
48
+ end
49
+
50
+ %w(authentication_failed authentication_succeeded current_user authorized? login_required access_denied store_location redirect_back_or_default logout_keeping_session!).each do |m|
51
+ it "should respond to the extension method '#{m}'" do
52
+ controller.should respond_to(m)
53
+ end
54
+ end
55
+
56
+ describe "#authentication_failed" do
57
+ it 'should set the flash[:error] to the message passed in' do
58
+ get :fail_auth
59
+ flash[:error].should == 'Auth FAIL.'
60
+ end
61
+
62
+ it 'should redirect to the root' do
63
+ get :fail_auth
64
+ should redirect_to('/')
65
+ end
66
+ end
67
+
68
+ describe "#authentication_succeeded" do
69
+ it 'should set the flash[:notice] to a default success message' do
70
+ get :pass_auth
71
+ flash[:notice].should == 'You have logged in successfully.'
72
+ end
73
+
74
+ it 'should be able ot receive a custom message' do
75
+ get :pass_auth, :message => 'Eat at Joes.'
76
+ flash[:notice].should == 'Eat at Joes.'
77
+ end
78
+ end
79
+
80
+ describe '#current_user' do
81
+ it 'should find the user based on the session user_id' do
82
+ user = Factory.create(:twitter_oauth_user)
83
+ request.session[:user_id] = user.id
84
+ get(:current_user_action)
85
+ assigns[:user].should == user
86
+ end
87
+
88
+ it 'should log the user in through a cookie' do
89
+ user = Factory(:twitter_oauth_user, :remember_token => 'abc', :remember_token_expires_at => (Time.now + 10.days))
90
+ controller.stub!(:cookies).and_return({:remember_token => 'abc'})
91
+ get :current_user_action
92
+ assigns[:user].should == user
93
+ end
94
+
95
+ it 'should return nil if there is no user matching that id' do
96
+ request.session[:user_id] = 2345
97
+ get :current_user_action
98
+ assigns[:user].should be_nil
99
+ end
100
+ end
101
+
102
+ describe "#authorized?" do
103
+ it 'should be true if there is a current_user' do
104
+ user = Factory.create(:twitter_oauth_user)
105
+ controller.stub!(:current_user).and_return(user)
106
+ controller.send(:authorized?).should be_true
107
+ end
108
+
109
+ it 'should be false if there is not current_user' do
110
+ controller.stub!(:current_user).and_return(nil)
111
+ controller.send(:authorized?).should be_false
112
+ end
113
+ end
114
+
115
+ describe '#access_denied' do
116
+ it 'should redirect to the login path' do
117
+ get :access_denied_action
118
+ should redirect_to(login_path)
119
+ end
120
+
121
+ it 'should store the location first' do
122
+ controller.should_receive(:store_location).once
123
+ get :access_denied_action
124
+ end
125
+ end
126
+
127
+ describe '#redirect_back_or_default' do
128
+ it 'should redirect if there is a session[:return_to]' do
129
+ request.session[:return_to] = '/'
130
+ get :redirect_back_action, :to => '/notroot'
131
+ should redirect_to('/')
132
+ end
133
+
134
+ it 'should redirect to the default provided otherwise' do
135
+ get :redirect_back_action, :to => '/someurl'
136
+ should redirect_to('/someurl')
137
+ end
138
+ end
139
+
140
+ describe 'logout_keeping_session!' do
141
+ before do
142
+ @user = Factory.create(:twitter_oauth_user)
143
+ request.session[:user_id] = @user.id
144
+ end
145
+
146
+ it 'should unset session[:user_id]' do
147
+ get :logout_keeping_session_action
148
+ request.session[:user_id].should be_nil
149
+ end
150
+
151
+ it 'should unset current_user' do
152
+ controller.send(:current_user).should == @user
153
+ get :logout_keeping_session_action
154
+ controller.send(:current_user).should be_nil
155
+ end
156
+
157
+ it 'should unset the cookie' do
158
+ controller.send(:cookies).should_receive(:delete).with(:remember_token)
159
+ get :logout_keeping_session_action
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,221 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe SessionsController do
4
+ integrate_views
5
+
6
+ describe 'routes' do
7
+ it 'should route /session/new to SessionsController#new' do
8
+ params_from(:get, '/session/new').should == {:controller => 'sessions', :action => 'new'}
9
+ end
10
+
11
+ it 'should route /login to SessionsController#new' do
12
+ params_from(:get, '/login').should == {:controller => 'sessions', :action => 'new'}
13
+ end
14
+
15
+ it 'should route /logout to SessionsController#destroy' do
16
+ params_from(:get, '/logout').should == {:controller => 'sessions', :action => 'destroy'}
17
+ end
18
+
19
+ it 'should route DELETE /session to SessionsController#destroy' do
20
+ params_from(:delete, '/session').should == {:controller => 'sessions', :action => 'destroy'}
21
+ end
22
+
23
+ it 'should route /oauth_callback to SessionsController#oauth_callback' do
24
+ params_from(:get, '/oauth_callback').should == {:controller => 'sessions', :action => 'oauth_callback'}
25
+ end
26
+
27
+ it 'should route POST /session to SessionsController#create' do
28
+ params_from(:post, '/session').should == {:controller => 'sessions', :action => 'create'}
29
+ end
30
+ end
31
+
32
+ describe 'with OAuth strategy' do
33
+ before do
34
+ stub_oauth!
35
+ end
36
+
37
+ describe '#new' do
38
+ it 'should retrieve a request token' do
39
+ get :new
40
+ assigns[:request_token].token.should == 'faketoken'
41
+ assigns[:request_token].secret.should == 'faketokensecret'
42
+ end
43
+
44
+ it 'should set session variables for the request token' do
45
+ get :new
46
+ session[:request_token].should == 'faketoken'
47
+ session[:request_token_secret].should == 'faketokensecret'
48
+ end
49
+
50
+ it 'should redirect to the oauth authorization url' do
51
+ get :new
52
+ response.should redirect_to('https://twitter.com/oauth/authorize?oauth_token=faketoken')
53
+ end
54
+
55
+ it 'should redirect to the oauth_callback if one is specified' do
56
+ TwitterAuth.stub!(:oauth_callback).and_return('http://localhost:3000/development')
57
+ TwitterAuth.stub!(:oauth_callback?).and_return(true)
58
+
59
+ get :new
60
+ response.should redirect_to('https://twitter.com/oauth/authorize?oauth_token=faketoken&oauth_callback=' + CGI.escape(TwitterAuth.oauth_callback))
61
+ end
62
+ end
63
+
64
+ describe '#oauth_callback' do
65
+ describe 'with no session info' do
66
+ it 'should set the flash[:error]' do
67
+ get :oauth_callback, :oauth_token => 'faketoken'
68
+ flash[:error].should == 'No authentication information was found in the session. Please try again.'
69
+ end
70
+
71
+ it 'should redirect to "/" by default' do
72
+ get :oauth_callback, :oauth_token => 'faketoken'
73
+ response.should redirect_to('/')
74
+ end
75
+
76
+ it 'should call authentication_failed' do
77
+ controller.should_receive(:authentication_failed).any_number_of_times
78
+ get :oauth_callback, :oauth_token => 'faketoken'
79
+ end
80
+ end
81
+
82
+ describe 'with proper info' do
83
+ before do
84
+ @user = Factory.create(:twitter_oauth_user)
85
+ @time = Time.now
86
+ @remember_token = ActiveSupport::SecureRandom.hex(10)
87
+
88
+ Time.stub!(:now).and_return(@time)
89
+ ActiveSupport::SecureRandom.stub!(:hex).and_return(@remember_token)
90
+
91
+ request.session[:request_token] = 'faketoken'
92
+ request.session[:request_token_secret] = 'faketokensecret'
93
+ get :oauth_callback, :oauth_token => 'faketoken'
94
+ end
95
+
96
+ describe 'building the access token' do
97
+ it 'should rebuild the request token' do
98
+ correct_token = OAuth::RequestToken.new(TwitterAuth.consumer,'faketoken','faketokensecret')
99
+
100
+ %w(token secret).each do |att|
101
+ assigns[:request_token].send(att).should == correct_token.send(att)
102
+ end
103
+ end
104
+
105
+ it 'should exchange the request token for an access token' do
106
+ assigns[:access_token].should be_a(OAuth::AccessToken)
107
+ assigns[:access_token].token.should == 'fakeaccesstoken'
108
+ assigns[:access_token].secret.should == 'fakeaccesstokensecret'
109
+ end
110
+
111
+ it 'should wipe the request token after exchange' do
112
+ session[:request_token].should be_nil
113
+ session[:request_token_secret].should be_nil
114
+ end
115
+ end
116
+
117
+ describe 'identifying the user' do
118
+ it "should find the user" do
119
+ assigns[:user].should == @user
120
+ end
121
+
122
+ it "should assign the user id to the session" do
123
+ session[:user_id].should == @user.id
124
+ end
125
+
126
+ it "should call remember me" do
127
+ @user.reload
128
+ @user.remember_token.should == @remember_token
129
+ end
130
+
131
+ it "should set a cookie" do
132
+ cookies[:remember_token].should == @remember_token
133
+ end
134
+ end
135
+
136
+ describe "when OAuth doesn't work" do
137
+ before do
138
+ request.session[:request_token] = 'faketoken'
139
+ request.session[:request_token_secret] = 'faketokensecret'
140
+ @request_token = OAuth::RequestToken.new(TwitterAuth.consumer, session[:request_token], session[:request_token_secret])
141
+ OAuth::RequestToken.stub!(:new).and_return(@request_token)
142
+ end
143
+
144
+ it 'should call authentication_failed when it gets a 401 from OAuth' do
145
+ @request_token.stub!(:get_access_token).and_raise(Net::HTTPServerException.new('401 "Unauthorized"', '401 "Unauthorized"'))
146
+ controller.should_receive(:authentication_failed).with('This authentication request is no longer valid. Please try again.')
147
+ # the should raise_error is hacky because of the expectation
148
+ # stubbing the proper behavior :-(
149
+ lambda{get :oauth_callback, :oauth_token => 'faketoken'}.should raise_error(ActionView::MissingTemplate)
150
+ end
151
+
152
+ it 'should call authentication_failed when it gets a different HTTPServerException' do
153
+ @request_token.stub!(:get_access_token).and_raise(Net::HTTPServerException.new('404 "Not Found"', '404 "Not Found"'))
154
+ controller.should_receive(:authentication_failed).with('There was a problem trying to authenticate you. Please try again.')
155
+ lambda{get :oauth_callback, :oauth_token => 'faketoken'}.should raise_error(ActionView::MissingTemplate)
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ describe 'with Basic strategy' do
163
+ before do
164
+ stub_basic!
165
+ end
166
+
167
+ describe '#new' do
168
+ it 'should render the new action' do
169
+ get :new
170
+ response.should render_template('sessions/new')
171
+ end
172
+
173
+ it 'should render the login form' do
174
+ get :new
175
+ response.should have_tag('form[action=/session][id=login_form][method=post]')
176
+ end
177
+
178
+ describe '#create' do
179
+ before do
180
+ @user = Factory.create(:twitter_basic_user)
181
+ end
182
+
183
+ it 'should call logout_keeping_session! to remove session info' do
184
+ controller.should_receive(:logout_keeping_session!)
185
+ post :create
186
+ end
187
+
188
+ it 'should try to authenticate the user' do
189
+ User.should_receive(:authenticate)
190
+ post :create
191
+ end
192
+
193
+ it 'should call authentication_failed on authenticate failure' do
194
+ User.should_receive(:authenticate).and_return(nil)
195
+ post :create, :login => 'wrong', :password => 'false'
196
+ response.should redirect_to('/login')
197
+ end
198
+
199
+ it 'should call authentication_succeeded on authentication success' do
200
+ User.should_receive(:authenticate).and_return(@user)
201
+ post :create, :login => 'twitterman', :password => 'cool'
202
+ response.should redirect_to('/')
203
+ flash[:notice].should_not be_blank
204
+ end
205
+ end
206
+ end
207
+
208
+ end
209
+
210
+ describe '#destroy' do
211
+ it 'should call logout_keeping_session!' do
212
+ controller.should_receive(:logout_keeping_session!).once
213
+ get :destroy
214
+ end
215
+
216
+ it 'should redirect to the root' do
217
+ get :destroy
218
+ response.should redirect_to('/')
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,17 @@
1
+ development:
2
+ strategy: oauth
3
+ base_url: "https://twitter.com"
4
+ oauth_consumer_key: devkey
5
+ oauth_consumer_secret: devsecret
6
+ oauth_callback: "http://localhost:3000"
7
+ test:
8
+ strategy: oauth
9
+ base_url: "https://twitter.com"
10
+ oauth_consumer_key: testkey
11
+ oauth_consumer_secret: testsecret
12
+ production:
13
+ strategy: oauth
14
+ base_url: "https://twitter.com"
15
+ oauth_consumer_key: prodkey
16
+ oauth_consumer_secret: prodsecret
17
+
@@ -0,0 +1,18 @@
1
+ require 'factory_girl'
2
+
3
+ Factory.define(:twitter_oauth_user, :class => User) do |u|
4
+ u.login 'twitterman'
5
+ u.access_token 'fakeaccesstoken'
6
+ u.access_secret 'fakeaccesstokensecret'
7
+
8
+ u.name 'Twitter Man'
9
+ u.description 'Saving the world for all Twitter kind.'
10
+ end
11
+
12
+ Factory.define(:twitter_basic_user, :class => User) do |u|
13
+ u.login 'twitterman'
14
+ u.password 'test'
15
+
16
+ u.name 'Twitter Man'
17
+ u.description 'Saving the world for all Twitter kind.'
18
+ end
@@ -0,0 +1,18 @@
1
+ # This is where we fake out all of the URLs that we
2
+ # will be calling as a part of this spec suite.
3
+ # You must have the 'fakeweb' gem in order to run
4
+ # the tests for TwitterAuth.
5
+ #
6
+ # gem install 'mbleigh-fakeweb'
7
+
8
+ require 'fake_web'
9
+
10
+ FakeWeb.allow_net_connect = false
11
+
12
+ FakeWeb.register_uri(:post, 'https://twitter.com:443/oauth/request_token', :string => 'oauth_token=faketoken&oauth_token_secret=faketokensecret')
13
+
14
+ FakeWeb.register_uri(:post, 'https://twitter.com:443/oauth/access_token', :string => 'oauth_token=fakeaccesstoken&oauth_token_secret=fakeaccesstokensecret')
15
+
16
+ FakeWeb.register_uri(:get, 'https://twitter.com:443/account/verify_credentials.json', :string => "{\"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\"}")
17
+
18
+ #FakeWeb.register_uri(:get, 'https://twitter.com:443/)
@@ -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,122 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe TwitterAuth::BasicUser do
4
+ before do
5
+ stub_basic!
6
+ end
7
+
8
+ describe '#password=' do
9
+ before do
10
+ @user = Factory.build(:twitter_basic_user)
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(:twitter_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(:twitter_basic_user)
44
+ end
45
+
46
+ it 'should return a JSON hash of the user when successful' do
47
+ hash = User.verify_credentials('twitterman','test')
48
+ hash.should be_a(Hash)
49
+ hash['screen_name'].should == 'twitterman'
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://twitter.com:443/account/verify_credentials.json', :string => '401 "Unauthorized"', :status => ['401',' Unauthorized'])
55
+ User.verify_credentials('twitterman','wrong').should be_false
56
+ end
57
+ end
58
+
59
+ describe '.authenticate' do
60
+ before do
61
+ @user = Factory.create(:twitter_basic_user)
62
+ end
63
+
64
+ it 'should make a call to verify_credentials' do
65
+ User.should_receive(:verify_credentials).with('twitterman','test')
66
+ User.authenticate('twitterman','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('twitterman','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.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\"}"))
76
+ User.authenticate('twitterman','test').should == @user
77
+ end
78
+ end
79
+
80
+ describe '.find_or_create_by_twitter_hash_and_password' do
81
+ before do
82
+ @user = Factory.create(:twitter_basic_user)
83
+ end
84
+
85
+ it 'should return the existing user if there is one' do
86
+ User.identify_or_create_from_twitter_hash_and_password({'screen_name' => 'twitterman'},'test').should == @user
87
+ end
88
+
89
+ it 'should update the attributes from the hash' do
90
+ User.identify_or_create_from_twitter_hash_and_password({'screen_name' => 'twitterman', '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_twitter_hash_and_password({'screen_name' => 'twitterman', '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_twitter_hash_and_password({'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_twitter_hash_and_password({'screen_name' => 'dude', 'name' => "Lebowski"}, 'test')
103
+ user.login.should == 'dude'
104
+ user.name.should == 'Lebowski'
105
+ user.password.should == 'test'
106
+ end
107
+ end
108
+
109
+ describe '#twitter' do
110
+ before do
111
+ @user = Factory.create(:twitter_basic_user)
112
+ end
113
+
114
+ it 'should be an instance of TwitterAuth::Dispatcher::Basic' do
115
+ @user.twitter.class.should == TwitterAuth::Dispatcher::Basic
116
+ end
117
+
118
+ it 'should have the correct user set' do
119
+ @user.twitter.user.should == @user
120
+ end
121
+ end
122
+ end