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