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