##// END OF EJS Templates
code layout clean up of test_should_not_close_duplicated_issue at test/unit/issue_test.rb...
Toshi MARUYAMA -
r7360:96e56f52ad70
parent child
Show More
@@ -1,1104 +1,1106
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 :trackers, :projects_trackers,
22 :trackers, :projects_trackers,
23 :enabled_modules,
23 :enabled_modules,
24 :versions,
24 :versions,
25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
26 :enumerations,
26 :enumerations,
27 :issues,
27 :issues,
28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
29 :time_entries
29 :time_entries
30
30
31 def test_create
31 def test_create
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
33 :status_id => 1, :priority => IssuePriority.all.first,
33 :status_id => 1, :priority => IssuePriority.all.first,
34 :subject => 'test_create',
34 :subject => 'test_create',
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
36 assert issue.save
36 assert issue.save
37 issue.reload
37 issue.reload
38 assert_equal 1.5, issue.estimated_hours
38 assert_equal 1.5, issue.estimated_hours
39 end
39 end
40
40
41 def test_create_minimal
41 def test_create_minimal
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
43 :status_id => 1, :priority => IssuePriority.all.first,
43 :status_id => 1, :priority => IssuePriority.all.first,
44 :subject => 'test_create')
44 :subject => 'test_create')
45 assert issue.save
45 assert issue.save
46 assert issue.description.nil?
46 assert issue.description.nil?
47 end
47 end
48
48
49 def test_create_with_required_custom_field
49 def test_create_with_required_custom_field
50 field = IssueCustomField.find_by_name('Database')
50 field = IssueCustomField.find_by_name('Database')
51 field.update_attribute(:is_required, true)
51 field.update_attribute(:is_required, true)
52
52
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
54 :status_id => 1, :subject => 'test_create',
54 :status_id => 1, :subject => 'test_create',
55 :description => 'IssueTest#test_create_with_required_custom_field')
55 :description => 'IssueTest#test_create_with_required_custom_field')
56 assert issue.available_custom_fields.include?(field)
56 assert issue.available_custom_fields.include?(field)
57 # No value for the custom field
57 # No value for the custom field
58 assert !issue.save
58 assert !issue.save
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
59 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
60 # Blank value
60 # Blank value
61 issue.custom_field_values = { field.id => '' }
61 issue.custom_field_values = { field.id => '' }
62 assert !issue.save
62 assert !issue.save
63 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
63 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
64 # Invalid value
64 # Invalid value
65 issue.custom_field_values = { field.id => 'SQLServer' }
65 issue.custom_field_values = { field.id => 'SQLServer' }
66 assert !issue.save
66 assert !issue.save
67 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
67 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
68 # Valid value
68 # Valid value
69 issue.custom_field_values = { field.id => 'PostgreSQL' }
69 issue.custom_field_values = { field.id => 'PostgreSQL' }
70 assert issue.save
70 assert issue.save
71 issue.reload
71 issue.reload
72 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
72 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
73 end
73 end
74
74
75 def test_create_with_group_assignment
75 def test_create_with_group_assignment
76 with_settings :issue_group_assignment => '1' do
76 with_settings :issue_group_assignment => '1' do
77 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
77 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
78 :subject => 'Group assignment',
78 :subject => 'Group assignment',
79 :assigned_to_id => 11).save
79 :assigned_to_id => 11).save
80 issue = Issue.first(:order => 'id DESC')
80 issue = Issue.first(:order => 'id DESC')
81 assert_kind_of Group, issue.assigned_to
81 assert_kind_of Group, issue.assigned_to
82 assert_equal Group.find(11), issue.assigned_to
82 assert_equal Group.find(11), issue.assigned_to
83 end
83 end
84 end
84 end
85
85
86 def assert_visibility_match(user, issues)
86 def assert_visibility_match(user, issues)
87 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
87 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
88 end
88 end
89
89
90 def test_visible_scope_for_anonymous
90 def test_visible_scope_for_anonymous
91 # Anonymous user should see issues of public projects only
91 # Anonymous user should see issues of public projects only
92 issues = Issue.visible(User.anonymous).all
92 issues = Issue.visible(User.anonymous).all
93 assert issues.any?
93 assert issues.any?
94 assert_nil issues.detect {|issue| !issue.project.is_public?}
94 assert_nil issues.detect {|issue| !issue.project.is_public?}
95 assert_nil issues.detect {|issue| issue.is_private?}
95 assert_nil issues.detect {|issue| issue.is_private?}
96 assert_visibility_match User.anonymous, issues
96 assert_visibility_match User.anonymous, issues
97 end
97 end
98
98
99 def test_visible_scope_for_anonymous_with_own_issues_visibility
99 def test_visible_scope_for_anonymous_with_own_issues_visibility
100 Role.anonymous.update_attribute :issues_visibility, 'own'
100 Role.anonymous.update_attribute :issues_visibility, 'own'
101 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => User.anonymous.id, :subject => 'Issue by anonymous')
101 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => User.anonymous.id, :subject => 'Issue by anonymous')
102
102
103 issues = Issue.visible(User.anonymous).all
103 issues = Issue.visible(User.anonymous).all
104 assert issues.any?
104 assert issues.any?
105 assert_nil issues.detect {|issue| issue.author != User.anonymous}
105 assert_nil issues.detect {|issue| issue.author != User.anonymous}
106 assert_visibility_match User.anonymous, issues
106 assert_visibility_match User.anonymous, issues
107 end
107 end
108
108
109 def test_visible_scope_for_anonymous_without_view_issues_permissions
109 def test_visible_scope_for_anonymous_without_view_issues_permissions
110 # Anonymous user should not see issues without permission
110 # Anonymous user should not see issues without permission
111 Role.anonymous.remove_permission!(:view_issues)
111 Role.anonymous.remove_permission!(:view_issues)
112 issues = Issue.visible(User.anonymous).all
112 issues = Issue.visible(User.anonymous).all
113 assert issues.empty?
113 assert issues.empty?
114 assert_visibility_match User.anonymous, issues
114 assert_visibility_match User.anonymous, issues
115 end
115 end
116
116
117 def test_visible_scope_for_non_member
117 def test_visible_scope_for_non_member
118 user = User.find(9)
118 user = User.find(9)
119 assert user.projects.empty?
119 assert user.projects.empty?
120 # Non member user should see issues of public projects only
120 # Non member user should see issues of public projects only
121 issues = Issue.visible(user).all
121 issues = Issue.visible(user).all
122 assert issues.any?
122 assert issues.any?
123 assert_nil issues.detect {|issue| !issue.project.is_public?}
123 assert_nil issues.detect {|issue| !issue.project.is_public?}
124 assert_nil issues.detect {|issue| issue.is_private?}
124 assert_nil issues.detect {|issue| issue.is_private?}
125 assert_visibility_match user, issues
125 assert_visibility_match user, issues
126 end
126 end
127
127
128 def test_visible_scope_for_non_member_with_own_issues_visibility
128 def test_visible_scope_for_non_member_with_own_issues_visibility
129 Role.non_member.update_attribute :issues_visibility, 'own'
129 Role.non_member.update_attribute :issues_visibility, 'own'
130 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
130 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
131 user = User.find(9)
131 user = User.find(9)
132
132
133 issues = Issue.visible(user).all
133 issues = Issue.visible(user).all
134 assert issues.any?
134 assert issues.any?
135 assert_nil issues.detect {|issue| issue.author != user}
135 assert_nil issues.detect {|issue| issue.author != user}
136 assert_visibility_match user, issues
136 assert_visibility_match user, issues
137 end
137 end
138
138
139 def test_visible_scope_for_non_member_without_view_issues_permissions
139 def test_visible_scope_for_non_member_without_view_issues_permissions
140 # Non member user should not see issues without permission
140 # Non member user should not see issues without permission
141 Role.non_member.remove_permission!(:view_issues)
141 Role.non_member.remove_permission!(:view_issues)
142 user = User.find(9)
142 user = User.find(9)
143 assert user.projects.empty?
143 assert user.projects.empty?
144 issues = Issue.visible(user).all
144 issues = Issue.visible(user).all
145 assert issues.empty?
145 assert issues.empty?
146 assert_visibility_match user, issues
146 assert_visibility_match user, issues
147 end
147 end
148
148
149 def test_visible_scope_for_member
149 def test_visible_scope_for_member
150 user = User.find(9)
150 user = User.find(9)
151 # User should see issues of projects for which he has view_issues permissions only
151 # User should see issues of projects for which he has view_issues permissions only
152 Role.non_member.remove_permission!(:view_issues)
152 Role.non_member.remove_permission!(:view_issues)
153 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
153 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
154 issues = Issue.visible(user).all
154 issues = Issue.visible(user).all
155 assert issues.any?
155 assert issues.any?
156 assert_nil issues.detect {|issue| issue.project_id != 3}
156 assert_nil issues.detect {|issue| issue.project_id != 3}
157 assert_nil issues.detect {|issue| issue.is_private?}
157 assert_nil issues.detect {|issue| issue.is_private?}
158 assert_visibility_match user, issues
158 assert_visibility_match user, issues
159 end
159 end
160
160
161 def test_visible_scope_for_admin
161 def test_visible_scope_for_admin
162 user = User.find(1)
162 user = User.find(1)
163 user.members.each(&:destroy)
163 user.members.each(&:destroy)
164 assert user.projects.empty?
164 assert user.projects.empty?
165 issues = Issue.visible(user).all
165 issues = Issue.visible(user).all
166 assert issues.any?
166 assert issues.any?
167 # Admin should see issues on private projects that he does not belong to
167 # Admin should see issues on private projects that he does not belong to
168 assert issues.detect {|issue| !issue.project.is_public?}
168 assert issues.detect {|issue| !issue.project.is_public?}
169 # Admin should see private issues of other users
169 # Admin should see private issues of other users
170 assert issues.detect {|issue| issue.is_private? && issue.author != user}
170 assert issues.detect {|issue| issue.is_private? && issue.author != user}
171 assert_visibility_match user, issues
171 assert_visibility_match user, issues
172 end
172 end
173
173
174 def test_visible_scope_with_project
174 def test_visible_scope_with_project
175 project = Project.find(1)
175 project = Project.find(1)
176 issues = Issue.visible(User.find(2), :project => project).all
176 issues = Issue.visible(User.find(2), :project => project).all
177 projects = issues.collect(&:project).uniq
177 projects = issues.collect(&:project).uniq
178 assert_equal 1, projects.size
178 assert_equal 1, projects.size
179 assert_equal project, projects.first
179 assert_equal project, projects.first
180 end
180 end
181
181
182 def test_visible_scope_with_project_and_subprojects
182 def test_visible_scope_with_project_and_subprojects
183 project = Project.find(1)
183 project = Project.find(1)
184 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
184 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
185 projects = issues.collect(&:project).uniq
185 projects = issues.collect(&:project).uniq
186 assert projects.size > 1
186 assert projects.size > 1
187 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
187 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
188 end
188 end
189
189
190 def test_visible_and_nested_set_scopes
190 def test_visible_and_nested_set_scopes
191 assert_equal 0, Issue.find(1).descendants.visible.all.size
191 assert_equal 0, Issue.find(1).descendants.visible.all.size
192 end
192 end
193
193
194 def test_errors_full_messages_should_include_custom_fields_errors
194 def test_errors_full_messages_should_include_custom_fields_errors
195 field = IssueCustomField.find_by_name('Database')
195 field = IssueCustomField.find_by_name('Database')
196
196
197 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
197 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
198 :status_id => 1, :subject => 'test_create',
198 :status_id => 1, :subject => 'test_create',
199 :description => 'IssueTest#test_create_with_required_custom_field')
199 :description => 'IssueTest#test_create_with_required_custom_field')
200 assert issue.available_custom_fields.include?(field)
200 assert issue.available_custom_fields.include?(field)
201 # Invalid value
201 # Invalid value
202 issue.custom_field_values = { field.id => 'SQLServer' }
202 issue.custom_field_values = { field.id => 'SQLServer' }
203
203
204 assert !issue.valid?
204 assert !issue.valid?
205 assert_equal 1, issue.errors.full_messages.size
205 assert_equal 1, issue.errors.full_messages.size
206 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first
206 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}", issue.errors.full_messages.first
207 end
207 end
208
208
209 def test_update_issue_with_required_custom_field
209 def test_update_issue_with_required_custom_field
210 field = IssueCustomField.find_by_name('Database')
210 field = IssueCustomField.find_by_name('Database')
211 field.update_attribute(:is_required, true)
211 field.update_attribute(:is_required, true)
212
212
213 issue = Issue.find(1)
213 issue = Issue.find(1)
214 assert_nil issue.custom_value_for(field)
214 assert_nil issue.custom_value_for(field)
215 assert issue.available_custom_fields.include?(field)
215 assert issue.available_custom_fields.include?(field)
216 # No change to custom values, issue can be saved
216 # No change to custom values, issue can be saved
217 assert issue.save
217 assert issue.save
218 # Blank value
218 # Blank value
219 issue.custom_field_values = { field.id => '' }
219 issue.custom_field_values = { field.id => '' }
220 assert !issue.save
220 assert !issue.save
221 # Valid value
221 # Valid value
222 issue.custom_field_values = { field.id => 'PostgreSQL' }
222 issue.custom_field_values = { field.id => 'PostgreSQL' }
223 assert issue.save
223 assert issue.save
224 issue.reload
224 issue.reload
225 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
225 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
226 end
226 end
227
227
228 def test_should_not_update_attributes_if_custom_fields_validation_fails
228 def test_should_not_update_attributes_if_custom_fields_validation_fails
229 issue = Issue.find(1)
229 issue = Issue.find(1)
230 field = IssueCustomField.find_by_name('Database')
230 field = IssueCustomField.find_by_name('Database')
231 assert issue.available_custom_fields.include?(field)
231 assert issue.available_custom_fields.include?(field)
232
232
233 issue.custom_field_values = { field.id => 'Invalid' }
233 issue.custom_field_values = { field.id => 'Invalid' }
234 issue.subject = 'Should be not be saved'
234 issue.subject = 'Should be not be saved'
235 assert !issue.save
235 assert !issue.save
236
236
237 issue.reload
237 issue.reload
238 assert_equal "Can't print recipes", issue.subject
238 assert_equal "Can't print recipes", issue.subject
239 end
239 end
240
240
241 def test_should_not_recreate_custom_values_objects_on_update
241 def test_should_not_recreate_custom_values_objects_on_update
242 field = IssueCustomField.find_by_name('Database')
242 field = IssueCustomField.find_by_name('Database')
243
243
244 issue = Issue.find(1)
244 issue = Issue.find(1)
245 issue.custom_field_values = { field.id => 'PostgreSQL' }
245 issue.custom_field_values = { field.id => 'PostgreSQL' }
246 assert issue.save
246 assert issue.save
247 custom_value = issue.custom_value_for(field)
247 custom_value = issue.custom_value_for(field)
248 issue.reload
248 issue.reload
249 issue.custom_field_values = { field.id => 'MySQL' }
249 issue.custom_field_values = { field.id => 'MySQL' }
250 assert issue.save
250 assert issue.save
251 issue.reload
251 issue.reload
252 assert_equal custom_value.id, issue.custom_value_for(field).id
252 assert_equal custom_value.id, issue.custom_value_for(field).id
253 end
253 end
254
254
255 def test_assigning_tracker_id_should_reload_custom_fields_values
255 def test_assigning_tracker_id_should_reload_custom_fields_values
256 issue = Issue.new(:project => Project.find(1))
256 issue = Issue.new(:project => Project.find(1))
257 assert issue.custom_field_values.empty?
257 assert issue.custom_field_values.empty?
258 issue.tracker_id = 1
258 issue.tracker_id = 1
259 assert issue.custom_field_values.any?
259 assert issue.custom_field_values.any?
260 end
260 end
261
261
262 def test_assigning_attributes_should_assign_tracker_id_first
262 def test_assigning_attributes_should_assign_tracker_id_first
263 attributes = ActiveSupport::OrderedHash.new
263 attributes = ActiveSupport::OrderedHash.new
264 attributes['custom_field_values'] = { '1' => 'MySQL' }
264 attributes['custom_field_values'] = { '1' => 'MySQL' }
265 attributes['tracker_id'] = '1'
265 attributes['tracker_id'] = '1'
266 issue = Issue.new(:project => Project.find(1))
266 issue = Issue.new(:project => Project.find(1))
267 issue.attributes = attributes
267 issue.attributes = attributes
268 assert_not_nil issue.custom_value_for(1)
268 assert_not_nil issue.custom_value_for(1)
269 assert_equal 'MySQL', issue.custom_value_for(1).value
269 assert_equal 'MySQL', issue.custom_value_for(1).value
270 end
270 end
271
271
272 def test_should_update_issue_with_disabled_tracker
272 def test_should_update_issue_with_disabled_tracker
273 p = Project.find(1)
273 p = Project.find(1)
274 issue = Issue.find(1)
274 issue = Issue.find(1)
275
275
276 p.trackers.delete(issue.tracker)
276 p.trackers.delete(issue.tracker)
277 assert !p.trackers.include?(issue.tracker)
277 assert !p.trackers.include?(issue.tracker)
278
278
279 issue.reload
279 issue.reload
280 issue.subject = 'New subject'
280 issue.subject = 'New subject'
281 assert issue.save
281 assert issue.save
282 end
282 end
283
283
284 def test_should_not_set_a_disabled_tracker
284 def test_should_not_set_a_disabled_tracker
285 p = Project.find(1)
285 p = Project.find(1)
286 p.trackers.delete(Tracker.find(2))
286 p.trackers.delete(Tracker.find(2))
287
287
288 issue = Issue.find(1)
288 issue = Issue.find(1)
289 issue.tracker_id = 2
289 issue.tracker_id = 2
290 issue.subject = 'New subject'
290 issue.subject = 'New subject'
291 assert !issue.save
291 assert !issue.save
292 assert_not_nil issue.errors.on(:tracker_id)
292 assert_not_nil issue.errors.on(:tracker_id)
293 end
293 end
294
294
295 def test_category_based_assignment
295 def test_category_based_assignment
296 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
296 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
297 :status_id => 1, :priority => IssuePriority.all.first,
297 :status_id => 1, :priority => IssuePriority.all.first,
298 :subject => 'Assignment test',
298 :subject => 'Assignment test',
299 :description => 'Assignment test', :category_id => 1)
299 :description => 'Assignment test', :category_id => 1)
300 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
300 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
301 end
301 end
302
302
303 def test_new_statuses_allowed_to
303 def test_new_statuses_allowed_to
304 Workflow.delete_all
304 Workflow.delete_all
305
305
306 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
306 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
307 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
307 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
308 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
308 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
309 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
309 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
310 status = IssueStatus.find(1)
310 status = IssueStatus.find(1)
311 role = Role.find(1)
311 role = Role.find(1)
312 tracker = Tracker.find(1)
312 tracker = Tracker.find(1)
313 user = User.find(2)
313 user = User.find(2)
314
314
315 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
315 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
316 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
316 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
317
317
318 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
318 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
319 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
319 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
320
320
321 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
321 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
322 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
322 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
323
323
324 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
324 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
325 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
325 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
326 end
326 end
327
327
328 def test_copy
328 def test_copy
329 issue = Issue.new.copy_from(1)
329 issue = Issue.new.copy_from(1)
330 assert issue.save
330 assert issue.save
331 issue.reload
331 issue.reload
332 orig = Issue.find(1)
332 orig = Issue.find(1)
333 assert_equal orig.subject, issue.subject
333 assert_equal orig.subject, issue.subject
334 assert_equal orig.tracker, issue.tracker
334 assert_equal orig.tracker, issue.tracker
335 assert_equal "125", issue.custom_value_for(2).value
335 assert_equal "125", issue.custom_value_for(2).value
336 end
336 end
337
337
338 def test_copy_should_copy_status
338 def test_copy_should_copy_status
339 orig = Issue.find(8)
339 orig = Issue.find(8)
340 assert orig.status != IssueStatus.default
340 assert orig.status != IssueStatus.default
341
341
342 issue = Issue.new.copy_from(orig)
342 issue = Issue.new.copy_from(orig)
343 assert issue.save
343 assert issue.save
344 issue.reload
344 issue.reload
345 assert_equal orig.status, issue.status
345 assert_equal orig.status, issue.status
346 end
346 end
347
347
348 def test_should_close_duplicates
348 def test_should_close_duplicates
349 # Create 3 issues
349 # Create 3 issues
350 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
350 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
351 assert issue1.save
351 assert issue1.save
352 issue2 = issue1.clone
352 issue2 = issue1.clone
353 assert issue2.save
353 assert issue2.save
354 issue3 = issue1.clone
354 issue3 = issue1.clone
355 assert issue3.save
355 assert issue3.save
356
356
357 # 2 is a dupe of 1
357 # 2 is a dupe of 1
358 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
358 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
359 # And 3 is a dupe of 2
359 # And 3 is a dupe of 2
360 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
360 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
361 # And 3 is a dupe of 1 (circular duplicates)
361 # And 3 is a dupe of 1 (circular duplicates)
362 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
362 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
363
363
364 assert issue1.reload.duplicates.include?(issue2)
364 assert issue1.reload.duplicates.include?(issue2)
365
365
366 # Closing issue 1
366 # Closing issue 1
367 issue1.init_journal(User.find(:first), "Closing issue1")
367 issue1.init_journal(User.find(:first), "Closing issue1")
368 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
368 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
369 assert issue1.save
369 assert issue1.save
370 # 2 and 3 should be also closed
370 # 2 and 3 should be also closed
371 assert issue2.reload.closed?
371 assert issue2.reload.closed?
372 assert issue3.reload.closed?
372 assert issue3.reload.closed?
373 end
373 end
374
374
375 def test_should_not_close_duplicated_issue
375 def test_should_not_close_duplicated_issue
376 # Create 3 issues
376 # Create 3 issues
377 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :priority => IssuePriority.all.first, :subject => 'Duplicates test', :description => 'Duplicates test')
377 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
378 :status_id => 1, :priority => IssuePriority.all.first,
379 :subject => 'Duplicates test', :description => 'Duplicates test')
378 assert issue1.save
380 assert issue1.save
379 issue2 = issue1.clone
381 issue2 = issue1.clone
380 assert issue2.save
382 assert issue2.save
381
383
382 # 2 is a dupe of 1
384 # 2 is a dupe of 1
383 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
385 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
384 # 2 is a dup of 1 but 1 is not a duplicate of 2
386 # 2 is a dup of 1 but 1 is not a duplicate of 2
385 assert !issue2.reload.duplicates.include?(issue1)
387 assert !issue2.reload.duplicates.include?(issue1)
386
388
387 # Closing issue 2
389 # Closing issue 2
388 issue2.init_journal(User.find(:first), "Closing issue2")
390 issue2.init_journal(User.find(:first), "Closing issue2")
389 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
391 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
390 assert issue2.save
392 assert issue2.save
391 # 1 should not be also closed
393 # 1 should not be also closed
392 assert !issue1.reload.closed?
394 assert !issue1.reload.closed?
393 end
395 end
394
396
395 def test_assignable_versions
397 def test_assignable_versions
396 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
398 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
397 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
399 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
398 end
400 end
399
401
400 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
402 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
401 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
403 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
402 assert !issue.save
404 assert !issue.save
403 assert_not_nil issue.errors.on(:fixed_version_id)
405 assert_not_nil issue.errors.on(:fixed_version_id)
404 end
406 end
405
407
406 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
408 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
407 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
409 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
408 assert !issue.save
410 assert !issue.save
409 assert_not_nil issue.errors.on(:fixed_version_id)
411 assert_not_nil issue.errors.on(:fixed_version_id)
410 end
412 end
411
413
412 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
414 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
413 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
415 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
414 assert issue.save
416 assert issue.save
415 end
417 end
416
418
417 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
419 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
418 issue = Issue.find(11)
420 issue = Issue.find(11)
419 assert_equal 'closed', issue.fixed_version.status
421 assert_equal 'closed', issue.fixed_version.status
420 issue.subject = 'Subject changed'
422 issue.subject = 'Subject changed'
421 assert issue.save
423 assert issue.save
422 end
424 end
423
425
424 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
426 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
425 issue = Issue.find(11)
427 issue = Issue.find(11)
426 issue.status_id = 1
428 issue.status_id = 1
427 assert !issue.save
429 assert !issue.save
428 assert_not_nil issue.errors.on_base
430 assert_not_nil issue.errors.on_base
429 end
431 end
430
432
431 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
433 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
432 issue = Issue.find(11)
434 issue = Issue.find(11)
433 issue.status_id = 1
435 issue.status_id = 1
434 issue.fixed_version_id = 3
436 issue.fixed_version_id = 3
435 assert issue.save
437 assert issue.save
436 end
438 end
437
439
438 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
440 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
439 issue = Issue.find(12)
441 issue = Issue.find(12)
440 assert_equal 'locked', issue.fixed_version.status
442 assert_equal 'locked', issue.fixed_version.status
441 issue.status_id = 1
443 issue.status_id = 1
442 assert issue.save
444 assert issue.save
443 end
445 end
444
446
445 def test_move_to_another_project_with_same_category
447 def test_move_to_another_project_with_same_category
446 issue = Issue.find(1)
448 issue = Issue.find(1)
447 assert issue.move_to_project(Project.find(2))
449 assert issue.move_to_project(Project.find(2))
448 issue.reload
450 issue.reload
449 assert_equal 2, issue.project_id
451 assert_equal 2, issue.project_id
450 # Category changes
452 # Category changes
451 assert_equal 4, issue.category_id
453 assert_equal 4, issue.category_id
452 # Make sure time entries were move to the target project
454 # Make sure time entries were move to the target project
453 assert_equal 2, issue.time_entries.first.project_id
455 assert_equal 2, issue.time_entries.first.project_id
454 end
456 end
455
457
456 def test_move_to_another_project_without_same_category
458 def test_move_to_another_project_without_same_category
457 issue = Issue.find(2)
459 issue = Issue.find(2)
458 assert issue.move_to_project(Project.find(2))
460 assert issue.move_to_project(Project.find(2))
459 issue.reload
461 issue.reload
460 assert_equal 2, issue.project_id
462 assert_equal 2, issue.project_id
461 # Category cleared
463 # Category cleared
462 assert_nil issue.category_id
464 assert_nil issue.category_id
463 end
465 end
464
466
465 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
467 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
466 issue = Issue.find(1)
468 issue = Issue.find(1)
467 issue.update_attribute(:fixed_version_id, 1)
469 issue.update_attribute(:fixed_version_id, 1)
468 assert issue.move_to_project(Project.find(2))
470 assert issue.move_to_project(Project.find(2))
469 issue.reload
471 issue.reload
470 assert_equal 2, issue.project_id
472 assert_equal 2, issue.project_id
471 # Cleared fixed_version
473 # Cleared fixed_version
472 assert_equal nil, issue.fixed_version
474 assert_equal nil, issue.fixed_version
473 end
475 end
474
476
475 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
477 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
476 issue = Issue.find(1)
478 issue = Issue.find(1)
477 issue.update_attribute(:fixed_version_id, 4)
479 issue.update_attribute(:fixed_version_id, 4)
478 assert issue.move_to_project(Project.find(5))
480 assert issue.move_to_project(Project.find(5))
479 issue.reload
481 issue.reload
480 assert_equal 5, issue.project_id
482 assert_equal 5, issue.project_id
481 # Keep fixed_version
483 # Keep fixed_version
482 assert_equal 4, issue.fixed_version_id
484 assert_equal 4, issue.fixed_version_id
483 end
485 end
484
486
485 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
487 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
486 issue = Issue.find(1)
488 issue = Issue.find(1)
487 issue.update_attribute(:fixed_version_id, 1)
489 issue.update_attribute(:fixed_version_id, 1)
488 assert issue.move_to_project(Project.find(5))
490 assert issue.move_to_project(Project.find(5))
489 issue.reload
491 issue.reload
490 assert_equal 5, issue.project_id
492 assert_equal 5, issue.project_id
491 # Cleared fixed_version
493 # Cleared fixed_version
492 assert_equal nil, issue.fixed_version
494 assert_equal nil, issue.fixed_version
493 end
495 end
494
496
495 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
497 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
496 issue = Issue.find(1)
498 issue = Issue.find(1)
497 issue.update_attribute(:fixed_version_id, 7)
499 issue.update_attribute(:fixed_version_id, 7)
498 assert issue.move_to_project(Project.find(2))
500 assert issue.move_to_project(Project.find(2))
499 issue.reload
501 issue.reload
500 assert_equal 2, issue.project_id
502 assert_equal 2, issue.project_id
501 # Keep fixed_version
503 # Keep fixed_version
502 assert_equal 7, issue.fixed_version_id
504 assert_equal 7, issue.fixed_version_id
503 end
505 end
504
506
505 def test_move_to_another_project_with_disabled_tracker
507 def test_move_to_another_project_with_disabled_tracker
506 issue = Issue.find(1)
508 issue = Issue.find(1)
507 target = Project.find(2)
509 target = Project.find(2)
508 target.tracker_ids = [3]
510 target.tracker_ids = [3]
509 target.save
511 target.save
510 assert_equal false, issue.move_to_project(target)
512 assert_equal false, issue.move_to_project(target)
511 issue.reload
513 issue.reload
512 assert_equal 1, issue.project_id
514 assert_equal 1, issue.project_id
513 end
515 end
514
516
515 def test_copy_to_the_same_project
517 def test_copy_to_the_same_project
516 issue = Issue.find(1)
518 issue = Issue.find(1)
517 copy = nil
519 copy = nil
518 assert_difference 'Issue.count' do
520 assert_difference 'Issue.count' do
519 copy = issue.move_to_project(issue.project, nil, :copy => true)
521 copy = issue.move_to_project(issue.project, nil, :copy => true)
520 end
522 end
521 assert_kind_of Issue, copy
523 assert_kind_of Issue, copy
522 assert_equal issue.project, copy.project
524 assert_equal issue.project, copy.project
523 assert_equal "125", copy.custom_value_for(2).value
525 assert_equal "125", copy.custom_value_for(2).value
524 end
526 end
525
527
526 def test_copy_to_another_project_and_tracker
528 def test_copy_to_another_project_and_tracker
527 issue = Issue.find(1)
529 issue = Issue.find(1)
528 copy = nil
530 copy = nil
529 assert_difference 'Issue.count' do
531 assert_difference 'Issue.count' do
530 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
532 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
531 end
533 end
532 copy.reload
534 copy.reload
533 assert_kind_of Issue, copy
535 assert_kind_of Issue, copy
534 assert_equal Project.find(3), copy.project
536 assert_equal Project.find(3), copy.project
535 assert_equal Tracker.find(2), copy.tracker
537 assert_equal Tracker.find(2), copy.tracker
536 # Custom field #2 is not associated with target tracker
538 # Custom field #2 is not associated with target tracker
537 assert_nil copy.custom_value_for(2)
539 assert_nil copy.custom_value_for(2)
538 end
540 end
539
541
540 context "#move_to_project" do
542 context "#move_to_project" do
541 context "as a copy" do
543 context "as a copy" do
542 setup do
544 setup do
543 @issue = Issue.find(1)
545 @issue = Issue.find(1)
544 @copy = nil
546 @copy = nil
545 end
547 end
546
548
547 should "not create a journal" do
549 should "not create a journal" do
548 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
550 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
549 assert_equal 0, @copy.reload.journals.size
551 assert_equal 0, @copy.reload.journals.size
550 end
552 end
551
553
552 should "allow assigned_to changes" do
554 should "allow assigned_to changes" do
553 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
555 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
554 assert_equal 3, @copy.assigned_to_id
556 assert_equal 3, @copy.assigned_to_id
555 end
557 end
556
558
557 should "allow status changes" do
559 should "allow status changes" do
558 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
560 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
559 assert_equal 2, @copy.status_id
561 assert_equal 2, @copy.status_id
560 end
562 end
561
563
562 should "allow start date changes" do
564 should "allow start date changes" do
563 date = Date.today
565 date = Date.today
564 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
566 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
565 assert_equal date, @copy.start_date
567 assert_equal date, @copy.start_date
566 end
568 end
567
569
568 should "allow due date changes" do
570 should "allow due date changes" do
569 date = Date.today
571 date = Date.today
570 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
572 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
571
573
572 assert_equal date, @copy.due_date
574 assert_equal date, @copy.due_date
573 end
575 end
574
576
575 should "set current user as author" do
577 should "set current user as author" do
576 User.current = User.find(9)
578 User.current = User.find(9)
577 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
579 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
578
580
579 assert_equal User.current, @copy.author
581 assert_equal User.current, @copy.author
580 end
582 end
581
583
582 should "keep journal notes" do
584 should "keep journal notes" do
583 date = Date.today
585 date = Date.today
584 notes = "Notes added when copying"
586 notes = "Notes added when copying"
585 User.current = User.find(9)
587 User.current = User.find(9)
586 @issue.init_journal(User.current, notes)
588 @issue.init_journal(User.current, notes)
587 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
589 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
588
590
589 assert_equal 1, @copy.journals.size
591 assert_equal 1, @copy.journals.size
590 journal = @copy.journals.first
592 journal = @copy.journals.first
591 assert_equal 0, journal.details.size
593 assert_equal 0, journal.details.size
592 assert_equal notes, journal.notes
594 assert_equal notes, journal.notes
593 end
595 end
594 end
596 end
595 end
597 end
596
598
597 def test_recipients_should_not_include_users_that_cannot_view_the_issue
599 def test_recipients_should_not_include_users_that_cannot_view_the_issue
598 issue = Issue.find(12)
600 issue = Issue.find(12)
599 assert issue.recipients.include?(issue.author.mail)
601 assert issue.recipients.include?(issue.author.mail)
600 # move the issue to a private project
602 # move the issue to a private project
601 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
603 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
602 # author is not a member of project anymore
604 # author is not a member of project anymore
603 assert !copy.recipients.include?(copy.author.mail)
605 assert !copy.recipients.include?(copy.author.mail)
604 end
606 end
605
607
606 def test_recipients_should_include_the_assigned_group_members
608 def test_recipients_should_include_the_assigned_group_members
607 group_member = User.generate_with_protected!
609 group_member = User.generate_with_protected!
608 group = Group.generate!
610 group = Group.generate!
609 group.users << group_member
611 group.users << group_member
610
612
611 issue = Issue.find(12)
613 issue = Issue.find(12)
612 issue.assigned_to = group
614 issue.assigned_to = group
613 assert issue.recipients.include?(group_member.mail)
615 assert issue.recipients.include?(group_member.mail)
614 end
616 end
615
617
616 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
618 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
617 user = User.find(3)
619 user = User.find(3)
618 issue = Issue.find(9)
620 issue = Issue.find(9)
619 Watcher.create!(:user => user, :watchable => issue)
621 Watcher.create!(:user => user, :watchable => issue)
620 assert issue.watched_by?(user)
622 assert issue.watched_by?(user)
621 assert !issue.watcher_recipients.include?(user.mail)
623 assert !issue.watcher_recipients.include?(user.mail)
622 end
624 end
623
625
624 def test_issue_destroy
626 def test_issue_destroy
625 Issue.find(1).destroy
627 Issue.find(1).destroy
626 assert_nil Issue.find_by_id(1)
628 assert_nil Issue.find_by_id(1)
627 assert_nil TimeEntry.find_by_issue_id(1)
629 assert_nil TimeEntry.find_by_issue_id(1)
628 end
630 end
629
631
630 def test_blocked
632 def test_blocked
631 blocked_issue = Issue.find(9)
633 blocked_issue = Issue.find(9)
632 blocking_issue = Issue.find(10)
634 blocking_issue = Issue.find(10)
633
635
634 assert blocked_issue.blocked?
636 assert blocked_issue.blocked?
635 assert !blocking_issue.blocked?
637 assert !blocking_issue.blocked?
636 end
638 end
637
639
638 def test_blocked_issues_dont_allow_closed_statuses
640 def test_blocked_issues_dont_allow_closed_statuses
639 blocked_issue = Issue.find(9)
641 blocked_issue = Issue.find(9)
640
642
641 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
643 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
642 assert !allowed_statuses.empty?
644 assert !allowed_statuses.empty?
643 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
645 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
644 assert closed_statuses.empty?
646 assert closed_statuses.empty?
645 end
647 end
646
648
647 def test_unblocked_issues_allow_closed_statuses
649 def test_unblocked_issues_allow_closed_statuses
648 blocking_issue = Issue.find(10)
650 blocking_issue = Issue.find(10)
649
651
650 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
652 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
651 assert !allowed_statuses.empty?
653 assert !allowed_statuses.empty?
652 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
654 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
653 assert !closed_statuses.empty?
655 assert !closed_statuses.empty?
654 end
656 end
655
657
656 def test_rescheduling_an_issue_should_reschedule_following_issue
658 def test_rescheduling_an_issue_should_reschedule_following_issue
657 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
659 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
658 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
660 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
659 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
661 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
660 assert_equal issue1.due_date + 1, issue2.reload.start_date
662 assert_equal issue1.due_date + 1, issue2.reload.start_date
661
663
662 issue1.due_date = Date.today + 5
664 issue1.due_date = Date.today + 5
663 issue1.save!
665 issue1.save!
664 assert_equal issue1.due_date + 1, issue2.reload.start_date
666 assert_equal issue1.due_date + 1, issue2.reload.start_date
665 end
667 end
666
668
667 def test_overdue
669 def test_overdue
668 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
670 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
669 assert !Issue.new(:due_date => Date.today).overdue?
671 assert !Issue.new(:due_date => Date.today).overdue?
670 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
672 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
671 assert !Issue.new(:due_date => nil).overdue?
673 assert !Issue.new(:due_date => nil).overdue?
672 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
674 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
673 end
675 end
674
676
675 context "#behind_schedule?" do
677 context "#behind_schedule?" do
676 should "be false if the issue has no start_date" do
678 should "be false if the issue has no start_date" do
677 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
679 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
678 end
680 end
679
681
680 should "be false if the issue has no end_date" do
682 should "be false if the issue has no end_date" do
681 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
683 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
682 end
684 end
683
685
684 should "be false if the issue has more done than it's calendar time" do
686 should "be false if the issue has more done than it's calendar time" do
685 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
687 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
686 end
688 end
687
689
688 should "be true if the issue hasn't been started at all" do
690 should "be true if the issue hasn't been started at all" do
689 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
691 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
690 end
692 end
691
693
692 should "be true if the issue has used more calendar time than it's done ratio" do
694 should "be true if the issue has used more calendar time than it's done ratio" do
693 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
695 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
694 end
696 end
695 end
697 end
696
698
697 context "#assignable_users" do
699 context "#assignable_users" do
698 should "be Users" do
700 should "be Users" do
699 assert_kind_of User, Issue.find(1).assignable_users.first
701 assert_kind_of User, Issue.find(1).assignable_users.first
700 end
702 end
701
703
702 should "include the issue author" do
704 should "include the issue author" do
703 project = Project.find(1)
705 project = Project.find(1)
704 non_project_member = User.generate!
706 non_project_member = User.generate!
705 issue = Issue.generate_for_project!(project, :author => non_project_member)
707 issue = Issue.generate_for_project!(project, :author => non_project_member)
706
708
707 assert issue.assignable_users.include?(non_project_member)
709 assert issue.assignable_users.include?(non_project_member)
708 end
710 end
709
711
710 should "include the current assignee" do
712 should "include the current assignee" do
711 project = Project.find(1)
713 project = Project.find(1)
712 user = User.generate!
714 user = User.generate!
713 issue = Issue.generate_for_project!(project, :assigned_to => user)
715 issue = Issue.generate_for_project!(project, :assigned_to => user)
714 user.lock!
716 user.lock!
715
717
716 assert Issue.find(issue.id).assignable_users.include?(user)
718 assert Issue.find(issue.id).assignable_users.include?(user)
717 end
719 end
718
720
719 should "not show the issue author twice" do
721 should "not show the issue author twice" do
720 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
722 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
721 assert_equal 2, assignable_user_ids.length
723 assert_equal 2, assignable_user_ids.length
722
724
723 assignable_user_ids.each do |user_id|
725 assignable_user_ids.each do |user_id|
724 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
726 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
725 end
727 end
726 end
728 end
727
729
728 context "with issue_group_assignment" do
730 context "with issue_group_assignment" do
729 should "include groups" do
731 should "include groups" do
730 issue = Issue.new(:project => Project.find(2))
732 issue = Issue.new(:project => Project.find(2))
731
733
732 with_settings :issue_group_assignment => '1' do
734 with_settings :issue_group_assignment => '1' do
733 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
735 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
734 assert issue.assignable_users.include?(Group.find(11))
736 assert issue.assignable_users.include?(Group.find(11))
735 end
737 end
736 end
738 end
737 end
739 end
738
740
739 context "without issue_group_assignment" do
741 context "without issue_group_assignment" do
740 should "not include groups" do
742 should "not include groups" do
741 issue = Issue.new(:project => Project.find(2))
743 issue = Issue.new(:project => Project.find(2))
742
744
743 with_settings :issue_group_assignment => '0' do
745 with_settings :issue_group_assignment => '0' do
744 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
746 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
745 assert !issue.assignable_users.include?(Group.find(11))
747 assert !issue.assignable_users.include?(Group.find(11))
746 end
748 end
747 end
749 end
748 end
750 end
749 end
751 end
750
752
751 def test_create_should_send_email_notification
753 def test_create_should_send_email_notification
752 ActionMailer::Base.deliveries.clear
754 ActionMailer::Base.deliveries.clear
753 issue = Issue.new(:project_id => 1, :tracker_id => 1,
755 issue = Issue.new(:project_id => 1, :tracker_id => 1,
754 :author_id => 3, :status_id => 1,
756 :author_id => 3, :status_id => 1,
755 :priority => IssuePriority.all.first,
757 :priority => IssuePriority.all.first,
756 :subject => 'test_create', :estimated_hours => '1:30')
758 :subject => 'test_create', :estimated_hours => '1:30')
757
759
758 assert issue.save
760 assert issue.save
759 assert_equal 1, ActionMailer::Base.deliveries.size
761 assert_equal 1, ActionMailer::Base.deliveries.size
760 end
762 end
761
763
762 def test_stale_issue_should_not_send_email_notification
764 def test_stale_issue_should_not_send_email_notification
763 ActionMailer::Base.deliveries.clear
765 ActionMailer::Base.deliveries.clear
764 issue = Issue.find(1)
766 issue = Issue.find(1)
765 stale = Issue.find(1)
767 stale = Issue.find(1)
766
768
767 issue.init_journal(User.find(1))
769 issue.init_journal(User.find(1))
768 issue.subject = 'Subjet update'
770 issue.subject = 'Subjet update'
769 assert issue.save
771 assert issue.save
770 assert_equal 1, ActionMailer::Base.deliveries.size
772 assert_equal 1, ActionMailer::Base.deliveries.size
771 ActionMailer::Base.deliveries.clear
773 ActionMailer::Base.deliveries.clear
772
774
773 stale.init_journal(User.find(1))
775 stale.init_journal(User.find(1))
774 stale.subject = 'Another subjet update'
776 stale.subject = 'Another subjet update'
775 assert_raise ActiveRecord::StaleObjectError do
777 assert_raise ActiveRecord::StaleObjectError do
776 stale.save
778 stale.save
777 end
779 end
778 assert ActionMailer::Base.deliveries.empty?
780 assert ActionMailer::Base.deliveries.empty?
779 end
781 end
780
782
781 def test_journalized_description
783 def test_journalized_description
782 IssueCustomField.delete_all
784 IssueCustomField.delete_all
783
785
784 i = Issue.first
786 i = Issue.first
785 old_description = i.description
787 old_description = i.description
786 new_description = "This is the new description"
788 new_description = "This is the new description"
787
789
788 i.init_journal(User.find(2))
790 i.init_journal(User.find(2))
789 i.description = new_description
791 i.description = new_description
790 assert_difference 'Journal.count', 1 do
792 assert_difference 'Journal.count', 1 do
791 assert_difference 'JournalDetail.count', 1 do
793 assert_difference 'JournalDetail.count', 1 do
792 i.save!
794 i.save!
793 end
795 end
794 end
796 end
795
797
796 detail = JournalDetail.first(:order => 'id DESC')
798 detail = JournalDetail.first(:order => 'id DESC')
797 assert_equal i, detail.journal.journalized
799 assert_equal i, detail.journal.journalized
798 assert_equal 'attr', detail.property
800 assert_equal 'attr', detail.property
799 assert_equal 'description', detail.prop_key
801 assert_equal 'description', detail.prop_key
800 assert_equal old_description, detail.old_value
802 assert_equal old_description, detail.old_value
801 assert_equal new_description, detail.value
803 assert_equal new_description, detail.value
802 end
804 end
803
805
804 def test_blank_descriptions_should_not_be_journalized
806 def test_blank_descriptions_should_not_be_journalized
805 IssueCustomField.delete_all
807 IssueCustomField.delete_all
806 Issue.update_all("description = NULL", "id=1")
808 Issue.update_all("description = NULL", "id=1")
807
809
808 i = Issue.find(1)
810 i = Issue.find(1)
809 i.init_journal(User.find(2))
811 i.init_journal(User.find(2))
810 i.subject = "blank description"
812 i.subject = "blank description"
811 i.description = "\r\n"
813 i.description = "\r\n"
812
814
813 assert_difference 'Journal.count', 1 do
815 assert_difference 'Journal.count', 1 do
814 assert_difference 'JournalDetail.count', 1 do
816 assert_difference 'JournalDetail.count', 1 do
815 i.save!
817 i.save!
816 end
818 end
817 end
819 end
818 end
820 end
819
821
820 def test_description_eol_should_be_normalized
822 def test_description_eol_should_be_normalized
821 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
823 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
822 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
824 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
823 end
825 end
824
826
825 def test_saving_twice_should_not_duplicate_journal_details
827 def test_saving_twice_should_not_duplicate_journal_details
826 i = Issue.find(:first)
828 i = Issue.find(:first)
827 i.init_journal(User.find(2), 'Some notes')
829 i.init_journal(User.find(2), 'Some notes')
828 # initial changes
830 # initial changes
829 i.subject = 'New subject'
831 i.subject = 'New subject'
830 i.done_ratio = i.done_ratio + 10
832 i.done_ratio = i.done_ratio + 10
831 assert_difference 'Journal.count' do
833 assert_difference 'Journal.count' do
832 assert i.save
834 assert i.save
833 end
835 end
834 # 1 more change
836 # 1 more change
835 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
837 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
836 assert_no_difference 'Journal.count' do
838 assert_no_difference 'Journal.count' do
837 assert_difference 'JournalDetail.count', 1 do
839 assert_difference 'JournalDetail.count', 1 do
838 i.save
840 i.save
839 end
841 end
840 end
842 end
841 # no more change
843 # no more change
842 assert_no_difference 'Journal.count' do
844 assert_no_difference 'Journal.count' do
843 assert_no_difference 'JournalDetail.count' do
845 assert_no_difference 'JournalDetail.count' do
844 i.save
846 i.save
845 end
847 end
846 end
848 end
847 end
849 end
848
850
849 def test_all_dependent_issues
851 def test_all_dependent_issues
850 IssueRelation.delete_all
852 IssueRelation.delete_all
851 assert IssueRelation.create!(:issue_from => Issue.find(1),
853 assert IssueRelation.create!(:issue_from => Issue.find(1),
852 :issue_to => Issue.find(2),
854 :issue_to => Issue.find(2),
853 :relation_type => IssueRelation::TYPE_PRECEDES)
855 :relation_type => IssueRelation::TYPE_PRECEDES)
854 assert IssueRelation.create!(:issue_from => Issue.find(2),
856 assert IssueRelation.create!(:issue_from => Issue.find(2),
855 :issue_to => Issue.find(3),
857 :issue_to => Issue.find(3),
856 :relation_type => IssueRelation::TYPE_PRECEDES)
858 :relation_type => IssueRelation::TYPE_PRECEDES)
857 assert IssueRelation.create!(:issue_from => Issue.find(3),
859 assert IssueRelation.create!(:issue_from => Issue.find(3),
858 :issue_to => Issue.find(8),
860 :issue_to => Issue.find(8),
859 :relation_type => IssueRelation::TYPE_PRECEDES)
861 :relation_type => IssueRelation::TYPE_PRECEDES)
860
862
861 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
863 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
862 end
864 end
863
865
864 def test_all_dependent_issues_with_persistent_circular_dependency
866 def test_all_dependent_issues_with_persistent_circular_dependency
865 IssueRelation.delete_all
867 IssueRelation.delete_all
866 assert IssueRelation.create!(:issue_from => Issue.find(1),
868 assert IssueRelation.create!(:issue_from => Issue.find(1),
867 :issue_to => Issue.find(2),
869 :issue_to => Issue.find(2),
868 :relation_type => IssueRelation::TYPE_PRECEDES)
870 :relation_type => IssueRelation::TYPE_PRECEDES)
869 assert IssueRelation.create!(:issue_from => Issue.find(2),
871 assert IssueRelation.create!(:issue_from => Issue.find(2),
870 :issue_to => Issue.find(3),
872 :issue_to => Issue.find(3),
871 :relation_type => IssueRelation::TYPE_PRECEDES)
873 :relation_type => IssueRelation::TYPE_PRECEDES)
872 # Validation skipping
874 # Validation skipping
873 assert IssueRelation.new(:issue_from => Issue.find(3),
875 assert IssueRelation.new(:issue_from => Issue.find(3),
874 :issue_to => Issue.find(1),
876 :issue_to => Issue.find(1),
875 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
877 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
876
878
877 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
879 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
878 end
880 end
879
881
880 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
882 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
881 IssueRelation.delete_all
883 IssueRelation.delete_all
882 assert IssueRelation.create!(:issue_from => Issue.find(1),
884 assert IssueRelation.create!(:issue_from => Issue.find(1),
883 :issue_to => Issue.find(2),
885 :issue_to => Issue.find(2),
884 :relation_type => IssueRelation::TYPE_RELATES)
886 :relation_type => IssueRelation::TYPE_RELATES)
885 assert IssueRelation.create!(:issue_from => Issue.find(2),
887 assert IssueRelation.create!(:issue_from => Issue.find(2),
886 :issue_to => Issue.find(3),
888 :issue_to => Issue.find(3),
887 :relation_type => IssueRelation::TYPE_RELATES)
889 :relation_type => IssueRelation::TYPE_RELATES)
888 assert IssueRelation.create!(:issue_from => Issue.find(3),
890 assert IssueRelation.create!(:issue_from => Issue.find(3),
889 :issue_to => Issue.find(8),
891 :issue_to => Issue.find(8),
890 :relation_type => IssueRelation::TYPE_RELATES)
892 :relation_type => IssueRelation::TYPE_RELATES)
891 # Validation skipping
893 # Validation skipping
892 assert IssueRelation.new(:issue_from => Issue.find(8),
894 assert IssueRelation.new(:issue_from => Issue.find(8),
893 :issue_to => Issue.find(2),
895 :issue_to => Issue.find(2),
894 :relation_type => IssueRelation::TYPE_RELATES).save(false)
896 :relation_type => IssueRelation::TYPE_RELATES).save(false)
895 assert IssueRelation.new(:issue_from => Issue.find(3),
897 assert IssueRelation.new(:issue_from => Issue.find(3),
896 :issue_to => Issue.find(1),
898 :issue_to => Issue.find(1),
897 :relation_type => IssueRelation::TYPE_RELATES).save(false)
899 :relation_type => IssueRelation::TYPE_RELATES).save(false)
898
900
899 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
901 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
900 end
902 end
901
903
902 context "#done_ratio" do
904 context "#done_ratio" do
903 setup do
905 setup do
904 @issue = Issue.find(1)
906 @issue = Issue.find(1)
905 @issue_status = IssueStatus.find(1)
907 @issue_status = IssueStatus.find(1)
906 @issue_status.update_attribute(:default_done_ratio, 50)
908 @issue_status.update_attribute(:default_done_ratio, 50)
907 @issue2 = Issue.find(2)
909 @issue2 = Issue.find(2)
908 @issue_status2 = IssueStatus.find(2)
910 @issue_status2 = IssueStatus.find(2)
909 @issue_status2.update_attribute(:default_done_ratio, 0)
911 @issue_status2.update_attribute(:default_done_ratio, 0)
910 end
912 end
911
913
912 context "with Setting.issue_done_ratio using the issue_field" do
914 context "with Setting.issue_done_ratio using the issue_field" do
913 setup do
915 setup do
914 Setting.issue_done_ratio = 'issue_field'
916 Setting.issue_done_ratio = 'issue_field'
915 end
917 end
916
918
917 should "read the issue's field" do
919 should "read the issue's field" do
918 assert_equal 0, @issue.done_ratio
920 assert_equal 0, @issue.done_ratio
919 assert_equal 30, @issue2.done_ratio
921 assert_equal 30, @issue2.done_ratio
920 end
922 end
921 end
923 end
922
924
923 context "with Setting.issue_done_ratio using the issue_status" do
925 context "with Setting.issue_done_ratio using the issue_status" do
924 setup do
926 setup do
925 Setting.issue_done_ratio = 'issue_status'
927 Setting.issue_done_ratio = 'issue_status'
926 end
928 end
927
929
928 should "read the Issue Status's default done ratio" do
930 should "read the Issue Status's default done ratio" do
929 assert_equal 50, @issue.done_ratio
931 assert_equal 50, @issue.done_ratio
930 assert_equal 0, @issue2.done_ratio
932 assert_equal 0, @issue2.done_ratio
931 end
933 end
932 end
934 end
933 end
935 end
934
936
935 context "#update_done_ratio_from_issue_status" do
937 context "#update_done_ratio_from_issue_status" do
936 setup do
938 setup do
937 @issue = Issue.find(1)
939 @issue = Issue.find(1)
938 @issue_status = IssueStatus.find(1)
940 @issue_status = IssueStatus.find(1)
939 @issue_status.update_attribute(:default_done_ratio, 50)
941 @issue_status.update_attribute(:default_done_ratio, 50)
940 @issue2 = Issue.find(2)
942 @issue2 = Issue.find(2)
941 @issue_status2 = IssueStatus.find(2)
943 @issue_status2 = IssueStatus.find(2)
942 @issue_status2.update_attribute(:default_done_ratio, 0)
944 @issue_status2.update_attribute(:default_done_ratio, 0)
943 end
945 end
944
946
945 context "with Setting.issue_done_ratio using the issue_field" do
947 context "with Setting.issue_done_ratio using the issue_field" do
946 setup do
948 setup do
947 Setting.issue_done_ratio = 'issue_field'
949 Setting.issue_done_ratio = 'issue_field'
948 end
950 end
949
951
950 should "not change the issue" do
952 should "not change the issue" do
951 @issue.update_done_ratio_from_issue_status
953 @issue.update_done_ratio_from_issue_status
952 @issue2.update_done_ratio_from_issue_status
954 @issue2.update_done_ratio_from_issue_status
953
955
954 assert_equal 0, @issue.read_attribute(:done_ratio)
956 assert_equal 0, @issue.read_attribute(:done_ratio)
955 assert_equal 30, @issue2.read_attribute(:done_ratio)
957 assert_equal 30, @issue2.read_attribute(:done_ratio)
956 end
958 end
957 end
959 end
958
960
959 context "with Setting.issue_done_ratio using the issue_status" do
961 context "with Setting.issue_done_ratio using the issue_status" do
960 setup do
962 setup do
961 Setting.issue_done_ratio = 'issue_status'
963 Setting.issue_done_ratio = 'issue_status'
962 end
964 end
963
965
964 should "change the issue's done ratio" do
966 should "change the issue's done ratio" do
965 @issue.update_done_ratio_from_issue_status
967 @issue.update_done_ratio_from_issue_status
966 @issue2.update_done_ratio_from_issue_status
968 @issue2.update_done_ratio_from_issue_status
967
969
968 assert_equal 50, @issue.read_attribute(:done_ratio)
970 assert_equal 50, @issue.read_attribute(:done_ratio)
969 assert_equal 0, @issue2.read_attribute(:done_ratio)
971 assert_equal 0, @issue2.read_attribute(:done_ratio)
970 end
972 end
971 end
973 end
972 end
974 end
973
975
974 test "#by_tracker" do
976 test "#by_tracker" do
975 User.current = User.anonymous
977 User.current = User.anonymous
976 groups = Issue.by_tracker(Project.find(1))
978 groups = Issue.by_tracker(Project.find(1))
977 assert_equal 3, groups.size
979 assert_equal 3, groups.size
978 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
980 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
979 end
981 end
980
982
981 test "#by_version" do
983 test "#by_version" do
982 User.current = User.anonymous
984 User.current = User.anonymous
983 groups = Issue.by_version(Project.find(1))
985 groups = Issue.by_version(Project.find(1))
984 assert_equal 3, groups.size
986 assert_equal 3, groups.size
985 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
987 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
986 end
988 end
987
989
988 test "#by_priority" do
990 test "#by_priority" do
989 User.current = User.anonymous
991 User.current = User.anonymous
990 groups = Issue.by_priority(Project.find(1))
992 groups = Issue.by_priority(Project.find(1))
991 assert_equal 4, groups.size
993 assert_equal 4, groups.size
992 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
994 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
993 end
995 end
994
996
995 test "#by_category" do
997 test "#by_category" do
996 User.current = User.anonymous
998 User.current = User.anonymous
997 groups = Issue.by_category(Project.find(1))
999 groups = Issue.by_category(Project.find(1))
998 assert_equal 2, groups.size
1000 assert_equal 2, groups.size
999 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1001 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1000 end
1002 end
1001
1003
1002 test "#by_assigned_to" do
1004 test "#by_assigned_to" do
1003 User.current = User.anonymous
1005 User.current = User.anonymous
1004 groups = Issue.by_assigned_to(Project.find(1))
1006 groups = Issue.by_assigned_to(Project.find(1))
1005 assert_equal 2, groups.size
1007 assert_equal 2, groups.size
1006 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1008 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1007 end
1009 end
1008
1010
1009 test "#by_author" do
1011 test "#by_author" do
1010 User.current = User.anonymous
1012 User.current = User.anonymous
1011 groups = Issue.by_author(Project.find(1))
1013 groups = Issue.by_author(Project.find(1))
1012 assert_equal 4, groups.size
1014 assert_equal 4, groups.size
1013 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1015 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1014 end
1016 end
1015
1017
1016 test "#by_subproject" do
1018 test "#by_subproject" do
1017 User.current = User.anonymous
1019 User.current = User.anonymous
1018 groups = Issue.by_subproject(Project.find(1))
1020 groups = Issue.by_subproject(Project.find(1))
1019 # Private descendant not visible
1021 # Private descendant not visible
1020 assert_equal 1, groups.size
1022 assert_equal 1, groups.size
1021 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1023 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1022 end
1024 end
1023
1025
1024 context ".allowed_target_projects_on_move" do
1026 context ".allowed_target_projects_on_move" do
1025 should "return all active projects for admin users" do
1027 should "return all active projects for admin users" do
1026 User.current = User.find(1)
1028 User.current = User.find(1)
1027 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1029 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1028 end
1030 end
1029
1031
1030 should "return allowed projects for non admin users" do
1032 should "return allowed projects for non admin users" do
1031 User.current = User.find(2)
1033 User.current = User.find(2)
1032 Role.non_member.remove_permission! :move_issues
1034 Role.non_member.remove_permission! :move_issues
1033 assert_equal 3, Issue.allowed_target_projects_on_move.size
1035 assert_equal 3, Issue.allowed_target_projects_on_move.size
1034
1036
1035 Role.non_member.add_permission! :move_issues
1037 Role.non_member.add_permission! :move_issues
1036 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1038 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1037 end
1039 end
1038 end
1040 end
1039
1041
1040 def test_recently_updated_with_limit_scopes
1042 def test_recently_updated_with_limit_scopes
1041 #should return the last updated issue
1043 #should return the last updated issue
1042 assert_equal 1, Issue.recently_updated.with_limit(1).length
1044 assert_equal 1, Issue.recently_updated.with_limit(1).length
1043 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1045 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1044 end
1046 end
1045
1047
1046 def test_on_active_projects_scope
1048 def test_on_active_projects_scope
1047 assert Project.find(2).archive
1049 assert Project.find(2).archive
1048
1050
1049 before = Issue.on_active_project.length
1051 before = Issue.on_active_project.length
1050 # test inclusion to results
1052 # test inclusion to results
1051 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1053 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1052 assert_equal before + 1, Issue.on_active_project.length
1054 assert_equal before + 1, Issue.on_active_project.length
1053
1055
1054 # Move to an archived project
1056 # Move to an archived project
1055 issue.project = Project.find(2)
1057 issue.project = Project.find(2)
1056 assert issue.save
1058 assert issue.save
1057 assert_equal before, Issue.on_active_project.length
1059 assert_equal before, Issue.on_active_project.length
1058 end
1060 end
1059
1061
1060 context "Issue#recipients" do
1062 context "Issue#recipients" do
1061 setup do
1063 setup do
1062 @project = Project.find(1)
1064 @project = Project.find(1)
1063 @author = User.generate_with_protected!
1065 @author = User.generate_with_protected!
1064 @assignee = User.generate_with_protected!
1066 @assignee = User.generate_with_protected!
1065 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1067 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1066 end
1068 end
1067
1069
1068 should "include project recipients" do
1070 should "include project recipients" do
1069 assert @project.recipients.present?
1071 assert @project.recipients.present?
1070 @project.recipients.each do |project_recipient|
1072 @project.recipients.each do |project_recipient|
1071 assert @issue.recipients.include?(project_recipient)
1073 assert @issue.recipients.include?(project_recipient)
1072 end
1074 end
1073 end
1075 end
1074
1076
1075 should "include the author if the author is active" do
1077 should "include the author if the author is active" do
1076 assert @issue.author, "No author set for Issue"
1078 assert @issue.author, "No author set for Issue"
1077 assert @issue.recipients.include?(@issue.author.mail)
1079 assert @issue.recipients.include?(@issue.author.mail)
1078 end
1080 end
1079
1081
1080 should "include the assigned to user if the assigned to user is active" do
1082 should "include the assigned to user if the assigned to user is active" do
1081 assert @issue.assigned_to, "No assigned_to set for Issue"
1083 assert @issue.assigned_to, "No assigned_to set for Issue"
1082 assert @issue.recipients.include?(@issue.assigned_to.mail)
1084 assert @issue.recipients.include?(@issue.assigned_to.mail)
1083 end
1085 end
1084
1086
1085 should "not include users who opt out of all email" do
1087 should "not include users who opt out of all email" do
1086 @author.update_attribute(:mail_notification, :none)
1088 @author.update_attribute(:mail_notification, :none)
1087
1089
1088 assert !@issue.recipients.include?(@issue.author.mail)
1090 assert !@issue.recipients.include?(@issue.author.mail)
1089 end
1091 end
1090
1092
1091 should "not include the issue author if they are only notified of assigned issues" do
1093 should "not include the issue author if they are only notified of assigned issues" do
1092 @author.update_attribute(:mail_notification, :only_assigned)
1094 @author.update_attribute(:mail_notification, :only_assigned)
1093
1095
1094 assert !@issue.recipients.include?(@issue.author.mail)
1096 assert !@issue.recipients.include?(@issue.author.mail)
1095 end
1097 end
1096
1098
1097 should "not include the assigned user if they are only notified of owned issues" do
1099 should "not include the assigned user if they are only notified of owned issues" do
1098 @assignee.update_attribute(:mail_notification, :only_owner)
1100 @assignee.update_attribute(:mail_notification, :only_owner)
1099
1101
1100 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1102 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1101 end
1103 end
1102
1104
1103 end
1105 end
1104 end
1106 end
General Comments 0
You need to be logged in to leave comments. Login now