diff test/unit/user_test.rb @ 1526:404aa68d4227

Merge from live branch
author Chris Cannam
date Thu, 11 Sep 2014 12:46:20 +0100
parents dffacf8a6908
children
line wrap: on
line diff
--- a/test/unit/user_test.rb	Mon Mar 17 08:57:04 2014 +0000
+++ b/test/unit/user_test.rb	Thu Sep 11 12:46:20 2014 +0100
@@ -1,5 +1,5 @@
 # Redmine - project management software
-# Copyright (C) 2006-2012  Jean-Philippe Lang
+# Copyright (C) 2006-2014  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -25,8 +25,7 @@
             :issue_categories, :enumerations, :issues,
             :journals, :journal_details,
             :groups_users,
-            :enabled_modules,
-            :workflows
+            :enabled_modules
 
   def setup
     @admin = User.find(1)
@@ -34,10 +33,15 @@
     @dlopper = User.find(3)
   end
 
+  def test_sorted_scope_should_sort_user_by_display_name
+    assert_equal User.all.map(&:name).map(&:downcase).sort,
+                 User.sorted.map(&:name).map(&:downcase)
+  end
+
   def test_generate
     User.generate!(:firstname => 'Testing connection')
     User.generate!(:firstname => 'Testing connection')
-    assert_equal 2, User.count(:all, :conditions => {:firstname => 'Testing connection'})
+    assert_equal 2, User.where(:firstname => 'Testing connection').count
   end
 
   def test_truth
@@ -67,6 +71,41 @@
     assert user.save
   end
 
+  def test_generate_password_should_respect_minimum_password_length
+    with_settings :password_min_length => 15 do
+      user = User.generate!(:generate_password => true)
+      assert user.password.length >= 15
+    end
+  end
+
+  def test_generate_password_should_not_generate_password_with_less_than_10_characters
+    with_settings :password_min_length => 4 do
+      user = User.generate!(:generate_password => true)
+      assert user.password.length >= 10
+    end
+  end
+
+  def test_generate_password_on_create_should_set_password
+    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
+    user.login = "newuser"
+    user.generate_password = true
+    assert user.save
+
+    password = user.password
+    assert user.check_password?(password)
+  end
+
+  def test_generate_password_on_update_should_update_password
+    user = User.find(2)
+    hash = user.hashed_password
+    user.generate_password = true
+    assert user.save
+
+    password = user.password
+    assert user.check_password?(password)
+    assert_not_equal hash, user.reload.hashed_password
+  end
+
   def test_create
     user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
 
@@ -100,7 +139,8 @@
     u.login = 'newuser'
     u.password, u.password_confirmation = "password", "password"
     assert u.save
-    u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
+    u = User.new(:firstname => "Similar", :lastname => "User",
+                 :mail => "similaruser@somenet.foo")
     u.login = 'NewUser'
     u.password, u.password_confirmation = "password", "password"
     assert !u.save
@@ -143,18 +183,18 @@
   end
 
   def test_destroy_should_delete_members_and_roles
-    members = Member.find_all_by_user_id(2)
-    ms = members.size
+    members = Member.where(:user_id => 2)
+    ms = members.count
     rs = members.collect(&:roles).flatten.size
-
+    assert ms > 0
+    assert rs > 0
     assert_difference 'Member.count', - ms do
       assert_difference 'MemberRole.count', - rs do
         User.find(2).destroy
       end
     end
-
     assert_nil User.find_by_id(2)
-    assert Member.find_all_by_user_id(2).empty?
+    assert_equal 0, Member.where(:user_id => 2).count
   end
 
   def test_destroy_should_update_attachments
@@ -169,7 +209,8 @@
 
   def test_destroy_should_update_comments
     comment = Comment.create!(
-      :commented => News.create!(:project_id => 1, :author_id => 1, :title => 'foo', :description => 'foo'),
+      :commented => News.create!(:project_id => 1,
+                                 :author_id => 1, :title => 'foo', :description => 'foo'),
       :author => User.find(2),
       :comments => 'foo'
     )
@@ -180,7 +221,8 @@
   end
 
   def test_destroy_should_update_issues
-    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
+    issue = Issue.create!(:project_id => 1, :author_id => 2,
+                          :tracker_id => 1, :subject => 'foo')
 
     User.find(2).destroy
     assert_nil User.find_by_id(2)
