##// END OF EJS Templates
code layout clean up test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version of unit issue test...
Toshi MARUYAMA -
r10444:9581afe06052
parent child
Show More
@@ -1,1797 +1,1799
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,
881 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
882 :status_id => 1, :fixed_version_id => 1,
882 :status_id => 1, :fixed_version_id => 1,
883 :subject => 'New issue')
883 :subject => 'New issue')
884 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
884 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
885 end
885 end
886
886
887 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
887 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
888 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
888 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
889 :status_id => 1, :fixed_version_id => 1,
889 :status_id => 1, :fixed_version_id => 1,
890 :subject => 'New issue')
890 :subject => 'New issue')
891 assert !issue.save
891 assert !issue.save
892 assert_not_nil issue.errors[:fixed_version_id]
892 assert_not_nil issue.errors[:fixed_version_id]
893 end
893 end
894
894
895 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
895 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
896 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
896 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
897 :status_id => 1, :fixed_version_id => 2,
898 :subject => 'New issue')
897 assert !issue.save
899 assert !issue.save
898 assert_not_nil issue.errors[:fixed_version_id]
900 assert_not_nil issue.errors[:fixed_version_id]
899 end
901 end
900
902
901 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
903 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
902 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
904 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
903 :status_id => 1, :fixed_version_id => 3,
905 :status_id => 1, :fixed_version_id => 3,
904 :subject => 'New issue')
906 :subject => 'New issue')
905 assert issue.save
907 assert issue.save
906 end
908 end
907
909
908 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
910 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
909 issue = Issue.find(11)
911 issue = Issue.find(11)
910 assert_equal 'closed', issue.fixed_version.status
912 assert_equal 'closed', issue.fixed_version.status
911 issue.subject = 'Subject changed'
913 issue.subject = 'Subject changed'
912 assert issue.save
914 assert issue.save
913 end
915 end
914
916
915 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
917 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
916 issue = Issue.find(11)
918 issue = Issue.find(11)
917 issue.status_id = 1
919 issue.status_id = 1
918 assert !issue.save
920 assert !issue.save
919 assert_not_nil issue.errors[:base]
921 assert_not_nil issue.errors[:base]
920 end
922 end
921
923
922 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
924 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
923 issue = Issue.find(11)
925 issue = Issue.find(11)
924 issue.status_id = 1
926 issue.status_id = 1
925 issue.fixed_version_id = 3
927 issue.fixed_version_id = 3
926 assert issue.save
928 assert issue.save
927 end
929 end
928
930
929 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
931 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
930 issue = Issue.find(12)
932 issue = Issue.find(12)
931 assert_equal 'locked', issue.fixed_version.status
933 assert_equal 'locked', issue.fixed_version.status
932 issue.status_id = 1
934 issue.status_id = 1
933 assert issue.save
935 assert issue.save
934 end
936 end
935
937
936 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
938 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
937 issue = Issue.find(2)
939 issue = Issue.find(2)
938 assert_equal 2, issue.fixed_version_id
940 assert_equal 2, issue.fixed_version_id
939 issue.project_id = 3
941 issue.project_id = 3
940 assert_nil issue.fixed_version_id
942 assert_nil issue.fixed_version_id
941 issue.fixed_version_id = 2
943 issue.fixed_version_id = 2
942 assert !issue.save
944 assert !issue.save
943 assert_include 'Target version is not included in the list', issue.errors.full_messages
945 assert_include 'Target version is not included in the list', issue.errors.full_messages
944 end
946 end
945
947
946 def test_should_keep_shared_version_when_changing_project
948 def test_should_keep_shared_version_when_changing_project
947 Version.find(2).update_attribute :sharing, 'tree'
949 Version.find(2).update_attribute :sharing, 'tree'
948
950
949 issue = Issue.find(2)
951 issue = Issue.find(2)
950 assert_equal 2, issue.fixed_version_id
952 assert_equal 2, issue.fixed_version_id
951 issue.project_id = 3
953 issue.project_id = 3
952 assert_equal 2, issue.fixed_version_id
954 assert_equal 2, issue.fixed_version_id
953 assert issue.save
955 assert issue.save
954 end
956 end
955
957
956 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
958 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
957 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
959 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
958 end
960 end
959
961
960 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
962 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
961 Project.find(2).disable_module! :issue_tracking
963 Project.find(2).disable_module! :issue_tracking
962 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
964 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
963 end
965 end
964
966
965 def test_move_to_another_project_with_same_category
967 def test_move_to_another_project_with_same_category
966 issue = Issue.find(1)
968 issue = Issue.find(1)
967 issue.project = Project.find(2)
969 issue.project = Project.find(2)
968 assert issue.save
970 assert issue.save
969 issue.reload
971 issue.reload
970 assert_equal 2, issue.project_id
972 assert_equal 2, issue.project_id
971 # Category changes
973 # Category changes
972 assert_equal 4, issue.category_id
974 assert_equal 4, issue.category_id
973 # Make sure time entries were move to the target project
975 # Make sure time entries were move to the target project
974 assert_equal 2, issue.time_entries.first.project_id
976 assert_equal 2, issue.time_entries.first.project_id
975 end
977 end
976
978
977 def test_move_to_another_project_without_same_category
979 def test_move_to_another_project_without_same_category
978 issue = Issue.find(2)
980 issue = Issue.find(2)
979 issue.project = Project.find(2)
981 issue.project = Project.find(2)
980 assert issue.save
982 assert issue.save
981 issue.reload
983 issue.reload
982 assert_equal 2, issue.project_id
984 assert_equal 2, issue.project_id
983 # Category cleared
985 # Category cleared
984 assert_nil issue.category_id
986 assert_nil issue.category_id
985 end
987 end
986
988
987 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
989 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
988 issue = Issue.find(1)
990 issue = Issue.find(1)
989 issue.update_attribute(:fixed_version_id, 1)
991 issue.update_attribute(:fixed_version_id, 1)
990 issue.project = Project.find(2)
992 issue.project = Project.find(2)
991 assert issue.save
993 assert issue.save
992 issue.reload
994 issue.reload
993 assert_equal 2, issue.project_id
995 assert_equal 2, issue.project_id
994 # Cleared fixed_version
996 # Cleared fixed_version
995 assert_equal nil, issue.fixed_version
997 assert_equal nil, issue.fixed_version
996 end
998 end
997
999
998 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
1000 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
999 issue = Issue.find(1)
1001 issue = Issue.find(1)
1000 issue.update_attribute(:fixed_version_id, 4)
1002 issue.update_attribute(:fixed_version_id, 4)
1001 issue.project = Project.find(5)
1003 issue.project = Project.find(5)
1002 assert issue.save
1004 assert issue.save
1003 issue.reload
1005 issue.reload
1004 assert_equal 5, issue.project_id
1006 assert_equal 5, issue.project_id
1005 # Keep fixed_version
1007 # Keep fixed_version
1006 assert_equal 4, issue.fixed_version_id
1008 assert_equal 4, issue.fixed_version_id
1007 end
1009 end
1008
1010
1009 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1011 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
1010 issue = Issue.find(1)
1012 issue = Issue.find(1)
1011 issue.update_attribute(:fixed_version_id, 1)
1013 issue.update_attribute(:fixed_version_id, 1)
1012 issue.project = Project.find(5)
1014 issue.project = Project.find(5)
1013 assert issue.save
1015 assert issue.save
1014 issue.reload
1016 issue.reload
1015 assert_equal 5, issue.project_id
1017 assert_equal 5, issue.project_id
1016 # Cleared fixed_version
1018 # Cleared fixed_version
1017 assert_equal nil, issue.fixed_version
1019 assert_equal nil, issue.fixed_version
1018 end
1020 end
1019
1021
1020 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1022 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
1021 issue = Issue.find(1)
1023 issue = Issue.find(1)
1022 issue.update_attribute(:fixed_version_id, 7)
1024 issue.update_attribute(:fixed_version_id, 7)
1023 issue.project = Project.find(2)
1025 issue.project = Project.find(2)
1024 assert issue.save
1026 assert issue.save
1025 issue.reload
1027 issue.reload
1026 assert_equal 2, issue.project_id
1028 assert_equal 2, issue.project_id
1027 # Keep fixed_version
1029 # Keep fixed_version
1028 assert_equal 7, issue.fixed_version_id
1030 assert_equal 7, issue.fixed_version_id
1029 end
1031 end
1030
1032
1031 def test_move_to_another_project_should_keep_parent_if_valid
1033 def test_move_to_another_project_should_keep_parent_if_valid
1032 issue = Issue.find(1)
1034 issue = Issue.find(1)
1033 issue.update_attribute(:parent_issue_id, 2)
1035 issue.update_attribute(:parent_issue_id, 2)
1034 issue.project = Project.find(3)
1036 issue.project = Project.find(3)
1035 assert issue.save
1037 assert issue.save
1036 issue.reload
1038 issue.reload
1037 assert_equal 2, issue.parent_id
1039 assert_equal 2, issue.parent_id
1038 end
1040 end
1039
1041
1040 def test_move_to_another_project_should_clear_parent_if_not_valid
1042 def test_move_to_another_project_should_clear_parent_if_not_valid
1041 issue = Issue.find(1)
1043 issue = Issue.find(1)
1042 issue.update_attribute(:parent_issue_id, 2)
1044 issue.update_attribute(:parent_issue_id, 2)
1043 issue.project = Project.find(2)
1045 issue.project = Project.find(2)
1044 assert issue.save
1046 assert issue.save
1045 issue.reload
1047 issue.reload
1046 assert_nil issue.parent_id
1048 assert_nil issue.parent_id
1047 end
1049 end
1048
1050
1049 def test_move_to_another_project_with_disabled_tracker
1051 def test_move_to_another_project_with_disabled_tracker
1050 issue = Issue.find(1)
1052 issue = Issue.find(1)
1051 target = Project.find(2)
1053 target = Project.find(2)
1052 target.tracker_ids = [3]
1054 target.tracker_ids = [3]
1053 target.save
1055 target.save
1054 issue.project = target
1056 issue.project = target
1055 assert issue.save
1057 assert issue.save
1056 issue.reload
1058 issue.reload
1057 assert_equal 2, issue.project_id
1059 assert_equal 2, issue.project_id
1058 assert_equal 3, issue.tracker_id
1060 assert_equal 3, issue.tracker_id
1059 end
1061 end
1060
1062
1061 def test_copy_to_the_same_project
1063 def test_copy_to_the_same_project
1062 issue = Issue.find(1)
1064 issue = Issue.find(1)
1063 copy = issue.copy
1065 copy = issue.copy
1064 assert_difference 'Issue.count' do
1066 assert_difference 'Issue.count' do
1065 copy.save!
1067 copy.save!
1066 end
1068 end
1067 assert_kind_of Issue, copy
1069 assert_kind_of Issue, copy
1068 assert_equal issue.project, copy.project
1070 assert_equal issue.project, copy.project
1069 assert_equal "125", copy.custom_value_for(2).value
1071 assert_equal "125", copy.custom_value_for(2).value
1070 end
1072 end
1071
1073
1072 def test_copy_to_another_project_and_tracker
1074 def test_copy_to_another_project_and_tracker
1073 issue = Issue.find(1)
1075 issue = Issue.find(1)
1074 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1076 copy = issue.copy(:project_id => 3, :tracker_id => 2)
1075 assert_difference 'Issue.count' do
1077 assert_difference 'Issue.count' do
1076 copy.save!
1078 copy.save!
1077 end
1079 end
1078 copy.reload
1080 copy.reload
1079 assert_kind_of Issue, copy
1081 assert_kind_of Issue, copy
1080 assert_equal Project.find(3), copy.project
1082 assert_equal Project.find(3), copy.project
1081 assert_equal Tracker.find(2), copy.tracker
1083 assert_equal Tracker.find(2), copy.tracker
1082 # Custom field #2 is not associated with target tracker
1084 # Custom field #2 is not associated with target tracker
1083 assert_nil copy.custom_value_for(2)
1085 assert_nil copy.custom_value_for(2)
1084 end
1086 end
1085
1087
1086 context "#copy" do
1088 context "#copy" do
1087 setup do
1089 setup do
1088 @issue = Issue.find(1)
1090 @issue = Issue.find(1)
1089 end
1091 end
1090
1092
1091 should "not create a journal" do
1093 should "not create a journal" do
1092 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1094 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1093 copy.save!
1095 copy.save!
1094 assert_equal 0, copy.reload.journals.size
1096 assert_equal 0, copy.reload.journals.size
1095 end
1097 end
1096
1098
1097 should "allow assigned_to changes" do
1099 should "allow assigned_to changes" do
1098 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1100 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1099 assert_equal 3, copy.assigned_to_id
1101 assert_equal 3, copy.assigned_to_id
1100 end
1102 end
1101
1103
1102 should "allow status changes" do
1104 should "allow status changes" do
1103 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1105 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1104 assert_equal 2, copy.status_id
1106 assert_equal 2, copy.status_id
1105 end
1107 end
1106
1108
1107 should "allow start date changes" do
1109 should "allow start date changes" do
1108 date = Date.today
1110 date = Date.today
1109 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1111 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1110 assert_equal date, copy.start_date
1112 assert_equal date, copy.start_date
1111 end
1113 end
1112
1114
1113 should "allow due date changes" do
1115 should "allow due date changes" do
1114 date = Date.today
1116 date = Date.today
1115 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1117 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1116 assert_equal date, copy.due_date
1118 assert_equal date, copy.due_date
1117 end
1119 end
1118
1120
1119 should "set current user as author" do
1121 should "set current user as author" do
1120 User.current = User.find(9)
1122 User.current = User.find(9)
1121 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1123 copy = @issue.copy(:project_id => 3, :tracker_id => 2)
1122 assert_equal User.current, copy.author
1124 assert_equal User.current, copy.author
1123 end
1125 end
1124
1126
1125 should "create a journal with notes" do
1127 should "create a journal with notes" do
1126 date = Date.today
1128 date = Date.today
1127 notes = "Notes added when copying"
1129 notes = "Notes added when copying"
1128 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1130 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1129 copy.init_journal(User.current, notes)
1131 copy.init_journal(User.current, notes)
1130 copy.save!
1132 copy.save!
1131
1133
1132 assert_equal 1, copy.journals.size
1134 assert_equal 1, copy.journals.size
1133 journal = copy.journals.first
1135 journal = copy.journals.first
1134 assert_equal 0, journal.details.size
1136 assert_equal 0, journal.details.size
1135 assert_equal notes, journal.notes
1137 assert_equal notes, journal.notes
1136 end
1138 end
1137 end
1139 end
1138
1140
1139 def test_valid_parent_project
1141 def test_valid_parent_project
1140 issue = Issue.find(1)
1142 issue = Issue.find(1)
1141 issue_in_same_project = Issue.find(2)
1143 issue_in_same_project = Issue.find(2)
1142 issue_in_child_project = Issue.find(5)
1144 issue_in_child_project = Issue.find(5)
1143 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1145 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
1144 issue_in_other_child_project = Issue.find(6)
1146 issue_in_other_child_project = Issue.find(6)
1145 issue_in_different_tree = Issue.find(4)
1147 issue_in_different_tree = Issue.find(4)
1146
1148
1147 with_settings :cross_project_subtasks => '' do
1149 with_settings :cross_project_subtasks => '' do
1148 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1150 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1149 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1151 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1150 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1152 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1151 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1153 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1152 end
1154 end
1153
1155
1154 with_settings :cross_project_subtasks => 'system' do
1156 with_settings :cross_project_subtasks => 'system' do
1155 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1157 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1156 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1158 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1157 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1159 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
1158 end
1160 end
1159
1161
1160 with_settings :cross_project_subtasks => 'tree' do
1162 with_settings :cross_project_subtasks => 'tree' do
1161 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1163 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1162 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1164 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
1163 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1165 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
1164 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1166 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1165
1167
1166 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1168 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
1167 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1169 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1168 end
1170 end
1169
1171
1170 with_settings :cross_project_subtasks => 'descendants' do
1172 with_settings :cross_project_subtasks => 'descendants' do
1171 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1173 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
1172 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1174 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
1173 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1175 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
1174 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1176 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
1175
1177
1176 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1178 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
1177 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1179 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
1178 end
1180 end
1179 end
1181 end
1180
1182
1181 def test_recipients_should_include_previous_assignee
1183 def test_recipients_should_include_previous_assignee
1182 user = User.find(3)
1184 user = User.find(3)
1183 user.members.update_all ["mail_notification = ?", false]
1185 user.members.update_all ["mail_notification = ?", false]
1184 user.update_attribute :mail_notification, 'only_assigned'
1186 user.update_attribute :mail_notification, 'only_assigned'
1185
1187
1186 issue = Issue.find(2)
1188 issue = Issue.find(2)
1187 issue.assigned_to = nil
1189 issue.assigned_to = nil
1188 assert_include user.mail, issue.recipients
1190 assert_include user.mail, issue.recipients
1189 issue.save!
1191 issue.save!
1190 assert !issue.recipients.include?(user.mail)
1192 assert !issue.recipients.include?(user.mail)
1191 end
1193 end
1192
1194
1193 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1195 def test_recipients_should_not_include_users_that_cannot_view_the_issue
1194 issue = Issue.find(12)
1196 issue = Issue.find(12)
1195 assert issue.recipients.include?(issue.author.mail)
1197 assert issue.recipients.include?(issue.author.mail)
1196 # copy the issue to a private project
1198 # copy the issue to a private project
1197 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1199 copy = issue.copy(:project_id => 5, :tracker_id => 2)
1198 # author is not a member of project anymore
1200 # author is not a member of project anymore
1199 assert !copy.recipients.include?(copy.author.mail)
1201 assert !copy.recipients.include?(copy.author.mail)
1200 end
1202 end
1201
1203
1202 def test_recipients_should_include_the_assigned_group_members
1204 def test_recipients_should_include_the_assigned_group_members
1203 group_member = User.generate!
1205 group_member = User.generate!
1204 group = Group.generate!
1206 group = Group.generate!
1205 group.users << group_member
1207 group.users << group_member
1206
1208
1207 issue = Issue.find(12)
1209 issue = Issue.find(12)
1208 issue.assigned_to = group
1210 issue.assigned_to = group
1209 assert issue.recipients.include?(group_member.mail)
1211 assert issue.recipients.include?(group_member.mail)
1210 end
1212 end
1211
1213
1212 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1214 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
1213 user = User.find(3)
1215 user = User.find(3)
1214 issue = Issue.find(9)
1216 issue = Issue.find(9)
1215 Watcher.create!(:user => user, :watchable => issue)
1217 Watcher.create!(:user => user, :watchable => issue)
1216 assert issue.watched_by?(user)
1218 assert issue.watched_by?(user)
1217 assert !issue.watcher_recipients.include?(user.mail)
1219 assert !issue.watcher_recipients.include?(user.mail)
1218 end
1220 end
1219
1221
1220 def test_issue_destroy
1222 def test_issue_destroy
1221 Issue.find(1).destroy
1223 Issue.find(1).destroy
1222 assert_nil Issue.find_by_id(1)
1224 assert_nil Issue.find_by_id(1)
1223 assert_nil TimeEntry.find_by_issue_id(1)
1225 assert_nil TimeEntry.find_by_issue_id(1)
1224 end
1226 end
1225
1227
1226 def test_destroying_a_deleted_issue_should_not_raise_an_error
1228 def test_destroying_a_deleted_issue_should_not_raise_an_error
1227 issue = Issue.find(1)
1229 issue = Issue.find(1)
1228 Issue.find(1).destroy
1230 Issue.find(1).destroy
1229
1231
1230 assert_nothing_raised do
1232 assert_nothing_raised do
1231 assert_no_difference 'Issue.count' do
1233 assert_no_difference 'Issue.count' do
1232 issue.destroy
1234 issue.destroy
1233 end
1235 end
1234 assert issue.destroyed?
1236 assert issue.destroyed?
1235 end
1237 end
1236 end
1238 end
1237
1239
1238 def test_destroying_a_stale_issue_should_not_raise_an_error
1240 def test_destroying_a_stale_issue_should_not_raise_an_error
1239 issue = Issue.find(1)
1241 issue = Issue.find(1)
1240 Issue.find(1).update_attribute :subject, "Updated"
1242 Issue.find(1).update_attribute :subject, "Updated"
1241
1243
1242 assert_nothing_raised do
1244 assert_nothing_raised do
1243 assert_difference 'Issue.count', -1 do
1245 assert_difference 'Issue.count', -1 do
1244 issue.destroy
1246 issue.destroy
1245 end
1247 end
1246 assert issue.destroyed?
1248 assert issue.destroyed?
1247 end
1249 end
1248 end
1250 end
1249
1251
1250 def test_blocked
1252 def test_blocked
1251 blocked_issue = Issue.find(9)
1253 blocked_issue = Issue.find(9)
1252 blocking_issue = Issue.find(10)
1254 blocking_issue = Issue.find(10)
1253
1255
1254 assert blocked_issue.blocked?
1256 assert blocked_issue.blocked?
1255 assert !blocking_issue.blocked?
1257 assert !blocking_issue.blocked?
1256 end
1258 end
1257
1259
1258 def test_blocked_issues_dont_allow_closed_statuses
1260 def test_blocked_issues_dont_allow_closed_statuses
1259 blocked_issue = Issue.find(9)
1261 blocked_issue = Issue.find(9)
1260
1262
1261 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1263 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
1262 assert !allowed_statuses.empty?
1264 assert !allowed_statuses.empty?
1263 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1265 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1264 assert closed_statuses.empty?
1266 assert closed_statuses.empty?
1265 end
1267 end
1266
1268
1267 def test_unblocked_issues_allow_closed_statuses
1269 def test_unblocked_issues_allow_closed_statuses
1268 blocking_issue = Issue.find(10)
1270 blocking_issue = Issue.find(10)
1269
1271
1270 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1272 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
1271 assert !allowed_statuses.empty?
1273 assert !allowed_statuses.empty?
1272 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1274 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
1273 assert !closed_statuses.empty?
1275 assert !closed_statuses.empty?
1274 end
1276 end
1275
1277
1276 def test_rescheduling_an_issue_should_reschedule_following_issue
1278 def test_rescheduling_an_issue_should_reschedule_following_issue
1277 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1,
1279 issue1 = 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 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1,
1283 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1,
1282 :author_id => 1, :status_id => 1,
1284 :author_id => 1, :status_id => 1,
1283 :subject => '-',
1285 :subject => '-',
1284 :start_date => Date.today, :due_date => Date.today + 2)
1286 :start_date => Date.today, :due_date => Date.today + 2)
1285 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1287 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1286 :relation_type => IssueRelation::TYPE_PRECEDES)
1288 :relation_type => IssueRelation::TYPE_PRECEDES)
1287 assert_equal issue1.due_date + 1, issue2.reload.start_date
1289 assert_equal issue1.due_date + 1, issue2.reload.start_date
1288
1290
1289 issue1.due_date = Date.today + 5
1291 issue1.due_date = Date.today + 5
1290 issue1.save!
1292 issue1.save!
1291 assert_equal issue1.due_date + 1, issue2.reload.start_date
1293 assert_equal issue1.due_date + 1, issue2.reload.start_date
1292 end
1294 end
1293
1295
1294 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1296 def test_rescheduling_a_stale_issue_should_not_raise_an_error
1295 stale = Issue.find(1)
1297 stale = Issue.find(1)
1296 issue = Issue.find(1)
1298 issue = Issue.find(1)
1297 issue.subject = "Updated"
1299 issue.subject = "Updated"
1298 issue.save!
1300 issue.save!
1299
1301
1300 date = 10.days.from_now.to_date
1302 date = 10.days.from_now.to_date
1301 assert_nothing_raised do
1303 assert_nothing_raised do
1302 stale.reschedule_after(date)
1304 stale.reschedule_after(date)
1303 end
1305 end
1304 assert_equal date, stale.reload.start_date
1306 assert_equal date, stale.reload.start_date
1305 end
1307 end
1306
1308
1307 def test_overdue
1309 def test_overdue
1308 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1310 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1309 assert !Issue.new(:due_date => Date.today).overdue?
1311 assert !Issue.new(:due_date => Date.today).overdue?
1310 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1312 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1311 assert !Issue.new(:due_date => nil).overdue?
1313 assert !Issue.new(:due_date => nil).overdue?
1312 assert !Issue.new(:due_date => 1.day.ago.to_date,
1314 assert !Issue.new(:due_date => 1.day.ago.to_date,
1313 :status => IssueStatus.find(:first,
1315 :status => IssueStatus.find(:first,
1314 :conditions => {:is_closed => true})
1316 :conditions => {:is_closed => true})
1315 ).overdue?
1317 ).overdue?
1316 end
1318 end
1317
1319
1318 context "#behind_schedule?" do
1320 context "#behind_schedule?" do
1319 should "be false if the issue has no start_date" do
1321 should "be false if the issue has no start_date" do
1320 assert !Issue.new(:start_date => nil,
1322 assert !Issue.new(:start_date => nil,
1321 :due_date => 1.day.from_now.to_date,
1323 :due_date => 1.day.from_now.to_date,
1322 :done_ratio => 0).behind_schedule?
1324 :done_ratio => 0).behind_schedule?
1323 end
1325 end
1324
1326
1325 should "be false if the issue has no end_date" do
1327 should "be false if the issue has no end_date" do
1326 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1328 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1327 :due_date => nil,
1329 :due_date => nil,
1328 :done_ratio => 0).behind_schedule?
1330 :done_ratio => 0).behind_schedule?
1329 end
1331 end
1330
1332
1331 should "be false if the issue has more done than it's calendar time" do
1333 should "be false if the issue has more done than it's calendar time" do
1332 assert !Issue.new(:start_date => 50.days.ago.to_date,
1334 assert !Issue.new(:start_date => 50.days.ago.to_date,
1333 :due_date => 50.days.from_now.to_date,
1335 :due_date => 50.days.from_now.to_date,
1334 :done_ratio => 90).behind_schedule?
1336 :done_ratio => 90).behind_schedule?
1335 end
1337 end
1336
1338
1337 should "be true if the issue hasn't been started at all" do
1339 should "be true if the issue hasn't been started at all" do
1338 assert Issue.new(:start_date => 1.day.ago.to_date,
1340 assert Issue.new(:start_date => 1.day.ago.to_date,
1339 :due_date => 1.day.from_now.to_date,
1341 :due_date => 1.day.from_now.to_date,
1340 :done_ratio => 0).behind_schedule?
1342 :done_ratio => 0).behind_schedule?
1341 end
1343 end
1342
1344
1343 should "be true if the issue has used more calendar time than it's done ratio" do
1345 should "be true if the issue has used more calendar time than it's done ratio" do
1344 assert Issue.new(:start_date => 100.days.ago.to_date,
1346 assert Issue.new(:start_date => 100.days.ago.to_date,
1345 :due_date => Date.today,
1347 :due_date => Date.today,
1346 :done_ratio => 90).behind_schedule?
1348 :done_ratio => 90).behind_schedule?
1347 end
1349 end
1348 end
1350 end
1349
1351
1350 context "#assignable_users" do
1352 context "#assignable_users" do
1351 should "be Users" do
1353 should "be Users" do
1352 assert_kind_of User, Issue.find(1).assignable_users.first
1354 assert_kind_of User, Issue.find(1).assignable_users.first
1353 end
1355 end
1354
1356
1355 should "include the issue author" do
1357 should "include the issue author" do
1356 non_project_member = User.generate!
1358 non_project_member = User.generate!
1357 issue = Issue.generate!(:author => non_project_member)
1359 issue = Issue.generate!(:author => non_project_member)
1358
1360
1359 assert issue.assignable_users.include?(non_project_member)
1361 assert issue.assignable_users.include?(non_project_member)
1360 end
1362 end
1361
1363
1362 should "include the current assignee" do
1364 should "include the current assignee" do
1363 user = User.generate!
1365 user = User.generate!
1364 issue = Issue.generate!(:assigned_to => user)
1366 issue = Issue.generate!(:assigned_to => user)
1365 user.lock!
1367 user.lock!
1366
1368
1367 assert Issue.find(issue.id).assignable_users.include?(user)
1369 assert Issue.find(issue.id).assignable_users.include?(user)
1368 end
1370 end
1369
1371
1370 should "not show the issue author twice" do
1372 should "not show the issue author twice" do
1371 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1373 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1372 assert_equal 2, assignable_user_ids.length
1374 assert_equal 2, assignable_user_ids.length
1373
1375
1374 assignable_user_ids.each do |user_id|
1376 assignable_user_ids.each do |user_id|
1375 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1377 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1376 "User #{user_id} appears more or less than once"
1378 "User #{user_id} appears more or less than once"
1377 end
1379 end
1378 end
1380 end
1379
1381
1380 context "with issue_group_assignment" do
1382 context "with issue_group_assignment" do
1381 should "include groups" do
1383 should "include groups" do
1382 issue = Issue.new(:project => Project.find(2))
1384 issue = Issue.new(:project => Project.find(2))
1383
1385
1384 with_settings :issue_group_assignment => '1' do
1386 with_settings :issue_group_assignment => '1' do
1385 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1387 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1386 assert issue.assignable_users.include?(Group.find(11))
1388 assert issue.assignable_users.include?(Group.find(11))
1387 end
1389 end
1388 end
1390 end
1389 end
1391 end
1390
1392
1391 context "without issue_group_assignment" do
1393 context "without issue_group_assignment" do
1392 should "not include groups" do
1394 should "not include groups" do
1393 issue = Issue.new(:project => Project.find(2))
1395 issue = Issue.new(:project => Project.find(2))
1394
1396
1395 with_settings :issue_group_assignment => '0' do
1397 with_settings :issue_group_assignment => '0' do
1396 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1398 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1397 assert !issue.assignable_users.include?(Group.find(11))
1399 assert !issue.assignable_users.include?(Group.find(11))
1398 end
1400 end
1399 end
1401 end
1400 end
1402 end
1401 end
1403 end
1402
1404
1403 def test_create_should_send_email_notification
1405 def test_create_should_send_email_notification
1404 ActionMailer::Base.deliveries.clear
1406 ActionMailer::Base.deliveries.clear
1405 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1407 issue = Issue.new(:project_id => 1, :tracker_id => 1,
1406 :author_id => 3, :status_id => 1,
1408 :author_id => 3, :status_id => 1,
1407 :priority => IssuePriority.all.first,
1409 :priority => IssuePriority.all.first,
1408 :subject => 'test_create', :estimated_hours => '1:30')
1410 :subject => 'test_create', :estimated_hours => '1:30')
1409
1411
1410 assert issue.save
1412 assert issue.save
1411 assert_equal 1, ActionMailer::Base.deliveries.size
1413 assert_equal 1, ActionMailer::Base.deliveries.size
1412 end
1414 end
1413
1415
1414 def test_stale_issue_should_not_send_email_notification
1416 def test_stale_issue_should_not_send_email_notification
1415 ActionMailer::Base.deliveries.clear
1417 ActionMailer::Base.deliveries.clear
1416 issue = Issue.find(1)
1418 issue = Issue.find(1)
1417 stale = Issue.find(1)
1419 stale = Issue.find(1)
1418
1420
1419 issue.init_journal(User.find(1))
1421 issue.init_journal(User.find(1))
1420 issue.subject = 'Subjet update'
1422 issue.subject = 'Subjet update'
1421 assert issue.save
1423 assert issue.save
1422 assert_equal 1, ActionMailer::Base.deliveries.size
1424 assert_equal 1, ActionMailer::Base.deliveries.size
1423 ActionMailer::Base.deliveries.clear
1425 ActionMailer::Base.deliveries.clear
1424
1426
1425 stale.init_journal(User.find(1))
1427 stale.init_journal(User.find(1))
1426 stale.subject = 'Another subjet update'
1428 stale.subject = 'Another subjet update'
1427 assert_raise ActiveRecord::StaleObjectError do
1429 assert_raise ActiveRecord::StaleObjectError do
1428 stale.save
1430 stale.save
1429 end
1431 end
1430 assert ActionMailer::Base.deliveries.empty?
1432 assert ActionMailer::Base.deliveries.empty?
1431 end
1433 end
1432
1434
1433 def test_journalized_description
1435 def test_journalized_description
1434 IssueCustomField.delete_all
1436 IssueCustomField.delete_all
1435
1437
1436 i = Issue.first
1438 i = Issue.first
1437 old_description = i.description
1439 old_description = i.description
1438 new_description = "This is the new description"
1440 new_description = "This is the new description"
1439
1441
1440 i.init_journal(User.find(2))
1442 i.init_journal(User.find(2))
1441 i.description = new_description
1443 i.description = new_description
1442 assert_difference 'Journal.count', 1 do
1444 assert_difference 'Journal.count', 1 do
1443 assert_difference 'JournalDetail.count', 1 do
1445 assert_difference 'JournalDetail.count', 1 do
1444 i.save!
1446 i.save!
1445 end
1447 end
1446 end
1448 end
1447
1449
1448 detail = JournalDetail.first(:order => 'id DESC')
1450 detail = JournalDetail.first(:order => 'id DESC')
1449 assert_equal i, detail.journal.journalized
1451 assert_equal i, detail.journal.journalized
1450 assert_equal 'attr', detail.property
1452 assert_equal 'attr', detail.property
1451 assert_equal 'description', detail.prop_key
1453 assert_equal 'description', detail.prop_key
1452 assert_equal old_description, detail.old_value
1454 assert_equal old_description, detail.old_value
1453 assert_equal new_description, detail.value
1455 assert_equal new_description, detail.value
1454 end
1456 end
1455
1457
1456 def test_blank_descriptions_should_not_be_journalized
1458 def test_blank_descriptions_should_not_be_journalized
1457 IssueCustomField.delete_all
1459 IssueCustomField.delete_all
1458 Issue.update_all("description = NULL", "id=1")
1460 Issue.update_all("description = NULL", "id=1")
1459
1461
1460 i = Issue.find(1)
1462 i = Issue.find(1)
1461 i.init_journal(User.find(2))
1463 i.init_journal(User.find(2))
1462 i.subject = "blank description"
1464 i.subject = "blank description"
1463 i.description = "\r\n"
1465 i.description = "\r\n"
1464
1466
1465 assert_difference 'Journal.count', 1 do
1467 assert_difference 'Journal.count', 1 do
1466 assert_difference 'JournalDetail.count', 1 do
1468 assert_difference 'JournalDetail.count', 1 do
1467 i.save!
1469 i.save!
1468 end
1470 end
1469 end
1471 end
1470 end
1472 end
1471
1473
1472 def test_journalized_multi_custom_field
1474 def test_journalized_multi_custom_field
1473 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1475 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
1474 :is_filter => true, :is_for_all => true,
1476 :is_filter => true, :is_for_all => true,
1475 :tracker_ids => [1],
1477 :tracker_ids => [1],
1476 :possible_values => ['value1', 'value2', 'value3'],
1478 :possible_values => ['value1', 'value2', 'value3'],
1477 :multiple => true)
1479 :multiple => true)
1478
1480
1479 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1481 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
1480 :subject => 'Test', :author_id => 1)
1482 :subject => 'Test', :author_id => 1)
1481
1483
1482 assert_difference 'Journal.count' do
1484 assert_difference 'Journal.count' do
1483 assert_difference 'JournalDetail.count' do
1485 assert_difference 'JournalDetail.count' do
1484 issue.init_journal(User.first)
1486 issue.init_journal(User.first)
1485 issue.custom_field_values = {field.id => ['value1']}
1487 issue.custom_field_values = {field.id => ['value1']}
1486 issue.save!
1488 issue.save!
1487 end
1489 end
1488 assert_difference 'JournalDetail.count' do
1490 assert_difference 'JournalDetail.count' do
1489 issue.init_journal(User.first)
1491 issue.init_journal(User.first)
1490 issue.custom_field_values = {field.id => ['value1', 'value2']}
1492 issue.custom_field_values = {field.id => ['value1', 'value2']}
1491 issue.save!
1493 issue.save!
1492 end
1494 end
1493 assert_difference 'JournalDetail.count', 2 do
1495 assert_difference 'JournalDetail.count', 2 do
1494 issue.init_journal(User.first)
1496 issue.init_journal(User.first)
1495 issue.custom_field_values = {field.id => ['value3', 'value2']}
1497 issue.custom_field_values = {field.id => ['value3', 'value2']}
1496 issue.save!
1498 issue.save!
1497 end
1499 end
1498 assert_difference 'JournalDetail.count', 2 do
1500 assert_difference 'JournalDetail.count', 2 do
1499 issue.init_journal(User.first)
1501 issue.init_journal(User.first)
1500 issue.custom_field_values = {field.id => nil}
1502 issue.custom_field_values = {field.id => nil}
1501 issue.save!
1503 issue.save!
1502 end
1504 end
1503 end
1505 end
1504 end
1506 end
1505
1507
1506 def test_description_eol_should_be_normalized
1508 def test_description_eol_should_be_normalized
1507 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1509 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1508 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1510 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1509 end
1511 end
1510
1512
1511 def test_saving_twice_should_not_duplicate_journal_details
1513 def test_saving_twice_should_not_duplicate_journal_details
1512 i = Issue.find(:first)
1514 i = Issue.find(:first)
1513 i.init_journal(User.find(2), 'Some notes')
1515 i.init_journal(User.find(2), 'Some notes')
1514 # initial changes
1516 # initial changes
1515 i.subject = 'New subject'
1517 i.subject = 'New subject'
1516 i.done_ratio = i.done_ratio + 10
1518 i.done_ratio = i.done_ratio + 10
1517 assert_difference 'Journal.count' do
1519 assert_difference 'Journal.count' do
1518 assert i.save
1520 assert i.save
1519 end
1521 end
1520 # 1 more change
1522 # 1 more change
1521 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1523 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
1522 assert_no_difference 'Journal.count' do
1524 assert_no_difference 'Journal.count' do
1523 assert_difference 'JournalDetail.count', 1 do
1525 assert_difference 'JournalDetail.count', 1 do
1524 i.save
1526 i.save
1525 end
1527 end
1526 end
1528 end
1527 # no more change
1529 # no more change
1528 assert_no_difference 'Journal.count' do
1530 assert_no_difference 'Journal.count' do
1529 assert_no_difference 'JournalDetail.count' do
1531 assert_no_difference 'JournalDetail.count' do
1530 i.save
1532 i.save
1531 end
1533 end
1532 end
1534 end
1533 end
1535 end
1534
1536
1535 def test_all_dependent_issues
1537 def test_all_dependent_issues
1536 IssueRelation.delete_all
1538 IssueRelation.delete_all
1537 assert IssueRelation.create!(:issue_from => Issue.find(1),
1539 assert IssueRelation.create!(:issue_from => Issue.find(1),
1538 :issue_to => Issue.find(2),
1540 :issue_to => Issue.find(2),
1539 :relation_type => IssueRelation::TYPE_PRECEDES)
1541 :relation_type => IssueRelation::TYPE_PRECEDES)
1540 assert IssueRelation.create!(:issue_from => Issue.find(2),
1542 assert IssueRelation.create!(:issue_from => Issue.find(2),
1541 :issue_to => Issue.find(3),
1543 :issue_to => Issue.find(3),
1542 :relation_type => IssueRelation::TYPE_PRECEDES)
1544 :relation_type => IssueRelation::TYPE_PRECEDES)
1543 assert IssueRelation.create!(:issue_from => Issue.find(3),
1545 assert IssueRelation.create!(:issue_from => Issue.find(3),
1544 :issue_to => Issue.find(8),
1546 :issue_to => Issue.find(8),
1545 :relation_type => IssueRelation::TYPE_PRECEDES)
1547 :relation_type => IssueRelation::TYPE_PRECEDES)
1546
1548
1547 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1549 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1548 end
1550 end
1549
1551
1550 def test_all_dependent_issues_with_persistent_circular_dependency
1552 def test_all_dependent_issues_with_persistent_circular_dependency
1551 IssueRelation.delete_all
1553 IssueRelation.delete_all
1552 assert IssueRelation.create!(:issue_from => Issue.find(1),
1554 assert IssueRelation.create!(:issue_from => Issue.find(1),
1553 :issue_to => Issue.find(2),
1555 :issue_to => Issue.find(2),
1554 :relation_type => IssueRelation::TYPE_PRECEDES)
1556 :relation_type => IssueRelation::TYPE_PRECEDES)
1555 assert IssueRelation.create!(:issue_from => Issue.find(2),
1557 assert IssueRelation.create!(:issue_from => Issue.find(2),
1556 :issue_to => Issue.find(3),
1558 :issue_to => Issue.find(3),
1557 :relation_type => IssueRelation::TYPE_PRECEDES)
1559 :relation_type => IssueRelation::TYPE_PRECEDES)
1558
1560
1559 r = IssueRelation.create!(:issue_from => Issue.find(3),
1561 r = IssueRelation.create!(:issue_from => Issue.find(3),
1560 :issue_to => Issue.find(7),
1562 :issue_to => Issue.find(7),
1561 :relation_type => IssueRelation::TYPE_PRECEDES)
1563 :relation_type => IssueRelation::TYPE_PRECEDES)
1562 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1564 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1563
1565
1564 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1566 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1565 end
1567 end
1566
1568
1567 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1569 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1568 IssueRelation.delete_all
1570 IssueRelation.delete_all
1569 assert IssueRelation.create!(:issue_from => Issue.find(1),
1571 assert IssueRelation.create!(:issue_from => Issue.find(1),
1570 :issue_to => Issue.find(2),
1572 :issue_to => Issue.find(2),
1571 :relation_type => IssueRelation::TYPE_RELATES)
1573 :relation_type => IssueRelation::TYPE_RELATES)
1572 assert IssueRelation.create!(:issue_from => Issue.find(2),
1574 assert IssueRelation.create!(:issue_from => Issue.find(2),
1573 :issue_to => Issue.find(3),
1575 :issue_to => Issue.find(3),
1574 :relation_type => IssueRelation::TYPE_RELATES)
1576 :relation_type => IssueRelation::TYPE_RELATES)
1575 assert IssueRelation.create!(:issue_from => Issue.find(3),
1577 assert IssueRelation.create!(:issue_from => Issue.find(3),
1576 :issue_to => Issue.find(8),
1578 :issue_to => Issue.find(8),
1577 :relation_type => IssueRelation::TYPE_RELATES)
1579 :relation_type => IssueRelation::TYPE_RELATES)
1578
1580
1579 r = IssueRelation.create!(:issue_from => Issue.find(8),
1581 r = IssueRelation.create!(:issue_from => Issue.find(8),
1580 :issue_to => Issue.find(7),
1582 :issue_to => Issue.find(7),
1581 :relation_type => IssueRelation::TYPE_RELATES)
1583 :relation_type => IssueRelation::TYPE_RELATES)
1582 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1584 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1583
1585
1584 r = IssueRelation.create!(:issue_from => Issue.find(3),
1586 r = IssueRelation.create!(:issue_from => Issue.find(3),
1585 :issue_to => Issue.find(7),
1587 :issue_to => Issue.find(7),
1586 :relation_type => IssueRelation::TYPE_RELATES)
1588 :relation_type => IssueRelation::TYPE_RELATES)
1587 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1589 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1588
1590
1589 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1591 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1590 end
1592 end
1591
1593
1592 context "#done_ratio" do
1594 context "#done_ratio" do
1593 setup do
1595 setup do
1594 @issue = Issue.find(1)
1596 @issue = Issue.find(1)
1595 @issue_status = IssueStatus.find(1)
1597 @issue_status = IssueStatus.find(1)
1596 @issue_status.update_attribute(:default_done_ratio, 50)
1598 @issue_status.update_attribute(:default_done_ratio, 50)
1597 @issue2 = Issue.find(2)
1599 @issue2 = Issue.find(2)
1598 @issue_status2 = IssueStatus.find(2)
1600 @issue_status2 = IssueStatus.find(2)
1599 @issue_status2.update_attribute(:default_done_ratio, 0)
1601 @issue_status2.update_attribute(:default_done_ratio, 0)
1600 end
1602 end
1601
1603
1602 teardown do
1604 teardown do
1603 Setting.issue_done_ratio = 'issue_field'
1605 Setting.issue_done_ratio = 'issue_field'
1604 end
1606 end
1605
1607
1606 context "with Setting.issue_done_ratio using the issue_field" do
1608 context "with Setting.issue_done_ratio using the issue_field" do
1607 setup do
1609 setup do
1608 Setting.issue_done_ratio = 'issue_field'
1610 Setting.issue_done_ratio = 'issue_field'
1609 end
1611 end
1610
1612
1611 should "read the issue's field" do
1613 should "read the issue's field" do
1612 assert_equal 0, @issue.done_ratio
1614 assert_equal 0, @issue.done_ratio
1613 assert_equal 30, @issue2.done_ratio
1615 assert_equal 30, @issue2.done_ratio
1614 end
1616 end
1615 end
1617 end
1616
1618
1617 context "with Setting.issue_done_ratio using the issue_status" do
1619 context "with Setting.issue_done_ratio using the issue_status" do
1618 setup do
1620 setup do
1619 Setting.issue_done_ratio = 'issue_status'
1621 Setting.issue_done_ratio = 'issue_status'
1620 end
1622 end
1621
1623
1622 should "read the Issue Status's default done ratio" do
1624 should "read the Issue Status's default done ratio" do
1623 assert_equal 50, @issue.done_ratio
1625 assert_equal 50, @issue.done_ratio
1624 assert_equal 0, @issue2.done_ratio
1626 assert_equal 0, @issue2.done_ratio
1625 end
1627 end
1626 end
1628 end
1627 end
1629 end
1628
1630
1629 context "#update_done_ratio_from_issue_status" do
1631 context "#update_done_ratio_from_issue_status" do
1630 setup do
1632 setup do
1631 @issue = Issue.find(1)
1633 @issue = Issue.find(1)
1632 @issue_status = IssueStatus.find(1)
1634 @issue_status = IssueStatus.find(1)
1633 @issue_status.update_attribute(:default_done_ratio, 50)
1635 @issue_status.update_attribute(:default_done_ratio, 50)
1634 @issue2 = Issue.find(2)
1636 @issue2 = Issue.find(2)
1635 @issue_status2 = IssueStatus.find(2)
1637 @issue_status2 = IssueStatus.find(2)
1636 @issue_status2.update_attribute(:default_done_ratio, 0)
1638 @issue_status2.update_attribute(:default_done_ratio, 0)
1637 end
1639 end
1638
1640
1639 context "with Setting.issue_done_ratio using the issue_field" do
1641 context "with Setting.issue_done_ratio using the issue_field" do
1640 setup do
1642 setup do
1641 Setting.issue_done_ratio = 'issue_field'
1643 Setting.issue_done_ratio = 'issue_field'
1642 end
1644 end
1643
1645
1644 should "not change the issue" do
1646 should "not change the issue" do
1645 @issue.update_done_ratio_from_issue_status
1647 @issue.update_done_ratio_from_issue_status
1646 @issue2.update_done_ratio_from_issue_status
1648 @issue2.update_done_ratio_from_issue_status
1647
1649
1648 assert_equal 0, @issue.read_attribute(:done_ratio)
1650 assert_equal 0, @issue.read_attribute(:done_ratio)
1649 assert_equal 30, @issue2.read_attribute(:done_ratio)
1651 assert_equal 30, @issue2.read_attribute(:done_ratio)
1650 end
1652 end
1651 end
1653 end
1652
1654
1653 context "with Setting.issue_done_ratio using the issue_status" do
1655 context "with Setting.issue_done_ratio using the issue_status" do
1654 setup do
1656 setup do
1655 Setting.issue_done_ratio = 'issue_status'
1657 Setting.issue_done_ratio = 'issue_status'
1656 end
1658 end
1657
1659
1658 should "change the issue's done ratio" do
1660 should "change the issue's done ratio" do
1659 @issue.update_done_ratio_from_issue_status
1661 @issue.update_done_ratio_from_issue_status
1660 @issue2.update_done_ratio_from_issue_status
1662 @issue2.update_done_ratio_from_issue_status
1661
1663
1662 assert_equal 50, @issue.read_attribute(:done_ratio)
1664 assert_equal 50, @issue.read_attribute(:done_ratio)
1663 assert_equal 0, @issue2.read_attribute(:done_ratio)
1665 assert_equal 0, @issue2.read_attribute(:done_ratio)
1664 end
1666 end
1665 end
1667 end
1666 end
1668 end
1667
1669
1668 test "#by_tracker" do
1670 test "#by_tracker" do
1669 User.current = User.anonymous
1671 User.current = User.anonymous
1670 groups = Issue.by_tracker(Project.find(1))
1672 groups = Issue.by_tracker(Project.find(1))
1671 assert_equal 3, groups.size
1673 assert_equal 3, groups.size
1672 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1674 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1673 end
1675 end
1674
1676
1675 test "#by_version" do
1677 test "#by_version" do
1676 User.current = User.anonymous
1678 User.current = User.anonymous
1677 groups = Issue.by_version(Project.find(1))
1679 groups = Issue.by_version(Project.find(1))
1678 assert_equal 3, groups.size
1680 assert_equal 3, groups.size
1679 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1681 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1680 end
1682 end
1681
1683
1682 test "#by_priority" do
1684 test "#by_priority" do
1683 User.current = User.anonymous
1685 User.current = User.anonymous
1684 groups = Issue.by_priority(Project.find(1))
1686 groups = Issue.by_priority(Project.find(1))
1685 assert_equal 4, groups.size
1687 assert_equal 4, groups.size
1686 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1688 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1687 end
1689 end
1688
1690
1689 test "#by_category" do
1691 test "#by_category" do
1690 User.current = User.anonymous
1692 User.current = User.anonymous
1691 groups = Issue.by_category(Project.find(1))
1693 groups = Issue.by_category(Project.find(1))
1692 assert_equal 2, groups.size
1694 assert_equal 2, groups.size
1693 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1695 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1694 end
1696 end
1695
1697
1696 test "#by_assigned_to" do
1698 test "#by_assigned_to" do
1697 User.current = User.anonymous
1699 User.current = User.anonymous
1698 groups = Issue.by_assigned_to(Project.find(1))
1700 groups = Issue.by_assigned_to(Project.find(1))
1699 assert_equal 2, groups.size
1701 assert_equal 2, groups.size
1700 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1702 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1701 end
1703 end
1702
1704
1703 test "#by_author" do
1705 test "#by_author" do
1704 User.current = User.anonymous
1706 User.current = User.anonymous
1705 groups = Issue.by_author(Project.find(1))
1707 groups = Issue.by_author(Project.find(1))
1706 assert_equal 4, groups.size
1708 assert_equal 4, groups.size
1707 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1709 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1708 end
1710 end
1709
1711
1710 test "#by_subproject" do
1712 test "#by_subproject" do
1711 User.current = User.anonymous
1713 User.current = User.anonymous
1712 groups = Issue.by_subproject(Project.find(1))
1714 groups = Issue.by_subproject(Project.find(1))
1713 # Private descendant not visible
1715 # Private descendant not visible
1714 assert_equal 1, groups.size
1716 assert_equal 1, groups.size
1715 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1717 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1716 end
1718 end
1717
1719
1718 def test_recently_updated_scope
1720 def test_recently_updated_scope
1719 #should return the last updated issue
1721 #should return the last updated issue
1720 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1722 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
1721 end
1723 end
1722
1724
1723 def test_on_active_projects_scope
1725 def test_on_active_projects_scope
1724 assert Project.find(2).archive
1726 assert Project.find(2).archive
1725
1727
1726 before = Issue.on_active_project.length
1728 before = Issue.on_active_project.length
1727 # test inclusion to results
1729 # test inclusion to results
1728 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1730 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
1729 assert_equal before + 1, Issue.on_active_project.length
1731 assert_equal before + 1, Issue.on_active_project.length
1730
1732
1731 # Move to an archived project
1733 # Move to an archived project
1732 issue.project = Project.find(2)
1734 issue.project = Project.find(2)
1733 assert issue.save
1735 assert issue.save
1734 assert_equal before, Issue.on_active_project.length
1736 assert_equal before, Issue.on_active_project.length
1735 end
1737 end
1736
1738
1737 context "Issue#recipients" do
1739 context "Issue#recipients" do
1738 setup do
1740 setup do
1739 @project = Project.find(1)
1741 @project = Project.find(1)
1740 @author = User.generate!
1742 @author = User.generate!
1741 @assignee = User.generate!
1743 @assignee = User.generate!
1742 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1744 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author)
1743 end
1745 end
1744
1746
1745 should "include project recipients" do
1747 should "include project recipients" do
1746 assert @project.recipients.present?
1748 assert @project.recipients.present?
1747 @project.recipients.each do |project_recipient|
1749 @project.recipients.each do |project_recipient|
1748 assert @issue.recipients.include?(project_recipient)
1750 assert @issue.recipients.include?(project_recipient)
1749 end
1751 end
1750 end
1752 end
1751
1753
1752 should "include the author if the author is active" do
1754 should "include the author if the author is active" do
1753 assert @issue.author, "No author set for Issue"
1755 assert @issue.author, "No author set for Issue"
1754 assert @issue.recipients.include?(@issue.author.mail)
1756 assert @issue.recipients.include?(@issue.author.mail)
1755 end
1757 end
1756
1758
1757 should "include the assigned to user if the assigned to user is active" do
1759 should "include the assigned to user if the assigned to user is active" do
1758 assert @issue.assigned_to, "No assigned_to set for Issue"
1760 assert @issue.assigned_to, "No assigned_to set for Issue"
1759 assert @issue.recipients.include?(@issue.assigned_to.mail)
1761 assert @issue.recipients.include?(@issue.assigned_to.mail)
1760 end
1762 end
1761
1763
1762 should "not include users who opt out of all email" do
1764 should "not include users who opt out of all email" do
1763 @author.update_attribute(:mail_notification, :none)
1765 @author.update_attribute(:mail_notification, :none)
1764
1766
1765 assert !@issue.recipients.include?(@issue.author.mail)
1767 assert !@issue.recipients.include?(@issue.author.mail)
1766 end
1768 end
1767
1769
1768 should "not include the issue author if they are only notified of assigned issues" do
1770 should "not include the issue author if they are only notified of assigned issues" do
1769 @author.update_attribute(:mail_notification, :only_assigned)
1771 @author.update_attribute(:mail_notification, :only_assigned)
1770
1772
1771 assert !@issue.recipients.include?(@issue.author.mail)
1773 assert !@issue.recipients.include?(@issue.author.mail)
1772 end
1774 end
1773
1775
1774 should "not include the assigned user if they are only notified of owned issues" do
1776 should "not include the assigned user if they are only notified of owned issues" do
1775 @assignee.update_attribute(:mail_notification, :only_owner)
1777 @assignee.update_attribute(:mail_notification, :only_owner)
1776
1778
1777 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1779 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1778 end
1780 end
1779 end
1781 end
1780
1782
1781 def test_last_journal_id_with_journals_should_return_the_journal_id
1783 def test_last_journal_id_with_journals_should_return_the_journal_id
1782 assert_equal 2, Issue.find(1).last_journal_id
1784 assert_equal 2, Issue.find(1).last_journal_id
1783 end
1785 end
1784
1786
1785 def test_last_journal_id_without_journals_should_return_nil
1787 def test_last_journal_id_without_journals_should_return_nil
1786 assert_nil Issue.find(3).last_journal_id
1788 assert_nil Issue.find(3).last_journal_id
1787 end
1789 end
1788
1790
1789 def test_journals_after_should_return_journals_with_greater_id
1791 def test_journals_after_should_return_journals_with_greater_id
1790 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1792 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
1791 assert_equal [], Issue.find(1).journals_after('2')
1793 assert_equal [], Issue.find(1).journals_after('2')
1792 end
1794 end
1793
1795
1794 def test_journals_after_with_blank_arg_should_return_all_journals
1796 def test_journals_after_with_blank_arg_should_return_all_journals
1795 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1797 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
1796 end
1798 end
1797 end
1799 end
General Comments 0
You need to be logged in to leave comments. Login now