##// END OF EJS Templates
Merged r14179 (#19569)....
Jean-Philippe Lang -
r13828:1fad29bc146b
parent child
Show More
@@ -1,139 +1,139
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Member < ActiveRecord::Base
18 class Member < ActiveRecord::Base
19 belongs_to :user
19 belongs_to :user
20 belongs_to :principal, :foreign_key => 'user_id'
20 belongs_to :principal, :foreign_key => 'user_id'
21 has_many :member_roles, :dependent => :destroy
21 has_many :member_roles, :dependent => :destroy
22 has_many :roles, :through => :member_roles
22 has_many :roles, lambda {uniq}, :through => :member_roles
23 belongs_to :project
23 belongs_to :project
24
24
25 validates_presence_of :principal, :project
25 validates_presence_of :principal, :project
26 validates_uniqueness_of :user_id, :scope => :project_id
26 validates_uniqueness_of :user_id, :scope => :project_id
27 validate :validate_role
27 validate :validate_role
28 attr_protected :id
28 attr_protected :id
29
29
30 before_destroy :set_issue_category_nil
30 before_destroy :set_issue_category_nil
31
31
32 def role
32 def role
33 end
33 end
34
34
35 def role=
35 def role=
36 end
36 end
37
37
38 def name
38 def name
39 self.user.name
39 self.user.name
40 end
40 end
41
41
42 alias :base_role_ids= :role_ids=
42 alias :base_role_ids= :role_ids=
43 def role_ids=(arg)
43 def role_ids=(arg)
44 ids = (arg || []).collect(&:to_i) - [0]
44 ids = (arg || []).collect(&:to_i) - [0]
45 # Keep inherited roles
45 # Keep inherited roles
46 ids += member_roles.select {|mr| !mr.inherited_from.nil?}.collect(&:role_id)
46 ids += member_roles.select {|mr| !mr.inherited_from.nil?}.collect(&:role_id)
47
47
48 new_role_ids = ids - role_ids
48 new_role_ids = ids - role_ids
49 # Add new roles
49 # Add new roles
50 new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id, :member => self) }
50 new_role_ids.each {|id| member_roles << MemberRole.new(:role_id => id, :member => self) }
51 # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
51 # Remove roles (Rails' #role_ids= will not trigger MemberRole#on_destroy)
52 member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
52 member_roles_to_destroy = member_roles.select {|mr| !ids.include?(mr.role_id)}
53 if member_roles_to_destroy.any?
53 if member_roles_to_destroy.any?
54 member_roles_to_destroy.each(&:destroy)
54 member_roles_to_destroy.each(&:destroy)
55 end
55 end
56 end
56 end
57
57
58 def <=>(member)
58 def <=>(member)
59 a, b = roles.sort.first, member.roles.sort.first
59 a, b = roles.sort.first, member.roles.sort.first
60 if a == b
60 if a == b
61 if principal
61 if principal
62 principal <=> member.principal
62 principal <=> member.principal
63 else
63 else
64 1
64 1
65 end
65 end
66 elsif a
66 elsif a
67 a <=> b
67 a <=> b
68 else
68 else
69 1
69 1
70 end
70 end
71 end
71 end
72
72
73 def deletable?
73 def deletable?
74 member_roles.detect {|mr| mr.inherited_from}.nil?
74 member_roles.detect {|mr| mr.inherited_from}.nil?
75 end
75 end
76
76
77 def destroy
77 def destroy
78 if member_roles.reload.present?
78 if member_roles.reload.present?
79 # destroying the last role will destroy another instance
79 # destroying the last role will destroy another instance
80 # of the same Member record, #super would then trigger callbacks twice
80 # of the same Member record, #super would then trigger callbacks twice
81 member_roles.destroy_all
81 member_roles.destroy_all
82 @destroyed = true
82 @destroyed = true
83 freeze
83 freeze
84 else
84 else
85 super
85 super
86 end
86 end
87 end
87 end
88
88
89 def include?(user)
89 def include?(user)
90 if principal.is_a?(Group)
90 if principal.is_a?(Group)
91 !user.nil? && user.groups.include?(principal)
91 !user.nil? && user.groups.include?(principal)
92 else
92 else
93 self.user == user
93 self.user == user
94 end
94 end
95 end
95 end
96
96
97 def set_issue_category_nil
97 def set_issue_category_nil
98 if user_id && project_id
98 if user_id && project_id
99 # remove category based auto assignments for this member
99 # remove category based auto assignments for this member
100 IssueCategory.where(["project_id = ? AND assigned_to_id = ?", project_id, user_id]).
100 IssueCategory.where(["project_id = ? AND assigned_to_id = ?", project_id, user_id]).
101 update_all("assigned_to_id = NULL")
101 update_all("assigned_to_id = NULL")
102 end
102 end
103 end
103 end
104
104
105 # Creates memberships for principal with the attributes
105 # Creates memberships for principal with the attributes
106 # * project_ids : one or more project ids
106 # * project_ids : one or more project ids
107 # * role_ids : ids of the roles to give to each membership
107 # * role_ids : ids of the roles to give to each membership
108 #
108 #
109 # Example:
109 # Example:
110 # Member.create_principal_memberships(user, :project_ids => [2, 5], :role_ids => [1, 3]
110 # Member.create_principal_memberships(user, :project_ids => [2, 5], :role_ids => [1, 3]
111 def self.create_principal_memberships(principal, attributes)
111 def self.create_principal_memberships(principal, attributes)
112 members = []
112 members = []
113 if attributes
113 if attributes
114 project_ids = Array.wrap(attributes[:project_ids] || attributes[:project_id])
114 project_ids = Array.wrap(attributes[:project_ids] || attributes[:project_id])
115 role_ids = attributes[:role_ids]
115 role_ids = attributes[:role_ids]
116 project_ids.each do |project_id|
116 project_ids.each do |project_id|
117 members << Member.new(:principal => principal, :role_ids => role_ids, :project_id => project_id)
117 members << Member.new(:principal => principal, :role_ids => role_ids, :project_id => project_id)
118 end
118 end
119 principal.members << members
119 principal.members << members
120 end
120 end
121 members
121 members
122 end
122 end
123
123
124 # Finds or initilizes a Member for the given project and principal
124 # Finds or initilizes a Member for the given project and principal
125 def self.find_or_new(project, principal)
125 def self.find_or_new(project, principal)
126 project_id = project.is_a?(Project) ? project.id : project
126 project_id = project.is_a?(Project) ? project.id : project
127 principal_id = principal.is_a?(Principal) ? principal.id : principal
127 principal_id = principal.is_a?(Principal) ? principal.id : principal
128
128
129 member = Member.find_by_project_id_and_user_id(project_id, principal_id)
129 member = Member.find_by_project_id_and_user_id(project_id, principal_id)
130 member ||= Member.new(:project_id => project_id, :user_id => principal_id)
130 member ||= Member.new(:project_id => project_id, :user_id => principal_id)
131 member
131 member
132 end
132 end
133
133
134 protected
134 protected
135
135
136 def validate_role
136 def validate_role
137 errors.add_on_empty :role if member_roles.empty? && roles.empty?
137 errors.add_on_empty :role if member_roles.empty? && roles.empty?
138 end
138 end
139 end
139 end
@@ -1,2619 +1,2640
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class IssueTest < ActiveSupport::TestCase
20 class IssueTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles,
22 :groups_users,
22 :groups_users,
23 :trackers, :projects_trackers,
23 :trackers, :projects_trackers,
24 :enabled_modules,
24 :enabled_modules,
25 :versions,
25 :versions,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
27 :enumerations,
27 :enumerations,
28 :issues, :journals, :journal_details,
28 :issues, :journals, :journal_details,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
30 :time_entries
30 :time_entries
31
31
32 include Redmine::I18n
32 include Redmine::I18n
33
33
34 def setup
34 def setup
35 set_language_if_valid 'en'
35 set_language_if_valid 'en'
36 end
36 end
37
37
38 def teardown
38 def teardown
39 User.current = nil
39 User.current = nil
40 end
40 end
41
41
42 def test_initialize
42 def test_initialize
43 issue = Issue.new
43 issue = Issue.new
44
44
45 assert_nil issue.project_id
45 assert_nil issue.project_id
46 assert_nil issue.tracker_id
46 assert_nil issue.tracker_id
47 assert_nil issue.status_id
47 assert_nil issue.status_id
48 assert_nil issue.author_id
48 assert_nil issue.author_id
49 assert_nil issue.assigned_to_id
49 assert_nil issue.assigned_to_id
50 assert_nil issue.category_id
50 assert_nil issue.category_id
51
51
52 assert_equal IssuePriority.default, issue.priority
52 assert_equal IssuePriority.default, issue.priority
53 end
53 end
54
54
55 def test_create
55 def test_create
56 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
56 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
57 :status_id => 1, :priority => IssuePriority.all.first,
57 :status_id => 1, :priority => IssuePriority.all.first,
58 :subject => 'test_create',
58 :subject => 'test_create',
59 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
59 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
60 assert issue.save
60 assert issue.save
61 issue.reload
61 issue.reload
62 assert_equal 1.5, issue.estimated_hours
62 assert_equal 1.5, issue.estimated_hours
63 end
63 end
64
64
65 def test_create_minimal
65 def test_create_minimal
66 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create')
66 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, :subject => 'test_create')
67 assert issue.save
67 assert issue.save
68 assert_equal issue.tracker.default_status, issue.status
68 assert_equal issue.tracker.default_status, issue.status
69 assert issue.description.nil?
69 assert issue.description.nil?
70 assert_nil issue.estimated_hours
70 assert_nil issue.estimated_hours
71 end
71 end
72
72
73 def test_start_date_format_should_be_validated
73 def test_start_date_format_should_be_validated
74 set_language_if_valid 'en'
74 set_language_if_valid 'en'
75 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
75 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
76 issue = Issue.new(:start_date => invalid_date)
76 issue = Issue.new(:start_date => invalid_date)
77 assert !issue.valid?
77 assert !issue.valid?
78 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
78 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
79 end
79 end
80 end
80 end
81
81
82 def test_due_date_format_should_be_validated
82 def test_due_date_format_should_be_validated
83 set_language_if_valid 'en'
83 set_language_if_valid 'en'
84 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
84 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
85 issue = Issue.new(:due_date => invalid_date)
85 issue = Issue.new(:due_date => invalid_date)
86 assert !issue.valid?
86 assert !issue.valid?
87 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
87 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
88 end
88 end
89 end
89 end
90
90
91 def test_due_date_lesser_than_start_date_should_not_validate
91 def test_due_date_lesser_than_start_date_should_not_validate
92 set_language_if_valid 'en'
92 set_language_if_valid 'en'
93 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
93 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
94 assert !issue.valid?
94 assert !issue.valid?
95 assert_include 'Due date must be greater than start date', issue.errors.full_messages
95 assert_include 'Due date must be greater than start date', issue.errors.full_messages
96 end
96 end
97
97
98 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
98 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
99 issue = Issue.generate(:start_date => '2013-06-04')
99 issue = Issue.generate(:start_date => '2013-06-04')
100 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
100 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
101 assert !issue.valid?
101 assert !issue.valid?
102 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
102 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
103 end
103 end
104
104
105 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
105 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
106 issue = Issue.generate!(:start_date => '2013-06-04')
106 issue = Issue.generate!(:start_date => '2013-06-04')
107 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
107 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
108 issue.start_date = '2013-06-07'
108 issue.start_date = '2013-06-07'
109 assert !issue.valid?
109 assert !issue.valid?
110 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
110 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
111 end
111 end
112
112
113 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
113 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
114 issue = Issue.generate!(:start_date => '2013-06-04')
114 issue = Issue.generate!(:start_date => '2013-06-04')
115 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
115 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
116 assert issue.valid?
116 assert issue.valid?
117 end
117 end
118
118
119 def test_estimated_hours_should_be_validated
119 def test_estimated_hours_should_be_validated
120 set_language_if_valid 'en'
120 set_language_if_valid 'en'
121 ['-2'].each do |invalid|
121 ['-2'].each do |invalid|
122 issue = Issue.new(:estimated_hours => invalid)
122 issue = Issue.new(:estimated_hours => invalid)
123 assert !issue.valid?
123 assert !issue.valid?
124 assert_include 'Estimated time is invalid', issue.errors.full_messages
124 assert_include 'Estimated time is invalid', issue.errors.full_messages
125 end
125 end
126 end
126 end
127
127
128 def test_create_with_required_custom_field
128 def test_create_with_required_custom_field
129 set_language_if_valid 'en'
129 set_language_if_valid 'en'
130 field = IssueCustomField.find_by_name('Database')
130 field = IssueCustomField.find_by_name('Database')
131 field.update_attribute(:is_required, true)
131 field.update_attribute(:is_required, true)
132
132
133 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
133 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
134 :status_id => 1, :subject => 'test_create',
134 :status_id => 1, :subject => 'test_create',
135 :description => 'IssueTest#test_create_with_required_custom_field')
135 :description => 'IssueTest#test_create_with_required_custom_field')
136 assert issue.available_custom_fields.include?(field)
136 assert issue.available_custom_fields.include?(field)
137 # No value for the custom field
137 # No value for the custom field
138 assert !issue.save
138 assert !issue.save
139 assert_equal ["Database cannot be blank"], issue.errors.full_messages
139 assert_equal ["Database cannot be blank"], issue.errors.full_messages
140 # Blank value
140 # Blank value
141 issue.custom_field_values = { field.id => '' }
141 issue.custom_field_values = { field.id => '' }
142 assert !issue.save
142 assert !issue.save
143 assert_equal ["Database cannot be blank"], issue.errors.full_messages
143 assert_equal ["Database cannot be blank"], issue.errors.full_messages
144 # Invalid value
144 # Invalid value
145 issue.custom_field_values = { field.id => 'SQLServer' }
145 issue.custom_field_values = { field.id => 'SQLServer' }
146 assert !issue.save
146 assert !issue.save
147 assert_equal ["Database is not included in the list"], issue.errors.full_messages
147 assert_equal ["Database is not included in the list"], issue.errors.full_messages
148 # Valid value
148 # Valid value
149 issue.custom_field_values = { field.id => 'PostgreSQL' }
149 issue.custom_field_values = { field.id => 'PostgreSQL' }
150 assert issue.save
150 assert issue.save
151 issue.reload
151 issue.reload
152 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
152 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
153 end
153 end
154
154
155 def test_create_with_group_assignment
155 def test_create_with_group_assignment
156 with_settings :issue_group_assignment => '1' do
156 with_settings :issue_group_assignment => '1' do
157 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
157 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
158 :subject => 'Group assignment',
158 :subject => 'Group assignment',
159 :assigned_to_id => 11).save
159 :assigned_to_id => 11).save
160 issue = Issue.order('id DESC').first
160 issue = Issue.order('id DESC').first
161 assert_kind_of Group, issue.assigned_to
161 assert_kind_of Group, issue.assigned_to
162 assert_equal Group.find(11), issue.assigned_to
162 assert_equal Group.find(11), issue.assigned_to
163 end
163 end
164 end
164 end
165
165
166 def test_create_with_parent_issue_id
166 def test_create_with_parent_issue_id
167 issue = Issue.new(:project_id => 1, :tracker_id => 1,
167 issue = Issue.new(:project_id => 1, :tracker_id => 1,
168 :author_id => 1, :subject => 'Group assignment',
168 :author_id => 1, :subject => 'Group assignment',
169 :parent_issue_id => 1)
169 :parent_issue_id => 1)
170 assert_save issue
170 assert_save issue
171 assert_equal 1, issue.parent_issue_id
171 assert_equal 1, issue.parent_issue_id
172 assert_equal Issue.find(1), issue.parent
172 assert_equal Issue.find(1), issue.parent
173 end
173 end
174
174
175 def test_create_with_sharp_parent_issue_id
175 def test_create_with_sharp_parent_issue_id
176 issue = Issue.new(:project_id => 1, :tracker_id => 1,
176 issue = Issue.new(:project_id => 1, :tracker_id => 1,
177 :author_id => 1, :subject => 'Group assignment',
177 :author_id => 1, :subject => 'Group assignment',
178 :parent_issue_id => "#1")
178 :parent_issue_id => "#1")
179 assert_save issue
179 assert_save issue
180 assert_equal 1, issue.parent_issue_id
180 assert_equal 1, issue.parent_issue_id
181 assert_equal Issue.find(1), issue.parent
181 assert_equal Issue.find(1), issue.parent
182 end
182 end
183
183
184 def test_create_with_invalid_parent_issue_id
184 def test_create_with_invalid_parent_issue_id
185 set_language_if_valid 'en'
185 set_language_if_valid 'en'
186 issue = Issue.new(:project_id => 1, :tracker_id => 1,
186 issue = Issue.new(:project_id => 1, :tracker_id => 1,
187 :author_id => 1, :subject => 'Group assignment',
187 :author_id => 1, :subject => 'Group assignment',
188 :parent_issue_id => '01ABC')
188 :parent_issue_id => '01ABC')
189 assert !issue.save
189 assert !issue.save
190 assert_equal '01ABC', issue.parent_issue_id
190 assert_equal '01ABC', issue.parent_issue_id
191 assert_include 'Parent task is invalid', issue.errors.full_messages
191 assert_include 'Parent task is invalid', issue.errors.full_messages
192 end
192 end
193
193
194 def test_create_with_invalid_sharp_parent_issue_id
194 def test_create_with_invalid_sharp_parent_issue_id
195 set_language_if_valid 'en'
195 set_language_if_valid 'en'
196 issue = Issue.new(:project_id => 1, :tracker_id => 1,
196 issue = Issue.new(:project_id => 1, :tracker_id => 1,
197 :author_id => 1, :subject => 'Group assignment',
197 :author_id => 1, :subject => 'Group assignment',
198 :parent_issue_id => '#01ABC')
198 :parent_issue_id => '#01ABC')
199 assert !issue.save
199 assert !issue.save
200 assert_equal '#01ABC', issue.parent_issue_id
200 assert_equal '#01ABC', issue.parent_issue_id
201 assert_include 'Parent task is invalid', issue.errors.full_messages
201 assert_include 'Parent task is invalid', issue.errors.full_messages
202 end
202 end
203
203
204 def assert_visibility_match(user, issues)
204 def assert_visibility_match(user, issues)
205 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
205 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
206 end
206 end
207
207
208 def test_visible_scope_for_anonymous
208 def test_visible_scope_for_anonymous
209 # Anonymous user should see issues of public projects only
209 # Anonymous user should see issues of public projects only
210 issues = Issue.visible(User.anonymous).to_a
210 issues = Issue.visible(User.anonymous).to_a
211 assert issues.any?
211 assert issues.any?
212 assert_nil issues.detect {|issue| !issue.project.is_public?}
212 assert_nil issues.detect {|issue| !issue.project.is_public?}
213 assert_nil issues.detect {|issue| issue.is_private?}
213 assert_nil issues.detect {|issue| issue.is_private?}
214 assert_visibility_match User.anonymous, issues
214 assert_visibility_match User.anonymous, issues
215 end
215 end
216
216
217 def test_visible_scope_for_anonymous_without_view_issues_permissions
217 def test_visible_scope_for_anonymous_without_view_issues_permissions
218 # Anonymous user should not see issues without permission
218 # Anonymous user should not see issues without permission
219 Role.anonymous.remove_permission!(:view_issues)
219 Role.anonymous.remove_permission!(:view_issues)
220 issues = Issue.visible(User.anonymous).to_a
220 issues = Issue.visible(User.anonymous).to_a
221 assert issues.empty?
221 assert issues.empty?
222 assert_visibility_match User.anonymous, issues
222 assert_visibility_match User.anonymous, issues
223 end
223 end
224
224
225 def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership
225 def test_visible_scope_for_anonymous_without_view_issues_permissions_and_membership
226 Role.anonymous.remove_permission!(:view_issues)
226 Role.anonymous.remove_permission!(:view_issues)
227 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2])
227 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [2])
228
228
229 issues = Issue.visible(User.anonymous).all
229 issues = Issue.visible(User.anonymous).all
230 assert issues.any?
230 assert issues.any?
231 assert_equal [1], issues.map(&:project_id).uniq.sort
231 assert_equal [1], issues.map(&:project_id).uniq.sort
232 assert_visibility_match User.anonymous, issues
232 assert_visibility_match User.anonymous, issues
233 end
233 end
234
234
235 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
235 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
236 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
236 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
237 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
237 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
238 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
238 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
239 assert !issue.visible?(User.anonymous)
239 assert !issue.visible?(User.anonymous)
240 end
240 end
241
241
242 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
242 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
243 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
243 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
244 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
244 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
245 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
245 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
246 assert !issue.visible?(User.anonymous)
246 assert !issue.visible?(User.anonymous)
247 end
247 end
248
248
249 def test_visible_scope_for_non_member
249 def test_visible_scope_for_non_member
250 user = User.find(9)
250 user = User.find(9)
251 assert user.projects.empty?
251 assert user.projects.empty?
252 # Non member user should see issues of public projects only
252 # Non member user should see issues of public projects only
253 issues = Issue.visible(user).to_a
253 issues = Issue.visible(user).to_a
254 assert issues.any?
254 assert issues.any?
255 assert_nil issues.detect {|issue| !issue.project.is_public?}
255 assert_nil issues.detect {|issue| !issue.project.is_public?}
256 assert_nil issues.detect {|issue| issue.is_private?}
256 assert_nil issues.detect {|issue| issue.is_private?}
257 assert_visibility_match user, issues
257 assert_visibility_match user, issues
258 end
258 end
259
259
260 def test_visible_scope_for_non_member_with_own_issues_visibility
260 def test_visible_scope_for_non_member_with_own_issues_visibility
261 Role.non_member.update_attribute :issues_visibility, 'own'
261 Role.non_member.update_attribute :issues_visibility, 'own'
262 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
262 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
263 user = User.find(9)
263 user = User.find(9)
264
264
265 issues = Issue.visible(user).to_a
265 issues = Issue.visible(user).to_a
266 assert issues.any?
266 assert issues.any?
267 assert_nil issues.detect {|issue| issue.author != user}
267 assert_nil issues.detect {|issue| issue.author != user}
268 assert_visibility_match user, issues
268 assert_visibility_match user, issues
269 end
269 end
270
270
271 def test_visible_scope_for_non_member_without_view_issues_permissions
271 def test_visible_scope_for_non_member_without_view_issues_permissions
272 # Non member user should not see issues without permission
272 # Non member user should not see issues without permission
273 Role.non_member.remove_permission!(:view_issues)
273 Role.non_member.remove_permission!(:view_issues)
274 user = User.find(9)
274 user = User.find(9)
275 assert user.projects.empty?
275 assert user.projects.empty?
276 issues = Issue.visible(user).to_a
276 issues = Issue.visible(user).to_a
277 assert issues.empty?
277 assert issues.empty?
278 assert_visibility_match user, issues
278 assert_visibility_match user, issues
279 end
279 end
280
280
281 def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership
281 def test_visible_scope_for_non_member_without_view_issues_permissions_and_membership
282 Role.non_member.remove_permission!(:view_issues)
282 Role.non_member.remove_permission!(:view_issues)
283 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2])
283 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [2])
284 user = User.find(9)
284 user = User.find(9)
285
285
286 issues = Issue.visible(user).all
286 issues = Issue.visible(user).all
287 assert issues.any?
287 assert issues.any?
288 assert_equal [1], issues.map(&:project_id).uniq.sort
288 assert_equal [1], issues.map(&:project_id).uniq.sort
289 assert_visibility_match user, issues
289 assert_visibility_match user, issues
290 end
290 end
291
291
292 def test_visible_scope_for_member
292 def test_visible_scope_for_member
293 user = User.find(9)
293 user = User.find(9)
294 # User should see issues of projects for which user has view_issues permissions only
294 # User should see issues of projects for which user has view_issues permissions only
295 Role.non_member.remove_permission!(:view_issues)
295 Role.non_member.remove_permission!(:view_issues)
296 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
296 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
297 issues = Issue.visible(user).to_a
297 issues = Issue.visible(user).to_a
298 assert issues.any?
298 assert issues.any?
299 assert_nil issues.detect {|issue| issue.project_id != 3}
299 assert_nil issues.detect {|issue| issue.project_id != 3}
300 assert_nil issues.detect {|issue| issue.is_private?}
300 assert_nil issues.detect {|issue| issue.is_private?}
301 assert_visibility_match user, issues
301 assert_visibility_match user, issues
302 end
302 end
303
303
304 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
304 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
305 user = User.find(8)
305 user = User.find(8)
306 assert user.groups.any?
306 assert user.groups.any?
307 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
307 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
308 Role.non_member.remove_permission!(:view_issues)
308 Role.non_member.remove_permission!(:view_issues)
309
309
310 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
310 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 3,
311 :status_id => 1, :priority => IssuePriority.all.first,
311 :status_id => 1, :priority => IssuePriority.all.first,
312 :subject => 'Assignment test',
312 :subject => 'Assignment test',
313 :assigned_to => user.groups.first,
313 :assigned_to => user.groups.first,
314 :is_private => true)
314 :is_private => true)
315
315
316 Role.find(2).update_attribute :issues_visibility, 'default'
316 Role.find(2).update_attribute :issues_visibility, 'default'
317 issues = Issue.visible(User.find(8)).to_a
317 issues = Issue.visible(User.find(8)).to_a
318 assert issues.any?
318 assert issues.any?
319 assert issues.include?(issue)
319 assert issues.include?(issue)
320
320
321 Role.find(2).update_attribute :issues_visibility, 'own'
321 Role.find(2).update_attribute :issues_visibility, 'own'
322 issues = Issue.visible(User.find(8)).to_a
322 issues = Issue.visible(User.find(8)).to_a
323 assert issues.any?
323 assert issues.any?
324 assert_include issue, issues
324 assert_include issue, issues
325 end
325 end
326
326
327 def test_visible_scope_for_admin
327 def test_visible_scope_for_admin
328 user = User.find(1)
328 user = User.find(1)
329 user.members.each(&:destroy)
329 user.members.each(&:destroy)
330 assert user.projects.empty?
330 assert user.projects.empty?
331 issues = Issue.visible(user).to_a
331 issues = Issue.visible(user).to_a
332 assert issues.any?
332 assert issues.any?
333 # Admin should see issues on private projects that admin does not belong to
333 # Admin should see issues on private projects that admin does not belong to
334 assert issues.detect {|issue| !issue.project.is_public?}
334 assert issues.detect {|issue| !issue.project.is_public?}
335 # Admin should see private issues of other users
335 # Admin should see private issues of other users
336 assert issues.detect {|issue| issue.is_private? && issue.author != user}
336 assert issues.detect {|issue| issue.is_private? && issue.author != user}
337 assert_visibility_match user, issues
337 assert_visibility_match user, issues
338 end
338 end
339
339
340 def test_visible_scope_with_project
340 def test_visible_scope_with_project
341 project = Project.find(1)
341 project = Project.find(1)
342 issues = Issue.visible(User.find(2), :project => project).to_a
342 issues = Issue.visible(User.find(2), :project => project).to_a
343 projects = issues.collect(&:project).uniq
343 projects = issues.collect(&:project).uniq
344 assert_equal 1, projects.size
344 assert_equal 1, projects.size
345 assert_equal project, projects.first
345 assert_equal project, projects.first
346 end
346 end
347
347
348 def test_visible_scope_with_project_and_subprojects
348 def test_visible_scope_with_project_and_subprojects
349 project = Project.find(1)
349 project = Project.find(1)
350 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a
350 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).to_a
351 projects = issues.collect(&:project).uniq
351 projects = issues.collect(&:project).uniq
352 assert projects.size > 1
352 assert projects.size > 1
353 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
353 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
354 end
354 end
355
355
356 def test_visible_and_nested_set_scopes
356 def test_visible_and_nested_set_scopes
357 user = User.generate!
357 user = User.generate!
358 parent = Issue.generate!(:assigned_to => user)
358 parent = Issue.generate!(:assigned_to => user)
359 assert parent.visible?(user)
359 assert parent.visible?(user)
360 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
360 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
361 child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
361 child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
362 parent.reload
362 parent.reload
363 child1.reload
363 child1.reload
364 child2.reload
364 child2.reload
365 assert child1.visible?(user)
365 assert child1.visible?(user)
366 assert child2.visible?(user)
366 assert child2.visible?(user)
367 assert_equal 2, parent.descendants.count
367 assert_equal 2, parent.descendants.count
368 assert_equal 2, parent.descendants.visible(user).count
368 assert_equal 2, parent.descendants.visible(user).count
369 # awesome_nested_set 2-1-stable branch has regression.
369 # awesome_nested_set 2-1-stable branch has regression.
370 # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6
370 # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6
371 # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft:
371 # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft:
372 assert_equal 2, parent.descendants.collect{|i| i}.size
372 assert_equal 2, parent.descendants.collect{|i| i}.size
373 assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size
373 assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size
374 end
374 end
375
375
376 def test_visible_scope_with_unsaved_user_should_not_raise_an_error
376 def test_visible_scope_with_unsaved_user_should_not_raise_an_error
377 user = User.new
377 user = User.new
378 assert_nothing_raised do
378 assert_nothing_raised do
379 Issue.visible(user).to_a
379 Issue.visible(user).to_a
380 end
380 end
381 end
381 end
382
382
383 def test_open_scope
383 def test_open_scope
384 issues = Issue.open.to_a
384 issues = Issue.open.to_a
385 assert_nil issues.detect(&:closed?)
385 assert_nil issues.detect(&:closed?)
386 end
386 end
387
387
388 def test_open_scope_with_arg
388 def test_open_scope_with_arg
389 issues = Issue.open(false).to_a
389 issues = Issue.open(false).to_a
390 assert_equal issues, issues.select(&:closed?)
390 assert_equal issues, issues.select(&:closed?)
391 end
391 end
392
392
393 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
393 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
394 version = Version.find(2)
394 version = Version.find(2)
395 assert version.fixed_issues.any?
395 assert version.fixed_issues.any?
396 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
396 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
397 end
397 end
398
398
399 def test_fixed_version_scope_with_empty_array_should_return_no_result
399 def test_fixed_version_scope_with_empty_array_should_return_no_result
400 assert_equal 0, Issue.fixed_version([]).count
400 assert_equal 0, Issue.fixed_version([]).count
401 end
401 end
402
402
403 def test_errors_full_messages_should_include_custom_fields_errors
403 def test_errors_full_messages_should_include_custom_fields_errors
404 field = IssueCustomField.find_by_name('Database')
404 field = IssueCustomField.find_by_name('Database')
405
405
406 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
406 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
407 :status_id => 1, :subject => 'test_create',
407 :status_id => 1, :subject => 'test_create',
408 :description => 'IssueTest#test_create_with_required_custom_field')
408 :description => 'IssueTest#test_create_with_required_custom_field')
409 assert issue.available_custom_fields.include?(field)
409 assert issue.available_custom_fields.include?(field)
410 # Invalid value
410 # Invalid value
411 issue.custom_field_values = { field.id => 'SQLServer' }
411 issue.custom_field_values = { field.id => 'SQLServer' }
412
412
413 assert !issue.valid?
413 assert !issue.valid?
414 assert_equal 1, issue.errors.full_messages.size
414 assert_equal 1, issue.errors.full_messages.size
415 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
415 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
416 issue.errors.full_messages.first
416 issue.errors.full_messages.first
417 end
417 end
418
418
419 def test_update_issue_with_required_custom_field
419 def test_update_issue_with_required_custom_field
420 field = IssueCustomField.find_by_name('Database')
420 field = IssueCustomField.find_by_name('Database')
421 field.update_attribute(:is_required, true)
421 field.update_attribute(:is_required, true)
422
422
423 issue = Issue.find(1)
423 issue = Issue.find(1)
424 assert_nil issue.custom_value_for(field)
424 assert_nil issue.custom_value_for(field)
425 assert issue.available_custom_fields.include?(field)
425 assert issue.available_custom_fields.include?(field)
426 # No change to custom values, issue can be saved
426 # No change to custom values, issue can be saved
427 assert issue.save
427 assert issue.save
428 # Blank value
428 # Blank value
429 issue.custom_field_values = { field.id => '' }
429 issue.custom_field_values = { field.id => '' }
430 assert !issue.save
430 assert !issue.save
431 # Valid value
431 # Valid value
432 issue.custom_field_values = { field.id => 'PostgreSQL' }
432 issue.custom_field_values = { field.id => 'PostgreSQL' }
433 assert issue.save
433 assert issue.save
434 issue.reload
434 issue.reload
435 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
435 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
436 end
436 end
437
437
438 def test_should_not_update_attributes_if_custom_fields_validation_fails
438 def test_should_not_update_attributes_if_custom_fields_validation_fails
439 issue = Issue.find(1)
439 issue = Issue.find(1)
440 field = IssueCustomField.find_by_name('Database')
440 field = IssueCustomField.find_by_name('Database')
441 assert issue.available_custom_fields.include?(field)
441 assert issue.available_custom_fields.include?(field)
442
442
443 issue.custom_field_values = { field.id => 'Invalid' }
443 issue.custom_field_values = { field.id => 'Invalid' }
444 issue.subject = 'Should be not be saved'
444 issue.subject = 'Should be not be saved'
445 assert !issue.save
445 assert !issue.save
446
446
447 issue.reload
447 issue.reload
448 assert_equal "Cannot print recipes", issue.subject
448 assert_equal "Cannot print recipes", issue.subject
449 end
449 end
450
450
451 def test_should_not_recreate_custom_values_objects_on_update
451 def test_should_not_recreate_custom_values_objects_on_update
452 field = IssueCustomField.find_by_name('Database')
452 field = IssueCustomField.find_by_name('Database')
453
453
454 issue = Issue.find(1)
454 issue = Issue.find(1)
455 issue.custom_field_values = { field.id => 'PostgreSQL' }
455 issue.custom_field_values = { field.id => 'PostgreSQL' }
456 assert issue.save
456 assert issue.save
457 custom_value = issue.custom_value_for(field)
457 custom_value = issue.custom_value_for(field)
458 issue.reload
458 issue.reload
459 issue.custom_field_values = { field.id => 'MySQL' }
459 issue.custom_field_values = { field.id => 'MySQL' }
460 assert issue.save
460 assert issue.save
461 issue.reload
461 issue.reload
462 assert_equal custom_value.id, issue.custom_value_for(field).id
462 assert_equal custom_value.id, issue.custom_value_for(field).id
463 end
463 end
464
464
465 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
465 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
466 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
466 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
467 :status_id => 1, :subject => 'Test',
467 :status_id => 1, :subject => 'Test',
468 :custom_field_values => {'2' => 'Test'})
468 :custom_field_values => {'2' => 'Test'})
469 assert !Tracker.find(2).custom_field_ids.include?(2)
469 assert !Tracker.find(2).custom_field_ids.include?(2)
470
470
471 issue = Issue.find(issue.id)
471 issue = Issue.find(issue.id)
472 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
472 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
473
473
474 issue = Issue.find(issue.id)
474 issue = Issue.find(issue.id)
475 custom_value = issue.custom_value_for(2)
475 custom_value = issue.custom_value_for(2)
476 assert_not_nil custom_value
476 assert_not_nil custom_value
477 assert_equal 'Test', custom_value.value
477 assert_equal 'Test', custom_value.value
478 end
478 end
479
479
480 def test_assigning_tracker_id_should_reload_custom_fields_values
480 def test_assigning_tracker_id_should_reload_custom_fields_values
481 issue = Issue.new(:project => Project.find(1))
481 issue = Issue.new(:project => Project.find(1))
482 assert issue.custom_field_values.empty?
482 assert issue.custom_field_values.empty?
483 issue.tracker_id = 1
483 issue.tracker_id = 1
484 assert issue.custom_field_values.any?
484 assert issue.custom_field_values.any?
485 end
485 end
486
486
487 def test_assigning_attributes_should_assign_project_and_tracker_first
487 def test_assigning_attributes_should_assign_project_and_tracker_first
488 seq = sequence('seq')
488 seq = sequence('seq')
489 issue = Issue.new
489 issue = Issue.new
490 issue.expects(:project_id=).in_sequence(seq)
490 issue.expects(:project_id=).in_sequence(seq)
491 issue.expects(:tracker_id=).in_sequence(seq)
491 issue.expects(:tracker_id=).in_sequence(seq)
492 issue.expects(:subject=).in_sequence(seq)
492 issue.expects(:subject=).in_sequence(seq)
493 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
493 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
494 end
494 end
495
495
496 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
496 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
497 attributes = ActiveSupport::OrderedHash.new
497 attributes = ActiveSupport::OrderedHash.new
498 attributes['custom_field_values'] = { '1' => 'MySQL' }
498 attributes['custom_field_values'] = { '1' => 'MySQL' }
499 attributes['tracker_id'] = '1'
499 attributes['tracker_id'] = '1'
500 issue = Issue.new(:project => Project.find(1))
500 issue = Issue.new(:project => Project.find(1))
501 issue.attributes = attributes
501 issue.attributes = attributes
502 assert_equal 'MySQL', issue.custom_field_value(1)
502 assert_equal 'MySQL', issue.custom_field_value(1)
503 end
503 end
504
504
505 def test_reload_should_reload_custom_field_values
505 def test_reload_should_reload_custom_field_values
506 issue = Issue.generate!
506 issue = Issue.generate!
507 issue.custom_field_values = {'2' => 'Foo'}
507 issue.custom_field_values = {'2' => 'Foo'}
508 issue.save!
508 issue.save!
509
509
510 issue = Issue.order('id desc').first
510 issue = Issue.order('id desc').first
511 assert_equal 'Foo', issue.custom_field_value(2)
511 assert_equal 'Foo', issue.custom_field_value(2)
512
512
513 issue.custom_field_values = {'2' => 'Bar'}
513 issue.custom_field_values = {'2' => 'Bar'}
514 assert_equal 'Bar', issue.custom_field_value(2)
514 assert_equal 'Bar', issue.custom_field_value(2)
515
515
516 issue.reload
516 issue.reload
517 assert_equal 'Foo', issue.custom_field_value(2)
517 assert_equal 'Foo', issue.custom_field_value(2)
518 end
518 end
519
519
520 def test_should_update_issue_with_disabled_tracker
520 def test_should_update_issue_with_disabled_tracker
521 p = Project.find(1)
521 p = Project.find(1)
522 issue = Issue.find(1)
522 issue = Issue.find(1)
523
523
524 p.trackers.delete(issue.tracker)
524 p.trackers.delete(issue.tracker)
525 assert !p.trackers.include?(issue.tracker)
525 assert !p.trackers.include?(issue.tracker)
526
526
527 issue.reload
527 issue.reload
528 issue.subject = 'New subject'
528 issue.subject = 'New subject'
529 assert issue.save
529 assert issue.save
530 end
530 end
531
531
532 def test_should_not_set_a_disabled_tracker
532 def test_should_not_set_a_disabled_tracker
533 p = Project.find(1)
533 p = Project.find(1)
534 p.trackers.delete(Tracker.find(2))
534 p.trackers.delete(Tracker.find(2))
535
535
536 issue = Issue.find(1)
536 issue = Issue.find(1)
537 issue.tracker_id = 2
537 issue.tracker_id = 2
538 issue.subject = 'New subject'
538 issue.subject = 'New subject'
539 assert !issue.save
539 assert !issue.save
540 assert_not_equal [], issue.errors[:tracker_id]
540 assert_not_equal [], issue.errors[:tracker_id]
541 end
541 end
542
542
543 def test_category_based_assignment
543 def test_category_based_assignment
544 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
544 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
545 :status_id => 1, :priority => IssuePriority.all.first,
545 :status_id => 1, :priority => IssuePriority.all.first,
546 :subject => 'Assignment test',
546 :subject => 'Assignment test',
547 :description => 'Assignment test', :category_id => 1)
547 :description => 'Assignment test', :category_id => 1)
548 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
548 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
549 end
549 end
550
550
551 def test_new_statuses_allowed_to
551 def test_new_statuses_allowed_to
552 WorkflowTransition.delete_all
552 WorkflowTransition.delete_all
553 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
553 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
554 :old_status_id => 1, :new_status_id => 2,
554 :old_status_id => 1, :new_status_id => 2,
555 :author => false, :assignee => false)
555 :author => false, :assignee => false)
556 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
556 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
557 :old_status_id => 1, :new_status_id => 3,
557 :old_status_id => 1, :new_status_id => 3,
558 :author => true, :assignee => false)
558 :author => true, :assignee => false)
559 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
559 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
560 :old_status_id => 1, :new_status_id => 4,
560 :old_status_id => 1, :new_status_id => 4,
561 :author => false, :assignee => true)
561 :author => false, :assignee => true)
562 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
562 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
563 :old_status_id => 1, :new_status_id => 5,
563 :old_status_id => 1, :new_status_id => 5,
564 :author => true, :assignee => true)
564 :author => true, :assignee => true)
565 status = IssueStatus.find(1)
565 status = IssueStatus.find(1)
566 role = Role.find(1)
566 role = Role.find(1)
567 tracker = Tracker.find(1)
567 tracker = Tracker.find(1)
568 user = User.find(2)
568 user = User.find(2)
569
569
570 issue = Issue.generate!(:tracker => tracker, :status => status,
570 issue = Issue.generate!(:tracker => tracker, :status => status,
571 :project_id => 1, :author_id => 1)
571 :project_id => 1, :author_id => 1)
572 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
572 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
573
573
574 issue = Issue.generate!(:tracker => tracker, :status => status,
574 issue = Issue.generate!(:tracker => tracker, :status => status,
575 :project_id => 1, :author => user)
575 :project_id => 1, :author => user)
576 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
576 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
577
577
578 issue = Issue.generate!(:tracker => tracker, :status => status,
578 issue = Issue.generate!(:tracker => tracker, :status => status,
579 :project_id => 1, :author_id => 1,
579 :project_id => 1, :author_id => 1,
580 :assigned_to => user)
580 :assigned_to => user)
581 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
581 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
582
582
583 issue = Issue.generate!(:tracker => tracker, :status => status,
583 issue = Issue.generate!(:tracker => tracker, :status => status,
584 :project_id => 1, :author => user,
584 :project_id => 1, :author => user,
585 :assigned_to => user)
585 :assigned_to => user)
586 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
586 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
587
587
588 group = Group.generate!
588 group = Group.generate!
589 group.users << user
589 group.users << user
590 issue = Issue.generate!(:tracker => tracker, :status => status,
590 issue = Issue.generate!(:tracker => tracker, :status => status,
591 :project_id => 1, :author => user,
591 :project_id => 1, :author => user,
592 :assigned_to => group)
592 :assigned_to => group)
593 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
593 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
594 end
594 end
595
595
596 def test_new_statuses_allowed_to_should_consider_group_assignment
596 def test_new_statuses_allowed_to_should_consider_group_assignment
597 WorkflowTransition.delete_all
597 WorkflowTransition.delete_all
598 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
598 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
599 :old_status_id => 1, :new_status_id => 4,
599 :old_status_id => 1, :new_status_id => 4,
600 :author => false, :assignee => true)
600 :author => false, :assignee => true)
601 user = User.find(2)
601 user = User.find(2)
602 group = Group.generate!
602 group = Group.generate!
603 group.users << user
603 group.users << user
604
604
605 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
605 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
606 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
606 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
607 end
607 end
608
608
609 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
609 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
610 admin = User.find(1)
610 admin = User.find(1)
611 issue = Issue.find(1)
611 issue = Issue.find(1)
612 assert !admin.member_of?(issue.project)
612 assert !admin.member_of?(issue.project)
613 expected_statuses = [issue.status] +
613 expected_statuses = [issue.status] +
614 WorkflowTransition.where(:old_status_id => issue.status_id).
614 WorkflowTransition.where(:old_status_id => issue.status_id).
615 map(&:new_status).uniq.sort
615 map(&:new_status).uniq.sort
616 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
616 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
617 end
617 end
618
618
619 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
619 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
620 issue = Issue.find(1).copy
620 issue = Issue.find(1).copy
621 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
621 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
622
622
623 issue = Issue.find(2).copy
623 issue = Issue.find(2).copy
624 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
624 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
625 end
625 end
626
626
627 def test_safe_attributes_names_should_not_include_disabled_field
627 def test_safe_attributes_names_should_not_include_disabled_field
628 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
628 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
629
629
630 issue = Issue.new(:tracker => tracker)
630 issue = Issue.new(:tracker => tracker)
631 assert_include 'tracker_id', issue.safe_attribute_names
631 assert_include 'tracker_id', issue.safe_attribute_names
632 assert_include 'status_id', issue.safe_attribute_names
632 assert_include 'status_id', issue.safe_attribute_names
633 assert_include 'subject', issue.safe_attribute_names
633 assert_include 'subject', issue.safe_attribute_names
634 assert_include 'description', issue.safe_attribute_names
634 assert_include 'description', issue.safe_attribute_names
635 assert_include 'custom_field_values', issue.safe_attribute_names
635 assert_include 'custom_field_values', issue.safe_attribute_names
636 assert_include 'custom_fields', issue.safe_attribute_names
636 assert_include 'custom_fields', issue.safe_attribute_names
637 assert_include 'lock_version', issue.safe_attribute_names
637 assert_include 'lock_version', issue.safe_attribute_names
638
638
639 tracker.core_fields.each do |field|
639 tracker.core_fields.each do |field|
640 assert_include field, issue.safe_attribute_names
640 assert_include field, issue.safe_attribute_names
641 end
641 end
642
642
643 tracker.disabled_core_fields.each do |field|
643 tracker.disabled_core_fields.each do |field|
644 assert_not_include field, issue.safe_attribute_names
644 assert_not_include field, issue.safe_attribute_names
645 end
645 end
646 end
646 end
647
647
648 def test_safe_attributes_should_ignore_disabled_fields
648 def test_safe_attributes_should_ignore_disabled_fields
649 tracker = Tracker.find(1)
649 tracker = Tracker.find(1)
650 tracker.core_fields = %w(assigned_to_id due_date)
650 tracker.core_fields = %w(assigned_to_id due_date)
651 tracker.save!
651 tracker.save!
652
652
653 issue = Issue.new(:tracker => tracker)
653 issue = Issue.new(:tracker => tracker)
654 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
654 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
655 assert_nil issue.start_date
655 assert_nil issue.start_date
656 assert_equal Date.parse('2012-07-14'), issue.due_date
656 assert_equal Date.parse('2012-07-14'), issue.due_date
657 end
657 end
658
658
659 def test_safe_attributes_should_accept_target_tracker_enabled_fields
659 def test_safe_attributes_should_accept_target_tracker_enabled_fields
660 source = Tracker.find(1)
660 source = Tracker.find(1)
661 source.core_fields = []
661 source.core_fields = []
662 source.save!
662 source.save!
663 target = Tracker.find(2)
663 target = Tracker.find(2)
664 target.core_fields = %w(assigned_to_id due_date)
664 target.core_fields = %w(assigned_to_id due_date)
665 target.save!
665 target.save!
666
666
667 issue = Issue.new(:tracker => source)
667 issue = Issue.new(:tracker => source)
668 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
668 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
669 assert_equal target, issue.tracker
669 assert_equal target, issue.tracker
670 assert_equal Date.parse('2012-07-14'), issue.due_date
670 assert_equal Date.parse('2012-07-14'), issue.due_date
671 end
671 end
672
672
673 def test_safe_attributes_should_not_include_readonly_fields
673 def test_safe_attributes_should_not_include_readonly_fields
674 WorkflowPermission.delete_all
674 WorkflowPermission.delete_all
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
675 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
676 :role_id => 1, :field_name => 'due_date',
676 :role_id => 1, :field_name => 'due_date',
677 :rule => 'readonly')
677 :rule => 'readonly')
678 user = User.find(2)
678 user = User.find(2)
679
679
680 issue = Issue.new(:project_id => 1, :tracker_id => 1)
680 issue = Issue.new(:project_id => 1, :tracker_id => 1)
681 assert_equal %w(due_date), issue.read_only_attribute_names(user)
681 assert_equal %w(due_date), issue.read_only_attribute_names(user)
682 assert_not_include 'due_date', issue.safe_attribute_names(user)
682 assert_not_include 'due_date', issue.safe_attribute_names(user)
683
683
684 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
684 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
685 assert_equal Date.parse('2012-07-14'), issue.start_date
685 assert_equal Date.parse('2012-07-14'), issue.start_date
686 assert_nil issue.due_date
686 assert_nil issue.due_date
687 end
687 end
688
688
689 def test_safe_attributes_should_not_include_readonly_custom_fields
689 def test_safe_attributes_should_not_include_readonly_custom_fields
690 cf1 = IssueCustomField.create!(:name => 'Writable field',
690 cf1 = IssueCustomField.create!(:name => 'Writable field',
691 :field_format => 'string',
691 :field_format => 'string',
692 :is_for_all => true, :tracker_ids => [1])
692 :is_for_all => true, :tracker_ids => [1])
693 cf2 = IssueCustomField.create!(:name => 'Readonly field',
693 cf2 = IssueCustomField.create!(:name => 'Readonly field',
694 :field_format => 'string',
694 :field_format => 'string',
695 :is_for_all => true, :tracker_ids => [1])
695 :is_for_all => true, :tracker_ids => [1])
696 WorkflowPermission.delete_all
696 WorkflowPermission.delete_all
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
698 :role_id => 1, :field_name => cf2.id.to_s,
698 :role_id => 1, :field_name => cf2.id.to_s,
699 :rule => 'readonly')
699 :rule => 'readonly')
700 user = User.find(2)
700 user = User.find(2)
701 issue = Issue.new(:project_id => 1, :tracker_id => 1)
701 issue = Issue.new(:project_id => 1, :tracker_id => 1)
702 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
702 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
703 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
703 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
704
704
705 issue.send :safe_attributes=, {'custom_field_values' => {
705 issue.send :safe_attributes=, {'custom_field_values' => {
706 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
706 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
707 }}, user
707 }}, user
708 assert_equal 'value1', issue.custom_field_value(cf1)
708 assert_equal 'value1', issue.custom_field_value(cf1)
709 assert_nil issue.custom_field_value(cf2)
709 assert_nil issue.custom_field_value(cf2)
710
710
711 issue.send :safe_attributes=, {'custom_fields' => [
711 issue.send :safe_attributes=, {'custom_fields' => [
712 {'id' => cf1.id.to_s, 'value' => 'valuea'},
712 {'id' => cf1.id.to_s, 'value' => 'valuea'},
713 {'id' => cf2.id.to_s, 'value' => 'valueb'}
713 {'id' => cf2.id.to_s, 'value' => 'valueb'}
714 ]}, user
714 ]}, user
715 assert_equal 'valuea', issue.custom_field_value(cf1)
715 assert_equal 'valuea', issue.custom_field_value(cf1)
716 assert_nil issue.custom_field_value(cf2)
716 assert_nil issue.custom_field_value(cf2)
717 end
717 end
718
718
719 def test_editable_custom_field_values_should_return_non_readonly_custom_values
719 def test_editable_custom_field_values_should_return_non_readonly_custom_values
720 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
720 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
721 :is_for_all => true, :tracker_ids => [1, 2])
721 :is_for_all => true, :tracker_ids => [1, 2])
722 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
722 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
723 :is_for_all => true, :tracker_ids => [1, 2])
723 :is_for_all => true, :tracker_ids => [1, 2])
724 WorkflowPermission.delete_all
724 WorkflowPermission.delete_all
725 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
725 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
726 :field_name => cf2.id.to_s, :rule => 'readonly')
726 :field_name => cf2.id.to_s, :rule => 'readonly')
727 user = User.find(2)
727 user = User.find(2)
728
728
729 issue = Issue.new(:project_id => 1, :tracker_id => 1)
729 issue = Issue.new(:project_id => 1, :tracker_id => 1)
730 values = issue.editable_custom_field_values(user)
730 values = issue.editable_custom_field_values(user)
731 assert values.detect {|value| value.custom_field == cf1}
731 assert values.detect {|value| value.custom_field == cf1}
732 assert_nil values.detect {|value| value.custom_field == cf2}
732 assert_nil values.detect {|value| value.custom_field == cf2}
733
733
734 issue.tracker_id = 2
734 issue.tracker_id = 2
735 values = issue.editable_custom_field_values(user)
735 values = issue.editable_custom_field_values(user)
736 assert values.detect {|value| value.custom_field == cf1}
736 assert values.detect {|value| value.custom_field == cf1}
737 assert values.detect {|value| value.custom_field == cf2}
737 assert values.detect {|value| value.custom_field == cf2}
738 end
738 end
739
739
740 def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only
740 def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only
741 enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
741 enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
742 disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
742 disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
743 user = User.find(2)
743 user = User.find(2)
744 issue = Issue.new(:project_id => 1, :tracker_id => 1)
744 issue = Issue.new(:project_id => 1, :tracker_id => 1)
745
745
746 assert_include enabled_cf, issue.editable_custom_fields(user)
746 assert_include enabled_cf, issue.editable_custom_fields(user)
747 assert_not_include disabled_cf, issue.editable_custom_fields(user)
747 assert_not_include disabled_cf, issue.editable_custom_fields(user)
748 end
748 end
749
749
750 def test_safe_attributes_should_accept_target_tracker_writable_fields
750 def test_safe_attributes_should_accept_target_tracker_writable_fields
751 WorkflowPermission.delete_all
751 WorkflowPermission.delete_all
752 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
752 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
753 :role_id => 1, :field_name => 'due_date',
753 :role_id => 1, :field_name => 'due_date',
754 :rule => 'readonly')
754 :rule => 'readonly')
755 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
755 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
756 :role_id => 1, :field_name => 'start_date',
756 :role_id => 1, :field_name => 'start_date',
757 :rule => 'readonly')
757 :rule => 'readonly')
758 user = User.find(2)
758 user = User.find(2)
759
759
760 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
760 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
761
761
762 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
762 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
763 'due_date' => '2012-07-14'}, user
763 'due_date' => '2012-07-14'}, user
764 assert_equal Date.parse('2012-07-12'), issue.start_date
764 assert_equal Date.parse('2012-07-12'), issue.start_date
765 assert_nil issue.due_date
765 assert_nil issue.due_date
766
766
767 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
767 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
768 'due_date' => '2012-07-16',
768 'due_date' => '2012-07-16',
769 'tracker_id' => 2}, user
769 'tracker_id' => 2}, user
770 assert_equal Date.parse('2012-07-12'), issue.start_date
770 assert_equal Date.parse('2012-07-12'), issue.start_date
771 assert_equal Date.parse('2012-07-16'), issue.due_date
771 assert_equal Date.parse('2012-07-16'), issue.due_date
772 end
772 end
773
773
774 def test_safe_attributes_should_accept_target_status_writable_fields
774 def test_safe_attributes_should_accept_target_status_writable_fields
775 WorkflowPermission.delete_all
775 WorkflowPermission.delete_all
776 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
776 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
777 :role_id => 1, :field_name => 'due_date',
777 :role_id => 1, :field_name => 'due_date',
778 :rule => 'readonly')
778 :rule => 'readonly')
779 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
779 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
780 :role_id => 1, :field_name => 'start_date',
780 :role_id => 1, :field_name => 'start_date',
781 :rule => 'readonly')
781 :rule => 'readonly')
782 user = User.find(2)
782 user = User.find(2)
783
783
784 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
784 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
785
785
786 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
786 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
787 'due_date' => '2012-07-14'},
787 'due_date' => '2012-07-14'},
788 user
788 user
789 assert_equal Date.parse('2012-07-12'), issue.start_date
789 assert_equal Date.parse('2012-07-12'), issue.start_date
790 assert_nil issue.due_date
790 assert_nil issue.due_date
791
791
792 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
792 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
793 'due_date' => '2012-07-16',
793 'due_date' => '2012-07-16',
794 'status_id' => 2},
794 'status_id' => 2},
795 user
795 user
796 assert_equal Date.parse('2012-07-12'), issue.start_date
796 assert_equal Date.parse('2012-07-12'), issue.start_date
797 assert_equal Date.parse('2012-07-16'), issue.due_date
797 assert_equal Date.parse('2012-07-16'), issue.due_date
798 end
798 end
799
799
800 def test_required_attributes_should_be_validated
800 def test_required_attributes_should_be_validated
801 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
801 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
802 :is_for_all => true, :tracker_ids => [1, 2])
802 :is_for_all => true, :tracker_ids => [1, 2])
803
803
804 WorkflowPermission.delete_all
804 WorkflowPermission.delete_all
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
805 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
806 :role_id => 1, :field_name => 'due_date',
806 :role_id => 1, :field_name => 'due_date',
807 :rule => 'required')
807 :rule => 'required')
808 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
808 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
809 :role_id => 1, :field_name => 'category_id',
809 :role_id => 1, :field_name => 'category_id',
810 :rule => 'required')
810 :rule => 'required')
811 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
811 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
812 :role_id => 1, :field_name => cf.id.to_s,
812 :role_id => 1, :field_name => cf.id.to_s,
813 :rule => 'required')
813 :rule => 'required')
814
814
815 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
815 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
816 :role_id => 1, :field_name => 'start_date',
816 :role_id => 1, :field_name => 'start_date',
817 :rule => 'required')
817 :rule => 'required')
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
818 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
819 :role_id => 1, :field_name => cf.id.to_s,
819 :role_id => 1, :field_name => cf.id.to_s,
820 :rule => 'required')
820 :rule => 'required')
821 user = User.find(2)
821 user = User.find(2)
822
822
823 issue = Issue.new(:project_id => 1, :tracker_id => 1,
823 issue = Issue.new(:project_id => 1, :tracker_id => 1,
824 :status_id => 1, :subject => 'Required fields',
824 :status_id => 1, :subject => 'Required fields',
825 :author => user)
825 :author => user)
826 assert_equal [cf.id.to_s, "category_id", "due_date"],
826 assert_equal [cf.id.to_s, "category_id", "due_date"],
827 issue.required_attribute_names(user).sort
827 issue.required_attribute_names(user).sort
828 assert !issue.save, "Issue was saved"
828 assert !issue.save, "Issue was saved"
829 assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"],
829 assert_equal ["Category cannot be blank", "Due date cannot be blank", "Foo cannot be blank"],
830 issue.errors.full_messages.sort
830 issue.errors.full_messages.sort
831
831
832 issue.tracker_id = 2
832 issue.tracker_id = 2
833 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
833 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
834 assert !issue.save, "Issue was saved"
834 assert !issue.save, "Issue was saved"
835 assert_equal ["Foo cannot be blank", "Start date cannot be blank"],
835 assert_equal ["Foo cannot be blank", "Start date cannot be blank"],
836 issue.errors.full_messages.sort
836 issue.errors.full_messages.sort
837
837
838 issue.start_date = Date.today
838 issue.start_date = Date.today
839 issue.custom_field_values = {cf.id.to_s => 'bar'}
839 issue.custom_field_values = {cf.id.to_s => 'bar'}
840 assert issue.save
840 assert issue.save
841 end
841 end
842
842
843 def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required
843 def test_required_attribute_that_is_disabled_for_the_tracker_should_not_be_required
844 WorkflowPermission.delete_all
844 WorkflowPermission.delete_all
845 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
845 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
846 :role_id => 1, :field_name => 'start_date',
846 :role_id => 1, :field_name => 'start_date',
847 :rule => 'required')
847 :rule => 'required')
848 user = User.find(2)
848 user = User.find(2)
849
849
850 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
850 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
851 :subject => 'Required fields', :author => user)
851 :subject => 'Required fields', :author => user)
852 assert !issue.save
852 assert !issue.save
853 assert_include "Start date cannot be blank", issue.errors.full_messages
853 assert_include "Start date cannot be blank", issue.errors.full_messages
854
854
855 tracker = Tracker.find(1)
855 tracker = Tracker.find(1)
856 tracker.core_fields -= %w(start_date)
856 tracker.core_fields -= %w(start_date)
857 tracker.save!
857 tracker.save!
858 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
858 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
859 :subject => 'Required fields', :author => user)
859 :subject => 'Required fields', :author => user)
860 assert issue.save
860 assert issue.save
861 end
861 end
862
862
863 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
863 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
864 WorkflowPermission.delete_all
864 WorkflowPermission.delete_all
865 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
865 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
866 :role_id => 1, :field_name => 'due_date',
866 :role_id => 1, :field_name => 'due_date',
867 :rule => 'required')
867 :rule => 'required')
868 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
868 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
869 :role_id => 1, :field_name => 'start_date',
869 :role_id => 1, :field_name => 'start_date',
870 :rule => 'required')
870 :rule => 'required')
871 user = User.find(2)
871 user = User.find(2)
872 member = Member.find(1)
872 member = Member.find(1)
873 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
873 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
874
874
875 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
875 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
876
876
877 member.role_ids = [1, 2]
877 member.role_ids = [1, 2]
878 member.save!
878 member.save!
879 assert_equal [], issue.required_attribute_names(user.reload)
879 assert_equal [], issue.required_attribute_names(user.reload)
880
880
881 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
881 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
882 :role_id => 2, :field_name => 'due_date',
882 :role_id => 2, :field_name => 'due_date',
883 :rule => 'required')
883 :rule => 'required')
884 assert_equal %w(due_date), issue.required_attribute_names(user)
884 assert_equal %w(due_date), issue.required_attribute_names(user)
885
885
886 member.role_ids = [1, 2, 3]
886 member.role_ids = [1, 2, 3]
887 member.save!
887 member.save!
888 assert_equal [], issue.required_attribute_names(user.reload)
888 assert_equal [], issue.required_attribute_names(user.reload)
889
889
890 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
890 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
891 :role_id => 3, :field_name => 'due_date',
891 :role_id => 3, :field_name => 'due_date',
892 :rule => 'readonly')
892 :rule => 'readonly')
893 # required + readonly => required
893 # required + readonly => required
894 assert_equal %w(due_date), issue.required_attribute_names(user)
894 assert_equal %w(due_date), issue.required_attribute_names(user)
895 end
895 end
896
896
897 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
897 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
898 WorkflowPermission.delete_all
898 WorkflowPermission.delete_all
899 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
899 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
900 :role_id => 1, :field_name => 'due_date',
900 :role_id => 1, :field_name => 'due_date',
901 :rule => 'readonly')
901 :rule => 'readonly')
902 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
902 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
903 :role_id => 1, :field_name => 'start_date',
903 :role_id => 1, :field_name => 'start_date',
904 :rule => 'readonly')
904 :rule => 'readonly')
905 user = User.find(2)
905 user = User.find(2)
906 member = Member.find(1)
906 member = Member.find(1)
907 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
907 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
908
908
909 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
909 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
910
910
911 member.role_ids = [1, 2]
911 member.role_ids = [1, 2]
912 member.save!
912 member.save!
913 assert_equal [], issue.read_only_attribute_names(user.reload)
913 assert_equal [], issue.read_only_attribute_names(user.reload)
914
914
915 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
915 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
916 :role_id => 2, :field_name => 'due_date',
916 :role_id => 2, :field_name => 'due_date',
917 :rule => 'readonly')
917 :rule => 'readonly')
918 assert_equal %w(due_date), issue.read_only_attribute_names(user)
918 assert_equal %w(due_date), issue.read_only_attribute_names(user)
919 end
919 end
920
920
921 # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2
921 # A field that is not visible by role 2 and readonly by role 1 should be readonly for user with role 1 and 2
922 def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles
922 def test_read_only_attribute_names_should_include_custom_fields_that_combine_readonly_and_not_visible_for_roles
923 field = IssueCustomField.generate!(
923 field = IssueCustomField.generate!(
924 :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1]
924 :is_for_all => true, :trackers => Tracker.all, :visible => false, :role_ids => [1]
925 )
925 )
926 WorkflowPermission.delete_all
926 WorkflowPermission.delete_all
927 WorkflowPermission.create!(
927 WorkflowPermission.create!(
928 :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly'
928 :old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => field.id, :rule => 'readonly'
929 )
929 )
930 user = User.generate!
930 user = User.generate!
931 project = Project.find(1)
931 project = Project.find(1)
932 User.add_to_project(user, project, Role.where(:id => [1, 2]))
932 User.add_to_project(user, project, Role.where(:id => [1, 2]))
933
933
934 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
934 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
935 assert_equal [field.id.to_s], issue.read_only_attribute_names(user)
935 assert_equal [field.id.to_s], issue.read_only_attribute_names(user)
936 end
936 end
937
937
938 def test_workflow_rules_should_ignore_roles_without_issue_permissions
938 def test_workflow_rules_should_ignore_roles_without_issue_permissions
939 role = Role.generate! :permissions => [:view_issues, :edit_issues]
939 role = Role.generate! :permissions => [:view_issues, :edit_issues]
940 ignored_role = Role.generate! :permissions => [:view_issues]
940 ignored_role = Role.generate! :permissions => [:view_issues]
941
941
942 WorkflowPermission.delete_all
942 WorkflowPermission.delete_all
943 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
943 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
944 :role => role, :field_name => 'due_date',
944 :role => role, :field_name => 'due_date',
945 :rule => 'required')
945 :rule => 'required')
946 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
946 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
947 :role => role, :field_name => 'start_date',
947 :role => role, :field_name => 'start_date',
948 :rule => 'readonly')
948 :rule => 'readonly')
949 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
949 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
950 :role => role, :field_name => 'done_ratio',
950 :role => role, :field_name => 'done_ratio',
951 :rule => 'readonly')
951 :rule => 'readonly')
952 user = User.generate!
952 user = User.generate!
953 User.add_to_project user, Project.find(1), [role, ignored_role]
953 User.add_to_project user, Project.find(1), [role, ignored_role]
954
954
955 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
955 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
956
956
957 assert_equal %w(due_date), issue.required_attribute_names(user)
957 assert_equal %w(due_date), issue.required_attribute_names(user)
958 assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort
958 assert_equal %w(done_ratio start_date), issue.read_only_attribute_names(user).sort
959 end
959 end
960
960
961 def test_workflow_rules_should_work_for_member_with_duplicate_role
962 WorkflowPermission.delete_all
963 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
964 :role_id => 1, :field_name => 'due_date',
965 :rule => 'required')
966 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
967 :role_id => 1, :field_name => 'start_date',
968 :rule => 'readonly')
969
970 user = User.generate!
971 m = Member.new(:user_id => user.id, :project_id => 1)
972 m.member_roles.build(:role_id => 1)
973 m.member_roles.build(:role_id => 1)
974 m.save!
975
976 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
977
978 assert_equal %w(due_date), issue.required_attribute_names(user)
979 assert_equal %w(start_date), issue.read_only_attribute_names(user)
980 end
981
961 def test_copy
982 def test_copy
962 issue = Issue.new.copy_from(1)
983 issue = Issue.new.copy_from(1)
963 assert issue.copy?
984 assert issue.copy?
964 assert issue.save
985 assert issue.save
965 issue.reload
986 issue.reload
966 orig = Issue.find(1)
987 orig = Issue.find(1)
967 assert_equal orig.subject, issue.subject
988 assert_equal orig.subject, issue.subject
968 assert_equal orig.tracker, issue.tracker
989 assert_equal orig.tracker, issue.tracker
969 assert_equal "125", issue.custom_value_for(2).value
990 assert_equal "125", issue.custom_value_for(2).value
970 end
991 end
971
992
972 def test_copy_should_copy_status
993 def test_copy_should_copy_status
973 orig = Issue.find(8)
994 orig = Issue.find(8)
974 assert orig.status != orig.default_status
995 assert orig.status != orig.default_status
975
996
976 issue = Issue.new.copy_from(orig)
997 issue = Issue.new.copy_from(orig)
977 assert issue.save
998 assert issue.save
978 issue.reload
999 issue.reload
979 assert_equal orig.status, issue.status
1000 assert_equal orig.status, issue.status
980 end
1001 end
981
1002
982 def test_copy_should_add_relation_with_copied_issue
1003 def test_copy_should_add_relation_with_copied_issue
983 copied = Issue.find(1)
1004 copied = Issue.find(1)
984 issue = Issue.new.copy_from(copied)
1005 issue = Issue.new.copy_from(copied)
985 assert issue.save
1006 assert issue.save
986 issue.reload
1007 issue.reload
987
1008
988 assert_equal 1, issue.relations.size
1009 assert_equal 1, issue.relations.size
989 relation = issue.relations.first
1010 relation = issue.relations.first
990 assert_equal 'copied_to', relation.relation_type
1011 assert_equal 'copied_to', relation.relation_type
991 assert_equal copied, relation.issue_from
1012 assert_equal copied, relation.issue_from
992 assert_equal issue, relation.issue_to
1013 assert_equal issue, relation.issue_to
993 end
1014 end
994
1015
995 def test_copy_should_copy_subtasks
1016 def test_copy_should_copy_subtasks
996 issue = Issue.generate_with_descendants!
1017 issue = Issue.generate_with_descendants!
997
1018
998 copy = issue.reload.copy
1019 copy = issue.reload.copy
999 copy.author = User.find(7)
1020 copy.author = User.find(7)
1000 assert_difference 'Issue.count', 1+issue.descendants.count do
1021 assert_difference 'Issue.count', 1+issue.descendants.count do
1001 assert copy.save
1022 assert copy.save
1002 end
1023 end
1003 copy.reload
1024 copy.reload
1004 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
1025 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
1005 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
1026 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
1006 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
1027 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
1007 assert_equal copy.author, child_copy.author
1028 assert_equal copy.author, child_copy.author
1008 end
1029 end
1009
1030
1010 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
1031 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
1011 parent = Issue.generate!
1032 parent = Issue.generate!
1012 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1033 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1013 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1034 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1014
1035
1015 copy = parent.reload.copy
1036 copy = parent.reload.copy
1016 copy.parent_issue_id = parent.id
1037 copy.parent_issue_id = parent.id
1017 copy.author = User.find(7)
1038 copy.author = User.find(7)
1018 assert_difference 'Issue.count', 3 do
1039 assert_difference 'Issue.count', 3 do
1019 assert copy.save
1040 assert copy.save
1020 end
1041 end
1021 parent.reload
1042 parent.reload
1022 copy.reload
1043 copy.reload
1023 assert_equal parent, copy.parent
1044 assert_equal parent, copy.parent
1024 assert_equal 3, parent.children.count
1045 assert_equal 3, parent.children.count
1025 assert_equal 5, parent.descendants.count
1046 assert_equal 5, parent.descendants.count
1026 assert_equal 2, copy.children.count
1047 assert_equal 2, copy.children.count
1027 assert_equal 2, copy.descendants.count
1048 assert_equal 2, copy.descendants.count
1028 end
1049 end
1029
1050
1030 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
1051 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
1031 parent = Issue.generate!
1052 parent = Issue.generate!
1032 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1053 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
1033 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1054 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
1034
1055
1035 copy = parent.reload.copy
1056 copy = parent.reload.copy
1036 copy.parent_issue_id = child1.id
1057 copy.parent_issue_id = child1.id
1037 copy.author = User.find(7)
1058 copy.author = User.find(7)
1038 assert_difference 'Issue.count', 3 do
1059 assert_difference 'Issue.count', 3 do
1039 assert copy.save
1060 assert copy.save
1040 end
1061 end
1041 parent.reload
1062 parent.reload
1042 child1.reload
1063 child1.reload
1043 copy.reload
1064 copy.reload
1044 assert_equal child1, copy.parent
1065 assert_equal child1, copy.parent
1045 assert_equal 2, parent.children.count
1066 assert_equal 2, parent.children.count
1046 assert_equal 5, parent.descendants.count
1067 assert_equal 5, parent.descendants.count
1047 assert_equal 1, child1.children.count
1068 assert_equal 1, child1.children.count
1048 assert_equal 3, child1.descendants.count
1069 assert_equal 3, child1.descendants.count
1049 assert_equal 2, copy.children.count
1070 assert_equal 2, copy.children.count
1050 assert_equal 2, copy.descendants.count
1071 assert_equal 2, copy.descendants.count
1051 end
1072 end
1052
1073
1053 def test_copy_should_copy_subtasks_to_target_project
1074 def test_copy_should_copy_subtasks_to_target_project
1054 issue = Issue.generate_with_descendants!
1075 issue = Issue.generate_with_descendants!
1055
1076
1056 copy = issue.copy(:project_id => 3)
1077 copy = issue.copy(:project_id => 3)
1057 assert_difference 'Issue.count', 1+issue.descendants.count do
1078 assert_difference 'Issue.count', 1+issue.descendants.count do
1058 assert copy.save
1079 assert copy.save
1059 end
1080 end
1060 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
1081 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
1061 end
1082 end
1062
1083
1063 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
1084 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
1064 issue = Issue.generate_with_descendants!
1085 issue = Issue.generate_with_descendants!
1065
1086
1066 copy = issue.reload.copy
1087 copy = issue.reload.copy
1067 assert_difference 'Issue.count', 1+issue.descendants.count do
1088 assert_difference 'Issue.count', 1+issue.descendants.count do
1068 assert copy.save
1089 assert copy.save
1069 assert copy.save
1090 assert copy.save
1070 end
1091 end
1071 end
1092 end
1072
1093
1073 def test_should_not_call_after_project_change_on_creation
1094 def test_should_not_call_after_project_change_on_creation
1074 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
1095 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
1075 :subject => 'Test', :author_id => 1)
1096 :subject => 'Test', :author_id => 1)
1076 issue.expects(:after_project_change).never
1097 issue.expects(:after_project_change).never
1077 issue.save!
1098 issue.save!
1078 end
1099 end
1079
1100
1080 def test_should_not_call_after_project_change_on_update
1101 def test_should_not_call_after_project_change_on_update
1081 issue = Issue.find(1)
1102 issue = Issue.find(1)
1082 issue.project = Project.find(1)
1103 issue.project = Project.find(1)
1083 issue.subject = 'No project change'
1104 issue.subject = 'No project change'
1084 issue.expects(:after_project_change).never
1105 issue.expects(:after_project_change).never
1085 issue.save!
1106 issue.save!
1086 end
1107 end
1087
1108
1088 def test_should_call_after_project_change_on_project_change
1109 def test_should_call_after_project_change_on_project_change
1089 issue = Issue.find(1)
1110 issue = Issue.find(1)
1090 issue.project = Project.find(2)
1111 issue.project = Project.find(2)
1091 issue.expects(:after_project_change).once
1112 issue.expects(:after_project_change).once
1092 issue.save!
1113 issue.save!
1093 end
1114 end
1094
1115
1095 def test_adding_journal_should_update_timestamp
1116 def test_adding_journal_should_update_timestamp
1096 issue = Issue.find(1)
1117 issue = Issue.find(1)
1097 updated_on_was = issue.updated_on
1118 updated_on_was = issue.updated_on
1098
1119
1099 issue.init_journal(User.first, "Adding notes")
1120 issue.init_journal(User.first, "Adding notes")
1100 assert_difference 'Journal.count' do
1121 assert_difference 'Journal.count' do
1101 assert issue.save
1122 assert issue.save
1102 end
1123 end
1103 issue.reload
1124 issue.reload
1104
1125
1105 assert_not_equal updated_on_was, issue.updated_on
1126 assert_not_equal updated_on_was, issue.updated_on
1106 end
1127 end
1107
1128
1108 def test_should_close_duplicates
1129 def test_should_close_duplicates
1109 # Create 3 issues
1130 # Create 3 issues
1110 issue1 = Issue.generate!
1131 issue1 = Issue.generate!
1111 issue2 = Issue.generate!
1132 issue2 = Issue.generate!
1112 issue3 = Issue.generate!
1133 issue3 = Issue.generate!
1113
1134
1114 # 2 is a dupe of 1
1135 # 2 is a dupe of 1
1115 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
1136 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
1116 :relation_type => IssueRelation::TYPE_DUPLICATES)
1137 :relation_type => IssueRelation::TYPE_DUPLICATES)
1117 # And 3 is a dupe of 2
1138 # And 3 is a dupe of 2
1118 # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1139 # IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1119 # :relation_type => IssueRelation::TYPE_DUPLICATES)
1140 # :relation_type => IssueRelation::TYPE_DUPLICATES)
1120 # And 3 is a dupe of 1 (circular duplicates)
1141 # And 3 is a dupe of 1 (circular duplicates)
1121 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1142 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
1122 :relation_type => IssueRelation::TYPE_DUPLICATES)
1143 :relation_type => IssueRelation::TYPE_DUPLICATES)
1123
1144
1124 assert issue1.reload.duplicates.include?(issue2)
1145 assert issue1.reload.duplicates.include?(issue2)
1125
1146
1126 # Closing issue 1
1147 # Closing issue 1
1127 issue1.init_journal(User.first, "Closing issue1")
1148 issue1.init_journal(User.first, "Closing issue1")
1128 issue1.status = IssueStatus.where(:is_closed => true).first
1149 issue1.status = IssueStatus.where(:is_closed => true).first
1129 assert issue1.save
1150 assert issue1.save
1130 # 2 and 3 should be also closed
1151 # 2 and 3 should be also closed
1131 assert issue2.reload.closed?
1152 assert issue2.reload.closed?
1132 assert issue3.reload.closed?
1153 assert issue3.reload.closed?
1133 end
1154 end
1134
1155
1135 def test_should_not_close_duplicated_issue
1156 def test_should_not_close_duplicated_issue
1136 issue1 = Issue.generate!
1157 issue1 = Issue.generate!
1137 issue2 = Issue.generate!
1158 issue2 = Issue.generate!
1138
1159
1139 # 2 is a dupe of 1
1160 # 2 is a dupe of 1
1140 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1161 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
1141 :relation_type => IssueRelation::TYPE_DUPLICATES)
1162 :relation_type => IssueRelation::TYPE_DUPLICATES)
1142 # 2 is a dup of 1 but 1 is not a duplicate of 2
1163 # 2 is a dup of 1 but 1 is not a duplicate of 2
1143 assert !issue2.reload.duplicates.include?(issue1)
1164 assert !issue2.reload.duplicates.include?(issue1)
1144
1165
1145 # Closing issue 2
1166 # Closing issue 2
1146 issue2.init_journal(User.first, "Closing issue2")
1167 issue2.init_journal(User.first, "Closing issue2")
1147 issue2.status = IssueStatus.where(:is_closed => true).first
1168 issue2.status = IssueStatus.where(:is_closed => true).first
1148 assert issue2.save
1169 assert issue2.save
1149 # 1 should not be also closed
1170 # 1 should not be also closed
1150 assert !issue1.reload.closed?
1171 assert !issue1.reload.closed?
1151 end
1172 end
1152
1173
1153 def test_assignable_versions
1174 def test_assignable_versions
1154 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1175 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1155 :status_id => 1, :fixed_version_id => 1,
1176 :status_id => 1, :fixed_version_id => 1,
1156 :subject => 'New issue')
1177 :subject => 'New issue')
1157 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1178 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
1158 end
1179 end
1159
1180
1160 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1181 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
1161 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1182 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1162 :status_id => 1, :fixed_version_id => 1,
1183 :status_id => 1, :fixed_version_id => 1,
1163 :subject => 'New issue')
1184 :subject => 'New issue')
1164 assert !issue.save
1185 assert !issue.save
1165 assert_not_equal [], issue.errors[:fixed_version_id]
1186 assert_not_equal [], issue.errors[:fixed_version_id]
1166 end
1187 end
1167
1188
1168 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1189 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
1169 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1190 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1170 :status_id => 1, :fixed_version_id => 2,
1191 :status_id => 1, :fixed_version_id => 2,
1171 :subject => 'New issue')
1192 :subject => 'New issue')
1172 assert !issue.save
1193 assert !issue.save
1173 assert_not_equal [], issue.errors[:fixed_version_id]
1194 assert_not_equal [], issue.errors[:fixed_version_id]
1174 end
1195 end
1175
1196
1176 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1197 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
1177 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1198 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
1178 :status_id => 1, :fixed_version_id => 3,
1199 :status_id => 1, :fixed_version_id => 3,
1179 :subject => 'New issue')
1200 :subject => 'New issue')
1180 assert issue.save
1201 assert issue.save
1181 end
1202 end
1182
1203
1183 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1204 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
1184 issue = Issue.find(11)
1205 issue = Issue.find(11)
1185 assert_equal 'closed', issue.fixed_version.status
1206 assert_equal 'closed', issue.fixed_version.status
1186 issue.subject = 'Subject changed'
1207 issue.subject = 'Subject changed'
1187 assert issue.save
1208 assert issue.save
1188 end
1209 end
1189
1210
1190 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1211 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
1191 issue = Issue.find(11)
1212 issue = Issue.find(11)
1192 issue.status_id = 1
1213 issue.status_id = 1
1193 assert !issue.save
1214 assert !issue.save
1194 assert_not_equal [], issue.errors[:base]
1215 assert_not_equal [], issue.errors[:base]
1195 end
1216 end
1196
1217
1197 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1218 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
1198 issue = Issue.find(11)
1219 issue = Issue.find(11)
1199 issue.status_id = 1
1220 issue.status_id = 1
1200 issue.fixed_version_id = 3
1221 issue.fixed_version_id = 3
1201 assert issue.save
1222 assert issue.save
1202 end
1223 end
1203
1224
1204 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1225 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1205 issue = Issue.find(12)
1226 issue = Issue.find(12)
1206 assert_equal 'locked', issue.fixed_version.status
1227 assert_equal 'locked', issue.fixed_version.status
1207 issue.status_id = 1
1228 issue.status_id = 1
1208 assert issue.save
1229 assert issue.save
1209 end
1230 end
1210
1231
1211 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1232 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1212 issue = Issue.find(2)
1233 issue = Issue.find(2)
1213 assert_equal 2, issue.fixed_version_id
1234 assert_equal 2, issue.fixed_version_id
1214 issue.project_id = 3
1235 issue.project_id = 3
1215 assert_nil issue.fixed_version_id
1236 assert_nil issue.fixed_version_id
1216 issue.fixed_version_id = 2
1237 issue.fixed_version_id = 2
1217 assert !issue.save
1238 assert !issue.save
1218 assert_include 'Target version is not included in the list', issue.errors.full_messages
1239 assert_include 'Target version is not included in the list', issue.errors.full_messages
1219 end
1240 end
1220
1241
1221 def test_should_keep_shared_version_when_changing_project
1242 def test_should_keep_shared_version_when_changing_project
1222 Version.find(2).update_attribute :sharing, 'tree'
1243 Version.find(2).update_attribute :sharing, 'tree'
1223
1244
1224 issue = Issue.find(2)
1245 issue = Issue.find(2)
1225 assert_equal 2, issue.fixed_version_id
1246 assert_equal 2, issue.fixed_version_id
1226 issue.project_id = 3
1247 issue.project_id = 3
1227 assert_equal 2, issue.fixed_version_id
1248 assert_equal 2, issue.fixed_version_id
1228 assert issue.save
1249 assert issue.save
1229 end
1250 end
1230
1251
1231 def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled
1252 def test_allowed_target_projects_should_include_projects_with_issue_tracking_enabled
1232 assert_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1253 assert_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1233 end
1254 end
1234
1255
1235 def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled
1256 def test_allowed_target_projects_should_not_include_projects_with_issue_tracking_disabled
1236 Project.find(2).disable_module! :issue_tracking
1257 Project.find(2).disable_module! :issue_tracking
1237 assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1258 assert_not_include Project.find(2), Issue.allowed_target_projects(User.find(2))
1238 end
1259 end
1239
1260
1240 def test_move_to_another_project_with_same_category
1261 def test_move_to_another_project_with_same_category
1241 issue = Issue.find(1)
1262 issue = Issue.find(1)
1242 issue.project = Project.find(2)
1263 issue.project = Project.find(2)
1243 assert issue.save
1264 assert issue.save
1244 issue.reload
1265 issue.reload
1245 assert_equal 2, issue.project_id
1266 assert_equal 2, issue.project_id
1246 # Category changes
1267 # Category changes
1247 assert_equal 4, issue.category_id
1268 assert_equal 4, issue.category_id
1248 # Make sure time entries were move to the target project
1269 # Make sure time entries were move to the target project
1249 assert_equal 2, issue.time_entries.first.project_id
1270 assert_equal 2, issue.time_entries.first.project_id
1250 end
1271 end
1251
1272
1252 def test_move_to_another_project_without_same_category
1273 def test_move_to_another_project_without_same_category
1253 issue = Issue.find(2)
1274 issue = Issue.find(2)
1254 issue.project = Project.find(2)
1275 issue.project = Project.find(2)
1255 assert issue.save
1276 assert issue.save
1256 issue.reload
1277 issue.reload
1257 assert_equal 2, issue.project_id
1278 assert_equal 2, issue.project_id
1258 # Category cleared
1279 # Category cleared
1259 assert_nil issue.category_id
1280 assert_nil issue.category_id
1260 end
1281 end
1261
1282
1262 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1283 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1263 issue = Issue.find(1)
1284 issue = Issue.find(1)
1264 issue.update_attribute(:fixed_version_id, 1)
1285 issue.update_attribute(:fixed_version_id, 1)
1265 issue.project = Project.find(2)
1286 issue.project = Project.find(2)
1266 assert issue.save
1287 assert issue.save
1267 issue.reload
1288 issue.reload
1268 assert_equal 2, issue.project_id
1289 assert_equal 2, issue.project_id
1269 # Cleared fixed_version
1290 # Cleared fixed_version
1270 assert_equal nil, issue.fixed_version
1291 assert_equal nil, issue.fixed_version
1271 end
1292 end
1272
1293
1273 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1294 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1274 issue = Issue.find(1)
1295 issue = Issue.find(1)
1275 issue.update_attribute(:fixed_version_id, 4)
1296 issue.update_attribute(:fixed_version_id, 4)
1276 issue.project = Project.find(5)
1297 issue.project = Project.find(5)
1277 assert issue.save
1298 assert issue.save
1278 issue.reload
1299 issue.reload
1279 assert_equal 5, issue.project_id
1300 assert_equal 5, issue.project_id
1280 # Keep fixed_version
1301 # Keep fixed_version
1281 assert_equal 4, issue.fixed_version_id
1302 assert_equal 4, issue.fixed_version_id
1282 end
1303 end
1283
1304
1284 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1305 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1285 issue = Issue.find(1)
1306 issue = Issue.find(1)
1286 issue.update_attribute(:fixed_version_id, 1)
1307 issue.update_attribute(:fixed_version_id, 1)
1287 issue.project = Project.find(5)
1308 issue.project = Project.find(5)
1288 assert issue.save
1309 assert issue.save
1289 issue.reload
1310 issue.reload
1290 assert_equal 5, issue.project_id
1311 assert_equal 5, issue.project_id
1291 # Cleared fixed_version
1312 # Cleared fixed_version
1292 assert_equal nil, issue.fixed_version
1313 assert_equal nil, issue.fixed_version
1293 end
1314 end
1294
1315
1295 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1316 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1296 issue = Issue.find(1)
1317 issue = Issue.find(1)
1297 issue.update_attribute(:fixed_version_id, 7)
1318 issue.update_attribute(:fixed_version_id, 7)
1298 issue.project = Project.find(2)
1319 issue.project = Project.find(2)
1299 assert issue.save
1320 assert issue.save
1300 issue.reload
1321 issue.reload
1301 assert_equal 2, issue.project_id
1322 assert_equal 2, issue.project_id
1302 # Keep fixed_version
1323 # Keep fixed_version
1303 assert_equal 7, issue.fixed_version_id
1324 assert_equal 7, issue.fixed_version_id
1304 end
1325 end
1305
1326
1306 def test_move_to_another_project_should_keep_parent_if_valid
1327 def test_move_to_another_project_should_keep_parent_if_valid
1307 issue = Issue.find(1)
1328 issue = Issue.find(1)
1308 issue.update_attribute(:parent_issue_id, 2)
1329 issue.update_attribute(:parent_issue_id, 2)
1309 issue.project = Project.find(3)
1330 issue.project = Project.find(3)
1310 assert issue.save
1331 assert issue.save
1311 issue.reload
1332 issue.reload
1312 assert_equal 2, issue.parent_id
1333 assert_equal 2, issue.parent_id
1313 end
1334 end
1314
1335
1315 def test_move_to_another_project_should_clear_parent_if_not_valid
1336 def test_move_to_another_project_should_clear_parent_if_not_valid
1316 issue = Issue.find(1)
1337 issue = Issue.find(1)
1317 issue.update_attribute(:parent_issue_id, 2)
1338 issue.update_attribute(:parent_issue_id, 2)
1318 issue.project = Project.find(2)
1339 issue.project = Project.find(2)
1319 assert issue.save
1340 assert issue.save
1320 issue.reload
1341 issue.reload
1321 assert_nil issue.parent_id
1342 assert_nil issue.parent_id
1322 end
1343 end
1323
1344
1324 def test_move_to_another_project_with_disabled_tracker
1345 def test_move_to_another_project_with_disabled_tracker
1325 issue = Issue.find(1)
1346 issue = Issue.find(1)
1326 target = Project.find(2)
1347 target = Project.find(2)
1327 target.tracker_ids = [3]
1348 target.tracker_ids = [3]
1328 target.save
1349 target.save
1329 issue.project = target
1350 issue.project = target
1330 assert issue.save
1351 assert issue.save
1331 issue.reload
1352 issue.reload
1332 assert_equal 2, issue.project_id
1353 assert_equal 2, issue.project_id
1333 assert_equal 3, issue.tracker_id
1354 assert_equal 3, issue.tracker_id
1334 end
1355 end
1335
1356
1336 def test_copy_to_the_same_project
1357 def test_copy_to_the_same_project
1337 issue = Issue.find(1)
1358 issue = Issue.find(1)
1338 copy = issue.copy
1359 copy = issue.copy
1339 assert_difference 'Issue.count' do
1360 assert_difference 'Issue.count' do
1340 copy.save!
1361 copy.save!
1341 end
1362 end
1342 assert_kind_of Issue, copy
1363 assert_kind_of Issue, copy
1343 assert_equal issue.project, copy.project
1364 assert_equal issue.project, copy.project
1344 assert_equal "125", copy.custom_value_for(2).value
1365 assert_equal "125", copy.custom_value_for(2).value
1345 end
1366 end
1346
1367
1347 def test_copy_to_another_project_and_tracker
1368 def test_copy_to_another_project_and_tracker
1348 issue = Issue.find(1)
1369 issue = Issue.find(1)
1349 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1370 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1350 assert_difference 'Issue.count' do
1371 assert_difference 'Issue.count' do
1351 copy.save!
1372 copy.save!
1352 end
1373 end
1353 copy.reload
1374 copy.reload
1354 assert_kind_of Issue, copy
1375 assert_kind_of Issue, copy
1355 assert_equal Project.find(3), copy.project
1376 assert_equal Project.find(3), copy.project
1356 assert_equal Tracker.find(2), copy.tracker
1377 assert_equal Tracker.find(2), copy.tracker
1357 # Custom field #2 is not associated with target tracker
1378 # Custom field #2 is not associated with target tracker
1358 assert_nil copy.custom_value_for(2)
1379 assert_nil copy.custom_value_for(2)
1359 end
1380 end
1360
1381
1361 test "#copy should not create a journal" do
1382 test "#copy should not create a journal" do
1362 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
1383 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :assigned_to_id => 3}, :link => false)
1363 copy.save!
1384 copy.save!
1364 assert_equal 0, copy.reload.journals.size
1385 assert_equal 0, copy.reload.journals.size
1365 end
1386 end
1366
1387
1367 test "#copy should allow assigned_to changes" do
1388 test "#copy should allow assigned_to changes" do
1368 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1389 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1369 assert_equal 3, copy.assigned_to_id
1390 assert_equal 3, copy.assigned_to_id
1370 end
1391 end
1371
1392
1372 test "#copy should allow status changes" do
1393 test "#copy should allow status changes" do
1373 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1394 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1374 assert_equal 2, copy.status_id
1395 assert_equal 2, copy.status_id
1375 end
1396 end
1376
1397
1377 test "#copy should allow start date changes" do
1398 test "#copy should allow start date changes" do
1378 date = Date.today
1399 date = Date.today
1379 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1400 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1380 assert_equal date, copy.start_date
1401 assert_equal date, copy.start_date
1381 end
1402 end
1382
1403
1383 test "#copy should allow due date changes" do
1404 test "#copy should allow due date changes" do
1384 date = Date.today
1405 date = Date.today
1385 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1406 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1386 assert_equal date, copy.due_date
1407 assert_equal date, copy.due_date
1387 end
1408 end
1388
1409
1389 test "#copy should set current user as author" do
1410 test "#copy should set current user as author" do
1390 User.current = User.find(9)
1411 User.current = User.find(9)
1391 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1412 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1392 assert_equal User.current, copy.author
1413 assert_equal User.current, copy.author
1393 end
1414 end
1394
1415
1395 test "#copy should create a journal with notes" do
1416 test "#copy should create a journal with notes" do
1396 date = Date.today
1417 date = Date.today
1397 notes = "Notes added when copying"
1418 notes = "Notes added when copying"
1398 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false)
1419 copy = Issue.find(1).copy({:project_id => 3, :tracker_id => 2, :start_date => date}, :link => false)
1399 copy.init_journal(User.current, notes)
1420 copy.init_journal(User.current, notes)
1400 copy.save!
1421 copy.save!
1401
1422
1402 assert_equal 1, copy.journals.size
1423 assert_equal 1, copy.journals.size
1403 journal = copy.journals.first
1424 journal = copy.journals.first
1404 assert_equal 0, journal.details.size
1425 assert_equal 0, journal.details.size
1405 assert_equal notes, journal.notes
1426 assert_equal notes, journal.notes
1406 end
1427 end
1407
1428
1408 def test_valid_parent_project
1429 def test_valid_parent_project
1409 issue = Issue.find(1)
1430 issue = Issue.find(1)
1410 issue_in_same_project = Issue.find(2)
1431 issue_in_same_project = Issue.find(2)
1411 issue_in_child_project = Issue.find(5)
1432 issue_in_child_project = Issue.find(5)
1412 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1433 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1413 issue_in_other_child_project = Issue.find(6)
1434 issue_in_other_child_project = Issue.find(6)
1414 issue_in_different_tree = Issue.find(4)
1435 issue_in_different_tree = Issue.find(4)
1415
1436
1416 with_settings :cross_project_subtasks => '' do
1437 with_settings :cross_project_subtasks => '' do
1417 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1438 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1418 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1439 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1419 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1440 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1420 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1441 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1421 end
1442 end
1422
1443
1423 with_settings :cross_project_subtasks => 'system' do
1444 with_settings :cross_project_subtasks => 'system' do
1424 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1445 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1425 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1446 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1426 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1447 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1427 end
1448 end
1428
1449
1429 with_settings :cross_project_subtasks => 'tree' do
1450 with_settings :cross_project_subtasks => 'tree' do
1430 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1451 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1431 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1452 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1432 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1453 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1433 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1454 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1434
1455
1435 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1456 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1436 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1457 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1437 end
1458 end
1438
1459
1439 with_settings :cross_project_subtasks => 'descendants' do
1460 with_settings :cross_project_subtasks => 'descendants' do
1440 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1461 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1441 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1462 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1442 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1463 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1443 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1464 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1444
1465
1445 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1466 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1446 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1467 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1447 end
1468 end
1448 end
1469 end
1449
1470
1450 def test_recipients_should_include_previous_assignee
1471 def test_recipients_should_include_previous_assignee
1451 user = User.find(3)
1472 user = User.find(3)
1452 user.members.update_all ["mail_notification = ?", false]
1473 user.members.update_all ["mail_notification = ?", false]
1453 user.update_attribute :mail_notification, 'only_assigned'
1474 user.update_attribute :mail_notification, 'only_assigned'
1454
1475
1455 issue = Issue.find(2)
1476 issue = Issue.find(2)
1456 issue.assigned_to = nil
1477 issue.assigned_to = nil
1457 assert_include user.mail, issue.recipients
1478 assert_include user.mail, issue.recipients
1458 issue.save!
1479 issue.save!
1459 assert !issue.recipients.include?(user.mail)
1480 assert !issue.recipients.include?(user.mail)
1460 end
1481 end
1461
1482
1462 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1483 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1463 issue = Issue.find(12)
1484 issue = Issue.find(12)
1464 assert issue.recipients.include?(issue.author.mail)
1485 assert issue.recipients.include?(issue.author.mail)
1465 # copy the issue to a private project
1486 # copy the issue to a private project
1466 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1487 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1467 # author is not a member of project anymore
1488 # author is not a member of project anymore
1468 assert !copy.recipients.include?(copy.author.mail)
1489 assert !copy.recipients.include?(copy.author.mail)
1469 end
1490 end
1470
1491
1471 def test_recipients_should_include_the_assigned_group_members
1492 def test_recipients_should_include_the_assigned_group_members
1472 group_member = User.generate!
1493 group_member = User.generate!
1473 group = Group.generate!
1494 group = Group.generate!
1474 group.users << group_member
1495 group.users << group_member
1475
1496
1476 issue = Issue.find(12)
1497 issue = Issue.find(12)
1477 issue.assigned_to = group
1498 issue.assigned_to = group
1478 assert issue.recipients.include?(group_member.mail)
1499 assert issue.recipients.include?(group_member.mail)
1479 end
1500 end
1480
1501
1481 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1502 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1482 user = User.find(3)
1503 user = User.find(3)
1483 issue = Issue.find(9)
1504 issue = Issue.find(9)
1484 Watcher.create!(:user => user, :watchable => issue)
1505 Watcher.create!(:user => user, :watchable => issue)
1485 assert issue.watched_by?(user)
1506 assert issue.watched_by?(user)
1486 assert !issue.watcher_recipients.include?(user.mail)
1507 assert !issue.watcher_recipients.include?(user.mail)
1487 end
1508 end
1488
1509
1489 def test_issue_destroy
1510 def test_issue_destroy
1490 Issue.find(1).destroy
1511 Issue.find(1).destroy
1491 assert_nil Issue.find_by_id(1)
1512 assert_nil Issue.find_by_id(1)
1492 assert_nil TimeEntry.find_by_issue_id(1)
1513 assert_nil TimeEntry.find_by_issue_id(1)
1493 end
1514 end
1494
1515
1495 def test_destroy_should_delete_time_entries_custom_values
1516 def test_destroy_should_delete_time_entries_custom_values
1496 issue = Issue.generate!
1517 issue = Issue.generate!
1497 time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'})
1518 time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'})
1498
1519
1499 assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do
1520 assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do
1500 assert issue.destroy
1521 assert issue.destroy
1501 end
1522 end
1502 end
1523 end
1503
1524
1504 def test_destroying_a_deleted_issue_should_not_raise_an_error
1525 def test_destroying_a_deleted_issue_should_not_raise_an_error
1505 issue = Issue.find(1)
1526 issue = Issue.find(1)
1506 Issue.find(1).destroy
1527 Issue.find(1).destroy
1507
1528
1508 assert_nothing_raised do
1529 assert_nothing_raised do
1509 assert_no_difference 'Issue.count' do
1530 assert_no_difference 'Issue.count' do
1510 issue.destroy
1531 issue.destroy
1511 end
1532 end
1512 assert issue.destroyed?
1533 assert issue.destroyed?
1513 end
1534 end
1514 end
1535 end
1515
1536
1516 def test_destroying_a_stale_issue_should_not_raise_an_error
1537 def test_destroying_a_stale_issue_should_not_raise_an_error
1517 issue = Issue.find(1)
1538 issue = Issue.find(1)
1518 Issue.find(1).update_attribute :subject, "Updated"
1539 Issue.find(1).update_attribute :subject, "Updated"
1519
1540
1520 assert_nothing_raised do
1541 assert_nothing_raised do
1521 assert_difference 'Issue.count', -1 do
1542 assert_difference 'Issue.count', -1 do
1522 issue.destroy
1543 issue.destroy
1523 end
1544 end
1524 assert issue.destroyed?
1545 assert issue.destroyed?
1525 end
1546 end
1526 end
1547 end
1527
1548
1528 def test_blocked
1549 def test_blocked
1529 blocked_issue = Issue.find(9)
1550 blocked_issue = Issue.find(9)
1530 blocking_issue = Issue.find(10)
1551 blocking_issue = Issue.find(10)
1531
1552
1532 assert blocked_issue.blocked?
1553 assert blocked_issue.blocked?
1533 assert !blocking_issue.blocked?
1554 assert !blocking_issue.blocked?
1534 end
1555 end
1535
1556
1536 def test_blocked_issues_dont_allow_closed_statuses
1557 def test_blocked_issues_dont_allow_closed_statuses
1537 blocked_issue = Issue.find(9)
1558 blocked_issue = Issue.find(9)
1538
1559
1539 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1560 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1540 assert !allowed_statuses.empty?
1561 assert !allowed_statuses.empty?
1541 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1562 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1542 assert closed_statuses.empty?
1563 assert closed_statuses.empty?
1543 end
1564 end
1544
1565
1545 def test_unblocked_issues_allow_closed_statuses
1566 def test_unblocked_issues_allow_closed_statuses
1546 blocking_issue = Issue.find(10)
1567 blocking_issue = Issue.find(10)
1547
1568
1548 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1569 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1549 assert !allowed_statuses.empty?
1570 assert !allowed_statuses.empty?
1550 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1571 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1551 assert !closed_statuses.empty?
1572 assert !closed_statuses.empty?
1552 end
1573 end
1553
1574
1554 def test_reschedule_an_issue_without_dates
1575 def test_reschedule_an_issue_without_dates
1555 with_settings :non_working_week_days => [] do
1576 with_settings :non_working_week_days => [] do
1556 issue = Issue.new(:start_date => nil, :due_date => nil)
1577 issue = Issue.new(:start_date => nil, :due_date => nil)
1557 issue.reschedule_on '2012-10-09'.to_date
1578 issue.reschedule_on '2012-10-09'.to_date
1558 assert_equal '2012-10-09'.to_date, issue.start_date
1579 assert_equal '2012-10-09'.to_date, issue.start_date
1559 assert_equal '2012-10-09'.to_date, issue.due_date
1580 assert_equal '2012-10-09'.to_date, issue.due_date
1560 end
1581 end
1561
1582
1562 with_settings :non_working_week_days => %w(6 7) do
1583 with_settings :non_working_week_days => %w(6 7) do
1563 issue = Issue.new(:start_date => nil, :due_date => nil)
1584 issue = Issue.new(:start_date => nil, :due_date => nil)
1564 issue.reschedule_on '2012-10-09'.to_date
1585 issue.reschedule_on '2012-10-09'.to_date
1565 assert_equal '2012-10-09'.to_date, issue.start_date
1586 assert_equal '2012-10-09'.to_date, issue.start_date
1566 assert_equal '2012-10-09'.to_date, issue.due_date
1587 assert_equal '2012-10-09'.to_date, issue.due_date
1567
1588
1568 issue = Issue.new(:start_date => nil, :due_date => nil)
1589 issue = Issue.new(:start_date => nil, :due_date => nil)
1569 issue.reschedule_on '2012-10-13'.to_date
1590 issue.reschedule_on '2012-10-13'.to_date
1570 assert_equal '2012-10-15'.to_date, issue.start_date
1591 assert_equal '2012-10-15'.to_date, issue.start_date
1571 assert_equal '2012-10-15'.to_date, issue.due_date
1592 assert_equal '2012-10-15'.to_date, issue.due_date
1572 end
1593 end
1573 end
1594 end
1574
1595
1575 def test_reschedule_an_issue_with_start_date
1596 def test_reschedule_an_issue_with_start_date
1576 with_settings :non_working_week_days => [] do
1597 with_settings :non_working_week_days => [] do
1577 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1598 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1578 issue.reschedule_on '2012-10-13'.to_date
1599 issue.reschedule_on '2012-10-13'.to_date
1579 assert_equal '2012-10-13'.to_date, issue.start_date
1600 assert_equal '2012-10-13'.to_date, issue.start_date
1580 assert_equal '2012-10-13'.to_date, issue.due_date
1601 assert_equal '2012-10-13'.to_date, issue.due_date
1581 end
1602 end
1582
1603
1583 with_settings :non_working_week_days => %w(6 7) do
1604 with_settings :non_working_week_days => %w(6 7) do
1584 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1605 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1585 issue.reschedule_on '2012-10-11'.to_date
1606 issue.reschedule_on '2012-10-11'.to_date
1586 assert_equal '2012-10-11'.to_date, issue.start_date
1607 assert_equal '2012-10-11'.to_date, issue.start_date
1587 assert_equal '2012-10-11'.to_date, issue.due_date
1608 assert_equal '2012-10-11'.to_date, issue.due_date
1588
1609
1589 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1610 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1590 issue.reschedule_on '2012-10-13'.to_date
1611 issue.reschedule_on '2012-10-13'.to_date
1591 assert_equal '2012-10-15'.to_date, issue.start_date
1612 assert_equal '2012-10-15'.to_date, issue.start_date
1592 assert_equal '2012-10-15'.to_date, issue.due_date
1613 assert_equal '2012-10-15'.to_date, issue.due_date
1593 end
1614 end
1594 end
1615 end
1595
1616
1596 def test_reschedule_an_issue_with_start_and_due_dates
1617 def test_reschedule_an_issue_with_start_and_due_dates
1597 with_settings :non_working_week_days => [] do
1618 with_settings :non_working_week_days => [] do
1598 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1619 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1599 issue.reschedule_on '2012-10-13'.to_date
1620 issue.reschedule_on '2012-10-13'.to_date
1600 assert_equal '2012-10-13'.to_date, issue.start_date
1621 assert_equal '2012-10-13'.to_date, issue.start_date
1601 assert_equal '2012-10-19'.to_date, issue.due_date
1622 assert_equal '2012-10-19'.to_date, issue.due_date
1602 end
1623 end
1603
1624
1604 with_settings :non_working_week_days => %w(6 7) do
1625 with_settings :non_working_week_days => %w(6 7) do
1605 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1626 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1606 issue.reschedule_on '2012-10-11'.to_date
1627 issue.reschedule_on '2012-10-11'.to_date
1607 assert_equal '2012-10-11'.to_date, issue.start_date
1628 assert_equal '2012-10-11'.to_date, issue.start_date
1608 assert_equal '2012-10-23'.to_date, issue.due_date
1629 assert_equal '2012-10-23'.to_date, issue.due_date
1609
1630
1610 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1631 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1611 issue.reschedule_on '2012-10-13'.to_date
1632 issue.reschedule_on '2012-10-13'.to_date
1612 assert_equal '2012-10-15'.to_date, issue.start_date
1633 assert_equal '2012-10-15'.to_date, issue.start_date
1613 assert_equal '2012-10-25'.to_date, issue.due_date
1634 assert_equal '2012-10-25'.to_date, issue.due_date
1614 end
1635 end
1615 end
1636 end
1616
1637
1617 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1638 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1618 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1639 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1619 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1640 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1620 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1641 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1621 :relation_type => IssueRelation::TYPE_PRECEDES)
1642 :relation_type => IssueRelation::TYPE_PRECEDES)
1622 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1643 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1623
1644
1624 issue1.reload
1645 issue1.reload
1625 issue1.due_date = '2012-10-23'
1646 issue1.due_date = '2012-10-23'
1626 issue1.save!
1647 issue1.save!
1627 issue2.reload
1648 issue2.reload
1628 assert_equal Date.parse('2012-10-24'), issue2.start_date
1649 assert_equal Date.parse('2012-10-24'), issue2.start_date
1629 assert_equal Date.parse('2012-10-26'), issue2.due_date
1650 assert_equal Date.parse('2012-10-26'), issue2.due_date
1630 end
1651 end
1631
1652
1632 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1653 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1633 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1654 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1634 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1655 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1635 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1656 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1636 :relation_type => IssueRelation::TYPE_PRECEDES)
1657 :relation_type => IssueRelation::TYPE_PRECEDES)
1637 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1658 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1638
1659
1639 issue1.reload
1660 issue1.reload
1640 issue1.start_date = '2012-09-17'
1661 issue1.start_date = '2012-09-17'
1641 issue1.due_date = '2012-09-18'
1662 issue1.due_date = '2012-09-18'
1642 issue1.save!
1663 issue1.save!
1643 issue2.reload
1664 issue2.reload
1644 assert_equal Date.parse('2012-09-19'), issue2.start_date
1665 assert_equal Date.parse('2012-09-19'), issue2.start_date
1645 assert_equal Date.parse('2012-09-21'), issue2.due_date
1666 assert_equal Date.parse('2012-09-21'), issue2.due_date
1646 end
1667 end
1647
1668
1648 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1669 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1649 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1670 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1650 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1671 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1651 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1672 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1652 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1673 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1653 :relation_type => IssueRelation::TYPE_PRECEDES)
1674 :relation_type => IssueRelation::TYPE_PRECEDES)
1654 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1675 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1655 :relation_type => IssueRelation::TYPE_PRECEDES)
1676 :relation_type => IssueRelation::TYPE_PRECEDES)
1656 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1677 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1657
1678
1658 issue1.reload
1679 issue1.reload
1659 issue1.start_date = '2012-09-17'
1680 issue1.start_date = '2012-09-17'
1660 issue1.due_date = '2012-09-18'
1681 issue1.due_date = '2012-09-18'
1661 issue1.save!
1682 issue1.save!
1662 issue2.reload
1683 issue2.reload
1663 # Issue 2 must start after Issue 3
1684 # Issue 2 must start after Issue 3
1664 assert_equal Date.parse('2012-10-03'), issue2.start_date
1685 assert_equal Date.parse('2012-10-03'), issue2.start_date
1665 assert_equal Date.parse('2012-10-05'), issue2.due_date
1686 assert_equal Date.parse('2012-10-05'), issue2.due_date
1666 end
1687 end
1667
1688
1668 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1689 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1669 with_settings :non_working_week_days => [] do
1690 with_settings :non_working_week_days => [] do
1670 stale = Issue.find(1)
1691 stale = Issue.find(1)
1671 issue = Issue.find(1)
1692 issue = Issue.find(1)
1672 issue.subject = "Updated"
1693 issue.subject = "Updated"
1673 issue.save!
1694 issue.save!
1674 date = 10.days.from_now.to_date
1695 date = 10.days.from_now.to_date
1675 assert_nothing_raised do
1696 assert_nothing_raised do
1676 stale.reschedule_on!(date)
1697 stale.reschedule_on!(date)
1677 end
1698 end
1678 assert_equal date, stale.reload.start_date
1699 assert_equal date, stale.reload.start_date
1679 end
1700 end
1680 end
1701 end
1681
1702
1682 def test_child_issue_should_consider_parent_soonest_start_on_create
1703 def test_child_issue_should_consider_parent_soonest_start_on_create
1683 set_language_if_valid 'en'
1704 set_language_if_valid 'en'
1684 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1705 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1685 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1706 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1686 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1707 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1687 :relation_type => IssueRelation::TYPE_PRECEDES)
1708 :relation_type => IssueRelation::TYPE_PRECEDES)
1688 issue1.reload
1709 issue1.reload
1689 issue2.reload
1710 issue2.reload
1690 assert_equal Date.parse('2012-10-18'), issue2.start_date
1711 assert_equal Date.parse('2012-10-18'), issue2.start_date
1691
1712
1692 with_settings :date_format => '%m/%d/%Y' do
1713 with_settings :date_format => '%m/%d/%Y' do
1693 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1714 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1694 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1715 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1695 assert !child.valid?
1716 assert !child.valid?
1696 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1717 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1697 assert_equal Date.parse('2012-10-18'), child.soonest_start
1718 assert_equal Date.parse('2012-10-18'), child.soonest_start
1698 child.start_date = '2012-10-18'
1719 child.start_date = '2012-10-18'
1699 assert child.save
1720 assert child.save
1700 end
1721 end
1701 end
1722 end
1702
1723
1703 def test_setting_parent_to_a_dependent_issue_should_not_validate
1724 def test_setting_parent_to_a_dependent_issue_should_not_validate
1704 set_language_if_valid 'en'
1725 set_language_if_valid 'en'
1705 issue1 = Issue.generate!
1726 issue1 = Issue.generate!
1706 issue2 = Issue.generate!
1727 issue2 = Issue.generate!
1707 issue3 = Issue.generate!
1728 issue3 = Issue.generate!
1708 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1729 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1709 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1730 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1710 issue3.reload
1731 issue3.reload
1711 issue3.parent_issue_id = issue2.id
1732 issue3.parent_issue_id = issue2.id
1712 assert !issue3.valid?
1733 assert !issue3.valid?
1713 assert_include 'Parent task is invalid', issue3.errors.full_messages
1734 assert_include 'Parent task is invalid', issue3.errors.full_messages
1714 end
1735 end
1715
1736
1716 def test_setting_parent_should_not_allow_circular_dependency
1737 def test_setting_parent_should_not_allow_circular_dependency
1717 set_language_if_valid 'en'
1738 set_language_if_valid 'en'
1718 issue1 = Issue.generate!
1739 issue1 = Issue.generate!
1719 issue2 = Issue.generate!
1740 issue2 = Issue.generate!
1720 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1741 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1721 issue3 = Issue.generate!
1742 issue3 = Issue.generate!
1722 issue2.reload
1743 issue2.reload
1723 issue2.parent_issue_id = issue3.id
1744 issue2.parent_issue_id = issue3.id
1724 issue2.save!
1745 issue2.save!
1725 issue4 = Issue.generate!
1746 issue4 = Issue.generate!
1726 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1747 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1727 issue4.reload
1748 issue4.reload
1728 issue4.parent_issue_id = issue1.id
1749 issue4.parent_issue_id = issue1.id
1729 assert !issue4.valid?
1750 assert !issue4.valid?
1730 assert_include 'Parent task is invalid', issue4.errors.full_messages
1751 assert_include 'Parent task is invalid', issue4.errors.full_messages
1731 end
1752 end
1732
1753
1733 def test_overdue
1754 def test_overdue
1734 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1755 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1735 assert !Issue.new(:due_date => Date.today).overdue?
1756 assert !Issue.new(:due_date => Date.today).overdue?
1736 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1757 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1737 assert !Issue.new(:due_date => nil).overdue?
1758 assert !Issue.new(:due_date => nil).overdue?
1738 assert !Issue.new(:due_date => 1.day.ago.to_date,
1759 assert !Issue.new(:due_date => 1.day.ago.to_date,
1739 :status => IssueStatus.where(:is_closed => true).first
1760 :status => IssueStatus.where(:is_closed => true).first
1740 ).overdue?
1761 ).overdue?
1741 end
1762 end
1742
1763
1743 test "#behind_schedule? should be false if the issue has no start_date" do
1764 test "#behind_schedule? should be false if the issue has no start_date" do
1744 assert !Issue.new(:start_date => nil,
1765 assert !Issue.new(:start_date => nil,
1745 :due_date => 1.day.from_now.to_date,
1766 :due_date => 1.day.from_now.to_date,
1746 :done_ratio => 0).behind_schedule?
1767 :done_ratio => 0).behind_schedule?
1747 end
1768 end
1748
1769
1749 test "#behind_schedule? should be false if the issue has no end_date" do
1770 test "#behind_schedule? should be false if the issue has no end_date" do
1750 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1771 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1751 :due_date => nil,
1772 :due_date => nil,
1752 :done_ratio => 0).behind_schedule?
1773 :done_ratio => 0).behind_schedule?
1753 end
1774 end
1754
1775
1755 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1776 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1756 assert !Issue.new(:start_date => 50.days.ago.to_date,
1777 assert !Issue.new(:start_date => 50.days.ago.to_date,
1757 :due_date => 50.days.from_now.to_date,
1778 :due_date => 50.days.from_now.to_date,
1758 :done_ratio => 90).behind_schedule?
1779 :done_ratio => 90).behind_schedule?
1759 end
1780 end
1760
1781
1761 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1782 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1762 assert Issue.new(:start_date => 1.day.ago.to_date,
1783 assert Issue.new(:start_date => 1.day.ago.to_date,
1763 :due_date => 1.day.from_now.to_date,
1784 :due_date => 1.day.from_now.to_date,
1764 :done_ratio => 0).behind_schedule?
1785 :done_ratio => 0).behind_schedule?
1765 end
1786 end
1766
1787
1767 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1788 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1768 assert Issue.new(:start_date => 100.days.ago.to_date,
1789 assert Issue.new(:start_date => 100.days.ago.to_date,
1769 :due_date => Date.today,
1790 :due_date => Date.today,
1770 :done_ratio => 90).behind_schedule?
1791 :done_ratio => 90).behind_schedule?
1771 end
1792 end
1772
1793
1773 test "#assignable_users should be Users" do
1794 test "#assignable_users should be Users" do
1774 assert_kind_of User, Issue.find(1).assignable_users.first
1795 assert_kind_of User, Issue.find(1).assignable_users.first
1775 end
1796 end
1776
1797
1777 test "#assignable_users should include the issue author" do
1798 test "#assignable_users should include the issue author" do
1778 non_project_member = User.generate!
1799 non_project_member = User.generate!
1779 issue = Issue.generate!(:author => non_project_member)
1800 issue = Issue.generate!(:author => non_project_member)
1780
1801
1781 assert issue.assignable_users.include?(non_project_member)
1802 assert issue.assignable_users.include?(non_project_member)
1782 end
1803 end
1783
1804
1784 test "#assignable_users should include the current assignee" do
1805 test "#assignable_users should include the current assignee" do
1785 user = User.generate!
1806 user = User.generate!
1786 issue = Issue.generate!(:assigned_to => user)
1807 issue = Issue.generate!(:assigned_to => user)
1787 user.lock!
1808 user.lock!
1788
1809
1789 assert Issue.find(issue.id).assignable_users.include?(user)
1810 assert Issue.find(issue.id).assignable_users.include?(user)
1790 end
1811 end
1791
1812
1792 test "#assignable_users should not show the issue author twice" do
1813 test "#assignable_users should not show the issue author twice" do
1793 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1814 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1794 assert_equal 2, assignable_user_ids.length
1815 assert_equal 2, assignable_user_ids.length
1795
1816
1796 assignable_user_ids.each do |user_id|
1817 assignable_user_ids.each do |user_id|
1797 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1818 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1798 "User #{user_id} appears more or less than once"
1819 "User #{user_id} appears more or less than once"
1799 end
1820 end
1800 end
1821 end
1801
1822
1802 test "#assignable_users with issue_group_assignment should include groups" do
1823 test "#assignable_users with issue_group_assignment should include groups" do
1803 issue = Issue.new(:project => Project.find(2))
1824 issue = Issue.new(:project => Project.find(2))
1804
1825
1805 with_settings :issue_group_assignment => '1' do
1826 with_settings :issue_group_assignment => '1' do
1806 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1827 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1807 assert issue.assignable_users.include?(Group.find(11))
1828 assert issue.assignable_users.include?(Group.find(11))
1808 end
1829 end
1809 end
1830 end
1810
1831
1811 test "#assignable_users without issue_group_assignment should not include groups" do
1832 test "#assignable_users without issue_group_assignment should not include groups" do
1812 issue = Issue.new(:project => Project.find(2))
1833 issue = Issue.new(:project => Project.find(2))
1813
1834
1814 with_settings :issue_group_assignment => '0' do
1835 with_settings :issue_group_assignment => '0' do
1815 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1836 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1816 assert !issue.assignable_users.include?(Group.find(11))
1837 assert !issue.assignable_users.include?(Group.find(11))
1817 end
1838 end
1818 end
1839 end
1819
1840
1820 def test_assignable_users_should_not_include_builtin_groups
1841 def test_assignable_users_should_not_include_builtin_groups
1821 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1])
1842 Member.create!(:project_id => 1, :principal => Group.non_member, :role_ids => [1])
1822 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1])
1843 Member.create!(:project_id => 1, :principal => Group.anonymous, :role_ids => [1])
1823 issue = Issue.new(:project => Project.find(1))
1844 issue = Issue.new(:project => Project.find(1))
1824
1845
1825 with_settings :issue_group_assignment => '1' do
1846 with_settings :issue_group_assignment => '1' do
1826 assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)}
1847 assert_nil issue.assignable_users.detect {|u| u.is_a?(GroupBuiltin)}
1827 end
1848 end
1828 end
1849 end
1829
1850
1830 def test_create_should_send_email_notification
1851 def test_create_should_send_email_notification
1831 ActionMailer::Base.deliveries.clear
1852 ActionMailer::Base.deliveries.clear
1832 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1853 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1833 :author_id => 3, :status_id => 1,
1854 :author_id => 3, :status_id => 1,
1834 :priority => IssuePriority.all.first,
1855 :priority => IssuePriority.all.first,
1835 :subject => 'test_create', :estimated_hours => '1:30')
1856 :subject => 'test_create', :estimated_hours => '1:30')
1836 with_settings :notified_events => %w(issue_added) do
1857 with_settings :notified_events => %w(issue_added) do
1837 assert issue.save
1858 assert issue.save
1838 assert_equal 1, ActionMailer::Base.deliveries.size
1859 assert_equal 1, ActionMailer::Base.deliveries.size
1839 end
1860 end
1840 end
1861 end
1841
1862
1842 def test_create_should_send_one_email_notification_with_both_settings
1863 def test_create_should_send_one_email_notification_with_both_settings
1843 ActionMailer::Base.deliveries.clear
1864 ActionMailer::Base.deliveries.clear
1844 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1865 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1845 :author_id => 3, :status_id => 1,
1866 :author_id => 3, :status_id => 1,
1846 :priority => IssuePriority.all.first,
1867 :priority => IssuePriority.all.first,
1847 :subject => 'test_create', :estimated_hours => '1:30')
1868 :subject => 'test_create', :estimated_hours => '1:30')
1848 with_settings :notified_events => %w(issue_added issue_updated) do
1869 with_settings :notified_events => %w(issue_added issue_updated) do
1849 assert issue.save
1870 assert issue.save
1850 assert_equal 1, ActionMailer::Base.deliveries.size
1871 assert_equal 1, ActionMailer::Base.deliveries.size
1851 end
1872 end
1852 end
1873 end
1853
1874
1854 def test_create_should_not_send_email_notification_with_no_setting
1875 def test_create_should_not_send_email_notification_with_no_setting
1855 ActionMailer::Base.deliveries.clear
1876 ActionMailer::Base.deliveries.clear
1856 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1877 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1857 :author_id => 3, :status_id => 1,
1878 :author_id => 3, :status_id => 1,
1858 :priority => IssuePriority.all.first,
1879 :priority => IssuePriority.all.first,
1859 :subject => 'test_create', :estimated_hours => '1:30')
1880 :subject => 'test_create', :estimated_hours => '1:30')
1860 with_settings :notified_events => [] do
1881 with_settings :notified_events => [] do
1861 assert issue.save
1882 assert issue.save
1862 assert_equal 0, ActionMailer::Base.deliveries.size
1883 assert_equal 0, ActionMailer::Base.deliveries.size
1863 end
1884 end
1864 end
1885 end
1865
1886
1866 def test_update_should_notify_previous_assignee
1887 def test_update_should_notify_previous_assignee
1867 ActionMailer::Base.deliveries.clear
1888 ActionMailer::Base.deliveries.clear
1868 user = User.find(3)
1889 user = User.find(3)
1869 user.members.update_all ["mail_notification = ?", false]
1890 user.members.update_all ["mail_notification = ?", false]
1870 user.update_attribute :mail_notification, 'only_assigned'
1891 user.update_attribute :mail_notification, 'only_assigned'
1871
1892
1872 with_settings :notified_events => %w(issue_updated) do
1893 with_settings :notified_events => %w(issue_updated) do
1873 issue = Issue.find(2)
1894 issue = Issue.find(2)
1874 issue.init_journal User.find(1)
1895 issue.init_journal User.find(1)
1875 issue.assigned_to = nil
1896 issue.assigned_to = nil
1876 issue.save!
1897 issue.save!
1877 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
1898 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
1878 end
1899 end
1879 end
1900 end
1880
1901
1881 def test_stale_issue_should_not_send_email_notification
1902 def test_stale_issue_should_not_send_email_notification
1882 ActionMailer::Base.deliveries.clear
1903 ActionMailer::Base.deliveries.clear
1883 issue = Issue.find(1)
1904 issue = Issue.find(1)
1884 stale = Issue.find(1)
1905 stale = Issue.find(1)
1885
1906
1886 issue.init_journal(User.find(1))
1907 issue.init_journal(User.find(1))
1887 issue.subject = 'Subjet update'
1908 issue.subject = 'Subjet update'
1888 with_settings :notified_events => %w(issue_updated) do
1909 with_settings :notified_events => %w(issue_updated) do
1889 assert issue.save
1910 assert issue.save
1890 assert_equal 1, ActionMailer::Base.deliveries.size
1911 assert_equal 1, ActionMailer::Base.deliveries.size
1891 ActionMailer::Base.deliveries.clear
1912 ActionMailer::Base.deliveries.clear
1892
1913
1893 stale.init_journal(User.find(1))
1914 stale.init_journal(User.find(1))
1894 stale.subject = 'Another subjet update'
1915 stale.subject = 'Another subjet update'
1895 assert_raise ActiveRecord::StaleObjectError do
1916 assert_raise ActiveRecord::StaleObjectError do
1896 stale.save
1917 stale.save
1897 end
1918 end
1898 assert ActionMailer::Base.deliveries.empty?
1919 assert ActionMailer::Base.deliveries.empty?
1899 end
1920 end
1900 end
1921 end
1901
1922
1902 def test_journalized_description
1923 def test_journalized_description
1903 IssueCustomField.delete_all
1924 IssueCustomField.delete_all
1904
1925
1905 i = Issue.first
1926 i = Issue.first
1906 old_description = i.description
1927 old_description = i.description
1907 new_description = "This is the new description"
1928 new_description = "This is the new description"
1908
1929
1909 i.init_journal(User.find(2))
1930 i.init_journal(User.find(2))
1910 i.description = new_description
1931 i.description = new_description
1911 assert_difference 'Journal.count', 1 do
1932 assert_difference 'Journal.count', 1 do
1912 assert_difference 'JournalDetail.count', 1 do
1933 assert_difference 'JournalDetail.count', 1 do
1913 i.save!
1934 i.save!
1914 end
1935 end
1915 end
1936 end
1916
1937
1917 detail = JournalDetail.order('id DESC').first
1938 detail = JournalDetail.order('id DESC').first
1918 assert_equal i, detail.journal.journalized
1939 assert_equal i, detail.journal.journalized
1919 assert_equal 'attr', detail.property
1940 assert_equal 'attr', detail.property
1920 assert_equal 'description', detail.prop_key
1941 assert_equal 'description', detail.prop_key
1921 assert_equal old_description, detail.old_value
1942 assert_equal old_description, detail.old_value
1922 assert_equal new_description, detail.value
1943 assert_equal new_description, detail.value
1923 end
1944 end
1924
1945
1925 def test_blank_descriptions_should_not_be_journalized
1946 def test_blank_descriptions_should_not_be_journalized
1926 IssueCustomField.delete_all
1947 IssueCustomField.delete_all
1927 Issue.where(:id => 1).update_all("description = NULL")
1948 Issue.where(:id => 1).update_all("description = NULL")
1928
1949
1929 i = Issue.find(1)
1950 i = Issue.find(1)
1930 i.init_journal(User.find(2))
1951 i.init_journal(User.find(2))
1931 i.subject = "blank description"
1952 i.subject = "blank description"
1932 i.description = "\r\n"
1953 i.description = "\r\n"
1933
1954
1934 assert_difference 'Journal.count', 1 do
1955 assert_difference 'Journal.count', 1 do
1935 assert_difference 'JournalDetail.count', 1 do
1956 assert_difference 'JournalDetail.count', 1 do
1936 i.save!
1957 i.save!
1937 end
1958 end
1938 end
1959 end
1939 end
1960 end
1940
1961
1941 def test_journalized_multi_custom_field
1962 def test_journalized_multi_custom_field
1942 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1963 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1943 :is_filter => true, :is_for_all => true,
1964 :is_filter => true, :is_for_all => true,
1944 :tracker_ids => [1],
1965 :tracker_ids => [1],
1945 :possible_values => ['value1', 'value2', 'value3'],
1966 :possible_values => ['value1', 'value2', 'value3'],
1946 :multiple => true)
1967 :multiple => true)
1947
1968
1948 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1969 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1949 :subject => 'Test', :author_id => 1)
1970 :subject => 'Test', :author_id => 1)
1950
1971
1951 assert_difference 'Journal.count' do
1972 assert_difference 'Journal.count' do
1952 assert_difference 'JournalDetail.count' do
1973 assert_difference 'JournalDetail.count' do
1953 issue.init_journal(User.first)
1974 issue.init_journal(User.first)
1954 issue.custom_field_values = {field.id => ['value1']}
1975 issue.custom_field_values = {field.id => ['value1']}
1955 issue.save!
1976 issue.save!
1956 end
1977 end
1957 assert_difference 'JournalDetail.count' do
1978 assert_difference 'JournalDetail.count' do
1958 issue.init_journal(User.first)
1979 issue.init_journal(User.first)
1959 issue.custom_field_values = {field.id => ['value1', 'value2']}
1980 issue.custom_field_values = {field.id => ['value1', 'value2']}
1960 issue.save!
1981 issue.save!
1961 end
1982 end
1962 assert_difference 'JournalDetail.count', 2 do
1983 assert_difference 'JournalDetail.count', 2 do
1963 issue.init_journal(User.first)
1984 issue.init_journal(User.first)
1964 issue.custom_field_values = {field.id => ['value3', 'value2']}
1985 issue.custom_field_values = {field.id => ['value3', 'value2']}
1965 issue.save!
1986 issue.save!
1966 end
1987 end
1967 assert_difference 'JournalDetail.count', 2 do
1988 assert_difference 'JournalDetail.count', 2 do
1968 issue.init_journal(User.first)
1989 issue.init_journal(User.first)
1969 issue.custom_field_values = {field.id => nil}
1990 issue.custom_field_values = {field.id => nil}
1970 issue.save!
1991 issue.save!
1971 end
1992 end
1972 end
1993 end
1973 end
1994 end
1974
1995
1975 def test_description_eol_should_be_normalized
1996 def test_description_eol_should_be_normalized
1976 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1997 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1977 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1998 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1978 end
1999 end
1979
2000
1980 def test_saving_twice_should_not_duplicate_journal_details
2001 def test_saving_twice_should_not_duplicate_journal_details
1981 i = Issue.first
2002 i = Issue.first
1982 i.init_journal(User.find(2), 'Some notes')
2003 i.init_journal(User.find(2), 'Some notes')
1983 # initial changes
2004 # initial changes
1984 i.subject = 'New subject'
2005 i.subject = 'New subject'
1985 i.done_ratio = i.done_ratio + 10
2006 i.done_ratio = i.done_ratio + 10
1986 assert_difference 'Journal.count' do
2007 assert_difference 'Journal.count' do
1987 assert i.save
2008 assert i.save
1988 end
2009 end
1989 # 1 more change
2010 # 1 more change
1990 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
2011 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1991 assert_no_difference 'Journal.count' do
2012 assert_no_difference 'Journal.count' do
1992 assert_difference 'JournalDetail.count', 1 do
2013 assert_difference 'JournalDetail.count', 1 do
1993 i.save
2014 i.save
1994 end
2015 end
1995 end
2016 end
1996 # no more change
2017 # no more change
1997 assert_no_difference 'Journal.count' do
2018 assert_no_difference 'Journal.count' do
1998 assert_no_difference 'JournalDetail.count' do
2019 assert_no_difference 'JournalDetail.count' do
1999 i.save
2020 i.save
2000 end
2021 end
2001 end
2022 end
2002 end
2023 end
2003
2024
2004 def test_all_dependent_issues
2025 def test_all_dependent_issues
2005 IssueRelation.delete_all
2026 IssueRelation.delete_all
2006 assert IssueRelation.create!(:issue_from => Issue.find(1),
2027 assert IssueRelation.create!(:issue_from => Issue.find(1),
2007 :issue_to => Issue.find(2),
2028 :issue_to => Issue.find(2),
2008 :relation_type => IssueRelation::TYPE_PRECEDES)
2029 :relation_type => IssueRelation::TYPE_PRECEDES)
2009 assert IssueRelation.create!(:issue_from => Issue.find(2),
2030 assert IssueRelation.create!(:issue_from => Issue.find(2),
2010 :issue_to => Issue.find(3),
2031 :issue_to => Issue.find(3),
2011 :relation_type => IssueRelation::TYPE_PRECEDES)
2032 :relation_type => IssueRelation::TYPE_PRECEDES)
2012 assert IssueRelation.create!(:issue_from => Issue.find(3),
2033 assert IssueRelation.create!(:issue_from => Issue.find(3),
2013 :issue_to => Issue.find(8),
2034 :issue_to => Issue.find(8),
2014 :relation_type => IssueRelation::TYPE_PRECEDES)
2035 :relation_type => IssueRelation::TYPE_PRECEDES)
2015
2036
2016 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2037 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2017 end
2038 end
2018
2039
2019 def test_all_dependent_issues_with_subtask
2040 def test_all_dependent_issues_with_subtask
2020 IssueRelation.delete_all
2041 IssueRelation.delete_all
2021
2042
2022 project = Project.generate!(:name => "testproject")
2043 project = Project.generate!(:name => "testproject")
2023
2044
2024 parentIssue = Issue.generate!(:project => project)
2045 parentIssue = Issue.generate!(:project => project)
2025 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2046 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2026 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2047 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2027
2048
2028 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
2049 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
2029 end
2050 end
2030
2051
2031 def test_all_dependent_issues_does_not_include_self
2052 def test_all_dependent_issues_does_not_include_self
2032 IssueRelation.delete_all
2053 IssueRelation.delete_all
2033
2054
2034 project = Project.generate!(:name => "testproject")
2055 project = Project.generate!(:name => "testproject")
2035
2056
2036 parentIssue = Issue.generate!(:project => project)
2057 parentIssue = Issue.generate!(:project => project)
2037 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2058 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2038
2059
2039 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
2060 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
2040 end
2061 end
2041
2062
2042 def test_all_dependent_issues_with_parenttask_and_sibling
2063 def test_all_dependent_issues_with_parenttask_and_sibling
2043 IssueRelation.delete_all
2064 IssueRelation.delete_all
2044
2065
2045 project = Project.generate!(:name => "testproject")
2066 project = Project.generate!(:name => "testproject")
2046
2067
2047 parentIssue = Issue.generate!(:project => project)
2068 parentIssue = Issue.generate!(:project => project)
2048 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2069 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2049 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2070 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
2050
2071
2051 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
2072 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
2052 end
2073 end
2053
2074
2054 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
2075 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
2055 IssueRelation.delete_all
2076 IssueRelation.delete_all
2056
2077
2057 project = Project.generate!(:name => "testproject")
2078 project = Project.generate!(:name => "testproject")
2058
2079
2059 parentIssue1 = Issue.generate!(:project => project)
2080 parentIssue1 = Issue.generate!(:project => project)
2060 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2081 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2061 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2082 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2062
2083
2063 parentIssue2 = Issue.generate!(:project => project)
2084 parentIssue2 = Issue.generate!(:project => project)
2064 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2085 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2065 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2086 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2066
2087
2067
2088
2068 assert IssueRelation.create(:issue_from => parentIssue1,
2089 assert IssueRelation.create(:issue_from => parentIssue1,
2069 :issue_to => childIssue2_2,
2090 :issue_to => childIssue2_2,
2070 :relation_type => IssueRelation::TYPE_BLOCKS)
2091 :relation_type => IssueRelation::TYPE_BLOCKS)
2071
2092
2072 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
2093 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
2073 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2094 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2074 end
2095 end
2075
2096
2076 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
2097 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
2077 IssueRelation.delete_all
2098 IssueRelation.delete_all
2078
2099
2079 project = Project.generate!(:name => "testproject")
2100 project = Project.generate!(:name => "testproject")
2080
2101
2081 parentIssue1 = Issue.generate!(:project => project)
2102 parentIssue1 = Issue.generate!(:project => project)
2082 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2103 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2083 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2104 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2084
2105
2085 parentIssue2 = Issue.generate!(:project => project)
2106 parentIssue2 = Issue.generate!(:project => project)
2086 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2107 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2087 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2108 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2088
2109
2089
2110
2090 assert IssueRelation.create(:issue_from => parentIssue1,
2111 assert IssueRelation.create(:issue_from => parentIssue1,
2091 :issue_to => parentIssue2,
2112 :issue_to => parentIssue2,
2092 :relation_type => IssueRelation::TYPE_BLOCKS)
2113 :relation_type => IssueRelation::TYPE_BLOCKS)
2093
2114
2094 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
2115 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
2095 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2116 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2096 end
2117 end
2097
2118
2098 def test_all_dependent_issues_with_transitive_relation
2119 def test_all_dependent_issues_with_transitive_relation
2099 IssueRelation.delete_all
2120 IssueRelation.delete_all
2100
2121
2101 project = Project.generate!(:name => "testproject")
2122 project = Project.generate!(:name => "testproject")
2102
2123
2103 parentIssue1 = Issue.generate!(:project => project)
2124 parentIssue1 = Issue.generate!(:project => project)
2104 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2125 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2105
2126
2106 parentIssue2 = Issue.generate!(:project => project)
2127 parentIssue2 = Issue.generate!(:project => project)
2107 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2128 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2108
2129
2109 independentIssue = Issue.generate!(:project => project)
2130 independentIssue = Issue.generate!(:project => project)
2110
2131
2111 assert IssueRelation.create(:issue_from => parentIssue1,
2132 assert IssueRelation.create(:issue_from => parentIssue1,
2112 :issue_to => childIssue2_1,
2133 :issue_to => childIssue2_1,
2113 :relation_type => IssueRelation::TYPE_RELATES)
2134 :relation_type => IssueRelation::TYPE_RELATES)
2114
2135
2115 assert IssueRelation.create(:issue_from => childIssue2_1,
2136 assert IssueRelation.create(:issue_from => childIssue2_1,
2116 :issue_to => independentIssue,
2137 :issue_to => independentIssue,
2117 :relation_type => IssueRelation::TYPE_RELATES)
2138 :relation_type => IssueRelation::TYPE_RELATES)
2118
2139
2119 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2140 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2120 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2141 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2121 end
2142 end
2122
2143
2123 def test_all_dependent_issues_with_transitive_relation2
2144 def test_all_dependent_issues_with_transitive_relation2
2124 IssueRelation.delete_all
2145 IssueRelation.delete_all
2125
2146
2126 project = Project.generate!(:name => "testproject")
2147 project = Project.generate!(:name => "testproject")
2127
2148
2128 parentIssue1 = Issue.generate!(:project => project)
2149 parentIssue1 = Issue.generate!(:project => project)
2129 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2150 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
2130
2151
2131 parentIssue2 = Issue.generate!(:project => project)
2152 parentIssue2 = Issue.generate!(:project => project)
2132 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2153 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
2133
2154
2134 independentIssue = Issue.generate!(:project => project)
2155 independentIssue = Issue.generate!(:project => project)
2135
2156
2136 assert IssueRelation.create(:issue_from => parentIssue1,
2157 assert IssueRelation.create(:issue_from => parentIssue1,
2137 :issue_to => independentIssue,
2158 :issue_to => independentIssue,
2138 :relation_type => IssueRelation::TYPE_RELATES)
2159 :relation_type => IssueRelation::TYPE_RELATES)
2139
2160
2140 assert IssueRelation.create(:issue_from => independentIssue,
2161 assert IssueRelation.create(:issue_from => independentIssue,
2141 :issue_to => childIssue2_1,
2162 :issue_to => childIssue2_1,
2142 :relation_type => IssueRelation::TYPE_RELATES)
2163 :relation_type => IssueRelation::TYPE_RELATES)
2143
2164
2144 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2165 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
2145 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2166 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
2146
2167
2147 end
2168 end
2148
2169
2149 def test_all_dependent_issues_with_persistent_circular_dependency
2170 def test_all_dependent_issues_with_persistent_circular_dependency
2150 IssueRelation.delete_all
2171 IssueRelation.delete_all
2151 assert IssueRelation.create!(:issue_from => Issue.find(1),
2172 assert IssueRelation.create!(:issue_from => Issue.find(1),
2152 :issue_to => Issue.find(2),
2173 :issue_to => Issue.find(2),
2153 :relation_type => IssueRelation::TYPE_PRECEDES)
2174 :relation_type => IssueRelation::TYPE_PRECEDES)
2154 assert IssueRelation.create!(:issue_from => Issue.find(2),
2175 assert IssueRelation.create!(:issue_from => Issue.find(2),
2155 :issue_to => Issue.find(3),
2176 :issue_to => Issue.find(3),
2156 :relation_type => IssueRelation::TYPE_PRECEDES)
2177 :relation_type => IssueRelation::TYPE_PRECEDES)
2157
2178
2158 r = IssueRelation.create!(:issue_from => Issue.find(3),
2179 r = IssueRelation.create!(:issue_from => Issue.find(3),
2159 :issue_to => Issue.find(7),
2180 :issue_to => Issue.find(7),
2160 :relation_type => IssueRelation::TYPE_PRECEDES)
2181 :relation_type => IssueRelation::TYPE_PRECEDES)
2161 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2182 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2162
2183
2163 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
2184 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
2164 end
2185 end
2165
2186
2166 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
2187 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
2167 IssueRelation.delete_all
2188 IssueRelation.delete_all
2168 assert IssueRelation.create!(:issue_from => Issue.find(1),
2189 assert IssueRelation.create!(:issue_from => Issue.find(1),
2169 :issue_to => Issue.find(2),
2190 :issue_to => Issue.find(2),
2170 :relation_type => IssueRelation::TYPE_RELATES)
2191 :relation_type => IssueRelation::TYPE_RELATES)
2171 assert IssueRelation.create!(:issue_from => Issue.find(2),
2192 assert IssueRelation.create!(:issue_from => Issue.find(2),
2172 :issue_to => Issue.find(3),
2193 :issue_to => Issue.find(3),
2173 :relation_type => IssueRelation::TYPE_RELATES)
2194 :relation_type => IssueRelation::TYPE_RELATES)
2174 assert IssueRelation.create!(:issue_from => Issue.find(3),
2195 assert IssueRelation.create!(:issue_from => Issue.find(3),
2175 :issue_to => Issue.find(8),
2196 :issue_to => Issue.find(8),
2176 :relation_type => IssueRelation::TYPE_RELATES)
2197 :relation_type => IssueRelation::TYPE_RELATES)
2177
2198
2178 r = IssueRelation.create!(:issue_from => Issue.find(8),
2199 r = IssueRelation.create!(:issue_from => Issue.find(8),
2179 :issue_to => Issue.find(7),
2200 :issue_to => Issue.find(7),
2180 :relation_type => IssueRelation::TYPE_RELATES)
2201 :relation_type => IssueRelation::TYPE_RELATES)
2181 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 2")
2202 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 2")
2182
2203
2183 r = IssueRelation.create!(:issue_from => Issue.find(3),
2204 r = IssueRelation.create!(:issue_from => Issue.find(3),
2184 :issue_to => Issue.find(7),
2205 :issue_to => Issue.find(7),
2185 :relation_type => IssueRelation::TYPE_RELATES)
2206 :relation_type => IssueRelation::TYPE_RELATES)
2186 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2207 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
2187
2208
2188 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2209 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
2189 end
2210 end
2190
2211
2191 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2212 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
2192 @issue = Issue.find(1)
2213 @issue = Issue.find(1)
2193 @issue_status = IssueStatus.find(1)
2214 @issue_status = IssueStatus.find(1)
2194 @issue_status.update_attribute(:default_done_ratio, 50)
2215 @issue_status.update_attribute(:default_done_ratio, 50)
2195 @issue2 = Issue.find(2)
2216 @issue2 = Issue.find(2)
2196 @issue_status2 = IssueStatus.find(2)
2217 @issue_status2 = IssueStatus.find(2)
2197 @issue_status2.update_attribute(:default_done_ratio, 0)
2218 @issue_status2.update_attribute(:default_done_ratio, 0)
2198
2219
2199 with_settings :issue_done_ratio => 'issue_field' do
2220 with_settings :issue_done_ratio => 'issue_field' do
2200 assert_equal 0, @issue.done_ratio
2221 assert_equal 0, @issue.done_ratio
2201 assert_equal 30, @issue2.done_ratio
2222 assert_equal 30, @issue2.done_ratio
2202 end
2223 end
2203
2224
2204 with_settings :issue_done_ratio => 'issue_status' do
2225 with_settings :issue_done_ratio => 'issue_status' do
2205 assert_equal 50, @issue.done_ratio
2226 assert_equal 50, @issue.done_ratio
2206 assert_equal 0, @issue2.done_ratio
2227 assert_equal 0, @issue2.done_ratio
2207 end
2228 end
2208 end
2229 end
2209
2230
2210 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2231 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
2211 @issue = Issue.find(1)
2232 @issue = Issue.find(1)
2212 @issue_status = IssueStatus.find(1)
2233 @issue_status = IssueStatus.find(1)
2213 @issue_status.update_attribute(:default_done_ratio, 50)
2234 @issue_status.update_attribute(:default_done_ratio, 50)
2214 @issue2 = Issue.find(2)
2235 @issue2 = Issue.find(2)
2215 @issue_status2 = IssueStatus.find(2)
2236 @issue_status2 = IssueStatus.find(2)
2216 @issue_status2.update_attribute(:default_done_ratio, 0)
2237 @issue_status2.update_attribute(:default_done_ratio, 0)
2217
2238
2218 with_settings :issue_done_ratio => 'issue_field' do
2239 with_settings :issue_done_ratio => 'issue_field' do
2219 @issue.update_done_ratio_from_issue_status
2240 @issue.update_done_ratio_from_issue_status
2220 @issue2.update_done_ratio_from_issue_status
2241 @issue2.update_done_ratio_from_issue_status
2221
2242
2222 assert_equal 0, @issue.read_attribute(:done_ratio)
2243 assert_equal 0, @issue.read_attribute(:done_ratio)
2223 assert_equal 30, @issue2.read_attribute(:done_ratio)
2244 assert_equal 30, @issue2.read_attribute(:done_ratio)
2224 end
2245 end
2225
2246
2226 with_settings :issue_done_ratio => 'issue_status' do
2247 with_settings :issue_done_ratio => 'issue_status' do
2227 @issue.update_done_ratio_from_issue_status
2248 @issue.update_done_ratio_from_issue_status
2228 @issue2.update_done_ratio_from_issue_status
2249 @issue2.update_done_ratio_from_issue_status
2229
2250
2230 assert_equal 50, @issue.read_attribute(:done_ratio)
2251 assert_equal 50, @issue.read_attribute(:done_ratio)
2231 assert_equal 0, @issue2.read_attribute(:done_ratio)
2252 assert_equal 0, @issue2.read_attribute(:done_ratio)
2232 end
2253 end
2233 end
2254 end
2234
2255
2235 test "#by_tracker" do
2256 test "#by_tracker" do
2236 User.current = User.anonymous
2257 User.current = User.anonymous
2237 groups = Issue.by_tracker(Project.find(1))
2258 groups = Issue.by_tracker(Project.find(1))
2238 assert_equal 3, groups.count
2259 assert_equal 3, groups.count
2239 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2260 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2240 end
2261 end
2241
2262
2242 test "#by_version" do
2263 test "#by_version" do
2243 User.current = User.anonymous
2264 User.current = User.anonymous
2244 groups = Issue.by_version(Project.find(1))
2265 groups = Issue.by_version(Project.find(1))
2245 assert_equal 3, groups.count
2266 assert_equal 3, groups.count
2246 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2267 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2247 end
2268 end
2248
2269
2249 test "#by_priority" do
2270 test "#by_priority" do
2250 User.current = User.anonymous
2271 User.current = User.anonymous
2251 groups = Issue.by_priority(Project.find(1))
2272 groups = Issue.by_priority(Project.find(1))
2252 assert_equal 4, groups.count
2273 assert_equal 4, groups.count
2253 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2274 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2254 end
2275 end
2255
2276
2256 test "#by_category" do
2277 test "#by_category" do
2257 User.current = User.anonymous
2278 User.current = User.anonymous
2258 groups = Issue.by_category(Project.find(1))
2279 groups = Issue.by_category(Project.find(1))
2259 assert_equal 2, groups.count
2280 assert_equal 2, groups.count
2260 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2281 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2261 end
2282 end
2262
2283
2263 test "#by_assigned_to" do
2284 test "#by_assigned_to" do
2264 User.current = User.anonymous
2285 User.current = User.anonymous
2265 groups = Issue.by_assigned_to(Project.find(1))
2286 groups = Issue.by_assigned_to(Project.find(1))
2266 assert_equal 2, groups.count
2287 assert_equal 2, groups.count
2267 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2288 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2268 end
2289 end
2269
2290
2270 test "#by_author" do
2291 test "#by_author" do
2271 User.current = User.anonymous
2292 User.current = User.anonymous
2272 groups = Issue.by_author(Project.find(1))
2293 groups = Issue.by_author(Project.find(1))
2273 assert_equal 4, groups.count
2294 assert_equal 4, groups.count
2274 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2295 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2275 end
2296 end
2276
2297
2277 test "#by_subproject" do
2298 test "#by_subproject" do
2278 User.current = User.anonymous
2299 User.current = User.anonymous
2279 groups = Issue.by_subproject(Project.find(1))
2300 groups = Issue.by_subproject(Project.find(1))
2280 # Private descendant not visible
2301 # Private descendant not visible
2281 assert_equal 1, groups.count
2302 assert_equal 1, groups.count
2282 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2303 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
2283 end
2304 end
2284
2305
2285 def test_recently_updated_scope
2306 def test_recently_updated_scope
2286 #should return the last updated issue
2307 #should return the last updated issue
2287 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2308 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
2288 end
2309 end
2289
2310
2290 def test_on_active_projects_scope
2311 def test_on_active_projects_scope
2291 assert Project.find(2).archive
2312 assert Project.find(2).archive
2292
2313
2293 before = Issue.on_active_project.length
2314 before = Issue.on_active_project.length
2294 # test inclusion to results
2315 # test inclusion to results
2295 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2316 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
2296 assert_equal before + 1, Issue.on_active_project.length
2317 assert_equal before + 1, Issue.on_active_project.length
2297
2318
2298 # Move to an archived project
2319 # Move to an archived project
2299 issue.project = Project.find(2)
2320 issue.project = Project.find(2)
2300 assert issue.save
2321 assert issue.save
2301 assert_equal before, Issue.on_active_project.length
2322 assert_equal before, Issue.on_active_project.length
2302 end
2323 end
2303
2324
2304 test "Issue#recipients should include project recipients" do
2325 test "Issue#recipients should include project recipients" do
2305 issue = Issue.generate!
2326 issue = Issue.generate!
2306 assert issue.project.recipients.present?
2327 assert issue.project.recipients.present?
2307 issue.project.recipients.each do |project_recipient|
2328 issue.project.recipients.each do |project_recipient|
2308 assert issue.recipients.include?(project_recipient)
2329 assert issue.recipients.include?(project_recipient)
2309 end
2330 end
2310 end
2331 end
2311
2332
2312 test "Issue#recipients should include the author if the author is active" do
2333 test "Issue#recipients should include the author if the author is active" do
2313 issue = Issue.generate!(:author => User.generate!)
2334 issue = Issue.generate!(:author => User.generate!)
2314 assert issue.author, "No author set for Issue"
2335 assert issue.author, "No author set for Issue"
2315 assert issue.recipients.include?(issue.author.mail)
2336 assert issue.recipients.include?(issue.author.mail)
2316 end
2337 end
2317
2338
2318 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2339 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
2319 issue = Issue.generate!(:assigned_to => User.generate!)
2340 issue = Issue.generate!(:assigned_to => User.generate!)
2320 assert issue.assigned_to, "No assigned_to set for Issue"
2341 assert issue.assigned_to, "No assigned_to set for Issue"
2321 assert issue.recipients.include?(issue.assigned_to.mail)
2342 assert issue.recipients.include?(issue.assigned_to.mail)
2322 end
2343 end
2323
2344
2324 test "Issue#recipients should not include users who opt out of all email" do
2345 test "Issue#recipients should not include users who opt out of all email" do
2325 issue = Issue.generate!(:author => User.generate!)
2346 issue = Issue.generate!(:author => User.generate!)
2326 issue.author.update_attribute(:mail_notification, :none)
2347 issue.author.update_attribute(:mail_notification, :none)
2327 assert !issue.recipients.include?(issue.author.mail)
2348 assert !issue.recipients.include?(issue.author.mail)
2328 end
2349 end
2329
2350
2330 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2351 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
2331 issue = Issue.generate!(:author => User.generate!)
2352 issue = Issue.generate!(:author => User.generate!)
2332 issue.author.update_attribute(:mail_notification, :only_assigned)
2353 issue.author.update_attribute(:mail_notification, :only_assigned)
2333 assert !issue.recipients.include?(issue.author.mail)
2354 assert !issue.recipients.include?(issue.author.mail)
2334 end
2355 end
2335
2356
2336 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2357 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
2337 issue = Issue.generate!(:assigned_to => User.generate!)
2358 issue = Issue.generate!(:assigned_to => User.generate!)
2338 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2359 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
2339 assert !issue.recipients.include?(issue.assigned_to.mail)
2360 assert !issue.recipients.include?(issue.assigned_to.mail)
2340 end
2361 end
2341
2362
2342 def test_last_journal_id_with_journals_should_return_the_journal_id
2363 def test_last_journal_id_with_journals_should_return_the_journal_id
2343 assert_equal 2, Issue.find(1).last_journal_id
2364 assert_equal 2, Issue.find(1).last_journal_id
2344 end
2365 end
2345
2366
2346 def test_last_journal_id_without_journals_should_return_nil
2367 def test_last_journal_id_without_journals_should_return_nil
2347 assert_nil Issue.find(3).last_journal_id
2368 assert_nil Issue.find(3).last_journal_id
2348 end
2369 end
2349
2370
2350 def test_journals_after_should_return_journals_with_greater_id
2371 def test_journals_after_should_return_journals_with_greater_id
2351 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2372 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
2352 assert_equal [], Issue.find(1).journals_after('2')
2373 assert_equal [], Issue.find(1).journals_after('2')
2353 end
2374 end
2354
2375
2355 def test_journals_after_with_blank_arg_should_return_all_journals
2376 def test_journals_after_with_blank_arg_should_return_all_journals
2356 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2377 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2357 end
2378 end
2358
2379
2359 def test_css_classes_should_include_tracker
2380 def test_css_classes_should_include_tracker
2360 issue = Issue.new(:tracker => Tracker.find(2))
2381 issue = Issue.new(:tracker => Tracker.find(2))
2361 classes = issue.css_classes.split(' ')
2382 classes = issue.css_classes.split(' ')
2362 assert_include 'tracker-2', classes
2383 assert_include 'tracker-2', classes
2363 end
2384 end
2364
2385
2365 def test_css_classes_should_include_priority
2386 def test_css_classes_should_include_priority
2366 issue = Issue.new(:priority => IssuePriority.find(8))
2387 issue = Issue.new(:priority => IssuePriority.find(8))
2367 classes = issue.css_classes.split(' ')
2388 classes = issue.css_classes.split(' ')
2368 assert_include 'priority-8', classes
2389 assert_include 'priority-8', classes
2369 assert_include 'priority-highest', classes
2390 assert_include 'priority-highest', classes
2370 end
2391 end
2371
2392
2372 def test_css_classes_should_include_user_and_group_assignment
2393 def test_css_classes_should_include_user_and_group_assignment
2373 project = Project.first
2394 project = Project.first
2374 user = User.generate!
2395 user = User.generate!
2375 group = Group.generate!
2396 group = Group.generate!
2376 Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
2397 Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
2377 group.users << user
2398 group.users << user
2378 assert user.member_of?(project)
2399 assert user.member_of?(project)
2379 issue1 = Issue.generate(:assigned_to_id => group.id)
2400 issue1 = Issue.generate(:assigned_to_id => group.id)
2380 assert_include 'assigned-to-my-group', issue1.css_classes(user)
2401 assert_include 'assigned-to-my-group', issue1.css_classes(user)
2381 assert_not_include 'assigned-to-me', issue1.css_classes(user)
2402 assert_not_include 'assigned-to-me', issue1.css_classes(user)
2382 issue2 = Issue.generate(:assigned_to_id => user.id)
2403 issue2 = Issue.generate(:assigned_to_id => user.id)
2383 assert_not_include 'assigned-to-my-group', issue2.css_classes(user)
2404 assert_not_include 'assigned-to-my-group', issue2.css_classes(user)
2384 assert_include 'assigned-to-me', issue2.css_classes(user)
2405 assert_include 'assigned-to-me', issue2.css_classes(user)
2385 end
2406 end
2386
2407
2387 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2408 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
2388 set_tmp_attachments_directory
2409 set_tmp_attachments_directory
2389 issue = Issue.generate!
2410 issue = Issue.generate!
2390 issue.save_attachments({
2411 issue.save_attachments({
2391 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2412 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
2392 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2413 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
2393 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2414 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
2394 })
2415 })
2395 issue.attach_saved_attachments
2416 issue.attach_saved_attachments
2396
2417
2397 assert_equal 3, issue.reload.attachments.count
2418 assert_equal 3, issue.reload.attachments.count
2398 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2419 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
2399 end
2420 end
2400
2421
2401 def test_closed_on_should_be_nil_when_creating_an_open_issue
2422 def test_closed_on_should_be_nil_when_creating_an_open_issue
2402 issue = Issue.generate!(:status_id => 1).reload
2423 issue = Issue.generate!(:status_id => 1).reload
2403 assert !issue.closed?
2424 assert !issue.closed?
2404 assert_nil issue.closed_on
2425 assert_nil issue.closed_on
2405 end
2426 end
2406
2427
2407 def test_closed_on_should_be_set_when_creating_a_closed_issue
2428 def test_closed_on_should_be_set_when_creating_a_closed_issue
2408 issue = Issue.generate!(:status_id => 5).reload
2429 issue = Issue.generate!(:status_id => 5).reload
2409 assert issue.closed?
2430 assert issue.closed?
2410 assert_not_nil issue.closed_on
2431 assert_not_nil issue.closed_on
2411 assert_equal issue.updated_on, issue.closed_on
2432 assert_equal issue.updated_on, issue.closed_on
2412 assert_equal issue.created_on, issue.closed_on
2433 assert_equal issue.created_on, issue.closed_on
2413 end
2434 end
2414
2435
2415 def test_closed_on_should_be_nil_when_updating_an_open_issue
2436 def test_closed_on_should_be_nil_when_updating_an_open_issue
2416 issue = Issue.find(1)
2437 issue = Issue.find(1)
2417 issue.subject = 'Not closed yet'
2438 issue.subject = 'Not closed yet'
2418 issue.save!
2439 issue.save!
2419 issue.reload
2440 issue.reload
2420 assert_nil issue.closed_on
2441 assert_nil issue.closed_on
2421 end
2442 end
2422
2443
2423 def test_closed_on_should_be_set_when_closing_an_open_issue
2444 def test_closed_on_should_be_set_when_closing_an_open_issue
2424 issue = Issue.find(1)
2445 issue = Issue.find(1)
2425 issue.subject = 'Now closed'
2446 issue.subject = 'Now closed'
2426 issue.status_id = 5
2447 issue.status_id = 5
2427 issue.save!
2448 issue.save!
2428 issue.reload
2449 issue.reload
2429 assert_not_nil issue.closed_on
2450 assert_not_nil issue.closed_on
2430 assert_equal issue.updated_on, issue.closed_on
2451 assert_equal issue.updated_on, issue.closed_on
2431 end
2452 end
2432
2453
2433 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2454 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2434 issue = Issue.open(false).first
2455 issue = Issue.open(false).first
2435 was_closed_on = issue.closed_on
2456 was_closed_on = issue.closed_on
2436 assert_not_nil was_closed_on
2457 assert_not_nil was_closed_on
2437 issue.subject = 'Updating a closed issue'
2458 issue.subject = 'Updating a closed issue'
2438 issue.save!
2459 issue.save!
2439 issue.reload
2460 issue.reload
2440 assert_equal was_closed_on, issue.closed_on
2461 assert_equal was_closed_on, issue.closed_on
2441 end
2462 end
2442
2463
2443 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2464 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2444 issue = Issue.open(false).first
2465 issue = Issue.open(false).first
2445 was_closed_on = issue.closed_on
2466 was_closed_on = issue.closed_on
2446 assert_not_nil was_closed_on
2467 assert_not_nil was_closed_on
2447 issue.subject = 'Reopening a closed issue'
2468 issue.subject = 'Reopening a closed issue'
2448 issue.status_id = 1
2469 issue.status_id = 1
2449 issue.save!
2470 issue.save!
2450 issue.reload
2471 issue.reload
2451 assert !issue.closed?
2472 assert !issue.closed?
2452 assert_equal was_closed_on, issue.closed_on
2473 assert_equal was_closed_on, issue.closed_on
2453 end
2474 end
2454
2475
2455 def test_status_was_should_return_nil_for_new_issue
2476 def test_status_was_should_return_nil_for_new_issue
2456 issue = Issue.new
2477 issue = Issue.new
2457 assert_nil issue.status_was
2478 assert_nil issue.status_was
2458 end
2479 end
2459
2480
2460 def test_status_was_should_return_status_before_change
2481 def test_status_was_should_return_status_before_change
2461 issue = Issue.find(1)
2482 issue = Issue.find(1)
2462 issue.status = IssueStatus.find(2)
2483 issue.status = IssueStatus.find(2)
2463 assert_equal IssueStatus.find(1), issue.status_was
2484 assert_equal IssueStatus.find(1), issue.status_was
2464 end
2485 end
2465
2486
2466 def test_status_was_should_return_status_before_change_with_status_id
2487 def test_status_was_should_return_status_before_change_with_status_id
2467 issue = Issue.find(1)
2488 issue = Issue.find(1)
2468 assert_equal IssueStatus.find(1), issue.status
2489 assert_equal IssueStatus.find(1), issue.status
2469 issue.status_id = 2
2490 issue.status_id = 2
2470 assert_equal IssueStatus.find(1), issue.status_was
2491 assert_equal IssueStatus.find(1), issue.status_was
2471 end
2492 end
2472
2493
2473 def test_status_was_should_be_reset_on_save
2494 def test_status_was_should_be_reset_on_save
2474 issue = Issue.find(1)
2495 issue = Issue.find(1)
2475 issue.status = IssueStatus.find(2)
2496 issue.status = IssueStatus.find(2)
2476 assert_equal IssueStatus.find(1), issue.status_was
2497 assert_equal IssueStatus.find(1), issue.status_was
2477 assert issue.save!
2498 assert issue.save!
2478 assert_equal IssueStatus.find(2), issue.status_was
2499 assert_equal IssueStatus.find(2), issue.status_was
2479 end
2500 end
2480
2501
2481 def test_closing_should_return_true_when_closing_an_issue
2502 def test_closing_should_return_true_when_closing_an_issue
2482 issue = Issue.find(1)
2503 issue = Issue.find(1)
2483 issue.status = IssueStatus.find(2)
2504 issue.status = IssueStatus.find(2)
2484 assert_equal false, issue.closing?
2505 assert_equal false, issue.closing?
2485 issue.status = IssueStatus.find(5)
2506 issue.status = IssueStatus.find(5)
2486 assert_equal true, issue.closing?
2507 assert_equal true, issue.closing?
2487 end
2508 end
2488
2509
2489 def test_closing_should_return_true_when_closing_an_issue_with_status_id
2510 def test_closing_should_return_true_when_closing_an_issue_with_status_id
2490 issue = Issue.find(1)
2511 issue = Issue.find(1)
2491 issue.status_id = 2
2512 issue.status_id = 2
2492 assert_equal false, issue.closing?
2513 assert_equal false, issue.closing?
2493 issue.status_id = 5
2514 issue.status_id = 5
2494 assert_equal true, issue.closing?
2515 assert_equal true, issue.closing?
2495 end
2516 end
2496
2517
2497 def test_closing_should_return_true_for_new_closed_issue
2518 def test_closing_should_return_true_for_new_closed_issue
2498 issue = Issue.new
2519 issue = Issue.new
2499 assert_equal false, issue.closing?
2520 assert_equal false, issue.closing?
2500 issue.status = IssueStatus.find(5)
2521 issue.status = IssueStatus.find(5)
2501 assert_equal true, issue.closing?
2522 assert_equal true, issue.closing?
2502 end
2523 end
2503
2524
2504 def test_closing_should_return_true_for_new_closed_issue_with_status_id
2525 def test_closing_should_return_true_for_new_closed_issue_with_status_id
2505 issue = Issue.new
2526 issue = Issue.new
2506 assert_equal false, issue.closing?
2527 assert_equal false, issue.closing?
2507 issue.status_id = 5
2528 issue.status_id = 5
2508 assert_equal true, issue.closing?
2529 assert_equal true, issue.closing?
2509 end
2530 end
2510
2531
2511 def test_closing_should_be_reset_after_save
2532 def test_closing_should_be_reset_after_save
2512 issue = Issue.find(1)
2533 issue = Issue.find(1)
2513 issue.status_id = 5
2534 issue.status_id = 5
2514 assert_equal true, issue.closing?
2535 assert_equal true, issue.closing?
2515 issue.save!
2536 issue.save!
2516 assert_equal false, issue.closing?
2537 assert_equal false, issue.closing?
2517 end
2538 end
2518
2539
2519 def test_reopening_should_return_true_when_reopening_an_issue
2540 def test_reopening_should_return_true_when_reopening_an_issue
2520 issue = Issue.find(8)
2541 issue = Issue.find(8)
2521 issue.status = IssueStatus.find(6)
2542 issue.status = IssueStatus.find(6)
2522 assert_equal false, issue.reopening?
2543 assert_equal false, issue.reopening?
2523 issue.status = IssueStatus.find(2)
2544 issue.status = IssueStatus.find(2)
2524 assert_equal true, issue.reopening?
2545 assert_equal true, issue.reopening?
2525 end
2546 end
2526
2547
2527 def test_reopening_should_return_true_when_reopening_an_issue_with_status_id
2548 def test_reopening_should_return_true_when_reopening_an_issue_with_status_id
2528 issue = Issue.find(8)
2549 issue = Issue.find(8)
2529 issue.status_id = 6
2550 issue.status_id = 6
2530 assert_equal false, issue.reopening?
2551 assert_equal false, issue.reopening?
2531 issue.status_id = 2
2552 issue.status_id = 2
2532 assert_equal true, issue.reopening?
2553 assert_equal true, issue.reopening?
2533 end
2554 end
2534
2555
2535 def test_reopening_should_return_false_for_new_open_issue
2556 def test_reopening_should_return_false_for_new_open_issue
2536 issue = Issue.new
2557 issue = Issue.new
2537 issue.status = IssueStatus.find(1)
2558 issue.status = IssueStatus.find(1)
2538 assert_equal false, issue.reopening?
2559 assert_equal false, issue.reopening?
2539 end
2560 end
2540
2561
2541 def test_reopening_should_be_reset_after_save
2562 def test_reopening_should_be_reset_after_save
2542 issue = Issue.find(8)
2563 issue = Issue.find(8)
2543 issue.status_id = 2
2564 issue.status_id = 2
2544 assert_equal true, issue.reopening?
2565 assert_equal true, issue.reopening?
2545 issue.save!
2566 issue.save!
2546 assert_equal false, issue.reopening?
2567 assert_equal false, issue.reopening?
2547 end
2568 end
2548
2569
2549 def test_default_status_without_tracker_should_be_nil
2570 def test_default_status_without_tracker_should_be_nil
2550 issue = Issue.new
2571 issue = Issue.new
2551 assert_nil issue.tracker
2572 assert_nil issue.tracker
2552 assert_nil issue.default_status
2573 assert_nil issue.default_status
2553 end
2574 end
2554
2575
2555 def test_default_status_should_be_tracker_default_status
2576 def test_default_status_should_be_tracker_default_status
2556 issue = Issue.new(:tracker_id => 1)
2577 issue = Issue.new(:tracker_id => 1)
2557 assert_not_nil issue.status
2578 assert_not_nil issue.status
2558 assert_equal issue.tracker.default_status, issue.default_status
2579 assert_equal issue.tracker.default_status, issue.default_status
2559 end
2580 end
2560
2581
2561 def test_initializing_with_tracker_should_set_default_status
2582 def test_initializing_with_tracker_should_set_default_status
2562 issue = Issue.new(:tracker => Tracker.find(1))
2583 issue = Issue.new(:tracker => Tracker.find(1))
2563 assert_not_nil issue.status
2584 assert_not_nil issue.status
2564 assert_equal issue.default_status, issue.status
2585 assert_equal issue.default_status, issue.status
2565 end
2586 end
2566
2587
2567 def test_initializing_with_tracker_id_should_set_default_status
2588 def test_initializing_with_tracker_id_should_set_default_status
2568 issue = Issue.new(:tracker_id => 1)
2589 issue = Issue.new(:tracker_id => 1)
2569 assert_not_nil issue.status
2590 assert_not_nil issue.status
2570 assert_equal issue.default_status, issue.status
2591 assert_equal issue.default_status, issue.status
2571 end
2592 end
2572
2593
2573 def test_setting_tracker_should_set_default_status
2594 def test_setting_tracker_should_set_default_status
2574 issue = Issue.new
2595 issue = Issue.new
2575 issue.tracker = Tracker.find(1)
2596 issue.tracker = Tracker.find(1)
2576 assert_not_nil issue.status
2597 assert_not_nil issue.status
2577 assert_equal issue.default_status, issue.status
2598 assert_equal issue.default_status, issue.status
2578 end
2599 end
2579
2600
2580 def test_changing_tracker_should_set_default_status_if_status_was_default
2601 def test_changing_tracker_should_set_default_status_if_status_was_default
2581 WorkflowTransition.delete_all
2602 WorkflowTransition.delete_all
2582 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1
2603 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1
2583 Tracker.find(2).update! :default_status_id => 2
2604 Tracker.find(2).update! :default_status_id => 2
2584
2605
2585 issue = Issue.new(:tracker_id => 1, :status_id => 1)
2606 issue = Issue.new(:tracker_id => 1, :status_id => 1)
2586 assert_equal IssueStatus.find(1), issue.status
2607 assert_equal IssueStatus.find(1), issue.status
2587 issue.tracker = Tracker.find(2)
2608 issue.tracker = Tracker.find(2)
2588 assert_equal IssueStatus.find(2), issue.status
2609 assert_equal IssueStatus.find(2), issue.status
2589 end
2610 end
2590
2611
2591 def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker
2612 def test_changing_tracker_should_set_default_status_if_status_is_not_used_by_tracker
2592 WorkflowTransition.delete_all
2613 WorkflowTransition.delete_all
2593 Tracker.find(2).update! :default_status_id => 2
2614 Tracker.find(2).update! :default_status_id => 2
2594
2615
2595 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2616 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2596 assert_equal IssueStatus.find(3), issue.status
2617 assert_equal IssueStatus.find(3), issue.status
2597 issue.tracker = Tracker.find(2)
2618 issue.tracker = Tracker.find(2)
2598 assert_equal IssueStatus.find(2), issue.status
2619 assert_equal IssueStatus.find(2), issue.status
2599 end
2620 end
2600
2621
2601 def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker
2622 def test_changing_tracker_should_keep_status_if_status_was_not_default_and_is_used_by_tracker
2602 WorkflowTransition.delete_all
2623 WorkflowTransition.delete_all
2603 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3
2624 WorkflowTransition.create! :role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3
2604 Tracker.find(2).update! :default_status_id => 2
2625 Tracker.find(2).update! :default_status_id => 2
2605
2626
2606 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2627 issue = Issue.new(:tracker_id => 1, :status_id => 3)
2607 assert_equal IssueStatus.find(3), issue.status
2628 assert_equal IssueStatus.find(3), issue.status
2608 issue.tracker = Tracker.find(2)
2629 issue.tracker = Tracker.find(2)
2609 assert_equal IssueStatus.find(3), issue.status
2630 assert_equal IssueStatus.find(3), issue.status
2610 end
2631 end
2611
2632
2612 def test_assigned_to_was_with_a_group
2633 def test_assigned_to_was_with_a_group
2613 group = Group.find(10)
2634 group = Group.find(10)
2614
2635
2615 issue = Issue.generate!(:assigned_to => group)
2636 issue = Issue.generate!(:assigned_to => group)
2616 issue.reload.assigned_to = nil
2637 issue.reload.assigned_to = nil
2617 assert_equal group, issue.assigned_to_was
2638 assert_equal group, issue.assigned_to_was
2618 end
2639 end
2619 end
2640 end
@@ -1,152 +1,162
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class MemberTest < ActiveSupport::TestCase
20 class MemberTest < ActiveSupport::TestCase
21 fixtures :projects, :trackers, :issue_statuses, :issues,
21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 :enumerations, :users, :issue_categories,
22 :enumerations, :users, :issue_categories,
23 :projects_trackers,
23 :projects_trackers,
24 :roles,
24 :roles,
25 :member_roles,
25 :member_roles,
26 :members,
26 :members,
27 :enabled_modules,
27 :enabled_modules,
28 :groups_users,
28 :groups_users,
29 :watchers,
29 :watchers,
30 :journals, :journal_details,
30 :journals, :journal_details,
31 :messages,
31 :messages,
32 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
32 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
33 :boards
33 :boards
34
34
35 include Redmine::I18n
35 include Redmine::I18n
36
36
37 def setup
37 def setup
38 @jsmith = Member.find(1)
38 @jsmith = Member.find(1)
39 end
39 end
40
40
41 def test_create
41 def test_create
42 member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
42 member = Member.new(:project_id => 1, :user_id => 4, :role_ids => [1, 2])
43 assert member.save
43 assert member.save
44 member.reload
44 member.reload
45
45
46 assert_equal 2, member.roles.size
46 assert_equal 2, member.roles.size
47 assert_equal Role.find(1), member.roles.sort.first
47 assert_equal Role.find(1), member.roles.sort.first
48 end
48 end
49
49
50 def test_update
50 def test_update
51 assert_equal "eCookbook", @jsmith.project.name
51 assert_equal "eCookbook", @jsmith.project.name
52 assert_equal "Manager", @jsmith.roles.first.name
52 assert_equal "Manager", @jsmith.roles.first.name
53 assert_equal "jsmith", @jsmith.user.login
53 assert_equal "jsmith", @jsmith.user.login
54
54
55 @jsmith.mail_notification = !@jsmith.mail_notification
55 @jsmith.mail_notification = !@jsmith.mail_notification
56 assert @jsmith.save
56 assert @jsmith.save
57 end
57 end
58
58
59 def test_update_roles
59 def test_update_roles
60 assert_equal 1, @jsmith.roles.size
60 assert_equal 1, @jsmith.roles.size
61 @jsmith.role_ids = [1, 2]
61 @jsmith.role_ids = [1, 2]
62 assert @jsmith.save
62 assert @jsmith.save
63 assert_equal 2, @jsmith.reload.roles.size
63 assert_equal 2, @jsmith.reload.roles.size
64 end
64 end
65
65
66 def test_validate
66 def test_validate
67 member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
67 member = Member.new(:project_id => 1, :user_id => 2, :role_ids => [2])
68 # same use cannot have more than one membership for a project
68 # same use cannot have more than one membership for a project
69 assert !member.save
69 assert !member.save
70
70
71 # must have one role at least
71 # must have one role at least
72 user = User.new(:firstname => "new1", :lastname => "user1",
72 user = User.new(:firstname => "new1", :lastname => "user1",
73 :mail => "test_validate@somenet.foo")
73 :mail => "test_validate@somenet.foo")
74 user.login = "test_validate"
74 user.login = "test_validate"
75 user.password, user.password_confirmation = "password", "password"
75 user.password, user.password_confirmation = "password", "password"
76 assert user.save
76 assert user.save
77
77
78 set_language_if_valid 'fr'
78 set_language_if_valid 'fr'
79 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
79 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [])
80 assert !member.save
80 assert !member.save
81 assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
81 assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role]
82 assert_equal "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8'),
82 assert_equal "R\xc3\xb4le doit \xc3\xaatre renseign\xc3\xa9(e)".force_encoding('UTF-8'),
83 [member.errors.full_messages].flatten.join
83 [member.errors.full_messages].flatten.join
84 end
84 end
85
85
86 def test_validate_member_role
86 def test_validate_member_role
87 user = User.new(:firstname => "new1", :lastname => "user1",
87 user = User.new(:firstname => "new1", :lastname => "user1",
88 :mail => "test_validate@somenet.foo")
88 :mail => "test_validate@somenet.foo")
89 user.login = "test_validate_member_role"
89 user.login = "test_validate_member_role"
90 user.password, user.password_confirmation = "password", "password"
90 user.password, user.password_confirmation = "password", "password"
91 assert user.save
91 assert user.save
92 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
92 member = Member.new(:project_id => 1, :user_id => user.id, :role_ids => [5])
93 assert !member.save
93 assert !member.save
94 end
94 end
95
95
96 def test_set_issue_category_nil_should_handle_nil_values
96 def test_set_issue_category_nil_should_handle_nil_values
97 m = Member.new
97 m = Member.new
98 assert_nil m.user
98 assert_nil m.user
99 assert_nil m.project
99 assert_nil m.project
100
100
101 assert_nothing_raised do
101 assert_nothing_raised do
102 m.set_issue_category_nil
102 m.set_issue_category_nil
103 end
103 end
104 end
104 end
105
105
106 def test_destroy
106 def test_destroy
107 category1 = IssueCategory.find(1)
107 category1 = IssueCategory.find(1)
108 assert_equal @jsmith.user.id, category1.assigned_to_id
108 assert_equal @jsmith.user.id, category1.assigned_to_id
109 assert_difference 'Member.count', -1 do
109 assert_difference 'Member.count', -1 do
110 assert_difference 'MemberRole.count', -1 do
110 assert_difference 'MemberRole.count', -1 do
111 @jsmith.destroy
111 @jsmith.destroy
112 end
112 end
113 end
113 end
114 assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
114 assert_raise(ActiveRecord::RecordNotFound) { Member.find(@jsmith.id) }
115 category1.reload
115 category1.reload
116 assert_nil category1.assigned_to_id
116 assert_nil category1.assigned_to_id
117 end
117 end
118
118
119 def test_destroy_should_trigger_callbacks_only_once
119 def test_destroy_should_trigger_callbacks_only_once
120 Member.class_eval { def destroy_test_callback; end}
120 Member.class_eval { def destroy_test_callback; end}
121 Member.after_destroy :destroy_test_callback
121 Member.after_destroy :destroy_test_callback
122
122
123 m = Member.create!(:user_id => 1, :project_id => 1, :role_ids => [1,3])
123 m = Member.create!(:user_id => 1, :project_id => 1, :role_ids => [1,3])
124
124
125 Member.any_instance.expects(:destroy_test_callback).once
125 Member.any_instance.expects(:destroy_test_callback).once
126 assert_difference 'Member.count', -1 do
126 assert_difference 'Member.count', -1 do
127 assert_difference 'MemberRole.count', -2 do
127 assert_difference 'MemberRole.count', -2 do
128 m.destroy
128 m.destroy
129 end
129 end
130 end
130 end
131 assert m.destroyed?
131 assert m.destroyed?
132 ensure
132 ensure
133 Member._destroy_callbacks.delete(:destroy_test_callback)
133 Member._destroy_callbacks.delete(:destroy_test_callback)
134 end
134 end
135
135
136 def test_roles_should_be_unique
137 m = Member.new(:user_id => 1, :project_id => 1)
138 m.member_roles.build(:role_id => 1)
139 m.member_roles.build(:role_id => 1)
140 m.save!
141 m.reload
142 assert_equal 1, m.roles.count
143 assert_equal [1], m.roles.ids
144 end
145
136 def test_sort_without_roles
146 def test_sort_without_roles
137 a = Member.new(:roles => [Role.first])
147 a = Member.new(:roles => [Role.first])
138 b = Member.new
148 b = Member.new
139
149
140 assert_equal -1, a <=> b
150 assert_equal -1, a <=> b
141 assert_equal 1, b <=> a
151 assert_equal 1, b <=> a
142 end
152 end
143
153
144 def test_sort_without_principal
154 def test_sort_without_principal
145 role = Role.first
155 role = Role.first
146 a = Member.new(:roles => [role], :principal => User.first)
156 a = Member.new(:roles => [role], :principal => User.first)
147 b = Member.new(:roles => [role])
157 b = Member.new(:roles => [role])
148
158
149 assert_equal -1, a <=> b
159 assert_equal -1, a <=> b
150 assert_equal 1, b <=> a
160 assert_equal 1, b <=> a
151 end
161 end
152 end
162 end
@@ -1,1216 +1,1228
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class UserTest < ActiveSupport::TestCase
20 class UserTest < ActiveSupport::TestCase
21 fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources,
21 fixtures :users, :email_addresses, :members, :projects, :roles, :member_roles, :auth_sources,
22 :trackers, :issue_statuses,
22 :trackers, :issue_statuses,
23 :projects_trackers,
23 :projects_trackers,
24 :watchers,
24 :watchers,
25 :issue_categories, :enumerations, :issues,
25 :issue_categories, :enumerations, :issues,
26 :journals, :journal_details,
26 :journals, :journal_details,
27 :groups_users,
27 :groups_users,
28 :enabled_modules
28 :enabled_modules
29
29
30 include Redmine::I18n
30 include Redmine::I18n
31
31
32 def setup
32 def setup
33 @admin = User.find(1)
33 @admin = User.find(1)
34 @jsmith = User.find(2)
34 @jsmith = User.find(2)
35 @dlopper = User.find(3)
35 @dlopper = User.find(3)
36 end
36 end
37
37
38 def test_sorted_scope_should_sort_user_by_display_name
38 def test_sorted_scope_should_sort_user_by_display_name
39 # Use .active to ignore anonymous with localized display name
39 # Use .active to ignore anonymous with localized display name
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
40 assert_equal User.active.map(&:name).map(&:downcase).sort,
41 User.active.sorted.map(&:name).map(&:downcase)
41 User.active.sorted.map(&:name).map(&:downcase)
42 end
42 end
43
43
44 def test_generate
44 def test_generate
45 User.generate!(:firstname => 'Testing connection')
45 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
46 User.generate!(:firstname => 'Testing connection')
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
47 assert_equal 2, User.where(:firstname => 'Testing connection').count
48 end
48 end
49
49
50 def test_truth
50 def test_truth
51 assert_kind_of User, @jsmith
51 assert_kind_of User, @jsmith
52 end
52 end
53
53
54 def test_mail_should_be_stripped
54 def test_mail_should_be_stripped
55 u = User.new
55 u = User.new
56 u.mail = " foo@bar.com "
56 u.mail = " foo@bar.com "
57 assert_equal "foo@bar.com", u.mail
57 assert_equal "foo@bar.com", u.mail
58 end
58 end
59
59
60 def test_should_create_email_address
60 def test_should_create_email_address
61 u = User.new(:firstname => "new", :lastname => "user")
61 u = User.new(:firstname => "new", :lastname => "user")
62 u.login = "create_email_address"
62 u.login = "create_email_address"
63 u.mail = "defaultemail@somenet.foo"
63 u.mail = "defaultemail@somenet.foo"
64 assert u.save
64 assert u.save
65 u.reload
65 u.reload
66 assert u.email_address
66 assert u.email_address
67 assert_equal "defaultemail@somenet.foo", u.email_address.address
67 assert_equal "defaultemail@somenet.foo", u.email_address.address
68 assert_equal true, u.email_address.is_default
68 assert_equal true, u.email_address.is_default
69 assert_equal true, u.email_address.notify
69 assert_equal true, u.email_address.notify
70 end
70 end
71
71
72 def test_should_not_create_user_without_mail
72 def test_should_not_create_user_without_mail
73 set_language_if_valid 'en'
73 set_language_if_valid 'en'
74 u = User.new(:firstname => "new", :lastname => "user")
74 u = User.new(:firstname => "new", :lastname => "user")
75 u.login = "user_without_mail"
75 u.login = "user_without_mail"
76 assert !u.save
76 assert !u.save
77 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
77 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
78 end
78 end
79
79
80 def test_should_not_create_user_with_blank_mail
80 def test_should_not_create_user_with_blank_mail
81 set_language_if_valid 'en'
81 set_language_if_valid 'en'
82 u = User.new(:firstname => "new", :lastname => "user")
82 u = User.new(:firstname => "new", :lastname => "user")
83 u.login = "user_with_blank_mail"
83 u.login = "user_with_blank_mail"
84 u.mail = ''
84 u.mail = ''
85 assert !u.save
85 assert !u.save
86 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
86 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
87 end
87 end
88
88
89 def test_should_not_update_user_with_blank_mail
89 def test_should_not_update_user_with_blank_mail
90 set_language_if_valid 'en'
90 set_language_if_valid 'en'
91 u = User.find(2)
91 u = User.find(2)
92 u.mail = ''
92 u.mail = ''
93 assert !u.save
93 assert !u.save
94 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
94 assert_equal ["Email #{I18n.translate('activerecord.errors.messages.blank')}"], u.errors.full_messages
95 end
95 end
96
96
97 def test_login_length_validation
97 def test_login_length_validation
98 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
98 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
99 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
99 user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
100 assert !user.valid?
100 assert !user.valid?
101
101
102 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
102 user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
103 assert user.valid?
103 assert user.valid?
104 assert user.save
104 assert user.save
105 end
105 end
106
106
107 def test_generate_password_should_respect_minimum_password_length
107 def test_generate_password_should_respect_minimum_password_length
108 with_settings :password_min_length => 15 do
108 with_settings :password_min_length => 15 do
109 user = User.generate!(:generate_password => true)
109 user = User.generate!(:generate_password => true)
110 assert user.password.length >= 15
110 assert user.password.length >= 15
111 end
111 end
112 end
112 end
113
113
114 def test_generate_password_should_not_generate_password_with_less_than_10_characters
114 def test_generate_password_should_not_generate_password_with_less_than_10_characters
115 with_settings :password_min_length => 4 do
115 with_settings :password_min_length => 4 do
116 user = User.generate!(:generate_password => true)
116 user = User.generate!(:generate_password => true)
117 assert user.password.length >= 10
117 assert user.password.length >= 10
118 end
118 end
119 end
119 end
120
120
121 def test_generate_password_on_create_should_set_password
121 def test_generate_password_on_create_should_set_password
122 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
122 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
123 user.login = "newuser"
123 user.login = "newuser"
124 user.generate_password = true
124 user.generate_password = true
125 assert user.save
125 assert user.save
126
126
127 password = user.password
127 password = user.password
128 assert user.check_password?(password)
128 assert user.check_password?(password)
129 end
129 end
130
130
131 def test_generate_password_on_update_should_update_password
131 def test_generate_password_on_update_should_update_password
132 user = User.find(2)
132 user = User.find(2)
133 hash = user.hashed_password
133 hash = user.hashed_password
134 user.generate_password = true
134 user.generate_password = true
135 assert user.save
135 assert user.save
136
136
137 password = user.password
137 password = user.password
138 assert user.check_password?(password)
138 assert user.check_password?(password)
139 assert_not_equal hash, user.reload.hashed_password
139 assert_not_equal hash, user.reload.hashed_password
140 end
140 end
141
141
142 def test_create
142 def test_create
143 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
143 user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
144
144
145 user.login = "jsmith"
145 user.login = "jsmith"
146 user.password, user.password_confirmation = "password", "password"
146 user.password, user.password_confirmation = "password", "password"
147 # login uniqueness
147 # login uniqueness
148 assert !user.save
148 assert !user.save
149 assert_equal 1, user.errors.count
149 assert_equal 1, user.errors.count
150
150
151 user.login = "newuser"
151 user.login = "newuser"
152 user.password, user.password_confirmation = "password", "pass"
152 user.password, user.password_confirmation = "password", "pass"
153 # password confirmation
153 # password confirmation
154 assert !user.save
154 assert !user.save
155 assert_equal 1, user.errors.count
155 assert_equal 1, user.errors.count
156
156
157 user.password, user.password_confirmation = "password", "password"
157 user.password, user.password_confirmation = "password", "password"
158 assert user.save
158 assert user.save
159 end
159 end
160
160
161 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
161 def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
162 @user1 = User.generate!
162 @user1 = User.generate!
163 assert_equal 'only_my_events', @user1.mail_notification
163 assert_equal 'only_my_events', @user1.mail_notification
164 with_settings :default_notification_option => 'all' do
164 with_settings :default_notification_option => 'all' do
165 @user2 = User.generate!
165 @user2 = User.generate!
166 assert_equal 'all', @user2.mail_notification
166 assert_equal 'all', @user2.mail_notification
167 end
167 end
168 end
168 end
169
169
170 def test_user_login_should_be_case_insensitive
170 def test_user_login_should_be_case_insensitive
171 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
171 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
172 u.login = 'newuser'
172 u.login = 'newuser'
173 u.password, u.password_confirmation = "password", "password"
173 u.password, u.password_confirmation = "password", "password"
174 assert u.save
174 assert u.save
175 u = User.new(:firstname => "Similar", :lastname => "User",
175 u = User.new(:firstname => "Similar", :lastname => "User",
176 :mail => "similaruser@somenet.foo")
176 :mail => "similaruser@somenet.foo")
177 u.login = 'NewUser'
177 u.login = 'NewUser'
178 u.password, u.password_confirmation = "password", "password"
178 u.password, u.password_confirmation = "password", "password"
179 assert !u.save
179 assert !u.save
180 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
180 assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
181 end
181 end
182
182
183 def test_mail_uniqueness_should_not_be_case_sensitive
183 def test_mail_uniqueness_should_not_be_case_sensitive
184 set_language_if_valid 'en'
184 set_language_if_valid 'en'
185 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
185 u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
186 u.login = 'newuser1'
186 u.login = 'newuser1'
187 u.password, u.password_confirmation = "password", "password"
187 u.password, u.password_confirmation = "password", "password"
188 assert u.save
188 assert u.save
189
189
190 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
190 u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
191 u.login = 'newuser2'
191 u.login = 'newuser2'
192 u.password, u.password_confirmation = "password", "password"
192 u.password, u.password_confirmation = "password", "password"
193 assert !u.save
193 assert !u.save
194 assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages
194 assert_include "Email #{I18n.translate('activerecord.errors.messages.taken')}", u.errors.full_messages
195 end
195 end
196
196
197 def test_update
197 def test_update
198 assert_equal "admin", @admin.login
198 assert_equal "admin", @admin.login
199 @admin.login = "john"
199 @admin.login = "john"
200 assert @admin.save, @admin.errors.full_messages.join("; ")
200 assert @admin.save, @admin.errors.full_messages.join("; ")
201 @admin.reload
201 @admin.reload
202 assert_equal "john", @admin.login
202 assert_equal "john", @admin.login
203 end
203 end
204
204
205 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
205 def test_update_should_not_fail_for_legacy_user_with_different_case_logins
206 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
206 u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
207 u1.login = 'newuser1'
207 u1.login = 'newuser1'
208 assert u1.save
208 assert u1.save
209
209
210 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
210 u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
211 u2.login = 'newuser1'
211 u2.login = 'newuser1'
212 assert u2.save(:validate => false)
212 assert u2.save(:validate => false)
213
213
214 user = User.find(u2.id)
214 user = User.find(u2.id)
215 user.firstname = "firstname"
215 user.firstname = "firstname"
216 assert user.save, "Save failed"
216 assert user.save, "Save failed"
217 end
217 end
218
218
219 def test_destroy_should_delete_members_and_roles
219 def test_destroy_should_delete_members_and_roles
220 members = Member.where(:user_id => 2)
220 members = Member.where(:user_id => 2)
221 ms = members.count
221 ms = members.count
222 rs = members.collect(&:roles).flatten.size
222 rs = members.collect(&:roles).flatten.size
223 assert ms > 0
223 assert ms > 0
224 assert rs > 0
224 assert rs > 0
225 assert_difference 'Member.count', - ms do
225 assert_difference 'Member.count', - ms do
226 assert_difference 'MemberRole.count', - rs do
226 assert_difference 'MemberRole.count', - rs do
227 User.find(2).destroy
227 User.find(2).destroy
228 end
228 end
229 end
229 end
230 assert_nil User.find_by_id(2)
230 assert_nil User.find_by_id(2)
231 assert_equal 0, Member.where(:user_id => 2).count
231 assert_equal 0, Member.where(:user_id => 2).count
232 end
232 end
233
233
234 def test_destroy_should_update_attachments
234 def test_destroy_should_update_attachments
235 attachment = Attachment.create!(:container => Project.find(1),
235 attachment = Attachment.create!(:container => Project.find(1),
236 :file => uploaded_test_file("testfile.txt", "text/plain"),
236 :file => uploaded_test_file("testfile.txt", "text/plain"),
237 :author_id => 2)
237 :author_id => 2)
238
238
239 User.find(2).destroy
239 User.find(2).destroy
240 assert_nil User.find_by_id(2)
240 assert_nil User.find_by_id(2)
241 assert_equal User.anonymous, attachment.reload.author
241 assert_equal User.anonymous, attachment.reload.author
242 end
242 end
243
243
244 def test_destroy_should_update_comments
244 def test_destroy_should_update_comments
245 comment = Comment.create!(
245 comment = Comment.create!(
246 :commented => News.create!(:project_id => 1,
246 :commented => News.create!(:project_id => 1,
247 :author_id => 1, :title => 'foo', :description => 'foo'),
247 :author_id => 1, :title => 'foo', :description => 'foo'),
248 :author => User.find(2),
248 :author => User.find(2),
249 :comments => 'foo'
249 :comments => 'foo'
250 )
250 )
251
251
252 User.find(2).destroy
252 User.find(2).destroy
253 assert_nil User.find_by_id(2)
253 assert_nil User.find_by_id(2)
254 assert_equal User.anonymous, comment.reload.author
254 assert_equal User.anonymous, comment.reload.author
255 end
255 end
256
256
257 def test_destroy_should_update_issues
257 def test_destroy_should_update_issues
258 issue = Issue.create!(:project_id => 1, :author_id => 2,
258 issue = Issue.create!(:project_id => 1, :author_id => 2,
259 :tracker_id => 1, :subject => 'foo')
259 :tracker_id => 1, :subject => 'foo')
260
260
261 User.find(2).destroy
261 User.find(2).destroy
262 assert_nil User.find_by_id(2)
262 assert_nil User.find_by_id(2)
263 assert_equal User.anonymous, issue.reload.author
263 assert_equal User.anonymous, issue.reload.author
264 end
264 end
265
265
266 def test_destroy_should_unassign_issues
266 def test_destroy_should_unassign_issues
267 issue = Issue.create!(:project_id => 1, :author_id => 1,
267 issue = Issue.create!(:project_id => 1, :author_id => 1,
268 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
268 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
269
269
270 User.find(2).destroy
270 User.find(2).destroy
271 assert_nil User.find_by_id(2)
271 assert_nil User.find_by_id(2)
272 assert_nil issue.reload.assigned_to
272 assert_nil issue.reload.assigned_to
273 end
273 end
274
274
275 def test_destroy_should_update_journals
275 def test_destroy_should_update_journals
276 issue = Issue.create!(:project_id => 1, :author_id => 2,
276 issue = Issue.create!(:project_id => 1, :author_id => 2,
277 :tracker_id => 1, :subject => 'foo')
277 :tracker_id => 1, :subject => 'foo')
278 issue.init_journal(User.find(2), "update")
278 issue.init_journal(User.find(2), "update")
279 issue.save!
279 issue.save!
280
280
281 User.find(2).destroy
281 User.find(2).destroy
282 assert_nil User.find_by_id(2)
282 assert_nil User.find_by_id(2)
283 assert_equal User.anonymous, issue.journals.first.reload.user
283 assert_equal User.anonymous, issue.journals.first.reload.user
284 end
284 end
285
285
286 def test_destroy_should_update_journal_details_old_value
286 def test_destroy_should_update_journal_details_old_value
287 issue = Issue.create!(:project_id => 1, :author_id => 1,
287 issue = Issue.create!(:project_id => 1, :author_id => 1,
288 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
288 :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
289 issue.init_journal(User.find(1), "update")
289 issue.init_journal(User.find(1), "update")
290 issue.assigned_to_id = nil
290 issue.assigned_to_id = nil
291 assert_difference 'JournalDetail.count' do
291 assert_difference 'JournalDetail.count' do
292 issue.save!
292 issue.save!
293 end
293 end
294 journal_detail = JournalDetail.order('id DESC').first
294 journal_detail = JournalDetail.order('id DESC').first
295 assert_equal '2', journal_detail.old_value
295 assert_equal '2', journal_detail.old_value
296
296
297 User.find(2).destroy
297 User.find(2).destroy
298 assert_nil User.find_by_id(2)
298 assert_nil User.find_by_id(2)
299 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
299 assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
300 end
300 end
301
301
302 def test_destroy_should_update_journal_details_value
302 def test_destroy_should_update_journal_details_value
303 issue = Issue.create!(:project_id => 1, :author_id => 1,
303 issue = Issue.create!(:project_id => 1, :author_id => 1,
304 :tracker_id => 1, :subject => 'foo')
304 :tracker_id => 1, :subject => 'foo')
305 issue.init_journal(User.find(1), "update")
305 issue.init_journal(User.find(1), "update")
306 issue.assigned_to_id = 2
306 issue.assigned_to_id = 2
307 assert_difference 'JournalDetail.count' do
307 assert_difference 'JournalDetail.count' do
308 issue.save!
308 issue.save!
309 end
309 end
310 journal_detail = JournalDetail.order('id DESC').first
310 journal_detail = JournalDetail.order('id DESC').first
311 assert_equal '2', journal_detail.value
311 assert_equal '2', journal_detail.value
312
312
313 User.find(2).destroy
313 User.find(2).destroy
314 assert_nil User.find_by_id(2)
314 assert_nil User.find_by_id(2)
315 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
315 assert_equal User.anonymous.id.to_s, journal_detail.reload.value
316 end
316 end
317
317
318 def test_destroy_should_update_messages
318 def test_destroy_should_update_messages
319 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
319 board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
320 message = Message.create!(:board_id => board.id, :author_id => 2,
320 message = Message.create!(:board_id => board.id, :author_id => 2,
321 :subject => 'foo', :content => 'foo')
321 :subject => 'foo', :content => 'foo')
322 User.find(2).destroy
322 User.find(2).destroy
323 assert_nil User.find_by_id(2)
323 assert_nil User.find_by_id(2)
324 assert_equal User.anonymous, message.reload.author
324 assert_equal User.anonymous, message.reload.author
325 end
325 end
326
326
327 def test_destroy_should_update_news
327 def test_destroy_should_update_news
328 news = News.create!(:project_id => 1, :author_id => 2,
328 news = News.create!(:project_id => 1, :author_id => 2,
329 :title => 'foo', :description => 'foo')
329 :title => 'foo', :description => 'foo')
330 User.find(2).destroy
330 User.find(2).destroy
331 assert_nil User.find_by_id(2)
331 assert_nil User.find_by_id(2)
332 assert_equal User.anonymous, news.reload.author
332 assert_equal User.anonymous, news.reload.author
333 end
333 end
334
334
335 def test_destroy_should_delete_private_queries
335 def test_destroy_should_delete_private_queries
336 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
336 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PRIVATE)
337 query.project_id = 1
337 query.project_id = 1
338 query.user_id = 2
338 query.user_id = 2
339 query.save!
339 query.save!
340
340
341 User.find(2).destroy
341 User.find(2).destroy
342 assert_nil User.find_by_id(2)
342 assert_nil User.find_by_id(2)
343 assert_nil Query.find_by_id(query.id)
343 assert_nil Query.find_by_id(query.id)
344 end
344 end
345
345
346 def test_destroy_should_update_public_queries
346 def test_destroy_should_update_public_queries
347 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
347 query = Query.new(:name => 'foo', :visibility => Query::VISIBILITY_PUBLIC)
348 query.project_id = 1
348 query.project_id = 1
349 query.user_id = 2
349 query.user_id = 2
350 query.save!
350 query.save!
351
351
352 User.find(2).destroy
352 User.find(2).destroy
353 assert_nil User.find_by_id(2)
353 assert_nil User.find_by_id(2)
354 assert_equal User.anonymous, query.reload.user
354 assert_equal User.anonymous, query.reload.user
355 end
355 end
356
356
357 def test_destroy_should_update_time_entries
357 def test_destroy_should_update_time_entries
358 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
358 entry = TimeEntry.new(:hours => '2', :spent_on => Date.today,
359 :activity => TimeEntryActivity.create!(:name => 'foo'))
359 :activity => TimeEntryActivity.create!(:name => 'foo'))
360 entry.project_id = 1
360 entry.project_id = 1
361 entry.user_id = 2
361 entry.user_id = 2
362 entry.save!
362 entry.save!
363
363
364 User.find(2).destroy
364 User.find(2).destroy
365 assert_nil User.find_by_id(2)
365 assert_nil User.find_by_id(2)
366 assert_equal User.anonymous, entry.reload.user
366 assert_equal User.anonymous, entry.reload.user
367 end
367 end
368
368
369 def test_destroy_should_delete_tokens
369 def test_destroy_should_delete_tokens
370 token = Token.create!(:user_id => 2, :value => 'foo')
370 token = Token.create!(:user_id => 2, :value => 'foo')
371
371
372 User.find(2).destroy
372 User.find(2).destroy
373 assert_nil User.find_by_id(2)
373 assert_nil User.find_by_id(2)
374 assert_nil Token.find_by_id(token.id)
374 assert_nil Token.find_by_id(token.id)
375 end
375 end
376
376
377 def test_destroy_should_delete_watchers
377 def test_destroy_should_delete_watchers
378 issue = Issue.create!(:project_id => 1, :author_id => 1,
378 issue = Issue.create!(:project_id => 1, :author_id => 1,
379 :tracker_id => 1, :subject => 'foo')
379 :tracker_id => 1, :subject => 'foo')
380 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
380 watcher = Watcher.create!(:user_id => 2, :watchable => issue)
381
381
382 User.find(2).destroy
382 User.find(2).destroy
383 assert_nil User.find_by_id(2)
383 assert_nil User.find_by_id(2)
384 assert_nil Watcher.find_by_id(watcher.id)
384 assert_nil Watcher.find_by_id(watcher.id)
385 end
385 end
386
386
387 def test_destroy_should_update_wiki_contents
387 def test_destroy_should_update_wiki_contents
388 wiki_content = WikiContent.create!(
388 wiki_content = WikiContent.create!(
389 :text => 'foo',
389 :text => 'foo',
390 :author_id => 2,
390 :author_id => 2,
391 :page => WikiPage.create!(:title => 'Foo',
391 :page => WikiPage.create!(:title => 'Foo',
392 :wiki => Wiki.create!(:project_id => 3,
392 :wiki => Wiki.create!(:project_id => 3,
393 :start_page => 'Start'))
393 :start_page => 'Start'))
394 )
394 )
395 wiki_content.text = 'bar'
395 wiki_content.text = 'bar'
396 assert_difference 'WikiContent::Version.count' do
396 assert_difference 'WikiContent::Version.count' do
397 wiki_content.save!
397 wiki_content.save!
398 end
398 end
399
399
400 User.find(2).destroy
400 User.find(2).destroy
401 assert_nil User.find_by_id(2)
401 assert_nil User.find_by_id(2)
402 assert_equal User.anonymous, wiki_content.reload.author
402 assert_equal User.anonymous, wiki_content.reload.author
403 wiki_content.versions.each do |version|
403 wiki_content.versions.each do |version|
404 assert_equal User.anonymous, version.reload.author
404 assert_equal User.anonymous, version.reload.author
405 end
405 end
406 end
406 end
407
407
408 def test_destroy_should_nullify_issue_categories
408 def test_destroy_should_nullify_issue_categories
409 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
409 category = IssueCategory.create!(:project_id => 1, :assigned_to_id => 2, :name => 'foo')
410
410
411 User.find(2).destroy
411 User.find(2).destroy
412 assert_nil User.find_by_id(2)
412 assert_nil User.find_by_id(2)
413 assert_nil category.reload.assigned_to_id
413 assert_nil category.reload.assigned_to_id
414 end
414 end
415
415
416 def test_destroy_should_nullify_changesets
416 def test_destroy_should_nullify_changesets
417 changeset = Changeset.create!(
417 changeset = Changeset.create!(
418 :repository => Repository::Subversion.create!(
418 :repository => Repository::Subversion.create!(
419 :project_id => 1,
419 :project_id => 1,
420 :url => 'file:///tmp',
420 :url => 'file:///tmp',
421 :identifier => 'tmp'
421 :identifier => 'tmp'
422 ),
422 ),
423 :revision => '12',
423 :revision => '12',
424 :committed_on => Time.now,
424 :committed_on => Time.now,
425 :committer => 'jsmith'
425 :committer => 'jsmith'
426 )
426 )
427 assert_equal 2, changeset.user_id
427 assert_equal 2, changeset.user_id
428
428
429 User.find(2).destroy
429 User.find(2).destroy
430 assert_nil User.find_by_id(2)
430 assert_nil User.find_by_id(2)
431 assert_nil changeset.reload.user_id
431 assert_nil changeset.reload.user_id
432 end
432 end
433
433
434 def test_anonymous_user_should_not_be_destroyable
434 def test_anonymous_user_should_not_be_destroyable
435 assert_no_difference 'User.count' do
435 assert_no_difference 'User.count' do
436 assert_equal false, User.anonymous.destroy
436 assert_equal false, User.anonymous.destroy
437 end
437 end
438 end
438 end
439
439
440 def test_password_change_should_destroy_tokens
440 def test_password_change_should_destroy_tokens
441 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
441 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
442 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
442 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
443
443
444 user = User.find(2)
444 user = User.find(2)
445 user.password, user.password_confirmation = "a new password", "a new password"
445 user.password, user.password_confirmation = "a new password", "a new password"
446 assert user.save
446 assert user.save
447
447
448 assert_nil Token.find_by_id(recovery_token.id)
448 assert_nil Token.find_by_id(recovery_token.id)
449 assert_nil Token.find_by_id(autologin_token.id)
449 assert_nil Token.find_by_id(autologin_token.id)
450 end
450 end
451
451
452 def test_mail_change_should_destroy_tokens
452 def test_mail_change_should_destroy_tokens
453 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
453 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
454 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
454 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
455
455
456 user = User.find(2)
456 user = User.find(2)
457 user.mail = "user@somwehere.com"
457 user.mail = "user@somwehere.com"
458 assert user.save
458 assert user.save
459
459
460 assert_nil Token.find_by_id(recovery_token.id)
460 assert_nil Token.find_by_id(recovery_token.id)
461 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
461 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
462 end
462 end
463
463
464 def test_change_on_other_fields_should_not_destroy_tokens
464 def test_change_on_other_fields_should_not_destroy_tokens
465 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
465 recovery_token = Token.create!(:user_id => 2, :action => 'recovery')
466 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
466 autologin_token = Token.create!(:user_id => 2, :action => 'autologin')
467
467
468 user = User.find(2)
468 user = User.find(2)
469 user.firstname = "Bobby"
469 user.firstname = "Bobby"
470 assert user.save
470 assert user.save
471
471
472 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
472 assert_equal recovery_token, Token.find_by_id(recovery_token.id)
473 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
473 assert_equal autologin_token, Token.find_by_id(autologin_token.id)
474 end
474 end
475
475
476 def test_validate_login_presence
476 def test_validate_login_presence
477 @admin.login = ""
477 @admin.login = ""
478 assert !@admin.save
478 assert !@admin.save
479 assert_equal 1, @admin.errors.count
479 assert_equal 1, @admin.errors.count
480 end
480 end
481
481
482 def test_validate_mail_notification_inclusion
482 def test_validate_mail_notification_inclusion
483 u = User.new
483 u = User.new
484 u.mail_notification = 'foo'
484 u.mail_notification = 'foo'
485 u.save
485 u.save
486 assert_not_equal [], u.errors[:mail_notification]
486 assert_not_equal [], u.errors[:mail_notification]
487 end
487 end
488
488
489 def test_password
489 def test_password
490 user = User.try_to_login("admin", "admin")
490 user = User.try_to_login("admin", "admin")
491 assert_kind_of User, user
491 assert_kind_of User, user
492 assert_equal "admin", user.login
492 assert_equal "admin", user.login
493 user.password = "hello123"
493 user.password = "hello123"
494 assert user.save
494 assert user.save
495
495
496 user = User.try_to_login("admin", "hello123")
496 user = User.try_to_login("admin", "hello123")
497 assert_kind_of User, user
497 assert_kind_of User, user
498 assert_equal "admin", user.login
498 assert_equal "admin", user.login
499 end
499 end
500
500
501 def test_validate_password_length
501 def test_validate_password_length
502 with_settings :password_min_length => '100' do
502 with_settings :password_min_length => '100' do
503 user = User.new(:firstname => "new100",
503 user = User.new(:firstname => "new100",
504 :lastname => "user100", :mail => "newuser100@somenet.foo")
504 :lastname => "user100", :mail => "newuser100@somenet.foo")
505 user.login = "newuser100"
505 user.login = "newuser100"
506 user.password, user.password_confirmation = "password100", "password100"
506 user.password, user.password_confirmation = "password100", "password100"
507 assert !user.save
507 assert !user.save
508 assert_equal 1, user.errors.count
508 assert_equal 1, user.errors.count
509 end
509 end
510 end
510 end
511
511
512 def test_name_format
512 def test_name_format
513 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
513 assert_equal 'John S.', @jsmith.name(:firstname_lastinitial)
514 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
514 assert_equal 'Smith, John', @jsmith.name(:lastname_coma_firstname)
515 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
515 assert_equal 'J. Smith', @jsmith.name(:firstinitial_lastname)
516 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
516 assert_equal 'J.-P. Lang', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').name(:firstinitial_lastname)
517 end
517 end
518
518
519 def test_name_should_use_setting_as_default_format
519 def test_name_should_use_setting_as_default_format
520 with_settings :user_format => :firstname_lastname do
520 with_settings :user_format => :firstname_lastname do
521 assert_equal 'John Smith', @jsmith.reload.name
521 assert_equal 'John Smith', @jsmith.reload.name
522 end
522 end
523 with_settings :user_format => :username do
523 with_settings :user_format => :username do
524 assert_equal 'jsmith', @jsmith.reload.name
524 assert_equal 'jsmith', @jsmith.reload.name
525 end
525 end
526 with_settings :user_format => :lastname do
526 with_settings :user_format => :lastname do
527 assert_equal 'Smith', @jsmith.reload.name
527 assert_equal 'Smith', @jsmith.reload.name
528 end
528 end
529 end
529 end
530
530
531 def test_today_should_return_the_day_according_to_user_time_zone
531 def test_today_should_return_the_day_according_to_user_time_zone
532 preference = User.find(1).pref
532 preference = User.find(1).pref
533 date = Date.new(2012, 05, 15)
533 date = Date.new(2012, 05, 15)
534 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
534 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
535 Date.stubs(:today).returns(date)
535 Date.stubs(:today).returns(date)
536 Time.stubs(:now).returns(time)
536 Time.stubs(:now).returns(time)
537
537
538 preference.update_attribute :time_zone, 'Baku' # UTC+4
538 preference.update_attribute :time_zone, 'Baku' # UTC+4
539 assert_equal '2012-05-16', User.find(1).today.to_s
539 assert_equal '2012-05-16', User.find(1).today.to_s
540
540
541 preference.update_attribute :time_zone, 'La Paz' # UTC-4
541 preference.update_attribute :time_zone, 'La Paz' # UTC-4
542 assert_equal '2012-05-15', User.find(1).today.to_s
542 assert_equal '2012-05-15', User.find(1).today.to_s
543
543
544 preference.update_attribute :time_zone, ''
544 preference.update_attribute :time_zone, ''
545 assert_equal '2012-05-15', User.find(1).today.to_s
545 assert_equal '2012-05-15', User.find(1).today.to_s
546 end
546 end
547
547
548 def test_time_to_date_should_return_the_date_according_to_user_time_zone
548 def test_time_to_date_should_return_the_date_according_to_user_time_zone
549 preference = User.find(1).pref
549 preference = User.find(1).pref
550 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
550 time = Time.gm(2012, 05, 15, 23, 30).utc # 2012-05-15 23:30 UTC
551
551
552 preference.update_attribute :time_zone, 'Baku' # UTC+4
552 preference.update_attribute :time_zone, 'Baku' # UTC+4
553 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
553 assert_equal '2012-05-16', User.find(1).time_to_date(time).to_s
554
554
555 preference.update_attribute :time_zone, 'La Paz' # UTC-4
555 preference.update_attribute :time_zone, 'La Paz' # UTC-4
556 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
556 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
557
557
558 preference.update_attribute :time_zone, ''
558 preference.update_attribute :time_zone, ''
559 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
559 assert_equal '2012-05-15', User.find(1).time_to_date(time).to_s
560 end
560 end
561
561
562 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
562 def test_fields_for_order_statement_should_return_fields_according_user_format_setting
563 with_settings :user_format => 'lastname_coma_firstname' do
563 with_settings :user_format => 'lastname_coma_firstname' do
564 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
564 assert_equal ['users.lastname', 'users.firstname', 'users.id'],
565 User.fields_for_order_statement
565 User.fields_for_order_statement
566 end
566 end
567 end
567 end
568
568
569 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
569 def test_fields_for_order_statement_width_table_name_should_prepend_table_name
570 with_settings :user_format => 'lastname_firstname' do
570 with_settings :user_format => 'lastname_firstname' do
571 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
571 assert_equal ['authors.lastname', 'authors.firstname', 'authors.id'],
572 User.fields_for_order_statement('authors')
572 User.fields_for_order_statement('authors')
573 end
573 end
574 end
574 end
575
575
576 def test_fields_for_order_statement_with_blank_format_should_return_default
576 def test_fields_for_order_statement_with_blank_format_should_return_default
577 with_settings :user_format => '' do
577 with_settings :user_format => '' do
578 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
578 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
579 User.fields_for_order_statement
579 User.fields_for_order_statement
580 end
580 end
581 end
581 end
582
582
583 def test_fields_for_order_statement_with_invalid_format_should_return_default
583 def test_fields_for_order_statement_with_invalid_format_should_return_default
584 with_settings :user_format => 'foo' do
584 with_settings :user_format => 'foo' do
585 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
585 assert_equal ['users.firstname', 'users.lastname', 'users.id'],
586 User.fields_for_order_statement
586 User.fields_for_order_statement
587 end
587 end
588 end
588 end
589
589
590 test ".try_to_login with good credentials should return the user" do
590 test ".try_to_login with good credentials should return the user" do
591 user = User.try_to_login("admin", "admin")
591 user = User.try_to_login("admin", "admin")
592 assert_kind_of User, user
592 assert_kind_of User, user
593 assert_equal "admin", user.login
593 assert_equal "admin", user.login
594 end
594 end
595
595
596 test ".try_to_login with wrong credentials should return nil" do
596 test ".try_to_login with wrong credentials should return nil" do
597 assert_nil User.try_to_login("admin", "foo")
597 assert_nil User.try_to_login("admin", "foo")
598 end
598 end
599
599
600 def test_try_to_login_with_locked_user_should_return_nil
600 def test_try_to_login_with_locked_user_should_return_nil
601 @jsmith.status = User::STATUS_LOCKED
601 @jsmith.status = User::STATUS_LOCKED
602 @jsmith.save!
602 @jsmith.save!
603
603
604 user = User.try_to_login("jsmith", "jsmith")
604 user = User.try_to_login("jsmith", "jsmith")
605 assert_equal nil, user
605 assert_equal nil, user
606 end
606 end
607
607
608 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
608 def test_try_to_login_with_locked_user_and_not_active_only_should_return_user
609 @jsmith.status = User::STATUS_LOCKED
609 @jsmith.status = User::STATUS_LOCKED
610 @jsmith.save!
610 @jsmith.save!
611
611
612 user = User.try_to_login("jsmith", "jsmith", false)
612 user = User.try_to_login("jsmith", "jsmith", false)
613 assert_equal @jsmith, user
613 assert_equal @jsmith, user
614 end
614 end
615
615
616 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
616 test ".try_to_login should fall-back to case-insensitive if user login is not found as-typed" do
617 user = User.try_to_login("AdMin", "admin")
617 user = User.try_to_login("AdMin", "admin")
618 assert_kind_of User, user
618 assert_kind_of User, user
619 assert_equal "admin", user.login
619 assert_equal "admin", user.login
620 end
620 end
621
621
622 test ".try_to_login should select the exact matching user first" do
622 test ".try_to_login should select the exact matching user first" do
623 case_sensitive_user = User.generate! do |user|
623 case_sensitive_user = User.generate! do |user|
624 user.password = "admin123"
624 user.password = "admin123"
625 end
625 end
626 # bypass validations to make it appear like existing data
626 # bypass validations to make it appear like existing data
627 case_sensitive_user.update_attribute(:login, 'ADMIN')
627 case_sensitive_user.update_attribute(:login, 'ADMIN')
628
628
629 user = User.try_to_login("ADMIN", "admin123")
629 user = User.try_to_login("ADMIN", "admin123")
630 assert_kind_of User, user
630 assert_kind_of User, user
631 assert_equal "ADMIN", user.login
631 assert_equal "ADMIN", user.login
632 end
632 end
633
633
634 if ldap_configured?
634 if ldap_configured?
635 test "#try_to_login using LDAP with failed connection to the LDAP server" do
635 test "#try_to_login using LDAP with failed connection to the LDAP server" do
636 auth_source = AuthSourceLdap.find(1)
636 auth_source = AuthSourceLdap.find(1)
637 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
637 AuthSource.any_instance.stubs(:initialize_ldap_con).raises(Net::LDAP::LdapError, 'Cannot connect')
638
638
639 assert_equal nil, User.try_to_login('edavis', 'wrong')
639 assert_equal nil, User.try_to_login('edavis', 'wrong')
640 end
640 end
641
641
642 test "#try_to_login using LDAP" do
642 test "#try_to_login using LDAP" do
643 assert_equal nil, User.try_to_login('edavis', 'wrong')
643 assert_equal nil, User.try_to_login('edavis', 'wrong')
644 end
644 end
645
645
646 test "#try_to_login using LDAP binding with user's account" do
646 test "#try_to_login using LDAP binding with user's account" do
647 auth_source = AuthSourceLdap.find(1)
647 auth_source = AuthSourceLdap.find(1)
648 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
648 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
649 auth_source.account_password = ''
649 auth_source.account_password = ''
650 auth_source.save!
650 auth_source.save!
651
651
652 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
652 ldap_user = User.new(:mail => 'example1@redmine.org', :firstname => 'LDAP', :lastname => 'user', :auth_source_id => 1)
653 ldap_user.login = 'example1'
653 ldap_user.login = 'example1'
654 ldap_user.save!
654 ldap_user.save!
655
655
656 assert_equal ldap_user, User.try_to_login('example1', '123456')
656 assert_equal ldap_user, User.try_to_login('example1', '123456')
657 assert_nil User.try_to_login('example1', '11111')
657 assert_nil User.try_to_login('example1', '11111')
658 end
658 end
659
659
660 test "#try_to_login using LDAP on the fly registration" do
660 test "#try_to_login using LDAP on the fly registration" do
661 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
661 AuthSourceLdap.find(1).update_attribute :onthefly_register, true
662
662
663 assert_difference('User.count') do
663 assert_difference('User.count') do
664 assert User.try_to_login('edavis', '123456')
664 assert User.try_to_login('edavis', '123456')
665 end
665 end
666
666
667 assert_no_difference('User.count') do
667 assert_no_difference('User.count') do
668 assert User.try_to_login('edavis', '123456')
668 assert User.try_to_login('edavis', '123456')
669 end
669 end
670
670
671 assert_nil User.try_to_login('example1', '11111')
671 assert_nil User.try_to_login('example1', '11111')
672 end
672 end
673
673
674 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
674 test "#try_to_login using LDAP on the fly registration and binding with user's account" do
675 auth_source = AuthSourceLdap.find(1)
675 auth_source = AuthSourceLdap.find(1)
676 auth_source.update_attribute :onthefly_register, true
676 auth_source.update_attribute :onthefly_register, true
677 auth_source = AuthSourceLdap.find(1)
677 auth_source = AuthSourceLdap.find(1)
678 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
678 auth_source.account = "uid=$login,ou=Person,dc=redmine,dc=org"
679 auth_source.account_password = ''
679 auth_source.account_password = ''
680 auth_source.save!
680 auth_source.save!
681
681
682 assert_difference('User.count') do
682 assert_difference('User.count') do
683 assert User.try_to_login('example1', '123456')
683 assert User.try_to_login('example1', '123456')
684 end
684 end
685
685
686 assert_no_difference('User.count') do
686 assert_no_difference('User.count') do
687 assert User.try_to_login('example1', '123456')
687 assert User.try_to_login('example1', '123456')
688 end
688 end
689
689
690 assert_nil User.try_to_login('example1', '11111')
690 assert_nil User.try_to_login('example1', '11111')
691 end
691 end
692
692
693 else
693 else
694 puts "Skipping LDAP tests."
694 puts "Skipping LDAP tests."
695 end
695 end
696
696
697 def test_create_anonymous
697 def test_create_anonymous
698 AnonymousUser.delete_all
698 AnonymousUser.delete_all
699 anon = User.anonymous
699 anon = User.anonymous
700 assert !anon.new_record?
700 assert !anon.new_record?
701 assert_kind_of AnonymousUser, anon
701 assert_kind_of AnonymousUser, anon
702 end
702 end
703
703
704 def test_ensure_single_anonymous_user
704 def test_ensure_single_anonymous_user
705 AnonymousUser.delete_all
705 AnonymousUser.delete_all
706 anon1 = User.anonymous
706 anon1 = User.anonymous
707 assert !anon1.new_record?
707 assert !anon1.new_record?
708 assert_kind_of AnonymousUser, anon1
708 assert_kind_of AnonymousUser, anon1
709 anon2 = AnonymousUser.create(
709 anon2 = AnonymousUser.create(
710 :lastname => 'Anonymous', :firstname => '',
710 :lastname => 'Anonymous', :firstname => '',
711 :login => '', :status => 0)
711 :login => '', :status => 0)
712 assert_equal 1, anon2.errors.count
712 assert_equal 1, anon2.errors.count
713 end
713 end
714
714
715 def test_rss_key
715 def test_rss_key
716 assert_nil @jsmith.rss_token
716 assert_nil @jsmith.rss_token
717 key = @jsmith.rss_key
717 key = @jsmith.rss_key
718 assert_equal 40, key.length
718 assert_equal 40, key.length
719
719
720 @jsmith.reload
720 @jsmith.reload
721 assert_equal key, @jsmith.rss_key
721 assert_equal key, @jsmith.rss_key
722 end
722 end
723
723
724 def test_rss_key_should_not_be_generated_twice
724 def test_rss_key_should_not_be_generated_twice
725 assert_difference 'Token.count', 1 do
725 assert_difference 'Token.count', 1 do
726 key1 = @jsmith.rss_key
726 key1 = @jsmith.rss_key
727 key2 = @jsmith.rss_key
727 key2 = @jsmith.rss_key
728 assert_equal key1, key2
728 assert_equal key1, key2
729 end
729 end
730 end
730 end
731
731
732 def test_api_key_should_not_be_generated_twice
732 def test_api_key_should_not_be_generated_twice
733 assert_difference 'Token.count', 1 do
733 assert_difference 'Token.count', 1 do
734 key1 = @jsmith.api_key
734 key1 = @jsmith.api_key
735 key2 = @jsmith.api_key
735 key2 = @jsmith.api_key
736 assert_equal key1, key2
736 assert_equal key1, key2
737 end
737 end
738 end
738 end
739
739
740 test "#api_key should generate a new one if the user doesn't have one" do
740 test "#api_key should generate a new one if the user doesn't have one" do
741 user = User.generate!(:api_token => nil)
741 user = User.generate!(:api_token => nil)
742 assert_nil user.api_token
742 assert_nil user.api_token
743
743
744 key = user.api_key
744 key = user.api_key
745 assert_equal 40, key.length
745 assert_equal 40, key.length
746 user.reload
746 user.reload
747 assert_equal key, user.api_key
747 assert_equal key, user.api_key
748 end
748 end
749
749
750 test "#api_key should return the existing api token value" do
750 test "#api_key should return the existing api token value" do
751 user = User.generate!
751 user = User.generate!
752 token = Token.create!(:action => 'api')
752 token = Token.create!(:action => 'api')
753 user.api_token = token
753 user.api_token = token
754 assert user.save
754 assert user.save
755
755
756 assert_equal token.value, user.api_key
756 assert_equal token.value, user.api_key
757 end
757 end
758
758
759 test "#find_by_api_key should return nil if no matching key is found" do
759 test "#find_by_api_key should return nil if no matching key is found" do
760 assert_nil User.find_by_api_key('zzzzzzzzz')
760 assert_nil User.find_by_api_key('zzzzzzzzz')
761 end
761 end
762
762
763 test "#find_by_api_key should return nil if the key is found for an inactive user" do
763 test "#find_by_api_key should return nil if the key is found for an inactive user" do
764 user = User.generate!
764 user = User.generate!
765 user.status = User::STATUS_LOCKED
765 user.status = User::STATUS_LOCKED
766 token = Token.create!(:action => 'api')
766 token = Token.create!(:action => 'api')
767 user.api_token = token
767 user.api_token = token
768 user.save
768 user.save
769
769
770 assert_nil User.find_by_api_key(token.value)
770 assert_nil User.find_by_api_key(token.value)
771 end
771 end
772
772
773 test "#find_by_api_key should return the user if the key is found for an active user" do
773 test "#find_by_api_key should return the user if the key is found for an active user" do
774 user = User.generate!
774 user = User.generate!
775 token = Token.create!(:action => 'api')
775 token = Token.create!(:action => 'api')
776 user.api_token = token
776 user.api_token = token
777 user.save
777 user.save
778
778
779 assert_equal user, User.find_by_api_key(token.value)
779 assert_equal user, User.find_by_api_key(token.value)
780 end
780 end
781
781
782 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
782 def test_default_admin_account_changed_should_return_false_if_account_was_not_changed
783 user = User.find_by_login("admin")
783 user = User.find_by_login("admin")
784 user.password = "admin"
784 user.password = "admin"
785 assert user.save(:validate => false)
785 assert user.save(:validate => false)
786
786
787 assert_equal false, User.default_admin_account_changed?
787 assert_equal false, User.default_admin_account_changed?
788 end
788 end
789
789
790 def test_default_admin_account_changed_should_return_true_if_password_was_changed
790 def test_default_admin_account_changed_should_return_true_if_password_was_changed
791 user = User.find_by_login("admin")
791 user = User.find_by_login("admin")
792 user.password = "newpassword"
792 user.password = "newpassword"
793 user.save!
793 user.save!
794
794
795 assert_equal true, User.default_admin_account_changed?
795 assert_equal true, User.default_admin_account_changed?
796 end
796 end
797
797
798 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
798 def test_default_admin_account_changed_should_return_true_if_account_is_disabled
799 user = User.find_by_login("admin")
799 user = User.find_by_login("admin")
800 user.password = "admin"
800 user.password = "admin"
801 user.status = User::STATUS_LOCKED
801 user.status = User::STATUS_LOCKED
802 assert user.save(:validate => false)
802 assert user.save(:validate => false)
803
803
804 assert_equal true, User.default_admin_account_changed?
804 assert_equal true, User.default_admin_account_changed?
805 end
805 end
806
806
807 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
807 def test_default_admin_account_changed_should_return_true_if_account_does_not_exist
808 user = User.find_by_login("admin")
808 user = User.find_by_login("admin")
809 user.destroy
809 user.destroy
810
810
811 assert_equal true, User.default_admin_account_changed?
811 assert_equal true, User.default_admin_account_changed?
812 end
812 end
813
813
814 def test_membership_with_project_should_return_membership
814 def test_membership_with_project_should_return_membership
815 project = Project.find(1)
815 project = Project.find(1)
816
816
817 membership = @jsmith.membership(project)
817 membership = @jsmith.membership(project)
818 assert_kind_of Member, membership
818 assert_kind_of Member, membership
819 assert_equal @jsmith, membership.user
819 assert_equal @jsmith, membership.user
820 assert_equal project, membership.project
820 assert_equal project, membership.project
821 end
821 end
822
822
823 def test_membership_with_project_id_should_return_membership
823 def test_membership_with_project_id_should_return_membership
824 project = Project.find(1)
824 project = Project.find(1)
825
825
826 membership = @jsmith.membership(1)
826 membership = @jsmith.membership(1)
827 assert_kind_of Member, membership
827 assert_kind_of Member, membership
828 assert_equal @jsmith, membership.user
828 assert_equal @jsmith, membership.user
829 assert_equal project, membership.project
829 assert_equal project, membership.project
830 end
830 end
831
831
832 def test_membership_for_non_member_should_return_nil
832 def test_membership_for_non_member_should_return_nil
833 project = Project.find(1)
833 project = Project.find(1)
834
834
835 user = User.generate!
835 user = User.generate!
836 membership = user.membership(1)
836 membership = user.membership(1)
837 assert_nil membership
837 assert_nil membership
838 end
838 end
839
839
840 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
840 def test_roles_for_project_with_member_on_public_project_should_return_roles_and_non_member
841 roles = @jsmith.roles_for_project(Project.find(1))
841 roles = @jsmith.roles_for_project(Project.find(1))
842 assert_kind_of Role, roles.first
842 assert_kind_of Role, roles.first
843 assert_equal ["Manager"], roles.map(&:name)
843 assert_equal ["Manager"], roles.map(&:name)
844 end
844 end
845
845
846 def test_roles_for_project_with_member_on_private_project_should_return_roles
846 def test_roles_for_project_with_member_on_private_project_should_return_roles
847 Project.find(1).update_attribute :is_public, false
847 Project.find(1).update_attribute :is_public, false
848
848
849 roles = @jsmith.roles_for_project(Project.find(1))
849 roles = @jsmith.roles_for_project(Project.find(1))
850 assert_kind_of Role, roles.first
850 assert_kind_of Role, roles.first
851 assert_equal ["Manager"], roles.map(&:name)
851 assert_equal ["Manager"], roles.map(&:name)
852 end
852 end
853
853
854 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
854 def test_roles_for_project_with_non_member_with_public_project_should_return_non_member
855 set_language_if_valid 'en'
855 set_language_if_valid 'en'
856 roles = User.find(8).roles_for_project(Project.find(1))
856 roles = User.find(8).roles_for_project(Project.find(1))
857 assert_equal ["Non member"], roles.map(&:name)
857 assert_equal ["Non member"], roles.map(&:name)
858 end
858 end
859
859
860 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
860 def test_roles_for_project_with_non_member_with_public_project_and_override_should_return_override_roles
861 project = Project.find(1)
861 project = Project.find(1)
862 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
862 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
863 roles = User.find(8).roles_for_project(project)
863 roles = User.find(8).roles_for_project(project)
864 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
864 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
865 end
865 end
866
866
867 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
867 def test_roles_for_project_with_non_member_with_private_project_should_return_no_roles
868 Project.find(1).update_attribute :is_public, false
868 Project.find(1).update_attribute :is_public, false
869
869
870 roles = User.find(8).roles_for_project(Project.find(1))
870 roles = User.find(8).roles_for_project(Project.find(1))
871 assert_equal [], roles.map(&:name)
871 assert_equal [], roles.map(&:name)
872 end
872 end
873
873
874 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
874 def test_roles_for_project_with_non_member_with_private_project_and_override_should_return_no_roles
875 project = Project.find(1)
875 project = Project.find(1)
876 project.update_attribute :is_public, false
876 project.update_attribute :is_public, false
877 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
877 Member.create!(:project => project, :principal => Group.non_member, :role_ids => [1, 2])
878 roles = User.find(8).roles_for_project(project)
878 roles = User.find(8).roles_for_project(project)
879 assert_equal [], roles.map(&:name).sort
879 assert_equal [], roles.map(&:name).sort
880 end
880 end
881
881
882 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
882 def test_roles_for_project_with_anonymous_with_public_project_should_return_anonymous
883 set_language_if_valid 'en'
883 set_language_if_valid 'en'
884 roles = User.anonymous.roles_for_project(Project.find(1))
884 roles = User.anonymous.roles_for_project(Project.find(1))
885 assert_equal ["Anonymous"], roles.map(&:name)
885 assert_equal ["Anonymous"], roles.map(&:name)
886 end
886 end
887
887
888 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
888 def test_roles_for_project_with_anonymous_with_public_project_and_override_should_return_override_roles
889 project = Project.find(1)
889 project = Project.find(1)
890 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
890 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
891 roles = User.anonymous.roles_for_project(project)
891 roles = User.anonymous.roles_for_project(project)
892 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
892 assert_equal ["Developer", "Manager"], roles.map(&:name).sort
893 end
893 end
894
894
895 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
895 def test_roles_for_project_with_anonymous_with_private_project_should_return_no_roles
896 Project.find(1).update_attribute :is_public, false
896 Project.find(1).update_attribute :is_public, false
897
897
898 roles = User.anonymous.roles_for_project(Project.find(1))
898 roles = User.anonymous.roles_for_project(Project.find(1))
899 assert_equal [], roles.map(&:name)
899 assert_equal [], roles.map(&:name)
900 end
900 end
901
901
902 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
902 def test_roles_for_project_with_anonymous_with_private_project_and_override_should_return_no_roles
903 project = Project.find(1)
903 project = Project.find(1)
904 project.update_attribute :is_public, false
904 project.update_attribute :is_public, false
905 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
905 Member.create!(:project => project, :principal => Group.anonymous, :role_ids => [1, 2])
906 roles = User.anonymous.roles_for_project(project)
906 roles = User.anonymous.roles_for_project(project)
907 assert_equal [], roles.map(&:name).sort
907 assert_equal [], roles.map(&:name).sort
908 end
908 end
909
909
910 def test_roles_for_project_should_be_unique
911 m = Member.new(:user_id => 1, :project_id => 1)
912 m.member_roles.build(:role_id => 1)
913 m.member_roles.build(:role_id => 1)
914 m.save!
915
916 user = User.find(1)
917 project = Project.find(1)
918 assert_equal 1, user.roles_for_project(project).size
919 assert_equal [1], user.roles_for_project(project).map(&:id)
920 end
921
910 def test_projects_by_role_for_user_with_role
922 def test_projects_by_role_for_user_with_role
911 user = User.find(2)
923 user = User.find(2)
912 assert_kind_of Hash, user.projects_by_role
924 assert_kind_of Hash, user.projects_by_role
913 assert_equal 2, user.projects_by_role.size
925 assert_equal 2, user.projects_by_role.size
914 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
926 assert_equal [1,5], user.projects_by_role[Role.find(1)].collect(&:id).sort
915 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
927 assert_equal [2], user.projects_by_role[Role.find(2)].collect(&:id).sort
916 end
928 end
917
929
918 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
930 def test_accessing_projects_by_role_with_no_projects_should_return_an_empty_array
919 user = User.find(2)
931 user = User.find(2)
920 assert_equal [], user.projects_by_role[Role.find(3)]
932 assert_equal [], user.projects_by_role[Role.find(3)]
921 # should not update the hash
933 # should not update the hash
922 assert_nil user.projects_by_role.values.detect(&:blank?)
934 assert_nil user.projects_by_role.values.detect(&:blank?)
923 end
935 end
924
936
925 def test_projects_by_role_for_user_with_no_role
937 def test_projects_by_role_for_user_with_no_role
926 user = User.generate!
938 user = User.generate!
927 assert_equal({}, user.projects_by_role)
939 assert_equal({}, user.projects_by_role)
928 end
940 end
929
941
930 def test_projects_by_role_for_anonymous
942 def test_projects_by_role_for_anonymous
931 assert_equal({}, User.anonymous.projects_by_role)
943 assert_equal({}, User.anonymous.projects_by_role)
932 end
944 end
933
945
934 def test_valid_notification_options
946 def test_valid_notification_options
935 # without memberships
947 # without memberships
936 assert_equal 5, User.find(7).valid_notification_options.size
948 assert_equal 5, User.find(7).valid_notification_options.size
937 # with memberships
949 # with memberships
938 assert_equal 6, User.find(2).valid_notification_options.size
950 assert_equal 6, User.find(2).valid_notification_options.size
939 end
951 end
940
952
941 def test_valid_notification_options_class_method
953 def test_valid_notification_options_class_method
942 assert_equal 5, User.valid_notification_options.size
954 assert_equal 5, User.valid_notification_options.size
943 assert_equal 5, User.valid_notification_options(User.find(7)).size
955 assert_equal 5, User.valid_notification_options(User.find(7)).size
944 assert_equal 6, User.valid_notification_options(User.find(2)).size
956 assert_equal 6, User.valid_notification_options(User.find(2)).size
945 end
957 end
946
958
947 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
959 def test_notified_project_ids_setter_should_coerce_to_unique_integer_array
948 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
960 @jsmith.notified_project_ids = ["1", "123", "2u", "wrong", "12", 6, 12, -35, ""]
949 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
961 assert_equal [1, 123, 2, 12, 6], @jsmith.notified_projects_ids
950 end
962 end
951
963
952 def test_mail_notification_all
964 def test_mail_notification_all
953 @jsmith.mail_notification = 'all'
965 @jsmith.mail_notification = 'all'
954 @jsmith.notified_project_ids = []
966 @jsmith.notified_project_ids = []
955 @jsmith.save
967 @jsmith.save
956 @jsmith.reload
968 @jsmith.reload
957 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
969 assert @jsmith.projects.first.recipients.include?(@jsmith.mail)
958 end
970 end
959
971
960 def test_mail_notification_selected
972 def test_mail_notification_selected
961 @jsmith.mail_notification = 'selected'
973 @jsmith.mail_notification = 'selected'
962 @jsmith.notified_project_ids = [1]
974 @jsmith.notified_project_ids = [1]
963 @jsmith.save
975 @jsmith.save
964 @jsmith.reload
976 @jsmith.reload
965 assert Project.find(1).recipients.include?(@jsmith.mail)
977 assert Project.find(1).recipients.include?(@jsmith.mail)
966 end
978 end
967
979
968 def test_mail_notification_only_my_events
980 def test_mail_notification_only_my_events
969 @jsmith.mail_notification = 'only_my_events'
981 @jsmith.mail_notification = 'only_my_events'
970 @jsmith.notified_project_ids = []
982 @jsmith.notified_project_ids = []
971 @jsmith.save
983 @jsmith.save
972 @jsmith.reload
984 @jsmith.reload
973 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
985 assert !@jsmith.projects.first.recipients.include?(@jsmith.mail)
974 end
986 end
975
987
976 def test_comments_sorting_preference
988 def test_comments_sorting_preference
977 assert !@jsmith.wants_comments_in_reverse_order?
989 assert !@jsmith.wants_comments_in_reverse_order?
978 @jsmith.pref.comments_sorting = 'asc'
990 @jsmith.pref.comments_sorting = 'asc'
979 assert !@jsmith.wants_comments_in_reverse_order?
991 assert !@jsmith.wants_comments_in_reverse_order?
980 @jsmith.pref.comments_sorting = 'desc'
992 @jsmith.pref.comments_sorting = 'desc'
981 assert @jsmith.wants_comments_in_reverse_order?
993 assert @jsmith.wants_comments_in_reverse_order?
982 end
994 end
983
995
984 def test_find_by_mail_should_be_case_insensitive
996 def test_find_by_mail_should_be_case_insensitive
985 u = User.find_by_mail('JSmith@somenet.foo')
997 u = User.find_by_mail('JSmith@somenet.foo')
986 assert_not_nil u
998 assert_not_nil u
987 assert_equal 'jsmith@somenet.foo', u.mail
999 assert_equal 'jsmith@somenet.foo', u.mail
988 end
1000 end
989
1001
990 def test_random_password
1002 def test_random_password
991 u = User.new
1003 u = User.new
992 u.random_password
1004 u.random_password
993 assert !u.password.blank?
1005 assert !u.password.blank?
994 assert !u.password_confirmation.blank?
1006 assert !u.password_confirmation.blank?
995 end
1007 end
996
1008
997 test "#change_password_allowed? should be allowed if no auth source is set" do
1009 test "#change_password_allowed? should be allowed if no auth source is set" do
998 user = User.generate!
1010 user = User.generate!
999 assert user.change_password_allowed?
1011 assert user.change_password_allowed?
1000 end
1012 end
1001
1013
1002 test "#change_password_allowed? should delegate to the auth source" do
1014 test "#change_password_allowed? should delegate to the auth source" do
1003 user = User.generate!
1015 user = User.generate!
1004
1016
1005 allowed_auth_source = AuthSource.generate!
1017 allowed_auth_source = AuthSource.generate!
1006 def allowed_auth_source.allow_password_changes?; true; end
1018 def allowed_auth_source.allow_password_changes?; true; end
1007
1019
1008 denied_auth_source = AuthSource.generate!
1020 denied_auth_source = AuthSource.generate!
1009 def denied_auth_source.allow_password_changes?; false; end
1021 def denied_auth_source.allow_password_changes?; false; end
1010
1022
1011 assert user.change_password_allowed?
1023 assert user.change_password_allowed?
1012
1024
1013 user.auth_source = allowed_auth_source
1025 user.auth_source = allowed_auth_source
1014 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1026 assert user.change_password_allowed?, "User not allowed to change password, though auth source does"
1015
1027
1016 user.auth_source = denied_auth_source
1028 user.auth_source = denied_auth_source
1017 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1029 assert !user.change_password_allowed?, "User allowed to change password, though auth source does not"
1018 end
1030 end
1019
1031
1020 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1032 def test_own_account_deletable_should_be_true_with_unsubscrive_enabled
1021 with_settings :unsubscribe => '1' do
1033 with_settings :unsubscribe => '1' do
1022 assert_equal true, User.find(2).own_account_deletable?
1034 assert_equal true, User.find(2).own_account_deletable?
1023 end
1035 end
1024 end
1036 end
1025
1037
1026 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1038 def test_own_account_deletable_should_be_false_with_unsubscrive_disabled
1027 with_settings :unsubscribe => '0' do
1039 with_settings :unsubscribe => '0' do
1028 assert_equal false, User.find(2).own_account_deletable?
1040 assert_equal false, User.find(2).own_account_deletable?
1029 end
1041 end
1030 end
1042 end
1031
1043
1032 def test_own_account_deletable_should_be_false_for_a_single_admin
1044 def test_own_account_deletable_should_be_false_for_a_single_admin
1033 User.delete_all(["admin = ? AND id <> ?", true, 1])
1045 User.delete_all(["admin = ? AND id <> ?", true, 1])
1034
1046
1035 with_settings :unsubscribe => '1' do
1047 with_settings :unsubscribe => '1' do
1036 assert_equal false, User.find(1).own_account_deletable?
1048 assert_equal false, User.find(1).own_account_deletable?
1037 end
1049 end
1038 end
1050 end
1039
1051
1040 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1052 def test_own_account_deletable_should_be_true_for_an_admin_if_other_admin_exists
1041 User.generate! do |user|
1053 User.generate! do |user|
1042 user.admin = true
1054 user.admin = true
1043 end
1055 end
1044
1056
1045 with_settings :unsubscribe => '1' do
1057 with_settings :unsubscribe => '1' do
1046 assert_equal true, User.find(1).own_account_deletable?
1058 assert_equal true, User.find(1).own_account_deletable?
1047 end
1059 end
1048 end
1060 end
1049
1061
1050 test "#allowed_to? for archived project should return false" do
1062 test "#allowed_to? for archived project should return false" do
1051 project = Project.find(1)
1063 project = Project.find(1)
1052 project.archive
1064 project.archive
1053 project.reload
1065 project.reload
1054 assert_equal false, @admin.allowed_to?(:view_issues, project)
1066 assert_equal false, @admin.allowed_to?(:view_issues, project)
1055 end
1067 end
1056
1068
1057 test "#allowed_to? for closed project should return true for read actions" do
1069 test "#allowed_to? for closed project should return true for read actions" do
1058 project = Project.find(1)
1070 project = Project.find(1)
1059 project.close
1071 project.close
1060 project.reload
1072 project.reload
1061 assert_equal false, @admin.allowed_to?(:edit_project, project)
1073 assert_equal false, @admin.allowed_to?(:edit_project, project)
1062 assert_equal true, @admin.allowed_to?(:view_project, project)
1074 assert_equal true, @admin.allowed_to?(:view_project, project)
1063 end
1075 end
1064
1076
1065 test "#allowed_to? for project with module disabled should return false" do
1077 test "#allowed_to? for project with module disabled should return false" do
1066 project = Project.find(1)
1078 project = Project.find(1)
1067 project.enabled_module_names = ["issue_tracking"]
1079 project.enabled_module_names = ["issue_tracking"]
1068 assert_equal true, @admin.allowed_to?(:add_issues, project)
1080 assert_equal true, @admin.allowed_to?(:add_issues, project)
1069 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1081 assert_equal false, @admin.allowed_to?(:view_wiki_pages, project)
1070 end
1082 end
1071
1083
1072 test "#allowed_to? for admin users should return true" do
1084 test "#allowed_to? for admin users should return true" do
1073 project = Project.find(1)
1085 project = Project.find(1)
1074 assert ! @admin.member_of?(project)
1086 assert ! @admin.member_of?(project)
1075 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1087 %w(edit_issues delete_issues manage_news add_documents manage_wiki).each do |p|
1076 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1088 assert_equal true, @admin.allowed_to?(p.to_sym, project)
1077 end
1089 end
1078 end
1090 end
1079
1091
1080 test "#allowed_to? for normal users" do
1092 test "#allowed_to? for normal users" do
1081 project = Project.find(1)
1093 project = Project.find(1)
1082 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1094 assert_equal true, @jsmith.allowed_to?(:delete_messages, project) #Manager
1083 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1095 assert_equal false, @dlopper.allowed_to?(:delete_messages, project) #Developper
1084 end
1096 end
1085
1097
1086 test "#allowed_to? with empty array should return false" do
1098 test "#allowed_to? with empty array should return false" do
1087 assert_equal false, @admin.allowed_to?(:view_project, [])
1099 assert_equal false, @admin.allowed_to?(:view_project, [])
1088 end
1100 end
1089
1101
1090 test "#allowed_to? with multiple projects" do
1102 test "#allowed_to? with multiple projects" do
1091 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1103 assert_equal true, @admin.allowed_to?(:view_project, Project.all.to_a)
1092 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1104 assert_equal false, @dlopper.allowed_to?(:view_project, Project.all.to_a) #cannot see Project(2)
1093 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1105 assert_equal true, @jsmith.allowed_to?(:edit_issues, @jsmith.projects.to_a) #Manager or Developer everywhere
1094 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1106 assert_equal false, @jsmith.allowed_to?(:delete_issue_watchers, @jsmith.projects.to_a) #Dev cannot delete_issue_watchers
1095 end
1107 end
1096
1108
1097 test "#allowed_to? with with options[:global] should return true if user has one role with the permission" do
1109 test "#allowed_to? with with options[:global] should return true if user has one role with the permission" do
1098 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1110 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1099 @anonymous = User.find(6)
1111 @anonymous = User.find(6)
1100 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1112 assert_equal true, @jsmith.allowed_to?(:delete_issue_watchers, nil, :global => true)
1101 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1113 assert_equal false, @dlopper2.allowed_to?(:delete_issue_watchers, nil, :global => true)
1102 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1114 assert_equal true, @dlopper2.allowed_to?(:add_issues, nil, :global => true)
1103 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1115 assert_equal false, @anonymous.allowed_to?(:add_issues, nil, :global => true)
1104 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1116 assert_equal true, @anonymous.allowed_to?(:view_issues, nil, :global => true)
1105 end
1117 end
1106
1118
1107 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1119 # this is just a proxy method, the test only calls it to ensure it doesn't break trivially
1108 test "#allowed_to_globally?" do
1120 test "#allowed_to_globally?" do
1109 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1121 @dlopper2 = User.find(5) #only Developper on a project, not Manager anywhere
1110 @anonymous = User.find(6)
1122 @anonymous = User.find(6)
1111 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1123 assert_equal true, @jsmith.allowed_to_globally?(:delete_issue_watchers)
1112 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1124 assert_equal false, @dlopper2.allowed_to_globally?(:delete_issue_watchers)
1113 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1125 assert_equal true, @dlopper2.allowed_to_globally?(:add_issues)
1114 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1126 assert_equal false, @anonymous.allowed_to_globally?(:add_issues)
1115 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1127 assert_equal true, @anonymous.allowed_to_globally?(:view_issues)
1116 end
1128 end
1117
1129
1118 def test_notify_about_issue
1130 def test_notify_about_issue
1119 project = Project.find(1)
1131 project = Project.find(1)
1120 author = User.generate!
1132 author = User.generate!
1121 assignee = User.generate!
1133 assignee = User.generate!
1122 member = User.generate!
1134 member = User.generate!
1123 Member.create!(:user => member, :project => project, :role_ids => [1])
1135 Member.create!(:user => member, :project => project, :role_ids => [1])
1124 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
1136 issue = Issue.generate!(:project => project, :assigned_to => assignee, :author => author)
1125
1137
1126 tests = {
1138 tests = {
1127 author => %w(all only_my_events only_owner selected),
1139 author => %w(all only_my_events only_owner selected),
1128 assignee => %w(all only_my_events only_assigned selected),
1140 assignee => %w(all only_my_events only_assigned selected),
1129 member => %w(all)
1141 member => %w(all)
1130 }
1142 }
1131
1143
1132 tests.each do |user, expected|
1144 tests.each do |user, expected|
1133 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1145 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1134 user.mail_notification = option
1146 user.mail_notification = option
1135 assert_equal expected.include?(option), user.notify_about?(issue)
1147 assert_equal expected.include?(option), user.notify_about?(issue)
1136 end
1148 end
1137 end
1149 end
1138 end
1150 end
1139
1151
1140 def test_notify_about_issue_for_previous_assignee
1152 def test_notify_about_issue_for_previous_assignee
1141 assignee = User.generate!(:mail_notification => 'only_assigned')
1153 assignee = User.generate!(:mail_notification => 'only_assigned')
1142 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1154 new_assignee = User.generate!(:mail_notification => 'only_assigned')
1143 issue = Issue.generate!(:assigned_to => assignee)
1155 issue = Issue.generate!(:assigned_to => assignee)
1144
1156
1145 assert assignee.notify_about?(issue)
1157 assert assignee.notify_about?(issue)
1146 assert !new_assignee.notify_about?(issue)
1158 assert !new_assignee.notify_about?(issue)
1147
1159
1148 issue.assigned_to = new_assignee
1160 issue.assigned_to = new_assignee
1149 assert assignee.notify_about?(issue)
1161 assert assignee.notify_about?(issue)
1150 assert new_assignee.notify_about?(issue)
1162 assert new_assignee.notify_about?(issue)
1151
1163
1152 issue.save!
1164 issue.save!
1153 assert !assignee.notify_about?(issue)
1165 assert !assignee.notify_about?(issue)
1154 assert new_assignee.notify_about?(issue)
1166 assert new_assignee.notify_about?(issue)
1155 end
1167 end
1156
1168
1157 def test_notify_about_news
1169 def test_notify_about_news
1158 user = User.generate!
1170 user = User.generate!
1159 news = News.new
1171 news = News.new
1160
1172
1161 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1173 User::MAIL_NOTIFICATION_OPTIONS.map(&:first).each do |option|
1162 user.mail_notification = option
1174 user.mail_notification = option
1163 assert_equal (option != 'none'), user.notify_about?(news)
1175 assert_equal (option != 'none'), user.notify_about?(news)
1164 end
1176 end
1165 end
1177 end
1166
1178
1167 def test_salt_unsalted_passwords
1179 def test_salt_unsalted_passwords
1168 # Restore a user with an unsalted password
1180 # Restore a user with an unsalted password
1169 user = User.find(1)
1181 user = User.find(1)
1170 user.salt = nil
1182 user.salt = nil
1171 user.hashed_password = User.hash_password("unsalted")
1183 user.hashed_password = User.hash_password("unsalted")
1172 user.save!
1184 user.save!
1173
1185
1174 User.salt_unsalted_passwords!
1186 User.salt_unsalted_passwords!
1175
1187
1176 user.reload
1188 user.reload
1177 # Salt added
1189 # Salt added
1178 assert !user.salt.blank?
1190 assert !user.salt.blank?
1179 # Password still valid
1191 # Password still valid
1180 assert user.check_password?("unsalted")
1192 assert user.check_password?("unsalted")
1181 assert_equal user, User.try_to_login(user.login, "unsalted")
1193 assert_equal user, User.try_to_login(user.login, "unsalted")
1182 end
1194 end
1183
1195
1184 if Object.const_defined?(:OpenID)
1196 if Object.const_defined?(:OpenID)
1185 def test_setting_identity_url
1197 def test_setting_identity_url
1186 normalized_open_id_url = 'http://example.com/'
1198 normalized_open_id_url = 'http://example.com/'
1187 u = User.new( :identity_url => 'http://example.com/' )
1199 u = User.new( :identity_url => 'http://example.com/' )
1188 assert_equal normalized_open_id_url, u.identity_url
1200 assert_equal normalized_open_id_url, u.identity_url
1189 end
1201 end
1190
1202
1191 def test_setting_identity_url_without_trailing_slash
1203 def test_setting_identity_url_without_trailing_slash
1192 normalized_open_id_url = 'http://example.com/'
1204 normalized_open_id_url = 'http://example.com/'
1193 u = User.new( :identity_url => 'http://example.com' )
1205 u = User.new( :identity_url => 'http://example.com' )
1194 assert_equal normalized_open_id_url, u.identity_url
1206 assert_equal normalized_open_id_url, u.identity_url
1195 end
1207 end
1196
1208
1197 def test_setting_identity_url_without_protocol
1209 def test_setting_identity_url_without_protocol
1198 normalized_open_id_url = 'http://example.com/'
1210 normalized_open_id_url = 'http://example.com/'
1199 u = User.new( :identity_url => 'example.com' )
1211 u = User.new( :identity_url => 'example.com' )
1200 assert_equal normalized_open_id_url, u.identity_url
1212 assert_equal normalized_open_id_url, u.identity_url
1201 end
1213 end
1202
1214
1203 def test_setting_blank_identity_url
1215 def test_setting_blank_identity_url
1204 u = User.new( :identity_url => 'example.com' )
1216 u = User.new( :identity_url => 'example.com' )
1205 u.identity_url = ''
1217 u.identity_url = ''
1206 assert u.identity_url.blank?
1218 assert u.identity_url.blank?
1207 end
1219 end
1208
1220
1209 def test_setting_invalid_identity_url
1221 def test_setting_invalid_identity_url
1210 u = User.new( :identity_url => 'this is not an openid url' )
1222 u = User.new( :identity_url => 'this is not an openid url' )
1211 assert u.identity_url.blank?
1223 assert u.identity_url.blank?
1212 end
1224 end
1213 else
1225 else
1214 puts "Skipping openid tests."
1226 puts "Skipping openid tests."
1215 end
1227 end
1216 end
1228 end
General Comments 0
You need to be logged in to leave comments. Login now