##// END OF EJS Templates
Removed the default 0 value for issues foreign keys....
Jean-Philippe Lang -
r11187:b4013dc9f2c0
parent child
Show More
@@ -0,0 +1,19
1 class RemoveIssuesDefaultFkValues < ActiveRecord::Migration
2 def up
3 change_column_default :issues, :tracker_id, nil
4 change_column_default :issues, :project_id, nil
5 change_column_default :issues, :status_id, nil
6 change_column_default :issues, :assigned_to_id, nil
7 change_column_default :issues, :priority_id, nil
8 change_column_default :issues, :author_id, nil
9 end
10
11 def down
12 change_column_default :issues, :tracker_id, 0
13 change_column_default :issues, :project_id, 0
14 change_column_default :issues, :status_id, 0
15 change_column_default :issues, :assigned_to_id, 0
16 change_column_default :issues, :priority_id, 0
17 change_column_default :issues, :author_id, 0
18 end
19 end
@@ -1,1993 +1,2006
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2013 Jean-Philippe Lang
2 # Copyright (C) 2006-2013 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, :members, :member_roles, :roles,
21 fixtures :projects, :users, :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 teardown
34 def teardown
35 User.current = nil
35 User.current = nil
36 end
36 end
37
37
38 def test_initialize
39 issue = Issue.new
40
41 assert_nil issue.project_id
42 assert_nil issue.tracker_id
43 assert_nil issue.author_id
44 assert_nil issue.assigned_to_id
45 assert_nil issue.category_id
46
47 assert_equal IssueStatus.default, issue.status
48 assert_equal IssuePriority.default, issue.priority
49 end
50
38 def test_create
51 def test_create
39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
52 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
40 :status_id => 1, :priority => IssuePriority.all.first,
53 :status_id => 1, :priority => IssuePriority.all.first,
41 :subject => 'test_create',
54 :subject => 'test_create',
42 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
55 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
43 assert issue.save
56 assert issue.save
44 issue.reload
57 issue.reload
45 assert_equal 1.5, issue.estimated_hours
58 assert_equal 1.5, issue.estimated_hours
46 end
59 end
47
60
48 def test_create_minimal
61 def test_create_minimal
49 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
50 :status_id => 1, :priority => IssuePriority.all.first,
63 :status_id => 1, :priority => IssuePriority.all.first,
51 :subject => 'test_create')
64 :subject => 'test_create')
52 assert issue.save
65 assert issue.save
53 assert issue.description.nil?
66 assert issue.description.nil?
54 assert_nil issue.estimated_hours
67 assert_nil issue.estimated_hours
55 end
68 end
56
69
57 def test_start_date_format_should_be_validated
70 def test_start_date_format_should_be_validated
58 set_language_if_valid 'en'
71 set_language_if_valid 'en'
59 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
72 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
60 issue = Issue.new(:start_date => invalid_date)
73 issue = Issue.new(:start_date => invalid_date)
61 assert !issue.valid?
74 assert !issue.valid?
62 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
75 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
63 end
76 end
64 end
77 end
65
78
66 def test_due_date_format_should_be_validated
79 def test_due_date_format_should_be_validated
67 set_language_if_valid 'en'
80 set_language_if_valid 'en'
68 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
81 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
69 issue = Issue.new(:due_date => invalid_date)
82 issue = Issue.new(:due_date => invalid_date)
70 assert !issue.valid?
83 assert !issue.valid?
71 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
84 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
72 end
85 end
73 end
86 end
74
87
75 def test_due_date_lesser_than_start_date_should_not_validate
88 def test_due_date_lesser_than_start_date_should_not_validate
76 set_language_if_valid 'en'
89 set_language_if_valid 'en'
77 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
90 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
78 assert !issue.valid?
91 assert !issue.valid?
79 assert_include 'Due date must be greater than start date', issue.errors.full_messages
92 assert_include 'Due date must be greater than start date', issue.errors.full_messages
80 end
93 end
81
94
82 def test_estimated_hours_should_be_validated
95 def test_estimated_hours_should_be_validated
83 set_language_if_valid 'en'
96 set_language_if_valid 'en'
84 ['-2'].each do |invalid|
97 ['-2'].each do |invalid|
85 issue = Issue.new(:estimated_hours => invalid)
98 issue = Issue.new(:estimated_hours => invalid)
86 assert !issue.valid?
99 assert !issue.valid?
87 assert_include 'Estimated time is invalid', issue.errors.full_messages
100 assert_include 'Estimated time is invalid', issue.errors.full_messages
88 end
101 end
89 end
102 end
90
103
91 def test_create_with_required_custom_field
104 def test_create_with_required_custom_field
92 set_language_if_valid 'en'
105 set_language_if_valid 'en'
93 field = IssueCustomField.find_by_name('Database')
106 field = IssueCustomField.find_by_name('Database')
94 field.update_attribute(:is_required, true)
107 field.update_attribute(:is_required, true)
95
108
96 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
109 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
97 :status_id => 1, :subject => 'test_create',
110 :status_id => 1, :subject => 'test_create',
98 :description => 'IssueTest#test_create_with_required_custom_field')
111 :description => 'IssueTest#test_create_with_required_custom_field')
99 assert issue.available_custom_fields.include?(field)
112 assert issue.available_custom_fields.include?(field)
100 # No value for the custom field
113 # No value for the custom field
101 assert !issue.save
114 assert !issue.save
102 assert_equal ["Database can't be blank"], issue.errors.full_messages
115 assert_equal ["Database can't be blank"], issue.errors.full_messages
103 # Blank value
116 # Blank value
104 issue.custom_field_values = { field.id => '' }
117 issue.custom_field_values = { field.id => '' }
105 assert !issue.save
118 assert !issue.save
106 assert_equal ["Database can't be blank"], issue.errors.full_messages
119 assert_equal ["Database can't be blank"], issue.errors.full_messages
107 # Invalid value
120 # Invalid value
108 issue.custom_field_values = { field.id => 'SQLServer' }
121 issue.custom_field_values = { field.id => 'SQLServer' }
109 assert !issue.save
122 assert !issue.save
110 assert_equal ["Database is not included in the list"], issue.errors.full_messages
123 assert_equal ["Database is not included in the list"], issue.errors.full_messages
111 # Valid value
124 # Valid value
112 issue.custom_field_values = { field.id => 'PostgreSQL' }
125 issue.custom_field_values = { field.id => 'PostgreSQL' }
113 assert issue.save
126 assert issue.save
114 issue.reload
127 issue.reload
115 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
128 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
116 end
129 end
117
130
118 def test_create_with_group_assignment
131 def test_create_with_group_assignment
119 with_settings :issue_group_assignment => '1' do
132 with_settings :issue_group_assignment => '1' do
120 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
133 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
121 :subject => 'Group assignment',
134 :subject => 'Group assignment',
122 :assigned_to_id => 11).save
135 :assigned_to_id => 11).save
123 issue = Issue.first(:order => 'id DESC')
136 issue = Issue.first(:order => 'id DESC')
124 assert_kind_of Group, issue.assigned_to
137 assert_kind_of Group, issue.assigned_to
125 assert_equal Group.find(11), issue.assigned_to
138 assert_equal Group.find(11), issue.assigned_to
126 end
139 end
127 end
140 end
128
141
129 def test_create_with_parent_issue_id
142 def test_create_with_parent_issue_id
130 issue = Issue.new(:project_id => 1, :tracker_id => 1,
143 issue = Issue.new(:project_id => 1, :tracker_id => 1,
131 :author_id => 1, :subject => 'Group assignment',
144 :author_id => 1, :subject => 'Group assignment',
132 :parent_issue_id => 1)
145 :parent_issue_id => 1)
133 assert_save issue
146 assert_save issue
134 assert_equal 1, issue.parent_issue_id
147 assert_equal 1, issue.parent_issue_id
135 assert_equal Issue.find(1), issue.parent
148 assert_equal Issue.find(1), issue.parent
136 end
149 end
137
150
138 def test_create_with_sharp_parent_issue_id
151 def test_create_with_sharp_parent_issue_id
139 issue = Issue.new(:project_id => 1, :tracker_id => 1,
152 issue = Issue.new(:project_id => 1, :tracker_id => 1,
140 :author_id => 1, :subject => 'Group assignment',
153 :author_id => 1, :subject => 'Group assignment',
141 :parent_issue_id => "#1")
154 :parent_issue_id => "#1")
142 assert_save issue
155 assert_save issue
143 assert_equal 1, issue.parent_issue_id
156 assert_equal 1, issue.parent_issue_id
144 assert_equal Issue.find(1), issue.parent
157 assert_equal Issue.find(1), issue.parent
145 end
158 end
146
159
147 def test_create_with_invalid_parent_issue_id
160 def test_create_with_invalid_parent_issue_id
148 set_language_if_valid 'en'
161 set_language_if_valid 'en'
149 issue = Issue.new(:project_id => 1, :tracker_id => 1,
162 issue = Issue.new(:project_id => 1, :tracker_id => 1,
150 :author_id => 1, :subject => 'Group assignment',
163 :author_id => 1, :subject => 'Group assignment',
151 :parent_issue_id => '01ABC')
164 :parent_issue_id => '01ABC')
152 assert !issue.save
165 assert !issue.save
153 assert_equal '01ABC', issue.parent_issue_id
166 assert_equal '01ABC', issue.parent_issue_id
154 assert_include 'Parent task is invalid', issue.errors.full_messages
167 assert_include 'Parent task is invalid', issue.errors.full_messages
155 end
168 end
156
169
157 def test_create_with_invalid_sharp_parent_issue_id
170 def test_create_with_invalid_sharp_parent_issue_id
158 set_language_if_valid 'en'
171 set_language_if_valid 'en'
159 issue = Issue.new(:project_id => 1, :tracker_id => 1,
172 issue = Issue.new(:project_id => 1, :tracker_id => 1,
160 :author_id => 1, :subject => 'Group assignment',
173 :author_id => 1, :subject => 'Group assignment',
161 :parent_issue_id => '#01ABC')
174 :parent_issue_id => '#01ABC')
162 assert !issue.save
175 assert !issue.save
163 assert_equal '#01ABC', issue.parent_issue_id
176 assert_equal '#01ABC', issue.parent_issue_id
164 assert_include 'Parent task is invalid', issue.errors.full_messages
177 assert_include 'Parent task is invalid', issue.errors.full_messages
165 end
178 end
166
179
167 def assert_visibility_match(user, issues)
180 def assert_visibility_match(user, issues)
168 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
181 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
169 end
182 end
170
183
171 def test_visible_scope_for_anonymous
184 def test_visible_scope_for_anonymous
172 # Anonymous user should see issues of public projects only
185 # Anonymous user should see issues of public projects only
173 issues = Issue.visible(User.anonymous).all
186 issues = Issue.visible(User.anonymous).all
174 assert issues.any?
187 assert issues.any?
175 assert_nil issues.detect {|issue| !issue.project.is_public?}
188 assert_nil issues.detect {|issue| !issue.project.is_public?}
176 assert_nil issues.detect {|issue| issue.is_private?}
189 assert_nil issues.detect {|issue| issue.is_private?}
177 assert_visibility_match User.anonymous, issues
190 assert_visibility_match User.anonymous, issues
178 end
191 end
179
192
180 def test_visible_scope_for_anonymous_without_view_issues_permissions
193 def test_visible_scope_for_anonymous_without_view_issues_permissions
181 # Anonymous user should not see issues without permission
194 # Anonymous user should not see issues without permission
182 Role.anonymous.remove_permission!(:view_issues)
195 Role.anonymous.remove_permission!(:view_issues)
183 issues = Issue.visible(User.anonymous).all
196 issues = Issue.visible(User.anonymous).all
184 assert issues.empty?
197 assert issues.empty?
185 assert_visibility_match User.anonymous, issues
198 assert_visibility_match User.anonymous, issues
186 end
199 end
187
200
188 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
201 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
189 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
202 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
190 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
203 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
191 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
204 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
192 assert !issue.visible?(User.anonymous)
205 assert !issue.visible?(User.anonymous)
193 end
206 end
194
207
195 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
208 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
196 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
209 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
197 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
210 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
198 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
211 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
199 assert !issue.visible?(User.anonymous)
212 assert !issue.visible?(User.anonymous)
200 end
213 end
201
214
202 def test_visible_scope_for_non_member
215 def test_visible_scope_for_non_member
203 user = User.find(9)
216 user = User.find(9)
204 assert user.projects.empty?
217 assert user.projects.empty?
205 # Non member user should see issues of public projects only
218 # Non member user should see issues of public projects only
206 issues = Issue.visible(user).all
219 issues = Issue.visible(user).all
207 assert issues.any?
220 assert issues.any?
208 assert_nil issues.detect {|issue| !issue.project.is_public?}
221 assert_nil issues.detect {|issue| !issue.project.is_public?}
209 assert_nil issues.detect {|issue| issue.is_private?}
222 assert_nil issues.detect {|issue| issue.is_private?}
210 assert_visibility_match user, issues
223 assert_visibility_match user, issues
211 end
224 end
212
225
213 def test_visible_scope_for_non_member_with_own_issues_visibility
226 def test_visible_scope_for_non_member_with_own_issues_visibility
214 Role.non_member.update_attribute :issues_visibility, 'own'
227 Role.non_member.update_attribute :issues_visibility, 'own'
215 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
228 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
216 user = User.find(9)
229 user = User.find(9)
217
230
218 issues = Issue.visible(user).all
231 issues = Issue.visible(user).all
219 assert issues.any?
232 assert issues.any?
220 assert_nil issues.detect {|issue| issue.author != user}
233 assert_nil issues.detect {|issue| issue.author != user}
221 assert_visibility_match user, issues
234 assert_visibility_match user, issues
222 end
235 end
223
236
224 def test_visible_scope_for_non_member_without_view_issues_permissions
237 def test_visible_scope_for_non_member_without_view_issues_permissions
225 # Non member user should not see issues without permission
238 # Non member user should not see issues without permission
226 Role.non_member.remove_permission!(:view_issues)
239 Role.non_member.remove_permission!(:view_issues)
227 user = User.find(9)
240 user = User.find(9)
228 assert user.projects.empty?
241 assert user.projects.empty?
229 issues = Issue.visible(user).all
242 issues = Issue.visible(user).all
230 assert issues.empty?
243 assert issues.empty?
231 assert_visibility_match user, issues
244 assert_visibility_match user, issues
232 end
245 end
233
246
234 def test_visible_scope_for_member
247 def test_visible_scope_for_member
235 user = User.find(9)
248 user = User.find(9)
236 # User should see issues of projects for which he has view_issues permissions only
249 # User should see issues of projects for which he has view_issues permissions only
237 Role.non_member.remove_permission!(:view_issues)
250 Role.non_member.remove_permission!(:view_issues)
238 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
251 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
239 issues = Issue.visible(user).all
252 issues = Issue.visible(user).all
240 assert issues.any?
253 assert issues.any?
241 assert_nil issues.detect {|issue| issue.project_id != 3}
254 assert_nil issues.detect {|issue| issue.project_id != 3}
242 assert_nil issues.detect {|issue| issue.is_private?}
255 assert_nil issues.detect {|issue| issue.is_private?}
243 assert_visibility_match user, issues
256 assert_visibility_match user, issues
244 end
257 end
245
258
246 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
259 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
247 user = User.find(8)
260 user = User.find(8)
248 assert user.groups.any?
261 assert user.groups.any?
249 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
262 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
250 Role.non_member.remove_permission!(:view_issues)
263 Role.non_member.remove_permission!(:view_issues)
251
264
252 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
265 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
253 :status_id => 1, :priority => IssuePriority.all.first,
266 :status_id => 1, :priority => IssuePriority.all.first,
254 :subject => 'Assignment test',
267 :subject => 'Assignment test',
255 :assigned_to => user.groups.first,
268 :assigned_to => user.groups.first,
256 :is_private => true)
269 :is_private => true)
257
270
258 Role.find(2).update_attribute :issues_visibility, 'default'
271 Role.find(2).update_attribute :issues_visibility, 'default'
259 issues = Issue.visible(User.find(8)).all
272 issues = Issue.visible(User.find(8)).all
260 assert issues.any?
273 assert issues.any?
261 assert issues.include?(issue)
274 assert issues.include?(issue)
262
275
263 Role.find(2).update_attribute :issues_visibility, 'own'
276 Role.find(2).update_attribute :issues_visibility, 'own'
264 issues = Issue.visible(User.find(8)).all
277 issues = Issue.visible(User.find(8)).all
265 assert issues.any?
278 assert issues.any?
266 assert issues.include?(issue)
279 assert issues.include?(issue)
267 end
280 end
268
281
269 def test_visible_scope_for_admin
282 def test_visible_scope_for_admin
270 user = User.find(1)
283 user = User.find(1)
271 user.members.each(&:destroy)
284 user.members.each(&:destroy)
272 assert user.projects.empty?
285 assert user.projects.empty?
273 issues = Issue.visible(user).all
286 issues = Issue.visible(user).all
274 assert issues.any?
287 assert issues.any?
275 # Admin should see issues on private projects that he does not belong to
288 # Admin should see issues on private projects that he does not belong to
276 assert issues.detect {|issue| !issue.project.is_public?}
289 assert issues.detect {|issue| !issue.project.is_public?}
277 # Admin should see private issues of other users
290 # Admin should see private issues of other users
278 assert issues.detect {|issue| issue.is_private? && issue.author != user}
291 assert issues.detect {|issue| issue.is_private? && issue.author != user}
279 assert_visibility_match user, issues
292 assert_visibility_match user, issues
280 end
293 end
281
294
282 def test_visible_scope_with_project
295 def test_visible_scope_with_project
283 project = Project.find(1)
296 project = Project.find(1)
284 issues = Issue.visible(User.find(2), :project => project).all
297 issues = Issue.visible(User.find(2), :project => project).all
285 projects = issues.collect(&:project).uniq
298 projects = issues.collect(&:project).uniq
286 assert_equal 1, projects.size
299 assert_equal 1, projects.size
287 assert_equal project, projects.first
300 assert_equal project, projects.first
288 end
301 end
289
302
290 def test_visible_scope_with_project_and_subprojects
303 def test_visible_scope_with_project_and_subprojects
291 project = Project.find(1)
304 project = Project.find(1)
292 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
305 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
293 projects = issues.collect(&:project).uniq
306 projects = issues.collect(&:project).uniq
294 assert projects.size > 1
307 assert projects.size > 1
295 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
308 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
296 end
309 end
297
310
298 def test_visible_and_nested_set_scopes
311 def test_visible_and_nested_set_scopes
299 assert_equal 0, Issue.find(1).descendants.visible.all.size
312 assert_equal 0, Issue.find(1).descendants.visible.all.size
300 end
313 end
301
314
302 def test_open_scope
315 def test_open_scope
303 issues = Issue.open.all
316 issues = Issue.open.all
304 assert_nil issues.detect(&:closed?)
317 assert_nil issues.detect(&:closed?)
305 end
318 end
306
319
307 def test_open_scope_with_arg
320 def test_open_scope_with_arg
308 issues = Issue.open(false).all
321 issues = Issue.open(false).all
309 assert_equal issues, issues.select(&:closed?)
322 assert_equal issues, issues.select(&:closed?)
310 end
323 end
311
324
312 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
325 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
313 version = Version.find(2)
326 version = Version.find(2)
314 assert version.fixed_issues.any?
327 assert version.fixed_issues.any?
315 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
328 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
316 end
329 end
317
330
318 def test_fixed_version_scope_with_empty_array_should_return_no_result
331 def test_fixed_version_scope_with_empty_array_should_return_no_result
319 assert_equal 0, Issue.fixed_version([]).count
332 assert_equal 0, Issue.fixed_version([]).count
320 end
333 end
321
334
322 def test_errors_full_messages_should_include_custom_fields_errors
335 def test_errors_full_messages_should_include_custom_fields_errors
323 field = IssueCustomField.find_by_name('Database')
336 field = IssueCustomField.find_by_name('Database')
324
337
325 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
338 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
326 :status_id => 1, :subject => 'test_create',
339 :status_id => 1, :subject => 'test_create',
327 :description => 'IssueTest#test_create_with_required_custom_field')
340 :description => 'IssueTest#test_create_with_required_custom_field')
328 assert issue.available_custom_fields.include?(field)
341 assert issue.available_custom_fields.include?(field)
329 # Invalid value
342 # Invalid value
330 issue.custom_field_values = { field.id => 'SQLServer' }
343 issue.custom_field_values = { field.id => 'SQLServer' }
331
344
332 assert !issue.valid?
345 assert !issue.valid?
333 assert_equal 1, issue.errors.full_messages.size
346 assert_equal 1, issue.errors.full_messages.size
334 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
347 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
335 issue.errors.full_messages.first
348 issue.errors.full_messages.first
336 end
349 end
337
350
338 def test_update_issue_with_required_custom_field
351 def test_update_issue_with_required_custom_field
339 field = IssueCustomField.find_by_name('Database')
352 field = IssueCustomField.find_by_name('Database')
340 field.update_attribute(:is_required, true)
353 field.update_attribute(:is_required, true)
341
354
342 issue = Issue.find(1)
355 issue = Issue.find(1)
343 assert_nil issue.custom_value_for(field)
356 assert_nil issue.custom_value_for(field)
344 assert issue.available_custom_fields.include?(field)
357 assert issue.available_custom_fields.include?(field)
345 # No change to custom values, issue can be saved
358 # No change to custom values, issue can be saved
346 assert issue.save
359 assert issue.save
347 # Blank value
360 # Blank value
348 issue.custom_field_values = { field.id => '' }
361 issue.custom_field_values = { field.id => '' }
349 assert !issue.save
362 assert !issue.save
350 # Valid value
363 # Valid value
351 issue.custom_field_values = { field.id => 'PostgreSQL' }
364 issue.custom_field_values = { field.id => 'PostgreSQL' }
352 assert issue.save
365 assert issue.save
353 issue.reload
366 issue.reload
354 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
367 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
355 end
368 end
356
369
357 def test_should_not_update_attributes_if_custom_fields_validation_fails
370 def test_should_not_update_attributes_if_custom_fields_validation_fails
358 issue = Issue.find(1)
371 issue = Issue.find(1)
359 field = IssueCustomField.find_by_name('Database')
372 field = IssueCustomField.find_by_name('Database')
360 assert issue.available_custom_fields.include?(field)
373 assert issue.available_custom_fields.include?(field)
361
374
362 issue.custom_field_values = { field.id => 'Invalid' }
375 issue.custom_field_values = { field.id => 'Invalid' }
363 issue.subject = 'Should be not be saved'
376 issue.subject = 'Should be not be saved'
364 assert !issue.save
377 assert !issue.save
365
378
366 issue.reload
379 issue.reload
367 assert_equal "Can't print recipes", issue.subject
380 assert_equal "Can't print recipes", issue.subject
368 end
381 end
369
382
370 def test_should_not_recreate_custom_values_objects_on_update
383 def test_should_not_recreate_custom_values_objects_on_update
371 field = IssueCustomField.find_by_name('Database')
384 field = IssueCustomField.find_by_name('Database')
372
385
373 issue = Issue.find(1)
386 issue = Issue.find(1)
374 issue.custom_field_values = { field.id => 'PostgreSQL' }
387 issue.custom_field_values = { field.id => 'PostgreSQL' }
375 assert issue.save
388 assert issue.save
376 custom_value = issue.custom_value_for(field)
389 custom_value = issue.custom_value_for(field)
377 issue.reload
390 issue.reload
378 issue.custom_field_values = { field.id => 'MySQL' }
391 issue.custom_field_values = { field.id => 'MySQL' }
379 assert issue.save
392 assert issue.save
380 issue.reload
393 issue.reload
381 assert_equal custom_value.id, issue.custom_value_for(field).id
394 assert_equal custom_value.id, issue.custom_value_for(field).id
382 end
395 end
383
396
384 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
397 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
385 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
398 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
386 :status_id => 1, :subject => 'Test',
399 :status_id => 1, :subject => 'Test',
387 :custom_field_values => {'2' => 'Test'})
400 :custom_field_values => {'2' => 'Test'})
388 assert !Tracker.find(2).custom_field_ids.include?(2)
401 assert !Tracker.find(2).custom_field_ids.include?(2)
389
402
390 issue = Issue.find(issue.id)
403 issue = Issue.find(issue.id)
391 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
404 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
392
405
393 issue = Issue.find(issue.id)
406 issue = Issue.find(issue.id)
394 custom_value = issue.custom_value_for(2)
407 custom_value = issue.custom_value_for(2)
395 assert_not_nil custom_value
408 assert_not_nil custom_value
396 assert_equal 'Test', custom_value.value
409 assert_equal 'Test', custom_value.value
397 end
410 end
398
411
399 def test_assigning_tracker_id_should_reload_custom_fields_values
412 def test_assigning_tracker_id_should_reload_custom_fields_values
400 issue = Issue.new(:project => Project.find(1))
413 issue = Issue.new(:project => Project.find(1))
401 assert issue.custom_field_values.empty?
414 assert issue.custom_field_values.empty?
402 issue.tracker_id = 1
415 issue.tracker_id = 1
403 assert issue.custom_field_values.any?
416 assert issue.custom_field_values.any?
404 end
417 end
405
418
406 def test_assigning_attributes_should_assign_project_and_tracker_first
419 def test_assigning_attributes_should_assign_project_and_tracker_first
407 seq = sequence('seq')
420 seq = sequence('seq')
408 issue = Issue.new
421 issue = Issue.new
409 issue.expects(:project_id=).in_sequence(seq)
422 issue.expects(:project_id=).in_sequence(seq)
410 issue.expects(:tracker_id=).in_sequence(seq)
423 issue.expects(:tracker_id=).in_sequence(seq)
411 issue.expects(:subject=).in_sequence(seq)
424 issue.expects(:subject=).in_sequence(seq)
412 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
425 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
413 end
426 end
414
427
415 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
428 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
416 attributes = ActiveSupport::OrderedHash.new
429 attributes = ActiveSupport::OrderedHash.new
417 attributes['custom_field_values'] = { '1' => 'MySQL' }
430 attributes['custom_field_values'] = { '1' => 'MySQL' }
418 attributes['tracker_id'] = '1'
431 attributes['tracker_id'] = '1'
419 issue = Issue.new(:project => Project.find(1))
432 issue = Issue.new(:project => Project.find(1))
420 issue.attributes = attributes
433 issue.attributes = attributes
421 assert_equal 'MySQL', issue.custom_field_value(1)
434 assert_equal 'MySQL', issue.custom_field_value(1)
422 end
435 end
423
436
424 def test_reload_should_reload_custom_field_values
437 def test_reload_should_reload_custom_field_values
425 issue = Issue.generate!
438 issue = Issue.generate!
426 issue.custom_field_values = {'2' => 'Foo'}
439 issue.custom_field_values = {'2' => 'Foo'}
427 issue.save!
440 issue.save!
428
441
429 issue = Issue.order('id desc').first
442 issue = Issue.order('id desc').first
430 assert_equal 'Foo', issue.custom_field_value(2)
443 assert_equal 'Foo', issue.custom_field_value(2)
431
444
432 issue.custom_field_values = {'2' => 'Bar'}
445 issue.custom_field_values = {'2' => 'Bar'}
433 assert_equal 'Bar', issue.custom_field_value(2)
446 assert_equal 'Bar', issue.custom_field_value(2)
434
447
435 issue.reload
448 issue.reload
436 assert_equal 'Foo', issue.custom_field_value(2)
449 assert_equal 'Foo', issue.custom_field_value(2)
437 end
450 end
438
451
439 def test_should_update_issue_with_disabled_tracker
452 def test_should_update_issue_with_disabled_tracker
440 p = Project.find(1)
453 p = Project.find(1)
441 issue = Issue.find(1)
454 issue = Issue.find(1)
442
455
443 p.trackers.delete(issue.tracker)
456 p.trackers.delete(issue.tracker)
444 assert !p.trackers.include?(issue.tracker)
457 assert !p.trackers.include?(issue.tracker)
445
458
446 issue.reload
459 issue.reload
447 issue.subject = 'New subject'
460 issue.subject = 'New subject'
448 assert issue.save
461 assert issue.save
449 end
462 end
450
463
451 def test_should_not_set_a_disabled_tracker
464 def test_should_not_set_a_disabled_tracker
452 p = Project.find(1)
465 p = Project.find(1)
453 p.trackers.delete(Tracker.find(2))
466 p.trackers.delete(Tracker.find(2))
454
467
455 issue = Issue.find(1)
468 issue = Issue.find(1)
456 issue.tracker_id = 2
469 issue.tracker_id = 2
457 issue.subject = 'New subject'
470 issue.subject = 'New subject'
458 assert !issue.save
471 assert !issue.save
459 assert_not_nil issue.errors[:tracker_id]
472 assert_not_nil issue.errors[:tracker_id]
460 end
473 end
461
474
462 def test_category_based_assignment
475 def test_category_based_assignment
463 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
476 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
464 :status_id => 1, :priority => IssuePriority.all.first,
477 :status_id => 1, :priority => IssuePriority.all.first,
465 :subject => 'Assignment test',
478 :subject => 'Assignment test',
466 :description => 'Assignment test', :category_id => 1)
479 :description => 'Assignment test', :category_id => 1)
467 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
480 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
468 end
481 end
469
482
470 def test_new_statuses_allowed_to
483 def test_new_statuses_allowed_to
471 WorkflowTransition.delete_all
484 WorkflowTransition.delete_all
472 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
485 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
473 :old_status_id => 1, :new_status_id => 2,
486 :old_status_id => 1, :new_status_id => 2,
474 :author => false, :assignee => false)
487 :author => false, :assignee => false)
475 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
488 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
476 :old_status_id => 1, :new_status_id => 3,
489 :old_status_id => 1, :new_status_id => 3,
477 :author => true, :assignee => false)
490 :author => true, :assignee => false)
478 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
491 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
479 :new_status_id => 4, :author => false,
492 :new_status_id => 4, :author => false,
480 :assignee => true)
493 :assignee => true)
481 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
494 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
482 :old_status_id => 1, :new_status_id => 5,
495 :old_status_id => 1, :new_status_id => 5,
483 :author => true, :assignee => true)
496 :author => true, :assignee => true)
484 status = IssueStatus.find(1)
497 status = IssueStatus.find(1)
485 role = Role.find(1)
498 role = Role.find(1)
486 tracker = Tracker.find(1)
499 tracker = Tracker.find(1)
487 user = User.find(2)
500 user = User.find(2)
488
501
489 issue = Issue.generate!(:tracker => tracker, :status => status,
502 issue = Issue.generate!(:tracker => tracker, :status => status,
490 :project_id => 1, :author_id => 1)
503 :project_id => 1, :author_id => 1)
491 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
504 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
492
505
493 issue = Issue.generate!(:tracker => tracker, :status => status,
506 issue = Issue.generate!(:tracker => tracker, :status => status,
494 :project_id => 1, :author => user)
507 :project_id => 1, :author => user)
495 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
508 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
496
509
497 issue = Issue.generate!(:tracker => tracker, :status => status,
510 issue = Issue.generate!(:tracker => tracker, :status => status,
498 :project_id => 1, :author_id => 1,
511 :project_id => 1, :author_id => 1,
499 :assigned_to => user)
512 :assigned_to => user)
500 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
513 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
501
514
502 issue = Issue.generate!(:tracker => tracker, :status => status,
515 issue = Issue.generate!(:tracker => tracker, :status => status,
503 :project_id => 1, :author => user,
516 :project_id => 1, :author => user,
504 :assigned_to => user)
517 :assigned_to => user)
505 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
518 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
506 end
519 end
507
520
508 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
521 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
509 admin = User.find(1)
522 admin = User.find(1)
510 issue = Issue.find(1)
523 issue = Issue.find(1)
511 assert !admin.member_of?(issue.project)
524 assert !admin.member_of?(issue.project)
512 expected_statuses = [issue.status] +
525 expected_statuses = [issue.status] +
513 WorkflowTransition.find_all_by_old_status_id(
526 WorkflowTransition.find_all_by_old_status_id(
514 issue.status_id).map(&:new_status).uniq.sort
527 issue.status_id).map(&:new_status).uniq.sort
515 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
528 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
516 end
529 end
517
530
518 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
531 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
519 issue = Issue.find(1).copy
532 issue = Issue.find(1).copy
520 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
533 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
521
534
522 issue = Issue.find(2).copy
535 issue = Issue.find(2).copy
523 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
536 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
524 end
537 end
525
538
526 def test_safe_attributes_names_should_not_include_disabled_field
539 def test_safe_attributes_names_should_not_include_disabled_field
527 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
540 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
528
541
529 issue = Issue.new(:tracker => tracker)
542 issue = Issue.new(:tracker => tracker)
530 assert_include 'tracker_id', issue.safe_attribute_names
543 assert_include 'tracker_id', issue.safe_attribute_names
531 assert_include 'status_id', issue.safe_attribute_names
544 assert_include 'status_id', issue.safe_attribute_names
532 assert_include 'subject', issue.safe_attribute_names
545 assert_include 'subject', issue.safe_attribute_names
533 assert_include 'description', issue.safe_attribute_names
546 assert_include 'description', issue.safe_attribute_names
534 assert_include 'custom_field_values', issue.safe_attribute_names
547 assert_include 'custom_field_values', issue.safe_attribute_names
535 assert_include 'custom_fields', issue.safe_attribute_names
548 assert_include 'custom_fields', issue.safe_attribute_names
536 assert_include 'lock_version', issue.safe_attribute_names
549 assert_include 'lock_version', issue.safe_attribute_names
537
550
538 tracker.core_fields.each do |field|
551 tracker.core_fields.each do |field|
539 assert_include field, issue.safe_attribute_names
552 assert_include field, issue.safe_attribute_names
540 end
553 end
541
554
542 tracker.disabled_core_fields.each do |field|
555 tracker.disabled_core_fields.each do |field|
543 assert_not_include field, issue.safe_attribute_names
556 assert_not_include field, issue.safe_attribute_names
544 end
557 end
545 end
558 end
546
559
547 def test_safe_attributes_should_ignore_disabled_fields
560 def test_safe_attributes_should_ignore_disabled_fields
548 tracker = Tracker.find(1)
561 tracker = Tracker.find(1)
549 tracker.core_fields = %w(assigned_to_id due_date)
562 tracker.core_fields = %w(assigned_to_id due_date)
550 tracker.save!
563 tracker.save!
551
564
552 issue = Issue.new(:tracker => tracker)
565 issue = Issue.new(:tracker => tracker)
553 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
566 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
554 assert_nil issue.start_date
567 assert_nil issue.start_date
555 assert_equal Date.parse('2012-07-14'), issue.due_date
568 assert_equal Date.parse('2012-07-14'), issue.due_date
556 end
569 end
557
570
558 def test_safe_attributes_should_accept_target_tracker_enabled_fields
571 def test_safe_attributes_should_accept_target_tracker_enabled_fields
559 source = Tracker.find(1)
572 source = Tracker.find(1)
560 source.core_fields = []
573 source.core_fields = []
561 source.save!
574 source.save!
562 target = Tracker.find(2)
575 target = Tracker.find(2)
563 target.core_fields = %w(assigned_to_id due_date)
576 target.core_fields = %w(assigned_to_id due_date)
564 target.save!
577 target.save!
565
578
566 issue = Issue.new(:tracker => source)
579 issue = Issue.new(:tracker => source)
567 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
580 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
568 assert_equal target, issue.tracker
581 assert_equal target, issue.tracker
569 assert_equal Date.parse('2012-07-14'), issue.due_date
582 assert_equal Date.parse('2012-07-14'), issue.due_date
570 end
583 end
571
584
572 def test_safe_attributes_should_not_include_readonly_fields
585 def test_safe_attributes_should_not_include_readonly_fields
573 WorkflowPermission.delete_all
586 WorkflowPermission.delete_all
574 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
587 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
575 :role_id => 1, :field_name => 'due_date',
588 :role_id => 1, :field_name => 'due_date',
576 :rule => 'readonly')
589 :rule => 'readonly')
577 user = User.find(2)
590 user = User.find(2)
578
591
579 issue = Issue.new(:project_id => 1, :tracker_id => 1)
592 issue = Issue.new(:project_id => 1, :tracker_id => 1)
580 assert_equal %w(due_date), issue.read_only_attribute_names(user)
593 assert_equal %w(due_date), issue.read_only_attribute_names(user)
581 assert_not_include 'due_date', issue.safe_attribute_names(user)
594 assert_not_include 'due_date', issue.safe_attribute_names(user)
582
595
583 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
596 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
584 assert_equal Date.parse('2012-07-14'), issue.start_date
597 assert_equal Date.parse('2012-07-14'), issue.start_date
585 assert_nil issue.due_date
598 assert_nil issue.due_date
586 end
599 end
587
600
588 def test_safe_attributes_should_not_include_readonly_custom_fields
601 def test_safe_attributes_should_not_include_readonly_custom_fields
589 cf1 = IssueCustomField.create!(:name => 'Writable field',
602 cf1 = IssueCustomField.create!(:name => 'Writable field',
590 :field_format => 'string',
603 :field_format => 'string',
591 :is_for_all => true, :tracker_ids => [1])
604 :is_for_all => true, :tracker_ids => [1])
592 cf2 = IssueCustomField.create!(:name => 'Readonly field',
605 cf2 = IssueCustomField.create!(:name => 'Readonly field',
593 :field_format => 'string',
606 :field_format => 'string',
594 :is_for_all => true, :tracker_ids => [1])
607 :is_for_all => true, :tracker_ids => [1])
595 WorkflowPermission.delete_all
608 WorkflowPermission.delete_all
596 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
609 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
597 :role_id => 1, :field_name => cf2.id.to_s,
610 :role_id => 1, :field_name => cf2.id.to_s,
598 :rule => 'readonly')
611 :rule => 'readonly')
599 user = User.find(2)
612 user = User.find(2)
600 issue = Issue.new(:project_id => 1, :tracker_id => 1)
613 issue = Issue.new(:project_id => 1, :tracker_id => 1)
601 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
614 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
602 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
615 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
603
616
604 issue.send :safe_attributes=, {'custom_field_values' => {
617 issue.send :safe_attributes=, {'custom_field_values' => {
605 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
618 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
606 }}, user
619 }}, user
607 assert_equal 'value1', issue.custom_field_value(cf1)
620 assert_equal 'value1', issue.custom_field_value(cf1)
608 assert_nil issue.custom_field_value(cf2)
621 assert_nil issue.custom_field_value(cf2)
609
622
610 issue.send :safe_attributes=, {'custom_fields' => [
623 issue.send :safe_attributes=, {'custom_fields' => [
611 {'id' => cf1.id.to_s, 'value' => 'valuea'},
624 {'id' => cf1.id.to_s, 'value' => 'valuea'},
612 {'id' => cf2.id.to_s, 'value' => 'valueb'}
625 {'id' => cf2.id.to_s, 'value' => 'valueb'}
613 ]}, user
626 ]}, user
614 assert_equal 'valuea', issue.custom_field_value(cf1)
627 assert_equal 'valuea', issue.custom_field_value(cf1)
615 assert_nil issue.custom_field_value(cf2)
628 assert_nil issue.custom_field_value(cf2)
616 end
629 end
617
630
618 def test_editable_custom_field_values_should_return_non_readonly_custom_values
631 def test_editable_custom_field_values_should_return_non_readonly_custom_values
619 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
632 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
620 :is_for_all => true, :tracker_ids => [1, 2])
633 :is_for_all => true, :tracker_ids => [1, 2])
621 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
634 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
622 :is_for_all => true, :tracker_ids => [1, 2])
635 :is_for_all => true, :tracker_ids => [1, 2])
623 WorkflowPermission.delete_all
636 WorkflowPermission.delete_all
624 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
637 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
625 :field_name => cf2.id.to_s, :rule => 'readonly')
638 :field_name => cf2.id.to_s, :rule => 'readonly')
626 user = User.find(2)
639 user = User.find(2)
627
640
628 issue = Issue.new(:project_id => 1, :tracker_id => 1)
641 issue = Issue.new(:project_id => 1, :tracker_id => 1)
629 values = issue.editable_custom_field_values(user)
642 values = issue.editable_custom_field_values(user)
630 assert values.detect {|value| value.custom_field == cf1}
643 assert values.detect {|value| value.custom_field == cf1}
631 assert_nil values.detect {|value| value.custom_field == cf2}
644 assert_nil values.detect {|value| value.custom_field == cf2}
632
645
633 issue.tracker_id = 2
646 issue.tracker_id = 2
634 values = issue.editable_custom_field_values(user)
647 values = issue.editable_custom_field_values(user)
635 assert values.detect {|value| value.custom_field == cf1}
648 assert values.detect {|value| value.custom_field == cf1}
636 assert values.detect {|value| value.custom_field == cf2}
649 assert values.detect {|value| value.custom_field == cf2}
637 end
650 end
638
651
639 def test_safe_attributes_should_accept_target_tracker_writable_fields
652 def test_safe_attributes_should_accept_target_tracker_writable_fields
640 WorkflowPermission.delete_all
653 WorkflowPermission.delete_all
641 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
654 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
642 :role_id => 1, :field_name => 'due_date',
655 :role_id => 1, :field_name => 'due_date',
643 :rule => 'readonly')
656 :rule => 'readonly')
644 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
657 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
645 :role_id => 1, :field_name => 'start_date',
658 :role_id => 1, :field_name => 'start_date',
646 :rule => 'readonly')
659 :rule => 'readonly')
647 user = User.find(2)
660 user = User.find(2)
648
661
649 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
662 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
650
663
651 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
664 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
652 'due_date' => '2012-07-14'}, user
665 'due_date' => '2012-07-14'}, user
653 assert_equal Date.parse('2012-07-12'), issue.start_date
666 assert_equal Date.parse('2012-07-12'), issue.start_date
654 assert_nil issue.due_date
667 assert_nil issue.due_date
655
668
656 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
669 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
657 'due_date' => '2012-07-16',
670 'due_date' => '2012-07-16',
658 'tracker_id' => 2}, user
671 'tracker_id' => 2}, user
659 assert_equal Date.parse('2012-07-12'), issue.start_date
672 assert_equal Date.parse('2012-07-12'), issue.start_date
660 assert_equal Date.parse('2012-07-16'), issue.due_date
673 assert_equal Date.parse('2012-07-16'), issue.due_date
661 end
674 end
662
675
663 def test_safe_attributes_should_accept_target_status_writable_fields
676 def test_safe_attributes_should_accept_target_status_writable_fields
664 WorkflowPermission.delete_all
677 WorkflowPermission.delete_all
665 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
678 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
666 :role_id => 1, :field_name => 'due_date',
679 :role_id => 1, :field_name => 'due_date',
667 :rule => 'readonly')
680 :rule => 'readonly')
668 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
681 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
669 :role_id => 1, :field_name => 'start_date',
682 :role_id => 1, :field_name => 'start_date',
670 :rule => 'readonly')
683 :rule => 'readonly')
671 user = User.find(2)
684 user = User.find(2)
672
685
673 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
686 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
674
687
675 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
688 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
676 'due_date' => '2012-07-14'},
689 'due_date' => '2012-07-14'},
677 user
690 user
678 assert_equal Date.parse('2012-07-12'), issue.start_date
691 assert_equal Date.parse('2012-07-12'), issue.start_date
679 assert_nil issue.due_date
692 assert_nil issue.due_date
680
693
681 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
694 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
682 'due_date' => '2012-07-16',
695 'due_date' => '2012-07-16',
683 'status_id' => 2},
696 'status_id' => 2},
684 user
697 user
685 assert_equal Date.parse('2012-07-12'), issue.start_date
698 assert_equal Date.parse('2012-07-12'), issue.start_date
686 assert_equal Date.parse('2012-07-16'), issue.due_date
699 assert_equal Date.parse('2012-07-16'), issue.due_date
687 end
700 end
688
701
689 def test_required_attributes_should_be_validated
702 def test_required_attributes_should_be_validated
690 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
703 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
691 :is_for_all => true, :tracker_ids => [1, 2])
704 :is_for_all => true, :tracker_ids => [1, 2])
692
705
693 WorkflowPermission.delete_all
706 WorkflowPermission.delete_all
694 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
707 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
695 :role_id => 1, :field_name => 'due_date',
708 :role_id => 1, :field_name => 'due_date',
696 :rule => 'required')
709 :rule => 'required')
697 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
710 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
698 :role_id => 1, :field_name => 'category_id',
711 :role_id => 1, :field_name => 'category_id',
699 :rule => 'required')
712 :rule => 'required')
700 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
713 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
701 :role_id => 1, :field_name => cf.id.to_s,
714 :role_id => 1, :field_name => cf.id.to_s,
702 :rule => 'required')
715 :rule => 'required')
703
716
704 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
717 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
705 :role_id => 1, :field_name => 'start_date',
718 :role_id => 1, :field_name => 'start_date',
706 :rule => 'required')
719 :rule => 'required')
707 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
720 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
708 :role_id => 1, :field_name => cf.id.to_s,
721 :role_id => 1, :field_name => cf.id.to_s,
709 :rule => 'required')
722 :rule => 'required')
710 user = User.find(2)
723 user = User.find(2)
711
724
712 issue = Issue.new(:project_id => 1, :tracker_id => 1,
725 issue = Issue.new(:project_id => 1, :tracker_id => 1,
713 :status_id => 1, :subject => 'Required fields',
726 :status_id => 1, :subject => 'Required fields',
714 :author => user)
727 :author => user)
715 assert_equal [cf.id.to_s, "category_id", "due_date"],
728 assert_equal [cf.id.to_s, "category_id", "due_date"],
716 issue.required_attribute_names(user).sort
729 issue.required_attribute_names(user).sort
717 assert !issue.save, "Issue was saved"
730 assert !issue.save, "Issue was saved"
718 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
731 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
719 issue.errors.full_messages.sort
732 issue.errors.full_messages.sort
720
733
721 issue.tracker_id = 2
734 issue.tracker_id = 2
722 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
735 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
723 assert !issue.save, "Issue was saved"
736 assert !issue.save, "Issue was saved"
724 assert_equal ["Foo can't be blank", "Start date can't be blank"],
737 assert_equal ["Foo can't be blank", "Start date can't be blank"],
725 issue.errors.full_messages.sort
738 issue.errors.full_messages.sort
726
739
727 issue.start_date = Date.today
740 issue.start_date = Date.today
728 issue.custom_field_values = {cf.id.to_s => 'bar'}
741 issue.custom_field_values = {cf.id.to_s => 'bar'}
729 assert issue.save
742 assert issue.save
730 end
743 end
731
744
732 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
745 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
733 WorkflowPermission.delete_all
746 WorkflowPermission.delete_all
734 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
747 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
735 :role_id => 1, :field_name => 'due_date',
748 :role_id => 1, :field_name => 'due_date',
736 :rule => 'required')
749 :rule => 'required')
737 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
750 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
738 :role_id => 1, :field_name => 'start_date',
751 :role_id => 1, :field_name => 'start_date',
739 :rule => 'required')
752 :rule => 'required')
740 user = User.find(2)
753 user = User.find(2)
741 member = Member.find(1)
754 member = Member.find(1)
742 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
755 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
743
756
744 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
757 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
745
758
746 member.role_ids = [1, 2]
759 member.role_ids = [1, 2]
747 member.save!
760 member.save!
748 assert_equal [], issue.required_attribute_names(user.reload)
761 assert_equal [], issue.required_attribute_names(user.reload)
749
762
750 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
763 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
751 :role_id => 2, :field_name => 'due_date',
764 :role_id => 2, :field_name => 'due_date',
752 :rule => 'required')
765 :rule => 'required')
753 assert_equal %w(due_date), issue.required_attribute_names(user)
766 assert_equal %w(due_date), issue.required_attribute_names(user)
754
767
755 member.role_ids = [1, 2, 3]
768 member.role_ids = [1, 2, 3]
756 member.save!
769 member.save!
757 assert_equal [], issue.required_attribute_names(user.reload)
770 assert_equal [], issue.required_attribute_names(user.reload)
758
771
759 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
772 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
760 :role_id => 2, :field_name => 'due_date',
773 :role_id => 2, :field_name => 'due_date',
761 :rule => 'readonly')
774 :rule => 'readonly')
762 # required + readonly => required
775 # required + readonly => required
763 assert_equal %w(due_date), issue.required_attribute_names(user)
776 assert_equal %w(due_date), issue.required_attribute_names(user)
764 end
777 end
765
778
766 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
779 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
767 WorkflowPermission.delete_all
780 WorkflowPermission.delete_all
768 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
781 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
769 :role_id => 1, :field_name => 'due_date',
782 :role_id => 1, :field_name => 'due_date',
770 :rule => 'readonly')
783 :rule => 'readonly')
771 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
784 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
772 :role_id => 1, :field_name => 'start_date',
785 :role_id => 1, :field_name => 'start_date',
773 :rule => 'readonly')
786 :rule => 'readonly')
774 user = User.find(2)
787 user = User.find(2)
775 member = Member.find(1)
788 member = Member.find(1)
776 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
789 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
777
790
778 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
791 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
779
792
780 member.role_ids = [1, 2]
793 member.role_ids = [1, 2]
781 member.save!
794 member.save!
782 assert_equal [], issue.read_only_attribute_names(user.reload)
795 assert_equal [], issue.read_only_attribute_names(user.reload)
783
796
784 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
797 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
785 :role_id => 2, :field_name => 'due_date',
798 :role_id => 2, :field_name => 'due_date',
786 :rule => 'readonly')
799 :rule => 'readonly')
787 assert_equal %w(due_date), issue.read_only_attribute_names(user)
800 assert_equal %w(due_date), issue.read_only_attribute_names(user)
788 end
801 end
789
802
790 def test_copy
803 def test_copy
791 issue = Issue.new.copy_from(1)
804 issue = Issue.new.copy_from(1)
792 assert issue.copy?
805 assert issue.copy?
793 assert issue.save
806 assert issue.save
794 issue.reload
807 issue.reload
795 orig = Issue.find(1)
808 orig = Issue.find(1)
796 assert_equal orig.subject, issue.subject
809 assert_equal orig.subject, issue.subject
797 assert_equal orig.tracker, issue.tracker
810 assert_equal orig.tracker, issue.tracker
798 assert_equal "125", issue.custom_value_for(2).value
811 assert_equal "125", issue.custom_value_for(2).value
799 end
812 end
800
813
801 def test_copy_should_copy_status
814 def test_copy_should_copy_status
802 orig = Issue.find(8)
815 orig = Issue.find(8)
803 assert orig.status != IssueStatus.default
816 assert orig.status != IssueStatus.default
804
817
805 issue = Issue.new.copy_from(orig)
818 issue = Issue.new.copy_from(orig)
806 assert issue.save
819 assert issue.save
807 issue.reload
820 issue.reload
808 assert_equal orig.status, issue.status
821 assert_equal orig.status, issue.status
809 end
822 end
810
823
811 def test_copy_should_add_relation_with_copied_issue
824 def test_copy_should_add_relation_with_copied_issue
812 copied = Issue.find(1)
825 copied = Issue.find(1)
813 issue = Issue.new.copy_from(copied)
826 issue = Issue.new.copy_from(copied)
814 assert issue.save
827 assert issue.save
815 issue.reload
828 issue.reload
816
829
817 assert_equal 1, issue.relations.size
830 assert_equal 1, issue.relations.size
818 relation = issue.relations.first
831 relation = issue.relations.first
819 assert_equal 'copied_to', relation.relation_type
832 assert_equal 'copied_to', relation.relation_type
820 assert_equal copied, relation.issue_from
833 assert_equal copied, relation.issue_from
821 assert_equal issue, relation.issue_to
834 assert_equal issue, relation.issue_to
822 end
835 end
823
836
824 def test_copy_should_copy_subtasks
837 def test_copy_should_copy_subtasks
825 issue = Issue.generate_with_descendants!
838 issue = Issue.generate_with_descendants!
826
839
827 copy = issue.reload.copy
840 copy = issue.reload.copy
828 copy.author = User.find(7)
841 copy.author = User.find(7)
829 assert_difference 'Issue.count', 1+issue.descendants.count do
842 assert_difference 'Issue.count', 1+issue.descendants.count do
830 assert copy.save
843 assert copy.save
831 end
844 end
832 copy.reload
845 copy.reload
833 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
846 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
834 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
847 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
835 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
848 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
836 assert_equal copy.author, child_copy.author
849 assert_equal copy.author, child_copy.author
837 end
850 end
838
851
839 def test_copy_should_copy_subtasks_to_target_project
852 def test_copy_should_copy_subtasks_to_target_project
840 issue = Issue.generate_with_descendants!
853 issue = Issue.generate_with_descendants!
841
854
842 copy = issue.copy(:project_id => 3)
855 copy = issue.copy(:project_id => 3)
843 assert_difference 'Issue.count', 1+issue.descendants.count do
856 assert_difference 'Issue.count', 1+issue.descendants.count do
844 assert copy.save
857 assert copy.save
845 end
858 end
846 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
859 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
847 end
860 end
848
861
849 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
862 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
850 issue = Issue.generate_with_descendants!
863 issue = Issue.generate_with_descendants!
851
864
852 copy = issue.reload.copy
865 copy = issue.reload.copy
853 assert_difference 'Issue.count', 1+issue.descendants.count do
866 assert_difference 'Issue.count', 1+issue.descendants.count do
854 assert copy.save
867 assert copy.save
855 assert copy.save
868 assert copy.save
856 end
869 end
857 end
870 end
858
871
859 def test_should_not_call_after_project_change_on_creation
872 def test_should_not_call_after_project_change_on_creation
860 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,
861 :subject => 'Test', :author_id => 1)
874 :subject => 'Test', :author_id => 1)
862 issue.expects(:after_project_change).never
875 issue.expects(:after_project_change).never
863 issue.save!
876 issue.save!
864 end
877 end
865
878
866 def test_should_not_call_after_project_change_on_update
879 def test_should_not_call_after_project_change_on_update
867 issue = Issue.find(1)
880 issue = Issue.find(1)
868 issue.project = Project.find(1)
881 issue.project = Project.find(1)
869 issue.subject = 'No project change'
882 issue.subject = 'No project change'
870 issue.expects(:after_project_change).never
883 issue.expects(:after_project_change).never
871 issue.save!
884 issue.save!
872 end
885 end
873
886
874 def test_should_call_after_project_change_on_project_change
887 def test_should_call_after_project_change_on_project_change
875 issue = Issue.find(1)
888 issue = Issue.find(1)
876 issue.project = Project.find(2)
889 issue.project = Project.find(2)
877 issue.expects(:after_project_change).once
890 issue.expects(:after_project_change).once
878 issue.save!
891 issue.save!
879 end
892 end
880
893
881 def test_adding_journal_should_update_timestamp
894 def test_adding_journal_should_update_timestamp
882 issue = Issue.find(1)
895 issue = Issue.find(1)
883 updated_on_was = issue.updated_on
896 updated_on_was = issue.updated_on
884
897
885 issue.init_journal(User.first, "Adding notes")
898 issue.init_journal(User.first, "Adding notes")
886 assert_difference 'Journal.count' do
899 assert_difference 'Journal.count' do
887 assert issue.save
900 assert issue.save
888 end
901 end
889 issue.reload
902 issue.reload
890
903
891 assert_not_equal updated_on_was, issue.updated_on
904 assert_not_equal updated_on_was, issue.updated_on
892 end
905 end
893
906
894 def test_should_close_duplicates
907 def test_should_close_duplicates
895 # Create 3 issues
908 # Create 3 issues
896 issue1 = Issue.generate!
909 issue1 = Issue.generate!
897 issue2 = Issue.generate!
910 issue2 = Issue.generate!
898 issue3 = Issue.generate!
911 issue3 = Issue.generate!
899
912
900 # 2 is a dupe of 1
913 # 2 is a dupe of 1
901 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
914 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
902 :relation_type => IssueRelation::TYPE_DUPLICATES)
915 :relation_type => IssueRelation::TYPE_DUPLICATES)
903 # And 3 is a dupe of 2
916 # And 3 is a dupe of 2
904 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
917 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
905 :relation_type => IssueRelation::TYPE_DUPLICATES)
918 :relation_type => IssueRelation::TYPE_DUPLICATES)
906 # And 3 is a dupe of 1 (circular duplicates)
919 # And 3 is a dupe of 1 (circular duplicates)
907 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
920 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
908 :relation_type => IssueRelation::TYPE_DUPLICATES)
921 :relation_type => IssueRelation::TYPE_DUPLICATES)
909
922
910 assert issue1.reload.duplicates.include?(issue2)
923 assert issue1.reload.duplicates.include?(issue2)
911
924
912 # Closing issue 1
925 # Closing issue 1
913 issue1.init_journal(User.first, "Closing issue1")
926 issue1.init_journal(User.first, "Closing issue1")
914 issue1.status = IssueStatus.where(:is_closed => true).first
927 issue1.status = IssueStatus.where(:is_closed => true).first
915 assert issue1.save
928 assert issue1.save
916 # 2 and 3 should be also closed
929 # 2 and 3 should be also closed
917 assert issue2.reload.closed?
930 assert issue2.reload.closed?
918 assert issue3.reload.closed?
931 assert issue3.reload.closed?
919 end
932 end
920
933
921 def test_should_not_close_duplicated_issue
934 def test_should_not_close_duplicated_issue
922 issue1 = Issue.generate!
935 issue1 = Issue.generate!
923 issue2 = Issue.generate!
936 issue2 = Issue.generate!
924
937
925 # 2 is a dupe of 1
938 # 2 is a dupe of 1
926 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
939 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
927 :relation_type => IssueRelation::TYPE_DUPLICATES)
940 :relation_type => IssueRelation::TYPE_DUPLICATES)
928 # 2 is a dup of 1 but 1 is not a duplicate of 2
941 # 2 is a dup of 1 but 1 is not a duplicate of 2
929 assert !issue2.reload.duplicates.include?(issue1)
942 assert !issue2.reload.duplicates.include?(issue1)
930
943
931 # Closing issue 2
944 # Closing issue 2
932 issue2.init_journal(User.first, "Closing issue2")
945 issue2.init_journal(User.first, "Closing issue2")
933 issue2.status = IssueStatus.where(:is_closed => true).first
946 issue2.status = IssueStatus.where(:is_closed => true).first
934 assert issue2.save
947 assert issue2.save
935 # 1 should not be also closed
948 # 1 should not be also closed
936 assert !issue1.reload.closed?
949 assert !issue1.reload.closed?
937 end
950 end
938
951
939 def test_assignable_versions
952 def test_assignable_versions
940 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
953 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
941 :status_id => 1, :fixed_version_id => 1,
954 :status_id => 1, :fixed_version_id => 1,
942 :subject => 'New issue')
955 :subject => 'New issue')
943 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
956 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
944 end
957 end
945
958
946 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
959 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
947 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
960 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
948 :status_id => 1, :fixed_version_id => 1,
961 :status_id => 1, :fixed_version_id => 1,
949 :subject => 'New issue')
962 :subject => 'New issue')
950 assert !issue.save
963 assert !issue.save
951 assert_not_nil issue.errors[:fixed_version_id]
964 assert_not_nil issue.errors[:fixed_version_id]
952 end
965 end
953
966
954 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
967 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
955 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
968 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
956 :status_id => 1, :fixed_version_id => 2,
969 :status_id => 1, :fixed_version_id => 2,
957 :subject => 'New issue')
970 :subject => 'New issue')
958 assert !issue.save
971 assert !issue.save
959 assert_not_nil issue.errors[:fixed_version_id]
972 assert_not_nil issue.errors[:fixed_version_id]
960 end
973 end
961
974
962 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
975 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
963 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
976 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
964 :status_id => 1, :fixed_version_id => 3,
977 :status_id => 1, :fixed_version_id => 3,
965 :subject => 'New issue')
978 :subject => 'New issue')
966 assert issue.save
979 assert issue.save
967 end
980 end
968
981
969 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
982 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
970 issue = Issue.find(11)
983 issue = Issue.find(11)
971 assert_equal 'closed', issue.fixed_version.status
984 assert_equal 'closed', issue.fixed_version.status
972 issue.subject = 'Subject changed'
985 issue.subject = 'Subject changed'
973 assert issue.save
986 assert issue.save
974 end
987 end
975
988
976 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
989 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
977 issue = Issue.find(11)
990 issue = Issue.find(11)
978 issue.status_id = 1
991 issue.status_id = 1
979 assert !issue.save
992 assert !issue.save
980 assert_not_nil issue.errors[:base]
993 assert_not_nil issue.errors[:base]
981 end
994 end
982
995
983 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
996 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
984 issue = Issue.find(11)
997 issue = Issue.find(11)
985 issue.status_id = 1
998 issue.status_id = 1
986 issue.fixed_version_id = 3
999 issue.fixed_version_id = 3
987 assert issue.save
1000 assert issue.save
988 end
1001 end
989
1002
990 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
1003 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
991 issue = Issue.find(12)
1004 issue = Issue.find(12)
992 assert_equal 'locked', issue.fixed_version.status
1005 assert_equal 'locked', issue.fixed_version.status
993 issue.status_id = 1
1006 issue.status_id = 1
994 assert issue.save
1007 assert issue.save
995 end
1008 end
996
1009
997 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
1010 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
998 issue = Issue.find(2)
1011 issue = Issue.find(2)
999 assert_equal 2, issue.fixed_version_id
1012 assert_equal 2, issue.fixed_version_id
1000 issue.project_id = 3
1013 issue.project_id = 3
1001 assert_nil issue.fixed_version_id
1014 assert_nil issue.fixed_version_id
1002 issue.fixed_version_id = 2
1015 issue.fixed_version_id = 2
1003 assert !issue.save
1016 assert !issue.save
1004 assert_include 'Target version is not included in the list', issue.errors.full_messages
1017 assert_include 'Target version is not included in the list', issue.errors.full_messages
1005 end
1018 end
1006
1019
1007 def test_should_keep_shared_version_when_changing_project
1020 def test_should_keep_shared_version_when_changing_project
1008 Version.find(2).update_attribute :sharing, 'tree'
1021 Version.find(2).update_attribute :sharing, 'tree'
1009
1022
1010 issue = Issue.find(2)
1023 issue = Issue.find(2)
1011 assert_equal 2, issue.fixed_version_id
1024 assert_equal 2, issue.fixed_version_id
1012 issue.project_id = 3
1025 issue.project_id = 3
1013 assert_equal 2, issue.fixed_version_id
1026 assert_equal 2, issue.fixed_version_id
1014 assert issue.save
1027 assert issue.save
1015 end
1028 end
1016
1029
1017 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1030 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
1018 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1031 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1019 end
1032 end
1020
1033
1021 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1034 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
1022 Project.find(2).disable_module! :issue_tracking
1035 Project.find(2).disable_module! :issue_tracking
1023 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1036 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
1024 end
1037 end
1025
1038
1026 def test_move_to_another_project_with_same_category
1039 def test_move_to_another_project_with_same_category
1027 issue = Issue.find(1)
1040 issue = Issue.find(1)
1028 issue.project = Project.find(2)
1041 issue.project = Project.find(2)
1029 assert issue.save
1042 assert issue.save
1030 issue.reload
1043 issue.reload
1031 assert_equal 2, issue.project_id
1044 assert_equal 2, issue.project_id
1032 # Category changes
1045 # Category changes
1033 assert_equal 4, issue.category_id
1046 assert_equal 4, issue.category_id
1034 # Make sure time entries were move to the target project
1047 # Make sure time entries were move to the target project
1035 assert_equal 2, issue.time_entries.first.project_id
1048 assert_equal 2, issue.time_entries.first.project_id
1036 end
1049 end
1037
1050
1038 def test_move_to_another_project_without_same_category
1051 def test_move_to_another_project_without_same_category
1039 issue = Issue.find(2)
1052 issue = Issue.find(2)
1040 issue.project = Project.find(2)
1053 issue.project = Project.find(2)
1041 assert issue.save
1054 assert issue.save
1042 issue.reload
1055 issue.reload
1043 assert_equal 2, issue.project_id
1056 assert_equal 2, issue.project_id
1044 # Category cleared
1057 # Category cleared
1045 assert_nil issue.category_id
1058 assert_nil issue.category_id
1046 end
1059 end
1047
1060
1048 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1061 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
1049 issue = Issue.find(1)
1062 issue = Issue.find(1)
1050 issue.update_attribute(:fixed_version_id, 1)
1063 issue.update_attribute(:fixed_version_id, 1)
1051 issue.project = Project.find(2)
1064 issue.project = Project.find(2)
1052 assert issue.save
1065 assert issue.save
1053 issue.reload
1066 issue.reload
1054 assert_equal 2, issue.project_id
1067 assert_equal 2, issue.project_id
1055 # Cleared fixed_version
1068 # Cleared fixed_version
1056 assert_equal nil, issue.fixed_version
1069 assert_equal nil, issue.fixed_version
1057 end
1070 end
1058
1071
1059 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1072 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1060 issue = Issue.find(1)
1073 issue = Issue.find(1)
1061 issue.update_attribute(:fixed_version_id, 4)
1074 issue.update_attribute(:fixed_version_id, 4)
1062 issue.project = Project.find(5)
1075 issue.project = Project.find(5)
1063 assert issue.save
1076 assert issue.save
1064 issue.reload
1077 issue.reload
1065 assert_equal 5, issue.project_id
1078 assert_equal 5, issue.project_id
1066 # Keep fixed_version
1079 # Keep fixed_version
1067 assert_equal 4, issue.fixed_version_id
1080 assert_equal 4, issue.fixed_version_id
1068 end
1081 end
1069
1082
1070 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1083 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1071 issue = Issue.find(1)
1084 issue = Issue.find(1)
1072 issue.update_attribute(:fixed_version_id, 1)
1085 issue.update_attribute(:fixed_version_id, 1)
1073 issue.project = Project.find(5)
1086 issue.project = Project.find(5)
1074 assert issue.save
1087 assert issue.save
1075 issue.reload
1088 issue.reload
1076 assert_equal 5, issue.project_id
1089 assert_equal 5, issue.project_id
1077 # Cleared fixed_version
1090 # Cleared fixed_version
1078 assert_equal nil, issue.fixed_version
1091 assert_equal nil, issue.fixed_version
1079 end
1092 end
1080
1093
1081 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1094 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1082 issue = Issue.find(1)
1095 issue = Issue.find(1)
1083 issue.update_attribute(:fixed_version_id, 7)
1096 issue.update_attribute(:fixed_version_id, 7)
1084 issue.project = Project.find(2)
1097 issue.project = Project.find(2)
1085 assert issue.save
1098 assert issue.save
1086 issue.reload
1099 issue.reload
1087 assert_equal 2, issue.project_id
1100 assert_equal 2, issue.project_id
1088 # Keep fixed_version
1101 # Keep fixed_version
1089 assert_equal 7, issue.fixed_version_id
1102 assert_equal 7, issue.fixed_version_id
1090 end
1103 end
1091
1104
1092 def test_move_to_another_project_should_keep_parent_if_valid
1105 def test_move_to_another_project_should_keep_parent_if_valid
1093 issue = Issue.find(1)
1106 issue = Issue.find(1)
1094 issue.update_attribute(:parent_issue_id, 2)
1107 issue.update_attribute(:parent_issue_id, 2)
1095 issue.project = Project.find(3)
1108 issue.project = Project.find(3)
1096 assert issue.save
1109 assert issue.save
1097 issue.reload
1110 issue.reload
1098 assert_equal 2, issue.parent_id
1111 assert_equal 2, issue.parent_id
1099 end
1112 end
1100
1113
1101 def test_move_to_another_project_should_clear_parent_if_not_valid
1114 def test_move_to_another_project_should_clear_parent_if_not_valid
1102 issue = Issue.find(1)
1115 issue = Issue.find(1)
1103 issue.update_attribute(:parent_issue_id, 2)
1116 issue.update_attribute(:parent_issue_id, 2)
1104 issue.project = Project.find(2)
1117 issue.project = Project.find(2)
1105 assert issue.save
1118 assert issue.save
1106 issue.reload
1119 issue.reload
1107 assert_nil issue.parent_id
1120 assert_nil issue.parent_id
1108 end
1121 end
1109
1122
1110 def test_move_to_another_project_with_disabled_tracker
1123 def test_move_to_another_project_with_disabled_tracker
1111 issue = Issue.find(1)
1124 issue = Issue.find(1)
1112 target = Project.find(2)
1125 target = Project.find(2)
1113 target.tracker_ids = [3]
1126 target.tracker_ids = [3]
1114 target.save
1127 target.save
1115 issue.project = target
1128 issue.project = target
1116 assert issue.save
1129 assert issue.save
1117 issue.reload
1130 issue.reload
1118 assert_equal 2, issue.project_id
1131 assert_equal 2, issue.project_id
1119 assert_equal 3, issue.tracker_id
1132 assert_equal 3, issue.tracker_id
1120 end
1133 end
1121
1134
1122 def test_copy_to_the_same_project
1135 def test_copy_to_the_same_project
1123 issue = Issue.find(1)
1136 issue = Issue.find(1)
1124 copy = issue.copy
1137 copy = issue.copy
1125 assert_difference 'Issue.count' do
1138 assert_difference 'Issue.count' do
1126 copy.save!
1139 copy.save!
1127 end
1140 end
1128 assert_kind_of Issue, copy
1141 assert_kind_of Issue, copy
1129 assert_equal issue.project, copy.project
1142 assert_equal issue.project, copy.project
1130 assert_equal "125", copy.custom_value_for(2).value
1143 assert_equal "125", copy.custom_value_for(2).value
1131 end
1144 end
1132
1145
1133 def test_copy_to_another_project_and_tracker
1146 def test_copy_to_another_project_and_tracker
1134 issue = Issue.find(1)
1147 issue = Issue.find(1)
1135 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1148 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1136 assert_difference 'Issue.count' do
1149 assert_difference 'Issue.count' do
1137 copy.save!
1150 copy.save!
1138 end
1151 end
1139 copy.reload
1152 copy.reload
1140 assert_kind_of Issue, copy
1153 assert_kind_of Issue, copy
1141 assert_equal Project.find(3), copy.project
1154 assert_equal Project.find(3), copy.project
1142 assert_equal Tracker.find(2), copy.tracker
1155 assert_equal Tracker.find(2), copy.tracker
1143 # Custom field #2 is not associated with target tracker
1156 # Custom field #2 is not associated with target tracker
1144 assert_nil copy.custom_value_for(2)
1157 assert_nil copy.custom_value_for(2)
1145 end
1158 end
1146
1159
1147 test "#copy should not create a journal" do
1160 test "#copy should not create a journal" do
1148 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1161 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1149 copy.save!
1162 copy.save!
1150 assert_equal 0, copy.reload.journals.size
1163 assert_equal 0, copy.reload.journals.size
1151 end
1164 end
1152
1165
1153 test "#copy should allow assigned_to changes" do
1166 test "#copy should allow assigned_to changes" do
1154 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1167 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1155 assert_equal 3, copy.assigned_to_id
1168 assert_equal 3, copy.assigned_to_id
1156 end
1169 end
1157
1170
1158 test "#copy should allow status changes" do
1171 test "#copy should allow status changes" do
1159 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1172 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1160 assert_equal 2, copy.status_id
1173 assert_equal 2, copy.status_id
1161 end
1174 end
1162
1175
1163 test "#copy should allow start date changes" do
1176 test "#copy should allow start date changes" do
1164 date = Date.today
1177 date = Date.today
1165 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1178 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1166 assert_equal date, copy.start_date
1179 assert_equal date, copy.start_date
1167 end
1180 end
1168
1181
1169 test "#copy should allow due date changes" do
1182 test "#copy should allow due date changes" do
1170 date = Date.today
1183 date = Date.today
1171 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1184 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1172 assert_equal date, copy.due_date
1185 assert_equal date, copy.due_date
1173 end
1186 end
1174
1187
1175 test "#copy should set current user as author" do
1188 test "#copy should set current user as author" do
1176 User.current = User.find(9)
1189 User.current = User.find(9)
1177 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1190 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1178 assert_equal User.current, copy.author
1191 assert_equal User.current, copy.author
1179 end
1192 end
1180
1193
1181 test "#copy should create a journal with notes" do
1194 test "#copy should create a journal with notes" do
1182 date = Date.today
1195 date = Date.today
1183 notes = "Notes added when copying"
1196 notes = "Notes added when copying"
1184 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1197 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1185 copy.init_journal(User.current, notes)
1198 copy.init_journal(User.current, notes)
1186 copy.save!
1199 copy.save!
1187
1200
1188 assert_equal 1, copy.journals.size
1201 assert_equal 1, copy.journals.size
1189 journal = copy.journals.first
1202 journal = copy.journals.first
1190 assert_equal 0, journal.details.size
1203 assert_equal 0, journal.details.size
1191 assert_equal notes, journal.notes
1204 assert_equal notes, journal.notes
1192 end
1205 end
1193
1206
1194 def test_valid_parent_project
1207 def test_valid_parent_project
1195 issue = Issue.find(1)
1208 issue = Issue.find(1)
1196 issue_in_same_project = Issue.find(2)
1209 issue_in_same_project = Issue.find(2)
1197 issue_in_child_project = Issue.find(5)
1210 issue_in_child_project = Issue.find(5)
1198 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1211 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1199 issue_in_other_child_project = Issue.find(6)
1212 issue_in_other_child_project = Issue.find(6)
1200 issue_in_different_tree = Issue.find(4)
1213 issue_in_different_tree = Issue.find(4)
1201
1214
1202 with_settings :cross_project_subtasks => '' do
1215 with_settings :cross_project_subtasks => '' do
1203 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1216 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1204 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1217 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1205 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1218 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1206 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1219 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1207 end
1220 end
1208
1221
1209 with_settings :cross_project_subtasks => 'system' do
1222 with_settings :cross_project_subtasks => 'system' do
1210 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1223 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1211 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1224 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1212 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1225 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1213 end
1226 end
1214
1227
1215 with_settings :cross_project_subtasks => 'tree' do
1228 with_settings :cross_project_subtasks => 'tree' do
1216 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1229 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1217 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1230 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1218 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1231 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1219 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1232 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1220
1233
1221 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1234 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1222 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1235 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1223 end
1236 end
1224
1237
1225 with_settings :cross_project_subtasks => 'descendants' do
1238 with_settings :cross_project_subtasks => 'descendants' do
1226 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1239 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1227 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1240 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1228 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1241 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1229 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1242 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1230
1243
1231 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1244 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1232 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1245 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1233 end
1246 end
1234 end
1247 end
1235
1248
1236 def test_recipients_should_include_previous_assignee
1249 def test_recipients_should_include_previous_assignee
1237 user = User.find(3)
1250 user = User.find(3)
1238 user.members.update_all ["mail_notification = ?", false]
1251 user.members.update_all ["mail_notification = ?", false]
1239 user.update_attribute :mail_notification, 'only_assigned'
1252 user.update_attribute :mail_notification, 'only_assigned'
1240
1253
1241 issue = Issue.find(2)
1254 issue = Issue.find(2)
1242 issue.assigned_to = nil
1255 issue.assigned_to = nil
1243 assert_include user.mail, issue.recipients
1256 assert_include user.mail, issue.recipients
1244 issue.save!
1257 issue.save!
1245 assert !issue.recipients.include?(user.mail)
1258 assert !issue.recipients.include?(user.mail)
1246 end
1259 end
1247
1260
1248 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1261 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1249 issue = Issue.find(12)
1262 issue = Issue.find(12)
1250 assert issue.recipients.include?(issue.author.mail)
1263 assert issue.recipients.include?(issue.author.mail)
1251 # copy the issue to a private project
1264 # copy the issue to a private project
1252 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1265 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1253 # author is not a member of project anymore
1266 # author is not a member of project anymore
1254 assert !copy.recipients.include?(copy.author.mail)
1267 assert !copy.recipients.include?(copy.author.mail)
1255 end
1268 end
1256
1269
1257 def test_recipients_should_include_the_assigned_group_members
1270 def test_recipients_should_include_the_assigned_group_members
1258 group_member = User.generate!
1271 group_member = User.generate!
1259 group = Group.generate!
1272 group = Group.generate!
1260 group.users << group_member
1273 group.users << group_member
1261
1274
1262 issue = Issue.find(12)
1275 issue = Issue.find(12)
1263 issue.assigned_to = group
1276 issue.assigned_to = group
1264 assert issue.recipients.include?(group_member.mail)
1277 assert issue.recipients.include?(group_member.mail)
1265 end
1278 end
1266
1279
1267 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1280 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1268 user = User.find(3)
1281 user = User.find(3)
1269 issue = Issue.find(9)
1282 issue = Issue.find(9)
1270 Watcher.create!(:user => user, :watchable => issue)
1283 Watcher.create!(:user => user, :watchable => issue)
1271 assert issue.watched_by?(user)
1284 assert issue.watched_by?(user)
1272 assert !issue.watcher_recipients.include?(user.mail)
1285 assert !issue.watcher_recipients.include?(user.mail)
1273 end
1286 end
1274
1287
1275 def test_issue_destroy
1288 def test_issue_destroy
1276 Issue.find(1).destroy
1289 Issue.find(1).destroy
1277 assert_nil Issue.find_by_id(1)
1290 assert_nil Issue.find_by_id(1)
1278 assert_nil TimeEntry.find_by_issue_id(1)
1291 assert_nil TimeEntry.find_by_issue_id(1)
1279 end
1292 end
1280
1293
1281 def test_destroying_a_deleted_issue_should_not_raise_an_error
1294 def test_destroying_a_deleted_issue_should_not_raise_an_error
1282 issue = Issue.find(1)
1295 issue = Issue.find(1)
1283 Issue.find(1).destroy
1296 Issue.find(1).destroy
1284
1297
1285 assert_nothing_raised do
1298 assert_nothing_raised do
1286 assert_no_difference 'Issue.count' do
1299 assert_no_difference 'Issue.count' do
1287 issue.destroy
1300 issue.destroy
1288 end
1301 end
1289 assert issue.destroyed?
1302 assert issue.destroyed?
1290 end
1303 end
1291 end
1304 end
1292
1305
1293 def test_destroying_a_stale_issue_should_not_raise_an_error
1306 def test_destroying_a_stale_issue_should_not_raise_an_error
1294 issue = Issue.find(1)
1307 issue = Issue.find(1)
1295 Issue.find(1).update_attribute :subject, "Updated"
1308 Issue.find(1).update_attribute :subject, "Updated"
1296
1309
1297 assert_nothing_raised do
1310 assert_nothing_raised do
1298 assert_difference 'Issue.count', -1 do
1311 assert_difference 'Issue.count', -1 do
1299 issue.destroy
1312 issue.destroy
1300 end
1313 end
1301 assert issue.destroyed?
1314 assert issue.destroyed?
1302 end
1315 end
1303 end
1316 end
1304
1317
1305 def test_blocked
1318 def test_blocked
1306 blocked_issue = Issue.find(9)
1319 blocked_issue = Issue.find(9)
1307 blocking_issue = Issue.find(10)
1320 blocking_issue = Issue.find(10)
1308
1321
1309 assert blocked_issue.blocked?
1322 assert blocked_issue.blocked?
1310 assert !blocking_issue.blocked?
1323 assert !blocking_issue.blocked?
1311 end
1324 end
1312
1325
1313 def test_blocked_issues_dont_allow_closed_statuses
1326 def test_blocked_issues_dont_allow_closed_statuses
1314 blocked_issue = Issue.find(9)
1327 blocked_issue = Issue.find(9)
1315
1328
1316 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1329 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1317 assert !allowed_statuses.empty?
1330 assert !allowed_statuses.empty?
1318 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1331 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1319 assert closed_statuses.empty?
1332 assert closed_statuses.empty?
1320 end
1333 end
1321
1334
1322 def test_unblocked_issues_allow_closed_statuses
1335 def test_unblocked_issues_allow_closed_statuses
1323 blocking_issue = Issue.find(10)
1336 blocking_issue = Issue.find(10)
1324
1337
1325 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1338 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1326 assert !allowed_statuses.empty?
1339 assert !allowed_statuses.empty?
1327 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1340 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1328 assert !closed_statuses.empty?
1341 assert !closed_statuses.empty?
1329 end
1342 end
1330
1343
1331 def test_reschedule_an_issue_without_dates
1344 def test_reschedule_an_issue_without_dates
1332 with_settings :non_working_week_days => [] do
1345 with_settings :non_working_week_days => [] do
1333 issue = Issue.new(:start_date => nil, :due_date => nil)
1346 issue = Issue.new(:start_date => nil, :due_date => nil)
1334 issue.reschedule_on '2012-10-09'.to_date
1347 issue.reschedule_on '2012-10-09'.to_date
1335 assert_equal '2012-10-09'.to_date, issue.start_date
1348 assert_equal '2012-10-09'.to_date, issue.start_date
1336 assert_equal '2012-10-09'.to_date, issue.due_date
1349 assert_equal '2012-10-09'.to_date, issue.due_date
1337 end
1350 end
1338
1351
1339 with_settings :non_working_week_days => %w(6 7) do
1352 with_settings :non_working_week_days => %w(6 7) do
1340 issue = Issue.new(:start_date => nil, :due_date => nil)
1353 issue = Issue.new(:start_date => nil, :due_date => nil)
1341 issue.reschedule_on '2012-10-09'.to_date
1354 issue.reschedule_on '2012-10-09'.to_date
1342 assert_equal '2012-10-09'.to_date, issue.start_date
1355 assert_equal '2012-10-09'.to_date, issue.start_date
1343 assert_equal '2012-10-09'.to_date, issue.due_date
1356 assert_equal '2012-10-09'.to_date, issue.due_date
1344
1357
1345 issue = Issue.new(:start_date => nil, :due_date => nil)
1358 issue = Issue.new(:start_date => nil, :due_date => nil)
1346 issue.reschedule_on '2012-10-13'.to_date
1359 issue.reschedule_on '2012-10-13'.to_date
1347 assert_equal '2012-10-15'.to_date, issue.start_date
1360 assert_equal '2012-10-15'.to_date, issue.start_date
1348 assert_equal '2012-10-15'.to_date, issue.due_date
1361 assert_equal '2012-10-15'.to_date, issue.due_date
1349 end
1362 end
1350 end
1363 end
1351
1364
1352 def test_reschedule_an_issue_with_start_date
1365 def test_reschedule_an_issue_with_start_date
1353 with_settings :non_working_week_days => [] do
1366 with_settings :non_working_week_days => [] do
1354 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1367 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1355 issue.reschedule_on '2012-10-13'.to_date
1368 issue.reschedule_on '2012-10-13'.to_date
1356 assert_equal '2012-10-13'.to_date, issue.start_date
1369 assert_equal '2012-10-13'.to_date, issue.start_date
1357 assert_equal '2012-10-13'.to_date, issue.due_date
1370 assert_equal '2012-10-13'.to_date, issue.due_date
1358 end
1371 end
1359
1372
1360 with_settings :non_working_week_days => %w(6 7) do
1373 with_settings :non_working_week_days => %w(6 7) do
1361 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1374 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1362 issue.reschedule_on '2012-10-11'.to_date
1375 issue.reschedule_on '2012-10-11'.to_date
1363 assert_equal '2012-10-11'.to_date, issue.start_date
1376 assert_equal '2012-10-11'.to_date, issue.start_date
1364 assert_equal '2012-10-11'.to_date, issue.due_date
1377 assert_equal '2012-10-11'.to_date, issue.due_date
1365
1378
1366 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1379 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
1367 issue.reschedule_on '2012-10-13'.to_date
1380 issue.reschedule_on '2012-10-13'.to_date
1368 assert_equal '2012-10-15'.to_date, issue.start_date
1381 assert_equal '2012-10-15'.to_date, issue.start_date
1369 assert_equal '2012-10-15'.to_date, issue.due_date
1382 assert_equal '2012-10-15'.to_date, issue.due_date
1370 end
1383 end
1371 end
1384 end
1372
1385
1373 def test_reschedule_an_issue_with_start_and_due_dates
1386 def test_reschedule_an_issue_with_start_and_due_dates
1374 with_settings :non_working_week_days => [] do
1387 with_settings :non_working_week_days => [] do
1375 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1388 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
1376 issue.reschedule_on '2012-10-13'.to_date
1389 issue.reschedule_on '2012-10-13'.to_date
1377 assert_equal '2012-10-13'.to_date, issue.start_date
1390 assert_equal '2012-10-13'.to_date, issue.start_date
1378 assert_equal '2012-10-19'.to_date, issue.due_date
1391 assert_equal '2012-10-19'.to_date, issue.due_date
1379 end
1392 end
1380
1393
1381 with_settings :non_working_week_days => %w(6 7) do
1394 with_settings :non_working_week_days => %w(6 7) do
1382 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1395 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
1383 issue.reschedule_on '2012-10-11'.to_date
1396 issue.reschedule_on '2012-10-11'.to_date
1384 assert_equal '2012-10-11'.to_date, issue.start_date
1397 assert_equal '2012-10-11'.to_date, issue.start_date
1385 assert_equal '2012-10-23'.to_date, issue.due_date
1398 assert_equal '2012-10-23'.to_date, issue.due_date
1386
1399
1387 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1400 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
1388 issue.reschedule_on '2012-10-13'.to_date
1401 issue.reschedule_on '2012-10-13'.to_date
1389 assert_equal '2012-10-15'.to_date, issue.start_date
1402 assert_equal '2012-10-15'.to_date, issue.start_date
1390 assert_equal '2012-10-25'.to_date, issue.due_date
1403 assert_equal '2012-10-25'.to_date, issue.due_date
1391 end
1404 end
1392 end
1405 end
1393
1406
1394 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1407 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
1395 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1408 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1396 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1409 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1397 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1410 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1398 :relation_type => IssueRelation::TYPE_PRECEDES)
1411 :relation_type => IssueRelation::TYPE_PRECEDES)
1399 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1412 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1400
1413
1401 issue1.due_date = '2012-10-23'
1414 issue1.due_date = '2012-10-23'
1402 issue1.save!
1415 issue1.save!
1403 issue2.reload
1416 issue2.reload
1404 assert_equal Date.parse('2012-10-24'), issue2.start_date
1417 assert_equal Date.parse('2012-10-24'), issue2.start_date
1405 assert_equal Date.parse('2012-10-26'), issue2.due_date
1418 assert_equal Date.parse('2012-10-26'), issue2.due_date
1406 end
1419 end
1407
1420
1408 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1421 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
1409 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1422 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1410 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1423 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1411 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1424 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1412 :relation_type => IssueRelation::TYPE_PRECEDES)
1425 :relation_type => IssueRelation::TYPE_PRECEDES)
1413 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1426 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1414
1427
1415 issue1.start_date = '2012-09-17'
1428 issue1.start_date = '2012-09-17'
1416 issue1.due_date = '2012-09-18'
1429 issue1.due_date = '2012-09-18'
1417 issue1.save!
1430 issue1.save!
1418 issue2.reload
1431 issue2.reload
1419 assert_equal Date.parse('2012-09-19'), issue2.start_date
1432 assert_equal Date.parse('2012-09-19'), issue2.start_date
1420 assert_equal Date.parse('2012-09-21'), issue2.due_date
1433 assert_equal Date.parse('2012-09-21'), issue2.due_date
1421 end
1434 end
1422
1435
1423 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1436 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
1424 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1437 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1425 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1438 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1426 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1439 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
1427 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1440 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1428 :relation_type => IssueRelation::TYPE_PRECEDES)
1441 :relation_type => IssueRelation::TYPE_PRECEDES)
1429 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1442 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1430 :relation_type => IssueRelation::TYPE_PRECEDES)
1443 :relation_type => IssueRelation::TYPE_PRECEDES)
1431 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1444 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1432
1445
1433 issue1.start_date = '2012-09-17'
1446 issue1.start_date = '2012-09-17'
1434 issue1.due_date = '2012-09-18'
1447 issue1.due_date = '2012-09-18'
1435 issue1.save!
1448 issue1.save!
1436 issue2.reload
1449 issue2.reload
1437 # Issue 2 must start after Issue 3
1450 # Issue 2 must start after Issue 3
1438 assert_equal Date.parse('2012-10-03'), issue2.start_date
1451 assert_equal Date.parse('2012-10-03'), issue2.start_date
1439 assert_equal Date.parse('2012-10-05'), issue2.due_date
1452 assert_equal Date.parse('2012-10-05'), issue2.due_date
1440 end
1453 end
1441
1454
1442 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1455 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1443 with_settings :non_working_week_days => [] do
1456 with_settings :non_working_week_days => [] do
1444 stale = Issue.find(1)
1457 stale = Issue.find(1)
1445 issue = Issue.find(1)
1458 issue = Issue.find(1)
1446 issue.subject = "Updated"
1459 issue.subject = "Updated"
1447 issue.save!
1460 issue.save!
1448 date = 10.days.from_now.to_date
1461 date = 10.days.from_now.to_date
1449 assert_nothing_raised do
1462 assert_nothing_raised do
1450 stale.reschedule_on!(date)
1463 stale.reschedule_on!(date)
1451 end
1464 end
1452 assert_equal date, stale.reload.start_date
1465 assert_equal date, stale.reload.start_date
1453 end
1466 end
1454 end
1467 end
1455
1468
1456 def test_overdue
1469 def test_overdue
1457 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1470 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1458 assert !Issue.new(:due_date => Date.today).overdue?
1471 assert !Issue.new(:due_date => Date.today).overdue?
1459 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1472 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1460 assert !Issue.new(:due_date => nil).overdue?
1473 assert !Issue.new(:due_date => nil).overdue?
1461 assert !Issue.new(:due_date => 1.day.ago.to_date,
1474 assert !Issue.new(:due_date => 1.day.ago.to_date,
1462 :status => IssueStatus.where(:is_closed => true).first
1475 :status => IssueStatus.where(:is_closed => true).first
1463 ).overdue?
1476 ).overdue?
1464 end
1477 end
1465
1478
1466 test "#behind_schedule? should be false if the issue has no start_date" do
1479 test "#behind_schedule? should be false if the issue has no start_date" do
1467 assert !Issue.new(:start_date => nil,
1480 assert !Issue.new(:start_date => nil,
1468 :due_date => 1.day.from_now.to_date,
1481 :due_date => 1.day.from_now.to_date,
1469 :done_ratio => 0).behind_schedule?
1482 :done_ratio => 0).behind_schedule?
1470 end
1483 end
1471
1484
1472 test "#behind_schedule? should be false if the issue has no end_date" do
1485 test "#behind_schedule? should be false if the issue has no end_date" do
1473 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1486 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1474 :due_date => nil,
1487 :due_date => nil,
1475 :done_ratio => 0).behind_schedule?
1488 :done_ratio => 0).behind_schedule?
1476 end
1489 end
1477
1490
1478 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1491 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1479 assert !Issue.new(:start_date => 50.days.ago.to_date,
1492 assert !Issue.new(:start_date => 50.days.ago.to_date,
1480 :due_date => 50.days.from_now.to_date,
1493 :due_date => 50.days.from_now.to_date,
1481 :done_ratio => 90).behind_schedule?
1494 :done_ratio => 90).behind_schedule?
1482 end
1495 end
1483
1496
1484 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1497 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1485 assert Issue.new(:start_date => 1.day.ago.to_date,
1498 assert Issue.new(:start_date => 1.day.ago.to_date,
1486 :due_date => 1.day.from_now.to_date,
1499 :due_date => 1.day.from_now.to_date,
1487 :done_ratio => 0).behind_schedule?
1500 :done_ratio => 0).behind_schedule?
1488 end
1501 end
1489
1502
1490 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1503 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1491 assert Issue.new(:start_date => 100.days.ago.to_date,
1504 assert Issue.new(:start_date => 100.days.ago.to_date,
1492 :due_date => Date.today,
1505 :due_date => Date.today,
1493 :done_ratio => 90).behind_schedule?
1506 :done_ratio => 90).behind_schedule?
1494 end
1507 end
1495
1508
1496 test "#assignable_users should be Users" do
1509 test "#assignable_users should be Users" do
1497 assert_kind_of User, Issue.find(1).assignable_users.first
1510 assert_kind_of User, Issue.find(1).assignable_users.first
1498 end
1511 end
1499
1512
1500 test "#assignable_users should include the issue author" do
1513 test "#assignable_users should include the issue author" do
1501 non_project_member = User.generate!
1514 non_project_member = User.generate!
1502 issue = Issue.generate!(:author => non_project_member)
1515 issue = Issue.generate!(:author => non_project_member)
1503
1516
1504 assert issue.assignable_users.include?(non_project_member)
1517 assert issue.assignable_users.include?(non_project_member)
1505 end
1518 end
1506
1519
1507 test "#assignable_users should include the current assignee" do
1520 test "#assignable_users should include the current assignee" do
1508 user = User.generate!
1521 user = User.generate!
1509 issue = Issue.generate!(:assigned_to => user)
1522 issue = Issue.generate!(:assigned_to => user)
1510 user.lock!
1523 user.lock!
1511
1524
1512 assert Issue.find(issue.id).assignable_users.include?(user)
1525 assert Issue.find(issue.id).assignable_users.include?(user)
1513 end
1526 end
1514
1527
1515 test "#assignable_users should not show the issue author twice" do
1528 test "#assignable_users should not show the issue author twice" do
1516 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1529 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1517 assert_equal 2, assignable_user_ids.length
1530 assert_equal 2, assignable_user_ids.length
1518
1531
1519 assignable_user_ids.each do |user_id|
1532 assignable_user_ids.each do |user_id|
1520 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1533 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1521 "User #{user_id} appears more or less than once"
1534 "User #{user_id} appears more or less than once"
1522 end
1535 end
1523 end
1536 end
1524
1537
1525 test "#assignable_users with issue_group_assignment should include groups" do
1538 test "#assignable_users with issue_group_assignment should include groups" do
1526 issue = Issue.new(:project => Project.find(2))
1539 issue = Issue.new(:project => Project.find(2))
1527
1540
1528 with_settings :issue_group_assignment => '1' do
1541 with_settings :issue_group_assignment => '1' do
1529 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1542 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1530 assert issue.assignable_users.include?(Group.find(11))
1543 assert issue.assignable_users.include?(Group.find(11))
1531 end
1544 end
1532 end
1545 end
1533
1546
1534 test "#assignable_users without issue_group_assignment should not include groups" do
1547 test "#assignable_users without issue_group_assignment should not include groups" do
1535 issue = Issue.new(:project => Project.find(2))
1548 issue = Issue.new(:project => Project.find(2))
1536
1549
1537 with_settings :issue_group_assignment => '0' do
1550 with_settings :issue_group_assignment => '0' do
1538 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1551 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1539 assert !issue.assignable_users.include?(Group.find(11))
1552 assert !issue.assignable_users.include?(Group.find(11))
1540 end
1553 end
1541 end
1554 end
1542
1555
1543 def test_create_should_send_email_notification
1556 def test_create_should_send_email_notification
1544 ActionMailer::Base.deliveries.clear
1557 ActionMailer::Base.deliveries.clear
1545 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1558 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1546 :author_id => 3, :status_id => 1,
1559 :author_id => 3, :status_id => 1,
1547 :priority => IssuePriority.all.first,
1560 :priority => IssuePriority.all.first,
1548 :subject => 'test_create', :estimated_hours => '1:30')
1561 :subject => 'test_create', :estimated_hours => '1:30')
1549
1562
1550 assert issue.save
1563 assert issue.save
1551 assert_equal 1, ActionMailer::Base.deliveries.size
1564 assert_equal 1, ActionMailer::Base.deliveries.size
1552 end
1565 end
1553
1566
1554 def test_stale_issue_should_not_send_email_notification
1567 def test_stale_issue_should_not_send_email_notification
1555 ActionMailer::Base.deliveries.clear
1568 ActionMailer::Base.deliveries.clear
1556 issue = Issue.find(1)
1569 issue = Issue.find(1)
1557 stale = Issue.find(1)
1570 stale = Issue.find(1)
1558
1571
1559 issue.init_journal(User.find(1))
1572 issue.init_journal(User.find(1))
1560 issue.subject = 'Subjet update'
1573 issue.subject = 'Subjet update'
1561 assert issue.save
1574 assert issue.save
1562 assert_equal 1, ActionMailer::Base.deliveries.size
1575 assert_equal 1, ActionMailer::Base.deliveries.size
1563 ActionMailer::Base.deliveries.clear
1576 ActionMailer::Base.deliveries.clear
1564
1577
1565 stale.init_journal(User.find(1))
1578 stale.init_journal(User.find(1))
1566 stale.subject = 'Another subjet update'
1579 stale.subject = 'Another subjet update'
1567 assert_raise ActiveRecord::StaleObjectError do
1580 assert_raise ActiveRecord::StaleObjectError do
1568 stale.save
1581 stale.save
1569 end
1582 end
1570 assert ActionMailer::Base.deliveries.empty?
1583 assert ActionMailer::Base.deliveries.empty?
1571 end
1584 end
1572
1585
1573 def test_journalized_description
1586 def test_journalized_description
1574 IssueCustomField.delete_all
1587 IssueCustomField.delete_all
1575
1588
1576 i = Issue.first
1589 i = Issue.first
1577 old_description = i.description
1590 old_description = i.description
1578 new_description = "This is the new description"
1591 new_description = "This is the new description"
1579
1592
1580 i.init_journal(User.find(2))
1593 i.init_journal(User.find(2))
1581 i.description = new_description
1594 i.description = new_description
1582 assert_difference 'Journal.count', 1 do
1595 assert_difference 'Journal.count', 1 do
1583 assert_difference 'JournalDetail.count', 1 do
1596 assert_difference 'JournalDetail.count', 1 do
1584 i.save!
1597 i.save!
1585 end
1598 end
1586 end
1599 end
1587
1600
1588 detail = JournalDetail.first(:order => 'id DESC')
1601 detail = JournalDetail.first(:order => 'id DESC')
1589 assert_equal i, detail.journal.journalized
1602 assert_equal i, detail.journal.journalized
1590 assert_equal 'attr', detail.property
1603 assert_equal 'attr', detail.property
1591 assert_equal 'description', detail.prop_key
1604 assert_equal 'description', detail.prop_key
1592 assert_equal old_description, detail.old_value
1605 assert_equal old_description, detail.old_value
1593 assert_equal new_description, detail.value
1606 assert_equal new_description, detail.value
1594 end
1607 end
1595
1608
1596 def test_blank_descriptions_should_not_be_journalized
1609 def test_blank_descriptions_should_not_be_journalized
1597 IssueCustomField.delete_all
1610 IssueCustomField.delete_all
1598 Issue.update_all("description = NULL", "id=1")
1611 Issue.update_all("description = NULL", "id=1")
1599
1612
1600 i = Issue.find(1)
1613 i = Issue.find(1)
1601 i.init_journal(User.find(2))
1614 i.init_journal(User.find(2))
1602 i.subject = "blank description"
1615 i.subject = "blank description"
1603 i.description = "\r\n"
1616 i.description = "\r\n"
1604
1617
1605 assert_difference 'Journal.count', 1 do
1618 assert_difference 'Journal.count', 1 do
1606 assert_difference 'JournalDetail.count', 1 do
1619 assert_difference 'JournalDetail.count', 1 do
1607 i.save!
1620 i.save!
1608 end
1621 end
1609 end
1622 end
1610 end
1623 end
1611
1624
1612 def test_journalized_multi_custom_field
1625 def test_journalized_multi_custom_field
1613 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1626 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1614 :is_filter => true, :is_for_all => true,
1627 :is_filter => true, :is_for_all => true,
1615 :tracker_ids => [1],
1628 :tracker_ids => [1],
1616 :possible_values => ['value1', 'value2', 'value3'],
1629 :possible_values => ['value1', 'value2', 'value3'],
1617 :multiple => true)
1630 :multiple => true)
1618
1631
1619 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1632 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1620 :subject => 'Test', :author_id => 1)
1633 :subject => 'Test', :author_id => 1)
1621
1634
1622 assert_difference 'Journal.count' do
1635 assert_difference 'Journal.count' do
1623 assert_difference 'JournalDetail.count' do
1636 assert_difference 'JournalDetail.count' do
1624 issue.init_journal(User.first)
1637 issue.init_journal(User.first)
1625 issue.custom_field_values = {field.id => ['value1']}
1638 issue.custom_field_values = {field.id => ['value1']}
1626 issue.save!
1639 issue.save!
1627 end
1640 end
1628 assert_difference 'JournalDetail.count' do
1641 assert_difference 'JournalDetail.count' do
1629 issue.init_journal(User.first)
1642 issue.init_journal(User.first)
1630 issue.custom_field_values = {field.id => ['value1', 'value2']}
1643 issue.custom_field_values = {field.id => ['value1', 'value2']}
1631 issue.save!
1644 issue.save!
1632 end
1645 end
1633 assert_difference 'JournalDetail.count', 2 do
1646 assert_difference 'JournalDetail.count', 2 do
1634 issue.init_journal(User.first)
1647 issue.init_journal(User.first)
1635 issue.custom_field_values = {field.id => ['value3', 'value2']}
1648 issue.custom_field_values = {field.id => ['value3', 'value2']}
1636 issue.save!
1649 issue.save!
1637 end
1650 end
1638 assert_difference 'JournalDetail.count', 2 do
1651 assert_difference 'JournalDetail.count', 2 do
1639 issue.init_journal(User.first)
1652 issue.init_journal(User.first)
1640 issue.custom_field_values = {field.id => nil}
1653 issue.custom_field_values = {field.id => nil}
1641 issue.save!
1654 issue.save!
1642 end
1655 end
1643 end
1656 end
1644 end
1657 end
1645
1658
1646 def test_description_eol_should_be_normalized
1659 def test_description_eol_should_be_normalized
1647 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1660 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1648 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1661 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1649 end
1662 end
1650
1663
1651 def test_saving_twice_should_not_duplicate_journal_details
1664 def test_saving_twice_should_not_duplicate_journal_details
1652 i = Issue.first
1665 i = Issue.first
1653 i.init_journal(User.find(2), 'Some notes')
1666 i.init_journal(User.find(2), 'Some notes')
1654 # initial changes
1667 # initial changes
1655 i.subject = 'New subject'
1668 i.subject = 'New subject'
1656 i.done_ratio = i.done_ratio + 10
1669 i.done_ratio = i.done_ratio + 10
1657 assert_difference 'Journal.count' do
1670 assert_difference 'Journal.count' do
1658 assert i.save
1671 assert i.save
1659 end
1672 end
1660 # 1 more change
1673 # 1 more change
1661 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1674 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1662 assert_no_difference 'Journal.count' do
1675 assert_no_difference 'Journal.count' do
1663 assert_difference 'JournalDetail.count', 1 do
1676 assert_difference 'JournalDetail.count', 1 do
1664 i.save
1677 i.save
1665 end
1678 end
1666 end
1679 end
1667 # no more change
1680 # no more change
1668 assert_no_difference 'Journal.count' do
1681 assert_no_difference 'Journal.count' do
1669 assert_no_difference 'JournalDetail.count' do
1682 assert_no_difference 'JournalDetail.count' do
1670 i.save
1683 i.save
1671 end
1684 end
1672 end
1685 end
1673 end
1686 end
1674
1687
1675 def test_all_dependent_issues
1688 def test_all_dependent_issues
1676 IssueRelation.delete_all
1689 IssueRelation.delete_all
1677 assert IssueRelation.create!(:issue_from => Issue.find(1),
1690 assert IssueRelation.create!(:issue_from => Issue.find(1),
1678 :issue_to => Issue.find(2),
1691 :issue_to => Issue.find(2),
1679 :relation_type => IssueRelation::TYPE_PRECEDES)
1692 :relation_type => IssueRelation::TYPE_PRECEDES)
1680 assert IssueRelation.create!(:issue_from => Issue.find(2),
1693 assert IssueRelation.create!(:issue_from => Issue.find(2),
1681 :issue_to => Issue.find(3),
1694 :issue_to => Issue.find(3),
1682 :relation_type => IssueRelation::TYPE_PRECEDES)
1695 :relation_type => IssueRelation::TYPE_PRECEDES)
1683 assert IssueRelation.create!(:issue_from => Issue.find(3),
1696 assert IssueRelation.create!(:issue_from => Issue.find(3),
1684 :issue_to => Issue.find(8),
1697 :issue_to => Issue.find(8),
1685 :relation_type => IssueRelation::TYPE_PRECEDES)
1698 :relation_type => IssueRelation::TYPE_PRECEDES)
1686
1699
1687 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1700 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1688 end
1701 end
1689
1702
1690 def test_all_dependent_issues_with_persistent_circular_dependency
1703 def test_all_dependent_issues_with_persistent_circular_dependency
1691 IssueRelation.delete_all
1704 IssueRelation.delete_all
1692 assert IssueRelation.create!(:issue_from => Issue.find(1),
1705 assert IssueRelation.create!(:issue_from => Issue.find(1),
1693 :issue_to => Issue.find(2),
1706 :issue_to => Issue.find(2),
1694 :relation_type => IssueRelation::TYPE_PRECEDES)
1707 :relation_type => IssueRelation::TYPE_PRECEDES)
1695 assert IssueRelation.create!(:issue_from => Issue.find(2),
1708 assert IssueRelation.create!(:issue_from => Issue.find(2),
1696 :issue_to => Issue.find(3),
1709 :issue_to => Issue.find(3),
1697 :relation_type => IssueRelation::TYPE_PRECEDES)
1710 :relation_type => IssueRelation::TYPE_PRECEDES)
1698
1711
1699 r = IssueRelation.create!(:issue_from => Issue.find(3),
1712 r = IssueRelation.create!(:issue_from => Issue.find(3),
1700 :issue_to => Issue.find(7),
1713 :issue_to => Issue.find(7),
1701 :relation_type => IssueRelation::TYPE_PRECEDES)
1714 :relation_type => IssueRelation::TYPE_PRECEDES)
1702 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1715 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1703
1716
1704 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1717 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1705 end
1718 end
1706
1719
1707 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1720 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1708 IssueRelation.delete_all
1721 IssueRelation.delete_all
1709 assert IssueRelation.create!(:issue_from => Issue.find(1),
1722 assert IssueRelation.create!(:issue_from => Issue.find(1),
1710 :issue_to => Issue.find(2),
1723 :issue_to => Issue.find(2),
1711 :relation_type => IssueRelation::TYPE_RELATES)
1724 :relation_type => IssueRelation::TYPE_RELATES)
1712 assert IssueRelation.create!(:issue_from => Issue.find(2),
1725 assert IssueRelation.create!(:issue_from => Issue.find(2),
1713 :issue_to => Issue.find(3),
1726 :issue_to => Issue.find(3),
1714 :relation_type => IssueRelation::TYPE_RELATES)
1727 :relation_type => IssueRelation::TYPE_RELATES)
1715 assert IssueRelation.create!(:issue_from => Issue.find(3),
1728 assert IssueRelation.create!(:issue_from => Issue.find(3),
1716 :issue_to => Issue.find(8),
1729 :issue_to => Issue.find(8),
1717 :relation_type => IssueRelation::TYPE_RELATES)
1730 :relation_type => IssueRelation::TYPE_RELATES)
1718
1731
1719 r = IssueRelation.create!(:issue_from => Issue.find(8),
1732 r = IssueRelation.create!(:issue_from => Issue.find(8),
1720 :issue_to => Issue.find(7),
1733 :issue_to => Issue.find(7),
1721 :relation_type => IssueRelation::TYPE_RELATES)
1734 :relation_type => IssueRelation::TYPE_RELATES)
1722 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1735 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1723
1736
1724 r = IssueRelation.create!(:issue_from => Issue.find(3),
1737 r = IssueRelation.create!(:issue_from => Issue.find(3),
1725 :issue_to => Issue.find(7),
1738 :issue_to => Issue.find(7),
1726 :relation_type => IssueRelation::TYPE_RELATES)
1739 :relation_type => IssueRelation::TYPE_RELATES)
1727 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1740 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1728
1741
1729 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1742 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1730 end
1743 end
1731
1744
1732 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
1745 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
1733 @issue = Issue.find(1)
1746 @issue = Issue.find(1)
1734 @issue_status = IssueStatus.find(1)
1747 @issue_status = IssueStatus.find(1)
1735 @issue_status.update_attribute(:default_done_ratio, 50)
1748 @issue_status.update_attribute(:default_done_ratio, 50)
1736 @issue2 = Issue.find(2)
1749 @issue2 = Issue.find(2)
1737 @issue_status2 = IssueStatus.find(2)
1750 @issue_status2 = IssueStatus.find(2)
1738 @issue_status2.update_attribute(:default_done_ratio, 0)
1751 @issue_status2.update_attribute(:default_done_ratio, 0)
1739
1752
1740 with_settings :issue_done_ratio => 'issue_field' do
1753 with_settings :issue_done_ratio => 'issue_field' do
1741 assert_equal 0, @issue.done_ratio
1754 assert_equal 0, @issue.done_ratio
1742 assert_equal 30, @issue2.done_ratio
1755 assert_equal 30, @issue2.done_ratio
1743 end
1756 end
1744
1757
1745 with_settings :issue_done_ratio => 'issue_status' do
1758 with_settings :issue_done_ratio => 'issue_status' do
1746 assert_equal 50, @issue.done_ratio
1759 assert_equal 50, @issue.done_ratio
1747 assert_equal 0, @issue2.done_ratio
1760 assert_equal 0, @issue2.done_ratio
1748 end
1761 end
1749 end
1762 end
1750
1763
1751 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
1764 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
1752 @issue = Issue.find(1)
1765 @issue = Issue.find(1)
1753 @issue_status = IssueStatus.find(1)
1766 @issue_status = IssueStatus.find(1)
1754 @issue_status.update_attribute(:default_done_ratio, 50)
1767 @issue_status.update_attribute(:default_done_ratio, 50)
1755 @issue2 = Issue.find(2)
1768 @issue2 = Issue.find(2)
1756 @issue_status2 = IssueStatus.find(2)
1769 @issue_status2 = IssueStatus.find(2)
1757 @issue_status2.update_attribute(:default_done_ratio, 0)
1770 @issue_status2.update_attribute(:default_done_ratio, 0)
1758
1771
1759 with_settings :issue_done_ratio => 'issue_field' do
1772 with_settings :issue_done_ratio => 'issue_field' do
1760 @issue.update_done_ratio_from_issue_status
1773 @issue.update_done_ratio_from_issue_status
1761 @issue2.update_done_ratio_from_issue_status
1774 @issue2.update_done_ratio_from_issue_status
1762
1775
1763 assert_equal 0, @issue.read_attribute(:done_ratio)
1776 assert_equal 0, @issue.read_attribute(:done_ratio)
1764 assert_equal 30, @issue2.read_attribute(:done_ratio)
1777 assert_equal 30, @issue2.read_attribute(:done_ratio)
1765 end
1778 end
1766
1779
1767 with_settings :issue_done_ratio => 'issue_status' do
1780 with_settings :issue_done_ratio => 'issue_status' do
1768 @issue.update_done_ratio_from_issue_status
1781 @issue.update_done_ratio_from_issue_status
1769 @issue2.update_done_ratio_from_issue_status
1782 @issue2.update_done_ratio_from_issue_status
1770
1783
1771 assert_equal 50, @issue.read_attribute(:done_ratio)
1784 assert_equal 50, @issue.read_attribute(:done_ratio)
1772 assert_equal 0, @issue2.read_attribute(:done_ratio)
1785 assert_equal 0, @issue2.read_attribute(:done_ratio)
1773 end
1786 end
1774 end
1787 end
1775
1788
1776 test "#by_tracker" do
1789 test "#by_tracker" do
1777 User.current = User.anonymous
1790 User.current = User.anonymous
1778 groups = Issue.by_tracker(Project.find(1))
1791 groups = Issue.by_tracker(Project.find(1))
1779 assert_equal 3, groups.size
1792 assert_equal 3, groups.size
1780 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1793 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1781 end
1794 end
1782
1795
1783 test "#by_version" do
1796 test "#by_version" do
1784 User.current = User.anonymous
1797 User.current = User.anonymous
1785 groups = Issue.by_version(Project.find(1))
1798 groups = Issue.by_version(Project.find(1))
1786 assert_equal 3, groups.size
1799 assert_equal 3, groups.size
1787 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1800 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1788 end
1801 end
1789
1802
1790 test "#by_priority" do
1803 test "#by_priority" do
1791 User.current = User.anonymous
1804 User.current = User.anonymous
1792 groups = Issue.by_priority(Project.find(1))
1805 groups = Issue.by_priority(Project.find(1))
1793 assert_equal 4, groups.size
1806 assert_equal 4, groups.size
1794 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1807 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1795 end
1808 end
1796
1809
1797 test "#by_category" do
1810 test "#by_category" do
1798 User.current = User.anonymous
1811 User.current = User.anonymous
1799 groups = Issue.by_category(Project.find(1))
1812 groups = Issue.by_category(Project.find(1))
1800 assert_equal 2, groups.size
1813 assert_equal 2, groups.size
1801 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1814 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1802 end
1815 end
1803
1816
1804 test "#by_assigned_to" do
1817 test "#by_assigned_to" do
1805 User.current = User.anonymous
1818 User.current = User.anonymous
1806 groups = Issue.by_assigned_to(Project.find(1))
1819 groups = Issue.by_assigned_to(Project.find(1))
1807 assert_equal 2, groups.size
1820 assert_equal 2, groups.size
1808 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1821 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1809 end
1822 end
1810
1823
1811 test "#by_author" do
1824 test "#by_author" do
1812 User.current = User.anonymous
1825 User.current = User.anonymous
1813 groups = Issue.by_author(Project.find(1))
1826 groups = Issue.by_author(Project.find(1))
1814 assert_equal 4, groups.size
1827 assert_equal 4, groups.size
1815 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1828 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1816 end
1829 end
1817
1830
1818 test "#by_subproject" do
1831 test "#by_subproject" do
1819 User.current = User.anonymous
1832 User.current = User.anonymous
1820 groups = Issue.by_subproject(Project.find(1))
1833 groups = Issue.by_subproject(Project.find(1))
1821 # Private descendant not visible
1834 # Private descendant not visible
1822 assert_equal 1, groups.size
1835 assert_equal 1, groups.size
1823 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1836 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1824 end
1837 end
1825
1838
1826 def test_recently_updated_scope
1839 def test_recently_updated_scope
1827 #should return the last updated issue
1840 #should return the last updated issue
1828 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1841 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1829 end
1842 end
1830
1843
1831 def test_on_active_projects_scope
1844 def test_on_active_projects_scope
1832 assert Project.find(2).archive
1845 assert Project.find(2).archive
1833
1846
1834 before = Issue.on_active_project.length
1847 before = Issue.on_active_project.length
1835 # test inclusion to results
1848 # test inclusion to results
1836 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1849 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1837 assert_equal before + 1, Issue.on_active_project.length
1850 assert_equal before + 1, Issue.on_active_project.length
1838
1851
1839 # Move to an archived project
1852 # Move to an archived project
1840 issue.project = Project.find(2)
1853 issue.project = Project.find(2)
1841 assert issue.save
1854 assert issue.save
1842 assert_equal before, Issue.on_active_project.length
1855 assert_equal before, Issue.on_active_project.length
1843 end
1856 end
1844
1857
1845 test "Issue#recipients should include project recipients" do
1858 test "Issue#recipients should include project recipients" do
1846 issue = Issue.generate!
1859 issue = Issue.generate!
1847 assert issue.project.recipients.present?
1860 assert issue.project.recipients.present?
1848 issue.project.recipients.each do |project_recipient|
1861 issue.project.recipients.each do |project_recipient|
1849 assert issue.recipients.include?(project_recipient)
1862 assert issue.recipients.include?(project_recipient)
1850 end
1863 end
1851 end
1864 end
1852
1865
1853 test "Issue#recipients should include the author if the author is active" do
1866 test "Issue#recipients should include the author if the author is active" do
1854 issue = Issue.generate!(:author => User.generate!)
1867 issue = Issue.generate!(:author => User.generate!)
1855 assert issue.author, "No author set for Issue"
1868 assert issue.author, "No author set for Issue"
1856 assert issue.recipients.include?(issue.author.mail)
1869 assert issue.recipients.include?(issue.author.mail)
1857 end
1870 end
1858
1871
1859 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
1872 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
1860 issue = Issue.generate!(:assigned_to => User.generate!)
1873 issue = Issue.generate!(:assigned_to => User.generate!)
1861 assert issue.assigned_to, "No assigned_to set for Issue"
1874 assert issue.assigned_to, "No assigned_to set for Issue"
1862 assert issue.recipients.include?(issue.assigned_to.mail)
1875 assert issue.recipients.include?(issue.assigned_to.mail)
1863 end
1876 end
1864
1877
1865 test "Issue#recipients should not include users who opt out of all email" do
1878 test "Issue#recipients should not include users who opt out of all email" do
1866 issue = Issue.generate!(:author => User.generate!)
1879 issue = Issue.generate!(:author => User.generate!)
1867 issue.author.update_attribute(:mail_notification, :none)
1880 issue.author.update_attribute(:mail_notification, :none)
1868 assert !issue.recipients.include?(issue.author.mail)
1881 assert !issue.recipients.include?(issue.author.mail)
1869 end
1882 end
1870
1883
1871 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
1884 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
1872 issue = Issue.generate!(:author => User.generate!)
1885 issue = Issue.generate!(:author => User.generate!)
1873 issue.author.update_attribute(:mail_notification, :only_assigned)
1886 issue.author.update_attribute(:mail_notification, :only_assigned)
1874 assert !issue.recipients.include?(issue.author.mail)
1887 assert !issue.recipients.include?(issue.author.mail)
1875 end
1888 end
1876
1889
1877 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
1890 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
1878 issue = Issue.generate!(:assigned_to => User.generate!)
1891 issue = Issue.generate!(:assigned_to => User.generate!)
1879 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
1892 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
1880 assert !issue.recipients.include?(issue.assigned_to.mail)
1893 assert !issue.recipients.include?(issue.assigned_to.mail)
1881 end
1894 end
1882
1895
1883 def test_last_journal_id_with_journals_should_return_the_journal_id
1896 def test_last_journal_id_with_journals_should_return_the_journal_id
1884 assert_equal 2, Issue.find(1).last_journal_id
1897 assert_equal 2, Issue.find(1).last_journal_id
1885 end
1898 end
1886
1899
1887 def test_last_journal_id_without_journals_should_return_nil
1900 def test_last_journal_id_without_journals_should_return_nil
1888 assert_nil Issue.find(3).last_journal_id
1901 assert_nil Issue.find(3).last_journal_id
1889 end
1902 end
1890
1903
1891 def test_journals_after_should_return_journals_with_greater_id
1904 def test_journals_after_should_return_journals_with_greater_id
1892 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1905 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1893 assert_equal [], Issue.find(1).journals_after('2')
1906 assert_equal [], Issue.find(1).journals_after('2')
1894 end
1907 end
1895
1908
1896 def test_journals_after_with_blank_arg_should_return_all_journals
1909 def test_journals_after_with_blank_arg_should_return_all_journals
1897 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1910 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1898 end
1911 end
1899
1912
1900 def test_css_classes_should_include_priority
1913 def test_css_classes_should_include_priority
1901 issue = Issue.new(:priority => IssuePriority.find(8))
1914 issue = Issue.new(:priority => IssuePriority.find(8))
1902 classes = issue.css_classes.split(' ')
1915 classes = issue.css_classes.split(' ')
1903 assert_include 'priority-8', classes
1916 assert_include 'priority-8', classes
1904 assert_include 'priority-highest', classes
1917 assert_include 'priority-highest', classes
1905 end
1918 end
1906
1919
1907 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
1920 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
1908 set_tmp_attachments_directory
1921 set_tmp_attachments_directory
1909 issue = Issue.generate!
1922 issue = Issue.generate!
1910 issue.save_attachments({
1923 issue.save_attachments({
1911 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
1924 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
1912 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
1925 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
1913 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
1926 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
1914 })
1927 })
1915 issue.attach_saved_attachments
1928 issue.attach_saved_attachments
1916
1929
1917 assert_equal 3, issue.reload.attachments.count
1930 assert_equal 3, issue.reload.attachments.count
1918 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
1931 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
1919 end
1932 end
1920
1933
1921 def test_closed_on_should_be_nil_when_creating_an_open_issue
1934 def test_closed_on_should_be_nil_when_creating_an_open_issue
1922 issue = Issue.generate!(:status_id => 1).reload
1935 issue = Issue.generate!(:status_id => 1).reload
1923 assert !issue.closed?
1936 assert !issue.closed?
1924 assert_nil issue.closed_on
1937 assert_nil issue.closed_on
1925 end
1938 end
1926
1939
1927 def test_closed_on_should_be_set_when_creating_a_closed_issue
1940 def test_closed_on_should_be_set_when_creating_a_closed_issue
1928 issue = Issue.generate!(:status_id => 5).reload
1941 issue = Issue.generate!(:status_id => 5).reload
1929 assert issue.closed?
1942 assert issue.closed?
1930 assert_not_nil issue.closed_on
1943 assert_not_nil issue.closed_on
1931 assert_equal issue.updated_on, issue.closed_on
1944 assert_equal issue.updated_on, issue.closed_on
1932 assert_equal issue.created_on, issue.closed_on
1945 assert_equal issue.created_on, issue.closed_on
1933 end
1946 end
1934
1947
1935 def test_closed_on_should_be_nil_when_updating_an_open_issue
1948 def test_closed_on_should_be_nil_when_updating_an_open_issue
1936 issue = Issue.find(1)
1949 issue = Issue.find(1)
1937 issue.subject = 'Not closed yet'
1950 issue.subject = 'Not closed yet'
1938 issue.save!
1951 issue.save!
1939 issue.reload
1952 issue.reload
1940 assert_nil issue.closed_on
1953 assert_nil issue.closed_on
1941 end
1954 end
1942
1955
1943 def test_closed_on_should_be_set_when_closing_an_open_issue
1956 def test_closed_on_should_be_set_when_closing_an_open_issue
1944 issue = Issue.find(1)
1957 issue = Issue.find(1)
1945 issue.subject = 'Now closed'
1958 issue.subject = 'Now closed'
1946 issue.status_id = 5
1959 issue.status_id = 5
1947 issue.save!
1960 issue.save!
1948 issue.reload
1961 issue.reload
1949 assert_not_nil issue.closed_on
1962 assert_not_nil issue.closed_on
1950 assert_equal issue.updated_on, issue.closed_on
1963 assert_equal issue.updated_on, issue.closed_on
1951 end
1964 end
1952
1965
1953 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
1966 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
1954 issue = Issue.open(false).first
1967 issue = Issue.open(false).first
1955 was_closed_on = issue.closed_on
1968 was_closed_on = issue.closed_on
1956 assert_not_nil was_closed_on
1969 assert_not_nil was_closed_on
1957 issue.subject = 'Updating a closed issue'
1970 issue.subject = 'Updating a closed issue'
1958 issue.save!
1971 issue.save!
1959 issue.reload
1972 issue.reload
1960 assert_equal was_closed_on, issue.closed_on
1973 assert_equal was_closed_on, issue.closed_on
1961 end
1974 end
1962
1975
1963 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
1976 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
1964 issue = Issue.open(false).first
1977 issue = Issue.open(false).first
1965 was_closed_on = issue.closed_on
1978 was_closed_on = issue.closed_on
1966 assert_not_nil was_closed_on
1979 assert_not_nil was_closed_on
1967 issue.subject = 'Reopening a closed issue'
1980 issue.subject = 'Reopening a closed issue'
1968 issue.status_id = 1
1981 issue.status_id = 1
1969 issue.save!
1982 issue.save!
1970 issue.reload
1983 issue.reload
1971 assert !issue.closed?
1984 assert !issue.closed?
1972 assert_equal was_closed_on, issue.closed_on
1985 assert_equal was_closed_on, issue.closed_on
1973 end
1986 end
1974
1987
1975 def test_status_was_should_return_nil_for_new_issue
1988 def test_status_was_should_return_nil_for_new_issue
1976 issue = Issue.new
1989 issue = Issue.new
1977 assert_nil issue.status_was
1990 assert_nil issue.status_was
1978 end
1991 end
1979
1992
1980 def test_status_was_should_return_status_before_change
1993 def test_status_was_should_return_status_before_change
1981 issue = Issue.find(1)
1994 issue = Issue.find(1)
1982 issue.status = IssueStatus.find(2)
1995 issue.status = IssueStatus.find(2)
1983 assert_equal IssueStatus.find(1), issue.status_was
1996 assert_equal IssueStatus.find(1), issue.status_was
1984 end
1997 end
1985
1998
1986 def test_status_was_should_be_reset_on_save
1999 def test_status_was_should_be_reset_on_save
1987 issue = Issue.find(1)
2000 issue = Issue.find(1)
1988 issue.status = IssueStatus.find(2)
2001 issue.status = IssueStatus.find(2)
1989 assert_equal IssueStatus.find(1), issue.status_was
2002 assert_equal IssueStatus.find(1), issue.status_was
1990 assert issue.save!
2003 assert issue.save!
1991 assert_equal IssueStatus.find(2), issue.status_was
2004 assert_equal IssueStatus.find(2), issue.status_was
1992 end
2005 end
1993 end
2006 end
General Comments 0
You need to be logged in to leave comments. Login now