Redirecting to a separate pre activation message screen instead of just flashing...
[gitorious:yousource.git] / test / functional / users_controller_test.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4 #   Copyright (C) 2007 Johan Sørensen <johan@johansorensen.com>
5 #
6 #   This program is free software: you can redistribute it and/or modify
7 #   it under the terms of the GNU Affero General Public License as published by
8 #   the Free Software Foundation, either version 3 of the License, or
9 #   (at your option) any later version.
10 #
11 #   This program is distributed in the hope that it will be useful,
12 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #   GNU Affero General Public License for more details.
15 #
16 #   You should have received a copy of the GNU Affero General Public License
17 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #++
19
20
21 require File.dirname(__FILE__) + '/../test_helper'
22
23 class UsersControllerTest < ActionController::TestCase
24   
25   def turn_ssl_on
26     @request.env["HTTPS"] = "on"
27   end
28   
29   without_ssl_context do
30     context "GET :new" do
31       setup { get :new }
32       should_redirect_to_ssl
33     end
34     context "POST :create" do
35       setup { post :create }
36       should_redirect_to_ssl
37     end
38     context "GET :edit" do
39       setup { get :edit }
40       should_redirect_to_ssl
41     end
42     context "PUT :update" do
43       setup { put :update }
44       should_redirect_to_ssl
45     end
46     context "GET :password" do
47       setup { get :password }
48       should_redirect_to_ssl
49     end
50     context "POST :forgot_password_create" do
51       setup { post :forgot_password_create }
52       should_redirect_to_ssl
53     end
54     context "PUT :update_password" do
55       setup { put :update_password }
56       should_redirect_to_ssl
57     end
58     context "GET :forgot_password" do
59       setup { get :forgot_password }
60       should_redirect_to_ssl
61     end
62     
63     context "GET :reset_password" do
64       setup { get :reset_password }
65       should_redirect_to_ssl
66     end
67   end
68   
69   should_render_in_global_context
70   
71   should "show pending activation" do
72     get :pending_activation
73     assert_response :success
74   end
75
76   should " activate user" do
77     assert_nil User.authenticate('moe', 'test')
78     get :activate, :activation_code => users(:moe).activation_code
79     assert_redirected_to('/')
80     assert_not_nil flash[:notice]
81     assert_equal users(:moe), User.authenticate('moe@example.com', 'test')
82   end
83
84   should "flashes a message when the activation code is invalid" do
85     get :activate, :activation_code => "fubar"
86     assert_redirected_to('/')
87     assert_nil flash[:notice]
88     assert_equal "Invalid activation code", flash[:error]
89     assert_nil User.authenticate('moe@example.com', 'test')
90   end
91
92   context "Routing" do
93     setup do
94       @user = users(:johan)
95     end
96   
97     should "recognizes routes starting with tilde as users/show/<name>" do
98       assert_generates("/~#{@user.to_param}", {
99         :controller => "users", 
100         :action => "show", 
101         :id => @user.to_param})
102     
103       assert_recognizes({
104         :controller => "users", :action => "show", :id => @user.to_param
105       }, {:path => "/~#{@user.to_param}", :method => :get})
106     end
107   
108     should "doesn't recognize controller collection actions as repositories" do
109       assert_recognizes({
110         :controller => "users", :action => "forgot_password"
111       }, {:path => "/users/forgot_password", :method => :get})
112     end
113   
114     should "doesn't recognize controller member actions as repositories" do
115       assert_recognizes({
116         :controller => "users", :action => "activate", :activation_code => "123"
117       }, {:path => "/users/activate/123", :method => :get})
118     end
119   end
120   
121   def create_user(options = {})
122     post :create, :user => { :login => 'quire', :email => 'quire@example.com',
123       :password => 'quire', :password_confirmation => 'quire', 
124       :terms_of_use => '1' }.merge(options)
125   end
126
127   with_ssl_context do
128     should "allow signups" do
129       assert_difference("User.count") do
130         create_user
131         assert_redirected_to :action => "pending_activation"
132       end
133     end
134     
135     should "require login on signup" do
136       assert_no_difference("User.count") do
137         create_user(:login => nil)
138         assert_not_nil assigns(:user).errors.on(:login)
139         assert_template("users/new")
140       end
141     end
142
143     should "require password on signup" do
144       assert_no_difference("User.count") do
145         create_user(:password => nil)
146         assert !assigns(:user).errors.on(:password).empty?
147         assert_template(("users/new"))
148       end
149     end
150
151     should "require password confirmation on signup" do
152       assert_no_difference("User.count") do
153         create_user(:password_confirmation => nil)
154         assert !assigns(:user).errors.on(:password_confirmation).empty?, 'empty? should be false'
155         assert_template(("users/new"))
156       end
157     end
158
159     should "require email on signup" do
160       assert_no_difference("User.count") do
161         create_user(:email => nil)
162         assert !assigns(:user).errors.on(:email).empty?, 'empty? should be false'
163         assert_template(("users/new"))
164       end
165     end
166     
167     should 'require acceptance of end user license agreement' do
168       assert_no_difference("User.count") do
169         create_user(:terms_of_use => nil)
170       end
171     end
172
173     should "be successful with valid data" do
174       assert_difference("User.count") do
175         create_user
176       end
177     end
178
179     should "requires the user to activate himself after posting valid data" do
180       create_user
181       assert_equal nil, User.authenticate('quire@example.com', 'quire')
182       assert !@controller.send(:logged_in?), 'controller.send(:logged_in?) should be false'
183     end
184   end
185
186   should "shows the user" do
187     get :show, :id => users(:johan).login
188     assert_response :success
189     assert_equal users(:johan), assigns(:user)
190   end
191   
192   should "not display the users email if he decides so" do
193     user = users(:johan)
194     user.update_attribute(:public_email, false)
195     get :show, :id => user.to_param
196     assert_response :success
197     assert_select "#sidebar ul li.email", 0
198   end
199
200   should "recognizes routing with dots in it" do
201     assert_recognizes({
202       :controller => "users",
203       :action => "show",
204       :id => "j.s"
205     }, "/users/j.s")
206     assert_recognizes({
207       :controller => "users",
208       :action => "show",
209       :id => "j.s"
210     }, "/~j.s")
211   end
212   
213   should "recognizes sub-resource routing with dots in it" do
214     assert_recognizes({
215       :controller => "licenses",
216       :action => "edit",
217       :user_id => "j.s"
218     }, "/users/j.s/license/edit")
219     assert_recognizes({
220       :controller => "licenses",
221       :action => "edit",
222       :user_id => "j.s"
223     }, "/~j.s/license/edit")
224   end
225
226   should "recognizes activate routes" do
227     assert_recognizes({
228       :controller => "users",
229       :action => "activate",
230       :activation_code => "abc123",
231     }, "/users/activate/abc123")
232   end
233   
234   context "GET show" do
235     should "counts the number of commits in the last week" do
236       get :show, :id => users(:johan).login
237       assert_response :success
238       assert_instance_of Fixnum, assigns(:commits_last_week)
239       assert (assigns(:commits_last_week) >= 0), '(assigns[:commits_last_week] >= 0) should be true'
240     end
241
242     should "#show sets atom feed autodiscovery" do
243       user = users(:johan)
244       get :show, :id => user.login
245       assert_equal feed_user_path(user, :format => :atom), assigns(:atom_auto_discovery_url)
246     end
247     
248     should "not display inactive users" do
249       user = users(:johan)
250       user.update_attribute(:activation_code, "123")
251       assert !user.activated?
252       
253       get :show, :id => user.to_param
254       assert_response :redirect
255       assert_match(/is not public/, flash[:notice])
256     end
257   end
258
259   should "has an atom feed" do
260     user = users(:johan)
261     get :feed, :id => user.login, :format => "atom"
262     assert_response :success
263     assert_equal user, assigns(:user)
264     assert_equal user.events.find(:all, :limit => 30, :order => "created_at desc"), assigns(:events)
265   end
266
267   with_ssl_context do
268     context "#forgot_password" do
269       should "GETs the page fine for everyone" do
270         get :forgot_password
271         assert_response :success
272         assert_template(("forgot_password"))
273       end
274     end
275     
276     context "#reset" do
277       setup do
278         @user = users(:johan)
279         @user.update_attribute(:password_key, "s3kr1t")
280         turn_ssl_on
281       end
282       
283       should "redirect if the token is invalid" do
284         get :reset_password, :token => "invalid"
285         assert_response :redirect
286         assert_redirected_to forgot_password_users_path
287         assert_not_nil flash[:error]
288       end
289       
290       should "render the form if the token is valid" do
291         get :reset_password, :token => "s3kr1t"
292         assert_response :success
293         assert_equal @user, assigns(:user)
294         assert_nil flash[:error]
295       end
296       
297       should "re-render if password confirmation doesn't match" do
298         put :reset_password, :token => "s3kr1t", :user => {
299           :password => "qwertyasdf",
300           :password_confirmation => "asdf"
301         }
302         assert_response :success
303         assert !assigns(:user).valid?
304         assert_nil User.authenticate(@user.email, "qwertyasdf")
305       end
306       
307       should "update the password" do
308         put :reset_password, :token => "s3kr1t", :user => {
309           :password => "qwertyasdf",
310           :password_confirmation => "qwertyasdf"
311         }
312         assert_response :redirect
313         assert_redirected_to new_sessions_path
314         assert User.authenticate(@user.email, "qwertyasdf")
315         assert_match(/Password updated/i, flash[:success])
316       end
317     end
318
319     context "#forgot_password_create" do
320       should "redirects to forgot_password if nothing was found" do
321         post :forgot_password_create, :user => {:email => "xxx"}
322         assert_redirected_to(forgot_password_users_path)
323         assert_match(/invalid email/i, flash[:error])
324       end
325   
326       should "sends a new password if email was found" do
327         u = users(:johan)
328         User.expects(:generate_reset_password_key).returns("secret")
329         Mailer.expects(:deliver_forgotten_password).with(u, "secret")
330         post :forgot_password_create, :user => {:email => u.email}
331         assert_redirected_to(root_path)
332         assert_match(/A password confirmation link has been sent/, flash[:success])
333       end
334       
335       should 'notify non-activated users that they need to activate their accounts before resetting the password' do
336         user = users(:johan)
337         user.expects(:'activated?').returns(false)
338         User.expects(:find_by_email).returns(user)
339         post :forgot_password_create, :user => {:email => user.email}
340         assert_redirected_to forgot_password_users_path
341         assert_match(/activated yet/, flash[:error])
342       end
343     end
344   end
345
346   context "in Private Mode" do
347     setup do
348       GitoriousConfig['public_mode'] = false
349     end
350
351     teardown do
352       GitoriousConfig['public_mode'] = true
353     end
354   
355     should "activate user" do
356       assert_nil User.authenticate('moe', 'test')
357       get :activate, :activation_code => users(:moe).activation_code
358       assert_redirected_to('/')
359       assert !flash[:notice].nil?
360       assert_equal users(:moe), User.authenticate('moe@example.com', 'test')
361     end
362
363     should "flashes a message when the activation code is invalid" do
364       get :activate, :activation_code => "fubar"
365       assert_redirected_to('/')
366       assert_nil flash[:notice]
367       assert_equal "Invalid activation code", flash[:error]
368       assert_nil User.authenticate('moe@example.com', 'test')
369     end
370   
371     should "GET /users/johan" do
372       get :show, :id => users(:johan).to_param
373       assert_redirected_to(root_path)
374       assert_match(/Action requires login/, flash[:error])
375     end
376     
377     should "GET /users/new" do
378       turn_ssl_on
379       get :new
380       assert_redirected_to(root_path)
381       assert_match(/Action requires login/, flash[:error])
382     end
383   
384     should "GET /users/forgot_password" do
385       turn_ssl_on
386       get :forgot_password
387       assert_response :success
388     end
389   end
390
391   context "account-related tests" do
392     setup do
393       login_as :johan
394       turn_ssl_on
395     end
396     
397     should "require current_user" do
398       login_as :moe
399       get :edit, :id => users(:johan).to_param
400       assert_response :redirect
401       assert_redirected_to user_path(users(:moe))
402     end
403
404     should "GET /users/johan/edit is successful" do
405       get :edit, :id => users(:johan).to_param
406       assert_response :success
407     end
408
409     should "PUT /users/create with valid data is successful" do
410       put :update, :id => users(:johan).to_param, :user => {
411         :password => "fubar", 
412         :password_confirmation => "fubar"
413       }
414       assert !flash[:success].nil?
415       assert_redirected_to(user_path(assigns(:user)))
416     end
417
418     should "GET require current_user" do
419       login_as :moe
420       get :password, :id => users(:johan).to_param
421       assert_response :redirect
422       assert_redirected_to user_path(users(:moe))
423     end
424
425     should "GET /users/johan/password is a-ok" do
426       get :password, :id => users(:johan).to_param
427       assert_response :success
428       assert_equal users(:johan), assigns(:user)
429     end
430   
431     should "PUT requires current_user" do
432       login_as :moe
433       put :update_password, :id => users(:johan).to_param, :user => {
434         :current_password => "test", 
435         :password => "fubar",
436         :password_confirmation => "fubar" }
437       assert_response :redirect
438       assert_redirected_to user_path(users(:moe))
439     end
440
441     should "PUT /users/joan/update_password updates password if old one matches" do
442       user = users(:johan)
443       put :update_password, :id => user.to_param, :user => {
444         :current_password => "test", 
445         :password => "fubar",
446         :password_confirmation => "fubar" }
447       assert_redirected_to(user_path(user))
448       assert_match(/Your password has been changed/i, flash[:success])
449       assert_equal user, User.authenticate(user.email, "fubar")
450     end
451
452     should "PUT /users/johan/update_password does not update password if old one is wrong" do
453       put :update_password, :id => users(:johan).to_param, :user => {
454         :current_password => "notthecurrentpassword", 
455         :password => "fubar",
456         :password_confirmation => "fubar" }
457       assert_nil flash[:notice]
458       assert_match(/doesn't seem to match/, flash[:error])
459       assert_template("users/password")
460       assert_equal users(:johan), User.authenticate(users(:johan).email, "test")
461       assert_nil User.authenticate(users(:johan).email, "fubar")
462     end
463
464     should " be able to update password, even if user is openid enabled" do
465       user = users(:johan)
466       user.update_attribute(:identity_url, "http://johan.someprovider.com/")
467       put :update_password, :id => user.to_param, :user => {
468         :current_password => "test", 
469         :password => "fubar",
470         :password_confirmation => "fubar" }
471       assert_match(/Your password has been changed/i, flash[:success])
472       assert_equal users(:johan), User.authenticate(users(:johan).email, "fubar")
473     end 
474
475     should "be able to update password, even if user created his account with openid" do
476       user = users(:johan)
477       user.update_attribute(:crypted_password, nil)
478       put :update_password, :id => user.to_param, :user => {
479         :password => "fubar",
480         :password_confirmation => "fubar" }
481       assert_redirected_to user_path(user)
482       assert_match(/Your password has been changed/i, flash[:success])
483       assert_equal users(:johan), User.authenticate(users(:johan).email, "fubar")
484     end
485     
486     should 'be able to delete his avatar' do
487       user = users(:johan)
488       user.update_attribute(:avatar_file_name, "foo.png")
489       assert user.avatar?
490       delete :avatar, :id => user.to_param
491       assert_redirected_to user_path(user)
492       assert !user.reload.avatar?
493     end
494   end
495   
496   context 'Creation from OpenID' do
497     setup do
498       @valid_session_options = {:openid_url => 'http://moe.example/', :openid_nickname => 'schmoe'}
499     end
500     should 'deny access unless OpenID information is present in the session' do
501       get :openid_build
502       assert_response :redirect
503     end
504     
505     should 'build a user from the OpenID information and render the form' do
506       get :openid_build, {}, @valid_session_options
507       user = assigns(:user)
508       assert_not_nil user
509       assert_equal 'http://moe.example/', user.identity_url
510       assert_response :success
511     end
512     
513     should 'render the form unless all required fields have been filled' do
514       post :openid_create, {:user => {}}, @valid_session_options
515       user = assigns(:user)
516       assert_response :success
517       assert_template 'users/openid_build'
518     end
519     
520     should 'create a user with the provided credentials and openid url on success' do
521       assert_incremented_by(ActionMailer::Base.deliveries, :size, 1) do
522         post :openid_create, {:user => {
523           :fullname => 'Moe Schmoe', 
524           :email => 'moe@schmoe.example', 
525           :login => 'schmoe', 
526           :terms_of_use => '1'
527           }
528         }, @valid_session_options
529       end
530       user = assigns(:user)
531       assert user.activated?
532       assert user.terms_accepted?
533       assert_nil session[:openid_url]
534       assert_equal user, @controller.send(:current_user)
535       assert_response :redirect
536     end
537   end
538
539 end