require File.dirname(__FILE__) + '/../test_helper' require 'user_controller' # Re-raise errors caught by the controller. class UserController; def rescue_action(e) raise e end; end class UserControllerTest < Test::Unit::TestCase fixtures :users def setup LoginEngine::CONFIG[:salt] = "test-salt" @controller = UserController.new @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new @request.host = "localhost" end #========================================================================== # # Login/Logout # #========================================================================== def test_home_without_login get :home assert_redirected_to :action => "login" end def test_invalid_login post :login, :user => { :login => "bob", :password => "wrong_password" } assert_response :success assert_nil session[:user] assert_template "login" end def test_login @request.session['return-to'] = "/bogus/location" post :login, :user => { :login => "bob", :password => "atest" } assert_response :redirect assert(@response.has_session_object?(:user)) assert_equal users(:bob), session[:user] assert_equal("http://#{@request.host}/bogus/location", @response.redirect_url) end def test_login_logoff post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) get :logout assert_nil session[:user] end #========================================================================== # # Signup # #========================================================================== def test_signup LoginEngine::CONFIG[:use_email_notification] = true LoginEngine::CONFIG[:confirm_account] = true ActionMailer::Base.deliveries = [] @request.session['return-to'] = "/bogus/location" assert_equal 5, User.count post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "newpassword", :email => "newbob@test.com" } assert_nil session[:user] assert_redirected_to :action => "login" assert_equal 1, ActionMailer::Base.deliveries.size mail = ActionMailer::Base.deliveries[0] assert_equal "newbob@test.com", mail.to_addrs[0].to_s assert_match /login:\s+\w+\n/, mail.encoded assert_match /password:\s+\w+\n/, mail.encoded #mail.encoded =~ /user_id=(.*?)&key=(.*?)"/ user_id = /user_id=(\d+)/.match(mail.encoded)[1] key = /key=([a-z0-9]+)/.match(mail.encoded)[1] assert_not_nil user_id assert_not_nil key user = User.find_by_email("newbob@test.com") assert_not_nil user assert_equal 0, user.verified # First past the expiration. Time.advance_by_days = 1 get :home, :user_id => "#{user_id}", :key => "#{key}" Time.advance_by_days = 0 user = User.find_by_email("newbob@test.com") assert_equal 0, user.verified # Then a bogus key. get :home, :user_id => "#{user_id}", :key => "boguskey" user = User.find_by_email("newbob@test.com") assert_equal 0, user.verified # Now the real one. get :home, :user_id => "#{user_id}", :key => "#{key}" user = User.find_by_email("newbob@test.com") assert_equal 1, user.verified post :login, :user => { :login => "newbob", :password => "newpassword" } assert(@response.has_session_object?(:user)) get :logout end def test_signup_bad_password LoginEngine::CONFIG[:use_email_notification] = true ActionMailer::Base.deliveries = [] @request.session['return-to'] = "/bogus/location" post :signup, :user => { :login => "newbob", :password => "bad", :password_confirmation => "bad", :email => "newbob@test.com" } assert_nil session[:user] #assert_invalid_column_on_record "user", "password" assert assigns["user"].errors.invalid?("password") assert_response :success assert_equal 0, ActionMailer::Base.deliveries.size end def test_signup_bad_email LoginEngine::CONFIG[:use_email_notification] = true ActionMailer::Base.deliveries = [] @request.session['return-to'] = "/bogus/location" ActionMailer::Base.inject_one_error = true post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "newpassword", :email => "newbob@test.com" } assert_nil session[:user] assert_equal 0, ActionMailer::Base.deliveries.size end def test_signup_without_email LoginEngine::CONFIG[:use_email_notification] = false @request.session['return-to'] = "/bogus/location" post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "newpassword", :email => "newbob@test.com" } assert_redirected_to :action => "login" assert_nil session[:user] assert_match /Signup successful/, flash[:notice] assert_not_nil User.find_by_login("newbob") user = User.find_by_email("newbob@test.com") assert_not_nil user post :login, :user => { :login => "newbob", :password => "newpassword" } assert(@response.has_session_object?(:user)) get :logout end def test_signup_bad_details @request.session['return-to'] = "/bogus/location" # mismatched password post :signup, :user => { :login => "newbob", :password => "newpassword", :password_confirmation => "wrong" } #assert_invalid_column_on_record "user", "password" assert assigns["user"].errors.invalid?("password") assert_response :success # login not long enough post :signup, :user => { :login => "yo", :password => "newpassword", :password_confirmation => "newpassword" } #assert_invalid_column_on_record "user", "login" assert assigns["user"].errors.invalid?("login") assert_response :success # both post :signup, :user => { :login => "yo", :password => "newpassword", :password_confirmation => "wrong" } #assert_invalid_column_on_record "user", ["login", "password"] assert assigns["user"].errors.invalid?("login") assert assigns["user"].errors.invalid?("password") assert_response :success # existing user post :signup, :user => { :login => "bob", :password => "doesnt_matter", :password_confirmation => "doesnt_matter" } #assert_invalid_column_on_record "user", "login" assert assigns["user"].errors.invalid?("login") assert_response :success # existing email post :signup, :user => { :login => "newbob", :email => "longbob@test.com", :password => "doesnt_matter", :password_confirmation => "doesnt_matter" } #assert_invalid_column_on_record "user", "email" assert assigns["user"].errors.invalid?("email") assert_response :success end #========================================================================== # # Edit # #========================================================================== def test_edit post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) post :edit, :user => { "firstname" => "Bob", "form" => "edit" } assert_equal @response.session[:user].firstname, "Bob" post :edit, :user => { "firstname" => "", "form" => "edit" } assert_equal @response.session[:user].firstname, "" get :logout end #========================================================================== # # Delete # #========================================================================== def test_delete LoginEngine::CONFIG[:use_email_notification] = true # Immediate delete post :login, :user => { :login => "deletebob1", :password => "alongtest" } assert(@response.has_session_object?(:user)) LoginEngine.config :delayed_delete, false, :force post :delete assert_equal 1, ActionMailer::Base.deliveries.size assert_nil session[:user] # try and login in again, we should fail. post :login, :user => { :login => "deletebob1", :password => "alongtest" } assert_nil session[:user] #assert_template_has "login" assert(@response.has_template_object?("login")) # Now try delayed delete ActionMailer::Base.deliveries = [] post :login, :user => { :login => "deletebob2", :password => "alongtest" } assert(@response.has_session_object?(:user)) LoginEngine.config :delayed_delete, true, :force post :delete assert_equal 1, ActionMailer::Base.deliveries.size mail = ActionMailer::Base.deliveries[0] user_id = /user_id=(\d+)/.match(mail.encoded)[1] key = /key=([a-z0-9]+)/.match(mail.encoded)[1] post :restore_deleted, :user_id => "#{user_id}", "key" => "badkey" assert_nil session[:user] # Advance the time past the delete date Time.advance_by_days = LoginEngine.config :delayed_delete_days post :restore_deleted, :user_id => "#{user_id}", "key" => "#{key}" assert_nil session[:user] Time.advance_by_days = 0 post :restore_deleted, :user_id => "#{user_id}", "key" => "#{key}" assert(@response.has_session_object?(:user)) end def test_delete_without_email LoginEngine::CONFIG[:use_email_notification] = false ActionMailer::Base.deliveries = [] # Immediate delete post :login, :user => { :login => "deletebob1", :password => "alongtest" } assert(@response.has_session_object?(:user)) LoginEngine.config :delayed_delete, false, :force post :delete assert_nil session[:user] assert_nil User.find_by_login("deletebob1") # try and login in again, we should fail. post :login, :user => { :login => "deletebob1", :password => "alongtest" } assert_nil session[:user] #assert_template_has "login" assert(@response.has_template_object?("login")) # Now try delayed delete ActionMailer::Base.deliveries = [] post :login, :user => { :login => "deletebob2", :password => "alongtest" } assert(@response.has_session_object?(:user)) # delayed delete is not really relevant currently without email. LoginEngine.config :delayed_delete, true, :force post :delete assert_equal 1, User.find_by_login("deletebob2").deleted end #========================================================================== # # Change Password # #========================================================================== def test_change_valid_password LoginEngine::CONFIG[:use_email_notification] = true ActionMailer::Base.deliveries = [] post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "changed_password", :password_confirmation => "changed_password" } assert_equal 1, ActionMailer::Base.deliveries.size mail = ActionMailer::Base.deliveries[0] assert_equal "bob@test.com", mail.to_addrs[0].to_s assert_match /login:\s+\w+\n/, mail.encoded assert_match /password:\s+\w+\n/, mail.encoded post :login, :user => { :login => "bob", :password => "changed_password" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "atest", :password_confirmation => "atest" } get :logout post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) get :logout end def test_change_valid_password_without_email LoginEngine::CONFIG[:use_email_notification] = false ActionMailer::Base.deliveries = [] post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "changed_password", :password_confirmation => "changed_password" } assert_redirected_to :action => "change_password" post :login, :user => { :login => "bob", :password => "changed_password" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "atest", :password_confirmation => "atest" } get :logout post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) get :logout end def test_change_short_password LoginEngine::CONFIG[:use_email_notification] = true ActionMailer::Base.deliveries = [] post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "bad", :password_confirmation => "bad" } #assert_invalid_column_on_record "user", "password" assert assigns["user"].errors.invalid?("password") assert_response :success assert_equal 0, ActionMailer::Base.deliveries.size post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) get :logout end def test_change_short_password_without_email LoginEngine::CONFIG[:use_email_notification] = false post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) post :change_password, :user => { :password => "bad", :password_confirmation => "bad" } #assert_invalid_column_on_record "user", "password" assert assigns["user"].errors.invalid?("password") assert_response :success post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) get :logout end def test_change_password_with_bad_email LoginEngine::CONFIG[:use_email_notification] = true ActionMailer::Base.deliveries = [] # log in post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) # change the password, but the email delivery will fail ActionMailer::Base.inject_one_error = true post :change_password, :user => { :password => "changed_password", :password_confirmation => "changed_password" } assert_equal 0, ActionMailer::Base.deliveries.size assert_match /Password could not be changed/, flash[:warning] # logout get :logout assert_nil session[:user] # ensure we can log in with our original password # TODO: WHY DOES THIS FAIL!! It looks like the transaction stuff in UserController#change_password isn't actually rolling back changes. post :login, :user => { :login => "bob", :password => "atest" } ################################################# # assert(@response.has_session_object?(:user)) # ################################################# get :logout end #========================================================================== # # Forgot Password # #========================================================================== def test_forgot_password LoginEngine::CONFIG[:use_email_notification] = true do_forgot_password(false, false, false) do_forgot_password(false, false, true) do_forgot_password(true, false, false) do_forgot_password(false, true, false) end def do_forgot_password(bad_address, bad_email, logged_in) ActionMailer::Base.deliveries = [] if logged_in post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) end @request.session['return-to'] = "/bogus/location" if not bad_address and not bad_email post :forgot_password, :user => { :email => "bob@test.com" } password = "anewpassword" if logged_in assert_equal 0, ActionMailer::Base.deliveries.size assert_redirected_to :action => "change_password" post :change_password, :user => { :password => "#{password}", :password_confirmation => "#{password}" } else assert_equal 1, ActionMailer::Base.deliveries.size mail = ActionMailer::Base.deliveries[0] assert_equal "bob@test.com", mail.to_addrs[0].to_s user_id = /user_id=(\d+)/.match(mail.encoded)[1] key = /key=([a-z0-9]+)/.match(mail.encoded)[1] post :change_password, :user => { :password => "#{password}", :password_confirmation => "#{password}"}, :user_id => "#{user_id}", :key => "#{key}" assert(@response.has_session_object?(:user)) get :logout end elsif bad_address post :forgot_password, :user => { :email => "bademail@test.com" } assert_equal 0, ActionMailer::Base.deliveries.size elsif bad_email ActionMailer::Base.inject_one_error = true post :forgot_password, :user => { :email => "bob@test.com" } assert_equal 0, ActionMailer::Base.deliveries.size else # Invalid test case assert false end if not bad_address and not bad_email if logged_in get :logout else assert_redirected_to :action => "login" end post :login, :user => { :login => "bob", :password => "#{password}" } else # Okay, make sure the database did not get changed if logged_in get :logout end post :login, :user => { :login => "bob", :password => "atest" } end assert(@response.has_session_object?(:user)) # Put the old settings back if not bad_address and not bad_email post :change_password, :user => { :password => "atest", :password_confirmation => "atest" } end get :logout end def test_forgot_password_without_email_and_logged_in LoginEngine::CONFIG[:use_email_notification] = false post :login, :user => { :login => "bob", :password => "atest" } assert(@response.has_session_object?(:user)) @request.session['return-to'] = "/bogus/location" post :forgot_password, :user => { :email => "bob@test.com" } password = "anewpassword" assert_redirected_to :action => "change_password" post :change_password, :user => { :password => "#{password}", :password_confirmation => "#{password}" } get :logout post :login, :user => { :login => "bob", :password => "#{password}" } assert(@response.has_session_object?(:user)) get :logout end def forgot_password_without_email_and_not_logged_in LoginEngine::CONFIG[:use_email_notification] = false @request.session['return-to'] = "/bogus/location" post :forgot_password, :user => { :email => "bob@test.com" } password = "anewpassword" # wothout email, you can't retrieve your forgotten password... assert_match /Please contact the system admin/, flash[:message] assert_nil session[:user] assert_equal("http://#{@request.host}/bogus/location", @response.redirect_url) end end