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