@@ -188,7 +230,8 @@
   end
 
   def test_destroy_should_unassign_issues
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
+    issue = Issue.create!(:project_id => 1, :author_id => 1,
+                          :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
 
     User.find(2).destroy
     assert_nil User.find_by_id(2)
@@ -196,7 +239,8 @@
   end
 
   def test_destroy_should_update_journals
-    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
+    issue = Issue.create!(:project_id => 1, :author_id => 2,
+                          :tracker_id => 1, :subject => 'foo')
     issue.init_journal(User.find(2), "update")
     issue.save!
 
@@ -206,13 +250,14 @@
   end
 
   def test_destroy_should_update_journal_details_old_value
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
+    issue = Issue.create!(:project_id => 1, :author_id => 1,
+                          :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
     issue.init_journal(User.find(1), "update")
     issue.assigned_to_id = nil
     assert_difference 'JournalDetail.count' do
       issue.save!
     end
-    journal_detail = JournalDetail.first(:order => 'id DESC')
+    journal_detail = JournalDetail.order('id DESC').first
     assert_equal '2', journal_detail.old_value
 
     User.find(2).destroy
@@ -221,13 +266,14 @@
   end
 
   def test_destroy_should_update_journal_details_value
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
+    issue = Issue.create!(:project_id => 1, :author_id => 1,
+                          :tracker_id => 1, :subject => 'foo')
     issue.init_journal(User.find(1), "update")
     issue.assigned_to_id = 2
     assert_difference 'JournalDetail.count' do
       issue.save!
     end
-    journal_detail = JournalDetail.first(:order => 'id DESC')
+    journal_detail = JournalDetail.order('id DESC').first
     assert_equal '2', journal_detail.value
 
     User.find(2).destroy
@@ -237,23 +283,23 @@
 
   def test_destroy_should_update_messages
     board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
-    message = Message.create!(:board_id => board.id, :author_id => 2, :subject => 'foo', :content => 'foo')
-
+    message = Message.create!(:board_id => board.id, :author_id => 2,
+                              :subject => 'foo', :content => 'foo')
     User.find(2).destroy
     assert_nil User.find_by_id(2)
     assert_equal User.anonymous, message.reload.author
   end
 
   def test_destroy_should_update_news
-    news = News.create!(:project_id => 1, :author_id => 2, :title => 'foo', :description => 'foo')
-
+    news = News.create!(:project_id => 1, :author_id => 2,
+                        :title => 'foo', :description => 'foo')
     User.find(2).destroy
     assert_nil User.find_by_id(2)
     assert_equal User.anonymous, news.reload.author
   end
 
   def test_destroy_should_delete_private_queries
-    query = Query.new(:name => 'foo', :is_public => false)
+    query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
     query.project_id = 1
     query.user_id = 2
     query.save!
@@ -264,7 +310,7 @@
   end
 
   def test_destroy_should_update_public_queries
-    query = Query.new(:name => 'foo', :is_public => true)
+    query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
     query.project_id = 1
     query.user_id = 2
     query.save!
@@ -275,7 +321,8 @@
   end
 
   def test_destroy_should_update_time_entries
-    entry = TimeEntry.new(:hours => '2', :spent_on => Date.today, :activity => TimeEntryActivity.create!(:name => 'foo'))
+    entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
+                          :activity => TimeEntryActivity.create!(:name => 'foo'))
     entry.project_id = 1
     entry.user_id = 2
     entry.save!
@@ -294,7 +341,8 @@
   end
 
   def test_destroy_should_delete_watchers
-    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
+    issue = Issue.create!(:project_id => 1, :author_id => 1,
+                          :tracker_id => 1, :subject => 'foo')
     watcher = Watcher.create!(:user_id => 2, :watchable => issue)
 
     User.find(2).destroy
@@ -306,7 +354,9 @@
     wiki_content = WikiContent.create!(
       :text => 'foo',
       :author_id => 2,
-      :page => WikiPage.create!(:title => 'Foo', :wiki => Wiki.create!(:project_id => 1, :start_page => 'Start'))
+      :page => WikiPage.create!(:title => 'Foo',
+                                :wiki => Wiki.create!(:project_id => 3,
+                                                      :start_page => 'Start'))
     )
     wiki_content.text = 'bar'
     assert_difference 'WikiContent::Version.count' do
@@ -363,28 +413,7 @@
     u = User.new
     u.mail_notification = 'foo'
     u.save
-    assert_not_nil u.errors[:mail_notification]
-  end
-
-  context "User#try_to_login" do
-    should "fall-back to case-insensitive if user login is not found as-typed." do
-      user = User.try_to_login("AdMin", "admin")
-      assert_kind_of User, user
-      assert_equal "admin", user.login
-    end
-
-    should "select the exact matching user first" do
-      case_sensitive_user = User.generate! do |user|
-        user.password = "admin123"
-      end
-      # bypass validations to make it appear like existing data
-      case_sensitive_user.update_attribute(:login, 'ADMIN')
-
-      user = User.try_to_login("ADMIN", "admin123")
-      assert_kind_of User, user
-      assert_equal "ADMIN", user.login
-
-    end
+    assert_not_equal [], u.errors[:mail_notification]
   end
 
   def test_password
@@ -401,7 +430,8 @@
 
   def test_validate_password_length
     with_settings :password_min_length => '100' do
-      user = User.new(:firstname => "new100", :lastname => "user100", :mail => "newuser100@somenet.foo")
+      user = User.new(:firstname => "new100",
+                      :lastname => "user100", :mail => "newuser100@somenet.foo")
       user.login = "newuser100"
       user.password, user.password_confirmation = "password100", "password100"
       assert !user.save
@@ -412,6 +442,11 @@
   def test_name_format
     assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
     assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
+    assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
+    assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
+  end
+
+  def test_name_should_use_setting_as_default_format
     with_settings :user_format => :firstname_lastname do
       assert_equal 'John Smith', @jsmith.reload.name
     end
@@ -456,53 +491,74 @@
 
   def test_fields_for_order_statement_should_return_fields_according_user_format_setting
     with_settings :user_format => 'lastname_coma_firstname' do
-      assert_equal ['users.lastname', 'users.firstname', 'users.id'], User.fields_for_order_statement
-    end
-  end
-  
-  def test_fields_for_order_statement_width_table_name_should_prepend_table_name
-    with_settings :user_format => 'lastname_firstname' do
-      assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'], User.fields_for_order_statement('authors')
-    end
-  end
-  
-  def test_fields_for_order_statement_with_blank_format_should_return_default
-    with_settings :user_format => '' do
-      assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
-    end
-  end
-  
-  def test_fields_for_order_statement_with_invalid_format_should_return_default
-    with_settings :user_format => 'foo' do
-      assert_equal ['users.firstname', 'users.lastname', 'users.id'], User.fields_for_order_statement
+      assert_equal ['users.lastname', 'users.firstname', 'users.id'],
+                   User.fields_for_order_statement
     end
   end
 
-  def test_lock
-    user = User.try_to_login("jsmith", "jsmith")
-    assert_equal @jsmith, user
+  def test_fields_for_order_statement_width_table_name_should_prepend_table_name
+    with_settings :user_format => 'lastname_firstname' do
+      assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
+                   User.fields_for_order_statement('authors')
+    end
+  end
 
+  def test_fields_for_order_statement_with_blank_format_should_return_default
+    with_settings :user_format => '' do
+      assert_equal ['users.firstname', 'users.lastname', 'users.id'],
+                   User.fields_for_order_statement
+    end
+  end
+
+  def test_fields_for_order_statement_with_invalid_format_should_return_default
+    with_settings :user_format => 'foo' do
+      assert_equal ['users.firstname', 'users.lastname', 'users.id'],
+                   User.fields_for_order_statement
+    end
+  end
+
+  test ".try_to_login with good credentials should return the user" do
+    user = User.try_to_login("admin", "admin")
+    assert_kind_of User, user
+    assert_equal "admin", user.login
+  end
+
+  test ".try_to_login with wrong credentials should return nil" do
+    assert_nil User.try_to_login("admin", "foo")
+  end
+
+  def test_try_to_login_with_locked_user_should_return_nil
     @jsmith.status = User::STATUS_LOCKED
-    assert @jsmith.save
+    @jsmith.save!
 
     user = User.try_to_login("jsmith", "jsmith")
     assert_equal nil, user
   end
 
-  context ".try_to_login" do
-    context "with good credentials" do
-      should "return the user" do
-        user = User.try_to_login("admin", "admin")
-        assert_kind_of User, user
-        assert_equal "admin", user.login
-      end
+  def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
+    @jsmith.status = User::STATUS_LOCKED
+    @jsmith.save!
+
+    user = User.try_to_login("jsmith", "jsmith", false)
+    assert_equal @jsmith, user
+  end
+
+  test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
+    user = User.try_to_login("AdMin", "admin")
+    assert_kind_of User, user
+    assert_equal "admin", user.login
+  end
+
+  test ".try_to_login should select the exact matching user first" do
+    case_sensitive_user = User.generate! do |user|
+      user.password = "admin123"
     end
+    # bypass validations to make it appear like existing data
+    case_sensitive_user.update_attribute(:login, 'ADMIN')
 
-    context "with wrong credentials" do
-      should "return nil" do
-        assert_nil User.try_to_login("admin", "foo")
-      end
-    end
+    user = User.try_to_login("ADMIN", "admin123")
+    assert_kind_of User, user
+    assert_equal "ADMIN", user.login
   end
 
   if ldap_configured?
@@ -580,7 +636,7 @@
             @auth_source.account_password = ''
             @auth_source.save!
           end
-  
+
           context "with a successful authentication" do
             should "create a new user account if it doesn't exist" do
               assert_difference('User.count') do
@@ -589,7 +645,7 @@
               end
             end
           end
-  
+
           context "with an unsuccessful authentication" do
             should "return nil" do
               assert_nil User.try_to_login('example1', '11111')
@@ -646,50 +702,46 @@
     end
   end
 
-  context "User#api_key" do
-    should "generate a new one if the user doesn't have one" do
-      user = User.generate!(:api_token => nil)
-      assert_nil user.api_token
+  test "#api_key should generate a new one if the user doesn't have one" do
+    user = User.generate!(:api_token => nil)
+    assert_nil user.api_token
 
-      key = user.api_key
-      assert_equal 40, key.length
-      user.reload
-      assert_equal key, user.api_key
-    end
-
-    should "return the existing api token value" do
-      user = User.generate!
-      token = Token.create!(:action => 'api')
-      user.api_token = token
-      assert user.save
-
-      assert_equal token.value, user.api_key
-    end
+    key = user.api_key
+    assert_equal 40, key.length
+    user.reload
+    assert_equal key, user.api_key
   end
 
-  context "User#find_by_api_key" do
-    should "return nil if no matching key is found" do
-      assert_nil User.find_by_api_key('zzzzzzzzz')
-    end
+  test "#api_key should return the existing api token value" do
+    user = User.generate!
+    token = Token.create!(:action => 'api')
+    user.api_token = token
+    assert user.save
 
-    should "return nil if the key is found for an inactive user" do
-      user = User.generate!
-      user.status = User::STATUS_LOCKED
-      token = Token.create!(:action => 'api')
-      user.api_token = token
-      user.save
+    assert_equal token.value, user.api_key
+  end
 
-      assert_nil User.find_by_api_key(token.value)
-    end
+  test "#find_by_api_key should return nil if no matching key is found" do
+    assert_nil User.find_by_api_key('zzzzzzzzz')
+  end
 
-    should "return the user if the key is found for an active user" do
-      user = User.generate!
-      token = Token.create!(:action => 'api')
-      user.api_token = token
-      user.save
+  test "#find_by_api_key should return nil if the key is found for an inactive user" do
+    user = User.generate!
+    user.status = User::STATUS_LOCKED
+    token = Token.create!(:action => 'api')
+    user.api_token = token
+    user.save
 
-      assert_equal user, User.find_by_api_key(token.value)
-    end
+    assert_nil User.find_by_api_key(token.value)
+  end
+
+  test "#find_by_api_key should return the user if the key is found for an active user" do
+    user = User.generate!
+    token = Token.create!(:action => 'api')
+    user.api_token = token
+    user.save
+
+    assert_equal user, User.find_by_api_key(token.value)
   end
 
   def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
@@ -724,6 +776,32 @@
     assert_equal true, User.default_admin_account_changed?
   end
 
+  def test_membership_with_project_should_return_membership
+    project = Project.find(1)
+
+    membership = @jsmith.membership(project)
+    assert_kind_of Member, membership
+    assert_equal @jsmith, membership.user
+    assert_equal project, membership.project
+  end
+
+  def test_membership_with_project_id_should_return_membership
+    project = Project.find(1)
+
+    membership = @jsmith.membership(1)
+    assert_kind_of Member, membership
+    assert_equal @jsmith, membership.user
+    assert_equal project, membership.project
+  end
+
+  def test_membership_for_non_member_should_return_nil
+    project = Project.find(1)
+
+    user = User.generate!
+    membership = user.membership(1)
+    assert_nil membership
+  end
+
   def test_roles_for_project
     # user with a role
     roles = @jsmith.roles_for_project(Project.find(1))
@@ -816,29 +894,27 @@
     assert !u.password_confirmation.blank?
   end
 
-  context "#change_password_allowed?" do
-    should "be allowed if no auth source is set" do
-      user = User.generate!
-      assert user.change_password_allowed?
-    end
+  test "#change_password_allowed? should be allowed if no auth source is set" do
+    user = User.generate!
+    assert user.change_password_allowed?
+  end
 
-    should "delegate to the auth source" do
-      user = User.generate!
+  test "#change_password_allowed? should delegate to the auth source" do
+    user = User.generate!
 
-      allowed_auth_source = AuthSource.generate!
-      def allowed_auth_source.allow_password_changes?; true; end
+    allowed_auth_source = AuthSource.generate!
+    def allowed_auth_source.allow_password_changes?; true; end
 
-      denied_auth_source = AuthSource.generate!
-      def denied_auth_source.allow_password_changes?; false; end
+    denied_auth_source = AuthSource.generate!
+    def denied_auth_source.allow_password_changes?; false; end
 
-      assert user.change_password_allowed?
+    assert user.change_password_allowed?
 
-      user.auth_source = allowed_auth_source
-      assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
+    user.auth_source = allowed_auth_source
+    assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
 
-      user.auth_source = denied_auth_source
-      assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
-    end
+    user.auth_source = denied_auth_source
+    assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
   end
 
   def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
@@ -901,7 +977,7 @@
       should "authorize nearly everything for admin users" do
         project = Project.find(1)
         assert ! @admin.member_of?(project)
-        %w(edit_issues delete_issues manage_news manage_documents manage_wiki).each do |p|
+        %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
           assert_equal true, @admin.allowed_to?(p.to_sym, project)
         end
       end
@@ -1014,9 +1090,15 @@
         assert ! @user.notify_about?(@issue)
       end
     end
+  end
 
-    context "other events" do
-      should 'be added and tested'
+  def test_notify_about_news
+    user = User.generate!
+    news = News.new
+
+    User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
+      user.mail_notification = option
+      assert_equal (option != 'none'), user.notify_about?(news)
     end
   end
 
@@ -1038,38 +1120,35 @@
   end
 
   if Object.const_defined?(:OpenID)
+    def test_setting_identity_url
+      normalized_open_id_url = 'http://example.com/'
+      u = User.new( :identity_url => 'http://example.com/' )
+      assert_equal normalized_open_id_url, u.identity_url
+    end
 
-  def test_setting_identity_url
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'http://example.com/' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
+    def test_setting_identity_url_without_trailing_slash
+      normalized_open_id_url = 'http://example.com/'
+      u = User.new( :identity_url => 'http://example.com' )
+      assert_equal normalized_open_id_url, u.identity_url
+    end
 
-  def test_setting_identity_url_without_trailing_slash
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'http://example.com' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
+    def test_setting_identity_url_without_protocol
+      normalized_open_id_url = 'http://example.com/'
+      u = User.new( :identity_url => 'example.com' )
+      assert_equal normalized_open_id_url, u.identity_url
+    end
 
-  def test_setting_identity_url_without_protocol
-    normalized_open_id_url = 'http://example.com/'
-    u = User.new( :identity_url => 'example.com' )
-    assert_equal normalized_open_id_url, u.identity_url
-  end
+    def test_setting_blank_identity_url
+      u = User.new( :identity_url => 'example.com' )
+      u.identity_url = ''
+      assert u.identity_url.blank?
+    end
 
-  def test_setting_blank_identity_url
-    u = User.new( :identity_url => 'example.com' )
-    u.identity_url = ''
-    assert u.identity_url.blank?
-  end
-
-  def test_setting_invalid_identity_url
-    u = User.new( :identity_url => 'this is not an openid url' )
-    assert u.identity_url.blank?
-  end
-
+    def test_setting_invalid_identity_url
+      u = User.new( :identity_url => 'this is not an openid url' )
+      assert u.identity_url.blank?
+    end
   else
     puts "Skipping openid tests."
   end
-
 end