auth-slice 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,157 @@
1
+ body {
2
+ font-family: Arial, Verdana, sans-serif;
3
+ font-size: 14px;
4
+ background-color: #fff;
5
+ color: #000;
6
+ background-color: #fff;
7
+ }
8
+
9
+ html {
10
+ height: 100%;
11
+ }
12
+
13
+ hr {
14
+ border: 0px;
15
+ color: #ccc;
16
+ background-color: #cdcdcd;
17
+ height: 1px;
18
+ width: 100%;
19
+ text-align: left;
20
+ }
21
+
22
+ h1, h2, h3 {
23
+ color: #003399;
24
+ color: #09579A;
25
+ background-color: #fff;
26
+ font-family: Arial, Verdana, sans-serif;
27
+ font-weight: 300;
28
+ }
29
+
30
+ h1 {
31
+ font-size: 20px;
32
+ }
33
+ h2 {
34
+ font-size: 15px;
35
+ }
36
+ h3 {
37
+ font-size: 15px;
38
+ }
39
+
40
+ p {
41
+ line-height: 20px;
42
+ padding: 5px;
43
+ }
44
+
45
+ a, a:hover {
46
+ color: #0033CC;
47
+ background-color: #fff;
48
+ text-decoration: underline;
49
+ }
50
+
51
+ #container {
52
+ width: 95%;
53
+ text-align: left;
54
+ background-color: #fff;
55
+ margin-right: auto;
56
+ margin-left: auto;
57
+ }
58
+
59
+ #header-container {
60
+ width: 100%;
61
+ padding-top: 15px;
62
+ }
63
+
64
+ #header-container h1, #header-container h2 {
65
+ margin-left: 6px;
66
+ margin-bottom: 6px;
67
+ }
68
+
69
+ #main-container {
70
+ padding: 15px;
71
+ min-height: 400px;
72
+ }
73
+
74
+ #footer-container {
75
+ clear: both;
76
+ font-size: 12px;
77
+ font-family: Verdana, Arial, sans-serif;
78
+ }
79
+
80
+ #main-container ul {
81
+ margin-left: 3.0em;
82
+ }
83
+
84
+ .right {
85
+ float: right;
86
+ font-size: 100%;
87
+ margin-top: 5px;
88
+ color: #999;
89
+ background-color: #fff;
90
+ }
91
+ .left {
92
+ float: left;
93
+ font-size: 100%;
94
+ margin-top: 5px;
95
+ color: #999;
96
+ background-color: #fff;
97
+ }
98
+
99
+ a#google_signup {
100
+ background:transparent url(/images/btn-google-signup.png) no-repeat scroll 0% 0%;
101
+ color:#FFFFFF;
102
+ display:block;
103
+ font-size:14px;
104
+ height:67px;
105
+ line-height:22px;
106
+ margin:0pt;
107
+ padding:0px;
108
+ text-align:center;
109
+ text-decoration:none;
110
+ width:151px;
111
+ }
112
+
113
+ a#google_signup div {
114
+ padding-top:8px;
115
+ }
116
+
117
+ #openid_url, .openid_link {
118
+ background:#FFFFFF url(/images/openid-login.gif) no-repeat scroll 2px 50%;
119
+ padding-left:25px;
120
+ width:14.25em;
121
+ }
122
+
123
+ /** Form inputs **/
124
+ label {
125
+ font-weight: bold;
126
+ display: block;
127
+ }
128
+
129
+ #remember_me {
130
+ margin: 2px 5px 0px 0px;
131
+ float: left;
132
+ }
133
+
134
+ div.error {
135
+ background-color:#FCECEC;
136
+ }
137
+
138
+ div.error ul {
139
+ padding-bottom:20px;
140
+ }
141
+
142
+ .error {
143
+ background-color:#FCECEC;
144
+ }
145
+
146
+ .error h2 {
147
+ background: #CC0000 no-repeat scroll left center;
148
+ border-color: #CC9999;
149
+ color:#FFFFFF;
150
+ border:1px solid #CCCCCC;
151
+ font-size:14px;
152
+ padding:5px 5px 5px 10px;
153
+ }
154
+
155
+ .error li {
156
+ color: #CC0000;
157
+ }
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "AuthSlice (module)" do
4
+
5
+ it "should be registered in Merb::Slices.slices" do
6
+ Merb::Slices.slices.should include(AuthSlice)
7
+ end
8
+
9
+ it "should have an :identifier property" do
10
+ AuthSlice.identifier.should == "auth-slice"
11
+ end
12
+
13
+ it "should have a :root property" do
14
+ AuthSlice.root.should == current_slice_root
15
+ AuthSlice.root_path('app').should == current_slice_root / 'app'
16
+ end
17
+
18
+ it "should have a dir_for method" do
19
+ app_path = AuthSlice.dir_for(:application)
20
+ app_path.should == current_slice_root / 'app'
21
+ [:view, :model, :controller, :helper, :mailer, :part].each do |type|
22
+ AuthSlice.dir_for(type).should == app_path / "#{type}s"
23
+ end
24
+ public_path = AuthSlice.dir_for(:public)
25
+ public_path.should == current_slice_root / 'public'
26
+ [:stylesheet, :javascript, :image].each do |type|
27
+ AuthSlice.dir_for(type).should == public_path / "#{type}s"
28
+ end
29
+ end
30
+
31
+ it "should have a app_dir_for method" do
32
+ app_path = AuthSlice.app_dir_for(:application)
33
+ app_path.should == Merb.root / 'slices' / 'auth-slice' / 'app'
34
+ [:view, :model, :controller, :helper, :mailer, :part].each do |type|
35
+ AuthSlice.app_dir_for(type).should == app_path / "#{type}s"
36
+ end
37
+ public_path = AuthSlice.app_dir_for(:public)
38
+ public_path.should == Merb.dir_for(:public) / 'slices' / 'auth-slice'
39
+ [:stylesheet, :javascript, :image].each do |type|
40
+ AuthSlice.app_dir_for(type).should == public_path / "#{type}s"
41
+ end
42
+ end
43
+
44
+ it "should have a public_dir_for method" do
45
+ public_path = AuthSlice.public_dir_for(:public)
46
+ public_path.should == '/slices' / 'auth-slice'
47
+ [:stylesheet, :javascript, :image].each do |type|
48
+ AuthSlice.public_dir_for(type).should == public_path / "#{type}s"
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ prefix = 'auth-slice'
4
+
5
+ describe "Router.add_slice(:AuthSlice)" do
6
+ include Merb::Test::Rspec::RouteMatchers
7
+
8
+ before(:all) do
9
+ Merb::Router.prepare { |r| r.add_slice(:AuthSlice) } if standalone?
10
+ end
11
+
12
+ it "should have named routes for :login, :logout and :signup" do
13
+ [:login, :logout, :signup].each do |name|
14
+ url(name).should == "/#{prefix}/#{name}"
15
+ end
16
+ end
17
+
18
+ it "should route /#{prefix}/login to Session#new" do
19
+ request_to("/#{prefix}/login", :get).should route_to(AuthSlice::Users, :login)
20
+ end
21
+
22
+ it "should route /#{prefix}/login via post to Session#create" do
23
+ request_to("/#{prefix}/login", :post).should route_to(AuthSlice::Users, :login)
24
+ end
25
+
26
+ it "should route /#{prefix}/logout via delete to Session#destroy" do
27
+ request_to("/#{prefix}/logout", :delete).should route_to(AuthSlice::Users, :logout)
28
+ end
29
+ end
@@ -0,0 +1,87 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ describe "Session Controller", "index action" do
4
+ before(:all) do
5
+ Merb::Router.prepare { |r| r.add_slice(:AuthSlice) } if standalone?
6
+ end
7
+
8
+ def login_with(params = {}, &blk)
9
+ dispatch_to(AuthSlice::Users, :login, params, {:request_method => 'post'}, &blk)
10
+ end
11
+
12
+ def logout(&blk)
13
+ dispatch_to(AuthSlice::Users, :logout, {}, {}, &blk)
14
+ end
15
+
16
+ it 'logins and redirects' do
17
+ controller = login_with(:username => 'quentin', :password => 'test') {|c|
18
+ c.should_receive(:verify_login).with('quentin', 'test').and_return(mock("User", :id => 1, :name => 'quentin'))
19
+ }
20
+
21
+ controller.session[:user].should_not be_nil
22
+ controller.session[:user].should == 1
23
+ controller.should redirect_to("/")
24
+ end
25
+
26
+ it 'fails login and does not redirect' do
27
+ controller = login_with(:username => 'quentin', :password => 'bad password') {|c|
28
+ c.should_receive(:verify_login).with('quentin', 'bad password').and_return(nil)
29
+ }
30
+ controller.session[:user].should be_nil
31
+ controller.should be_successful
32
+ end
33
+
34
+ it 'logs out' do
35
+ controller = logout {|c|
36
+ c.stub!(:current_user).and_return(mock("User", :forget_me => true))
37
+ }
38
+ controller.session[:user].should be_nil
39
+ controller.should redirect
40
+ end
41
+
42
+ it 'remembers me' do
43
+ controller = login_with(:username => 'quentin', :password => 'test', :remember_me => "1") {|c|
44
+ user = mock("User", :id => 1)
45
+ c.should_receive(:verify_login).with('quentin', 'test').and_return(user)
46
+ user.should_receive(:remember_me)
47
+ user.should_receive(:remember_token).and_return("abc123")
48
+ user.should_receive(:remember_token_expires_at).and_return(Date.today)
49
+ }
50
+ controller.cookies["auth_token"].should_not be_nil
51
+ end
52
+
53
+ it 'does not remember me' do
54
+ controller = login_with(:username => 'quentin', :password => 'test', :remember_me => "0") {|c|
55
+ user = mock("User", :id => 1)
56
+ c.should_receive(:verify_login).with('quentin', 'test').and_return(user)
57
+ }
58
+ controller.cookies["auth_token"].should be_nil
59
+ end
60
+
61
+ it 'deletes token on logout' do
62
+ controller = logout {|c| controller.stub!(:current_user).and_return(@quentin) }
63
+ controller.cookies["auth_token"].should == nil
64
+ end
65
+
66
+
67
+ it 'logs in with cookie' do
68
+ controller = login_with do |c|
69
+ c.request.env[Merb::Const::HTTP_COOKIE] = "auth_token=abc123"
70
+ c.should_receive(:verify_login).and_return(nil)
71
+ user = mock("User", :id => 1, :remember_token? => true)
72
+ c.should_receive(:find_user_by_remember_token).with('abc123').and_return(user)
73
+ user.should_receive(:remember_me)
74
+ user.should_receive(:remember_token).and_return("abc123")
75
+ user.should_receive(:remember_token_expires_at).and_return(Date.today)
76
+ end
77
+ controller.should be_logged_in
78
+ end
79
+
80
+ def auth_token(token)
81
+ CGI::Cookie.new('name' => 'auth_token', 'value' => token)
82
+ end
83
+
84
+ def cookie_for(user)
85
+ auth_token user.remember_token
86
+ end
87
+ end
@@ -0,0 +1,37 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
2
+
3
+ def user_hash(options = {})
4
+ { 'name' => 'ctran',
5
+ 'username' => "ctran",
6
+ 'email' => "ctran@example.com",
7
+ 'password' => "sekret",
8
+ 'password_confirmation' => "sekret"}.merge(options)
9
+ end
10
+
11
+ describe AuthSlice::Users do
12
+ before(:all) do
13
+ Merb::Router.prepare { |r| r.add_slice(:AuthSlice) } if standalone?
14
+ end
15
+
16
+ before(:each) do
17
+ @user = mock("User", user_hash)
18
+ AuthSlice::User.should_receive(:new).with(user_hash).and_return(@user)
19
+ end
20
+
21
+ it 'allows signup and redirect to /' do
22
+ @user.should_receive(:save).and_return(true)
23
+
24
+ controller = dispatch_to(AuthSlice::Users, :signup, {'auth_slice::user' => user_hash }, {:request_method => 'post'})
25
+ controller.assigns(:user).should == @user
26
+ controller.should redirect_to('/')
27
+ end
28
+
29
+ it 'reject signup and render errors in template' do
30
+ @user.should_receive(:save).and_return(false)
31
+ controller = dispatch_to(AuthSlice::Users, :signup, {'auth_slice::user' => user_hash}, {:request_method => 'post'}) {|c|
32
+ c.should_receive(:render)
33
+ }
34
+ controller.assigns(:user).should == @user
35
+ controller.should respond_successfully
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module AuthSlice
4
+ class Main < Application
5
+ def index
6
+ 'index'
7
+ end
8
+ end
9
+ end
10
+
11
+ describe "AuthSlice::Main (controller)" do
12
+ before :all do
13
+ Merb::Router.prepare { |r| r.add_slice(:AuthSlice) } if standalone?
14
+ end
15
+
16
+ it "should have helper methods for dealing with public paths" do
17
+ controller = dispatch_to(AuthSlice::Main, :index)
18
+ controller.public_path_for(:image).should == "/slices/auth-slice/images"
19
+ controller.public_path_for(:javascript).should == "/slices/auth-slice/javascripts"
20
+ controller.public_path_for(:stylesheet).should == "/slices/auth-slice/stylesheets"
21
+ end
22
+
23
+ it "should have a slice-specific _template_root" do
24
+ AuthSlice::Main._template_root.should == AuthSlice.dir_for(:view)
25
+ AuthSlice::Main._template_root.should == AuthSlice::Application._template_root
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require File.join( File.dirname(__FILE__), "shared_user_spec")
2
+
3
+ require 'activerecord'
4
+ use_orm :activerecord
5
+
6
+ describe "User with Activerecord adapter" do
7
+ before(:all) do
8
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
9
+ AuthSlice.use_adapter(:activerecord)
10
+ end
11
+
12
+ before(:each) do
13
+ AuthSlice::User.create_db_table
14
+ end
15
+
16
+ after(:each) do
17
+ AuthSlice::User.drop_db_table
18
+ end
19
+
20
+ it_should_behave_like "AuthSlice::User"
21
+ end
@@ -0,0 +1,20 @@
1
+ require File.join( File.dirname(__FILE__), "shared_user_spec")
2
+
3
+ use_orm :datamapper
4
+
5
+ describe "User with Datamapper adapter" do
6
+ before(:all) do
7
+ DataMapper.setup(:default, 'sqlite3::memory:')
8
+ AuthSlice.use_adapter(:datamapper)
9
+ end
10
+
11
+ before(:each) do
12
+ AuthSlice::User.create_db_table
13
+ end
14
+
15
+ after(:each) do
16
+ AuthSlice::User.drop_db_table
17
+ end
18
+
19
+ it_should_behave_like "AuthSlice::User"
20
+ end
@@ -0,0 +1,251 @@
1
+ require File.join( File.dirname(__FILE__), "..", "spec_helper" )
2
+
3
+ def valid_user_hash(options = {})
4
+ { :name => 'ctran',
5
+ :username => "ctran",
6
+ :email => "ctran@example.com",
7
+ :password => "sekret",
8
+ :password_confirmation => "sekret"}.merge(options)
9
+ end
10
+
11
+ describe "AuthSlice::User", :shared => true do
12
+ describe "username" do
13
+ it "should require username field" do
14
+ user = AuthSlice::User.new
15
+ user.should respond_to(:username)
16
+ user.should_not be_valid
17
+ user.errors.on(:username).should_not be_nil
18
+ end
19
+
20
+ it "should fail validation with username less than 3 chars" do
21
+ user = AuthSlice::User.new
22
+ user.username = "AB"
23
+ user.should_not be_valid
24
+ user.errors.on(:username).should_not be_nil
25
+ end
26
+
27
+ it "should require username with between 3 and 40 chars" do
28
+ user = AuthSlice::User.new(valid_user_hash(:username => nil))
29
+ [3,40].each do |num|
30
+ user.username = "a" * num
31
+ user.should be_valid
32
+ user.errors.on(:username).should be_nil
33
+ end
34
+ end
35
+
36
+ it "should fail validation with username over 90 chars" do
37
+ user = AuthSlice::User.new
38
+ user.username = "A" * 41
39
+ user.valid?
40
+ user.errors.on(:username).should_not be_nil
41
+ end
42
+
43
+ it "should make a valid user with all required fields set" do
44
+ user = AuthSlice::User.new(valid_user_hash)
45
+ user.save.should be_true
46
+ user.errors.should be_empty
47
+ end
48
+
49
+ it "should set timestamps after save" do
50
+ user = AuthSlice::User.new(valid_user_hash)
51
+ user.save.should be_true
52
+ user.created_at.should_not be_nil
53
+ user.updated_at.should_not be_nil
54
+ end
55
+
56
+ it "should make sure username is unique" do
57
+ user = AuthSlice::User.new( valid_user_hash(:username => "Daniel") )
58
+ user2 = AuthSlice::User.new( valid_user_hash(:username => "Daniel"))
59
+ user.save.should be_true
60
+ user.username.should == "daniel"
61
+ user2.save.should be_false
62
+ user2.errors.on(:username).should_not be_nil
63
+ end
64
+
65
+ it "should make sure username is unique regardless of case" do
66
+ user = AuthSlice::User.new( valid_user_hash(:username => "Daniel") )
67
+ user2 = AuthSlice::User.new( valid_user_hash(:username => "daniel"))
68
+ user.save.should be_true
69
+ user.username = "Daniel"
70
+ user2.save.should be_false
71
+ user2.errors.on(:username).should_not be_nil
72
+ end
73
+
74
+ it "should downcase username" do
75
+ user = AuthSlice::User.new( valid_user_hash(:username => "DaNieL"))
76
+ user.username.should == "daniel"
77
+ end
78
+
79
+ it "should authenticate a user using a class method" do
80
+ user = AuthSlice::User.new(valid_user_hash)
81
+ user.save.should be_true
82
+ AuthSlice::User.authenticate(valid_user_hash[:username], valid_user_hash[:password]).should_not be_nil
83
+ end
84
+
85
+ it "should not authenticate a user using the wrong password" do
86
+ user = AuthSlice::User.new(valid_user_hash)
87
+ user.save.should be_true
88
+ AuthSlice::User.authenticate(valid_user_hash[:username], "not_the_password").should be_nil
89
+ end
90
+
91
+ it "should not authenticate a user using the wrong username" do
92
+ user = AuthSlice::User.create(valid_user_hash)
93
+ AuthSlice::User.authenticate("not_the_username", valid_user_hash[:password]).should be_nil
94
+ end
95
+
96
+ it "should not authenticate a user that does not exist" do
97
+ AuthSlice::User.authenticate("i_dont_exist", "password").should be_nil
98
+ end
99
+ end
100
+
101
+ describe "the password fields for User" do
102
+ before(:each) do
103
+ @user = AuthSlice::User.new( valid_user_hash )
104
+ end
105
+
106
+ it "should respond to password" do
107
+ @user.should respond_to(:password)
108
+ end
109
+
110
+ it "should respond to password_confirmation" do
111
+ @user.should respond_to(:password_confirmation)
112
+ end
113
+
114
+ it "should have a protected password_required method" do
115
+ @user.protected_methods.should include("password_required?")
116
+ end
117
+
118
+ it "should respond to crypted_password" do
119
+ @user.should respond_to(:crypted_password)
120
+ end
121
+
122
+ it "should require password if password is required" do
123
+ user = AuthSlice::User.new( valid_user_hash(:password => nil))
124
+ user.stub!(:password_required?).and_return(true)
125
+ user.should_not be_valid
126
+ user.errors.on(:password).should_not be_nil
127
+ user.errors.on(:password).should_not be_empty
128
+ end
129
+
130
+ it "should set the salt" do
131
+ user = AuthSlice::User.new(valid_user_hash)
132
+ user.salt.should be_nil
133
+ user.send(:encrypt_password)
134
+ user.salt.should_not be_nil
135
+ end
136
+
137
+ it "should require the password on create" do
138
+ user = AuthSlice::User.new(valid_user_hash(:password => nil))
139
+ user.save.should_not be_true
140
+ user.errors.on(:password).should_not be_nil
141
+ user.errors.on(:password).should_not be_empty
142
+ end
143
+
144
+ it "should require password_confirmation if the password_required?" do
145
+ user = AuthSlice::User.new(valid_user_hash(:password_confirmation => nil))
146
+ user.save.should_not be_true
147
+ (user.errors.on(:password) || user.errors.on(:password_confirmation)).should_not be_nil
148
+ end
149
+
150
+ it "should fail when password is outside 4 and 40 chars" do
151
+ [3,41].each do |num|
152
+ user = AuthSlice::User.new(valid_user_hash(:password => ("a" * num)))
153
+ user.should_not be_valid
154
+ user.errors.on(:password).should_not be_nil
155
+ end
156
+ end
157
+
158
+ it "should pass when password is within 4 and 40 chars" do
159
+ [4,30,40].each do |num|
160
+ user = AuthSlice::User.new(valid_user_hash(:password => ("a" * num), :password_confirmation => ("a" * num)))
161
+ user.should be_valid
162
+ user.errors.on(:password).should be_nil
163
+ end
164
+ end
165
+
166
+ it "should autenticate against a password" do
167
+ user = AuthSlice::User.new(valid_user_hash)
168
+ user.save.should be_true
169
+ user.should be_authenticated(valid_user_hash[:password])
170
+ end
171
+
172
+ it "should not require a password when saving an existing user" do
173
+ user = AuthSlice::User.create(valid_user_hash)
174
+ user = AuthSlice::User.find_by_username(valid_user_hash[:username])
175
+ user.password.should be_nil
176
+ user.password_confirmation.should be_nil
177
+ user.username = "some_different_username_to_allow_saving"
178
+ user.save.should be_true
179
+ end
180
+ end
181
+
182
+ describe "remember_me" do
183
+ predicate_matchers[:remember_token] = :remember_token?
184
+
185
+ before do
186
+ @user = AuthSlice::User.new(valid_user_hash)
187
+
188
+ t = Date.today
189
+ Date.stub!(:today).and_return(t)
190
+ end
191
+
192
+ it "should have a remember_token_expires_at attribute" do
193
+ @user.attributes.keys.any?{|a| a.to_s == "remember_token_expires_at"}.should_not be_nil
194
+ end
195
+
196
+ it "should return true if remember_token_expires_at is set and is in the future" do
197
+ @user.remember_token_expires_at = Date.today + 7
198
+ @user.should remember_token
199
+ end
200
+
201
+ it "should set remember_token_expires_at to a specific date" do
202
+ time = Date.new(2009,12,25)
203
+ @user.remember_me_until(time)
204
+ @user.remember_token_expires_at.should == time
205
+ end
206
+
207
+ it "should set the remember_me token when remembering" do
208
+ time = Date.new(2009,12,25)
209
+ @user.remember_me_until(time)
210
+ @user.remember_token.should_not be_nil
211
+ @user.save
212
+ @user = AuthSlice::User.find_by_username(valid_user_hash[:username])
213
+ @user.remember_token.should_not be_nil
214
+ @user.remember_token_expires_at.should == time
215
+ end
216
+
217
+ it "should set remember_me token for" do
218
+ remember_until = Date.today + 7
219
+ @user.remember_me_for(7)
220
+ @user.remember_token_expires_at.should == (remember_until)
221
+ end
222
+
223
+ it "should remember_me token for two weeks" do
224
+ @user.remember_me
225
+ @user.remember_token_expires_at.should == (Date.today + 14)
226
+ end
227
+
228
+ it "should forget me" do
229
+ @user.remember_me
230
+ @user.save
231
+ @user.forget_me
232
+ @user.remember_token.should be_nil
233
+ @user.remember_token_expires_at.should be_nil
234
+ end
235
+
236
+ it "should persist the remember_me token to the database" do
237
+ @user.remember_me
238
+ @user.save
239
+
240
+ @user = AuthSlice::User.find_by_username(valid_user_hash[:username])
241
+ @user.remember_token.should_not be_nil
242
+ @user.remember_token_expires_at == (Date.today + 14)
243
+
244
+ @user.forget_me
245
+
246
+ @user = AuthSlice::User.find_by_username(valid_user_hash[:username])
247
+ @user.remember_token.should be_nil
248
+ @user.remember_token_expires_at.should be_nil
249
+ end
250
+ end
251
+ end