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