##// END OF EJS Templates
code layout clean up of test_should_close_duplicates at test/unit/issue_test.rb...
Toshi MARUYAMA -
r7361:a281752e4f20
parent child
Show More
@@ -1,1106 +1,1108
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,
351 :status_id => 1, :priority => IssuePriority.all.first,
352 :subject => 'Duplicates test', :description => 'Duplicates test')
351 assert issue1.save
353 assert issue1.save
352 issue2 = issue1.clone
354 issue2 = issue1.clone
353 assert issue2.save
355 assert issue2.save
354 issue3 = issue1.clone
356 issue3 = issue1.clone
355 assert issue3.save
357 assert issue3.save
356
358
357 # 2 is a dupe of 1
359 # 2 is a dupe of 1
358 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
360 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
359 # And 3 is a dupe of 2
361 # And 3 is a dupe of 2
360 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
362 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
361 # And 3 is a dupe of 1 (circular duplicates)
363 # And 3 is a dupe of 1 (circular duplicates)
362 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
364 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
363
365
364 assert issue1.reload.duplicates.include?(issue2)
366 assert issue1.reload.duplicates.include?(issue2)
365
367
366 # Closing issue 1
368 # Closing issue 1
367 issue1.init_journal(User.find(:first), "Closing issue1")
369 issue1.init_journal(User.find(:first), "Closing issue1")
368 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
370 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
369 assert issue1.save
371 assert issue1.save
370 # 2 and 3 should be also closed
372 # 2 and 3 should be also closed
371 assert issue2.reload.closed?
373 assert issue2.reload.closed?
372 assert issue3.reload.closed?
374 assert issue3.reload.closed?
373 end
375 end
374
376
375 def test_should_not_close_duplicated_issue
377 def test_should_not_close_duplicated_issue
376 # Create 3 issues
378 # Create 3 issues
377 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
379 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
378 :status_id => 1, :priority => IssuePriority.all.first,
380 :status_id => 1, :priority => IssuePriority.all.first,
379 :subject => 'Duplicates test', :description => 'Duplicates test')
381 :subject => 'Duplicates test', :description => 'Duplicates test')
380 assert issue1.save
382 assert issue1.save
381 issue2 = issue1.clone
383 issue2 = issue1.clone
382 assert issue2.save
384 assert issue2.save
383
385
384 # 2 is a dupe of 1
386 # 2 is a dupe of 1
385 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
387 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
386 # 2 is a dup of 1 but 1 is not a duplicate of 2
388 # 2 is a dup of 1 but 1 is not a duplicate of 2
387 assert !issue2.reload.duplicates.include?(issue1)
389 assert !issue2.reload.duplicates.include?(issue1)
388
390
389 # Closing issue 2
391 # Closing issue 2
390 issue2.init_journal(User.find(:first), "Closing issue2")
392 issue2.init_journal(User.find(:first), "Closing issue2")
391 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
393 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
392 assert issue2.save
394 assert issue2.save
393 # 1 should not be also closed
395 # 1 should not be also closed
394 assert !issue1.reload.closed?
396 assert !issue1.reload.closed?
395 end
397 end
396
398
397 def test_assignable_versions
399 def test_assignable_versions
398 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
400 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
399 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
401 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
400 end
402 end
401
403
402 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
404 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
403 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
405 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
404 assert !issue.save
406 assert !issue.save
405 assert_not_nil issue.errors.on(:fixed_version_id)
407 assert_not_nil issue.errors.on(:fixed_version_id)
406 end
408 end
407
409
408 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
410 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
409 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
411 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
410 assert !issue.save
412 assert !issue.save
411 assert_not_nil issue.errors.on(:fixed_version_id)
413 assert_not_nil issue.errors.on(:fixed_version_id)
412 end
414 end
413
415
414 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
416 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
415 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
417 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
416 assert issue.save
418 assert issue.save
417 end
419 end
418
420
419 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
421 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
420 issue = Issue.find(11)
422 issue = Issue.find(11)
421 assert_equal 'closed', issue.fixed_version.status
423 assert_equal 'closed', issue.fixed_version.status
422 issue.subject = 'Subject changed'
424 issue.subject = 'Subject changed'
423 assert issue.save
425 assert issue.save
424 end
426 end
425
427
426 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
428 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
427 issue = Issue.find(11)
429 issue = Issue.find(11)
428 issue.status_id = 1
430 issue.status_id = 1
429 assert !issue.save
431 assert !issue.save
430 assert_not_nil issue.errors.on_base
432 assert_not_nil issue.errors.on_base
431 end
433 end
432
434
433 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
435 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
434 issue = Issue.find(11)
436 issue = Issue.find(11)
435 issue.status_id = 1
437 issue.status_id = 1
436 issue.fixed_version_id = 3
438 issue.fixed_version_id = 3
437 assert issue.save
439 assert issue.save
438 end
440 end
439
441
440 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
442 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
441 issue = Issue.find(12)
443 issue = Issue.find(12)
442 assert_equal 'locked', issue.fixed_version.status
444 assert_equal 'locked', issue.fixed_version.status
443 issue.status_id = 1
445 issue.status_id = 1
444 assert issue.save
446 assert issue.save
445 end
447 end
446
448
447 def test_move_to_another_project_with_same_category
449 def test_move_to_another_project_with_same_category
448 issue = Issue.find(1)
450 issue = Issue.find(1)
449 assert issue.move_to_project(Project.find(2))
451 assert issue.move_to_project(Project.find(2))
450 issue.reload
452 issue.reload
451 assert_equal 2, issue.project_id
453 assert_equal 2, issue.project_id
452 # Category changes
454 # Category changes
453 assert_equal 4, issue.category_id
455 assert_equal 4, issue.category_id
454 # Make sure time entries were move to the target project
456 # Make sure time entries were move to the target project
455 assert_equal 2, issue.time_entries.first.project_id
457 assert_equal 2, issue.time_entries.first.project_id
456 end
458 end
457
459
458 def test_move_to_another_project_without_same_category
460 def test_move_to_another_project_without_same_category
459 issue = Issue.find(2)
461 issue = Issue.find(2)
460 assert issue.move_to_project(Project.find(2))
462 assert issue.move_to_project(Project.find(2))
461 issue.reload
463 issue.reload
462 assert_equal 2, issue.project_id
464 assert_equal 2, issue.project_id
463 # Category cleared
465 # Category cleared
464 assert_nil issue.category_id
466 assert_nil issue.category_id
465 end
467 end
466
468
467 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
469 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
468 issue = Issue.find(1)
470 issue = Issue.find(1)
469 issue.update_attribute(:fixed_version_id, 1)
471 issue.update_attribute(:fixed_version_id, 1)
470 assert issue.move_to_project(Project.find(2))
472 assert issue.move_to_project(Project.find(2))
471 issue.reload
473 issue.reload
472 assert_equal 2, issue.project_id
474 assert_equal 2, issue.project_id
473 # Cleared fixed_version
475 # Cleared fixed_version
474 assert_equal nil, issue.fixed_version
476 assert_equal nil, issue.fixed_version
475 end
477 end
476
478
477 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
479 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
478 issue = Issue.find(1)
480 issue = Issue.find(1)
479 issue.update_attribute(:fixed_version_id, 4)
481 issue.update_attribute(:fixed_version_id, 4)
480 assert issue.move_to_project(Project.find(5))
482 assert issue.move_to_project(Project.find(5))
481 issue.reload
483 issue.reload
482 assert_equal 5, issue.project_id
484 assert_equal 5, issue.project_id
483 # Keep fixed_version
485 # Keep fixed_version
484 assert_equal 4, issue.fixed_version_id
486 assert_equal 4, issue.fixed_version_id
485 end
487 end
486
488
487 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
489 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
488 issue = Issue.find(1)
490 issue = Issue.find(1)
489 issue.update_attribute(:fixed_version_id, 1)
491 issue.update_attribute(:fixed_version_id, 1)
490 assert issue.move_to_project(Project.find(5))
492 assert issue.move_to_project(Project.find(5))
491 issue.reload
493 issue.reload
492 assert_equal 5, issue.project_id
494 assert_equal 5, issue.project_id
493 # Cleared fixed_version
495 # Cleared fixed_version
494 assert_equal nil, issue.fixed_version
496 assert_equal nil, issue.fixed_version
495 end
497 end
496
498
497 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
499 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
498 issue = Issue.find(1)
500 issue = Issue.find(1)
499 issue.update_attribute(:fixed_version_id, 7)
501 issue.update_attribute(:fixed_version_id, 7)
500 assert issue.move_to_project(Project.find(2))
502 assert issue.move_to_project(Project.find(2))
501 issue.reload
503 issue.reload
502 assert_equal 2, issue.project_id
504 assert_equal 2, issue.project_id
503 # Keep fixed_version
505 # Keep fixed_version
504 assert_equal 7, issue.fixed_version_id
506 assert_equal 7, issue.fixed_version_id
505 end
507 end
506
508
507 def test_move_to_another_project_with_disabled_tracker
509 def test_move_to_another_project_with_disabled_tracker
508 issue = Issue.find(1)
510 issue = Issue.find(1)
509 target = Project.find(2)
511 target = Project.find(2)
510 target.tracker_ids = [3]
512 target.tracker_ids = [3]
511 target.save
513 target.save
512 assert_equal false, issue.move_to_project(target)
514 assert_equal false, issue.move_to_project(target)
513 issue.reload
515 issue.reload
514 assert_equal 1, issue.project_id
516 assert_equal 1, issue.project_id
515 end
517 end
516
518
517 def test_copy_to_the_same_project
519 def test_copy_to_the_same_project
518 issue = Issue.find(1)
520 issue = Issue.find(1)
519 copy = nil
521 copy = nil
520 assert_difference 'Issue.count' do
522 assert_difference 'Issue.count' do
521 copy = issue.move_to_project(issue.project, nil, :copy => true)
523 copy = issue.move_to_project(issue.project, nil, :copy => true)
522 end
524 end
523 assert_kind_of Issue, copy
525 assert_kind_of Issue, copy
524 assert_equal issue.project, copy.project
526 assert_equal issue.project, copy.project
525 assert_equal "125", copy.custom_value_for(2).value
527 assert_equal "125", copy.custom_value_for(2).value
526 end
528 end
527
529
528 def test_copy_to_another_project_and_tracker
530 def test_copy_to_another_project_and_tracker
529 issue = Issue.find(1)
531 issue = Issue.find(1)
530 copy = nil
532 copy = nil
531 assert_difference 'Issue.count' do
533 assert_difference 'Issue.count' do
532 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
534 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
533 end
535 end
534 copy.reload
536 copy.reload
535 assert_kind_of Issue, copy
537 assert_kind_of Issue, copy
536 assert_equal Project.find(3), copy.project
538 assert_equal Project.find(3), copy.project
537 assert_equal Tracker.find(2), copy.tracker
539 assert_equal Tracker.find(2), copy.tracker
538 # Custom field #2 is not associated with target tracker
540 # Custom field #2 is not associated with target tracker
539 assert_nil copy.custom_value_for(2)
541 assert_nil copy.custom_value_for(2)
540 end
542 end
541
543
542 context "#move_to_project" do
544 context "#move_to_project" do
543 context "as a copy" do
545 context "as a copy" do
544 setup do
546 setup do
545 @issue = Issue.find(1)
547 @issue = Issue.find(1)
546 @copy = nil
548 @copy = nil
547 end
549 end
548
550
549 should "not create a journal" do
551 should "not create a journal" do
550 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
552 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
551 assert_equal 0, @copy.reload.journals.size
553 assert_equal 0, @copy.reload.journals.size
552 end
554 end
553
555
554 should "allow assigned_to changes" do
556 should "allow assigned_to changes" do
555 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
557 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
556 assert_equal 3, @copy.assigned_to_id
558 assert_equal 3, @copy.assigned_to_id
557 end
559 end
558
560
559 should "allow status changes" do
561 should "allow status changes" do
560 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
562 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
561 assert_equal 2, @copy.status_id
563 assert_equal 2, @copy.status_id
562 end
564 end
563
565
564 should "allow start date changes" do
566 should "allow start date changes" do
565 date = Date.today
567 date = Date.today
566 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
568 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
567 assert_equal date, @copy.start_date
569 assert_equal date, @copy.start_date
568 end
570 end
569
571
570 should "allow due date changes" do
572 should "allow due date changes" do
571 date = Date.today
573 date = Date.today
572 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
574 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
573
575
574 assert_equal date, @copy.due_date
576 assert_equal date, @copy.due_date
575 end
577 end
576
578
577 should "set current user as author" do
579 should "set current user as author" do
578 User.current = User.find(9)
580 User.current = User.find(9)
579 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
581 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
580
582
581 assert_equal User.current, @copy.author
583 assert_equal User.current, @copy.author
582 end
584 end
583
585
584 should "keep journal notes" do
586 should "keep journal notes" do
585 date = Date.today
587 date = Date.today
586 notes = "Notes added when copying"
588 notes = "Notes added when copying"
587 User.current = User.find(9)
589 User.current = User.find(9)
588 @issue.init_journal(User.current, notes)
590 @issue.init_journal(User.current, notes)
589 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
591 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
590
592
591 assert_equal 1, @copy.journals.size
593 assert_equal 1, @copy.journals.size
592 journal = @copy.journals.first
594 journal = @copy.journals.first
593 assert_equal 0, journal.details.size
595 assert_equal 0, journal.details.size
594 assert_equal notes, journal.notes
596 assert_equal notes, journal.notes
595 end
597 end
596 end
598 end
597 end
599 end
598
600
599 def test_recipients_should_not_include_users_that_cannot_view_the_issue
601 def test_recipients_should_not_include_users_that_cannot_view_the_issue
600 issue = Issue.find(12)
602 issue = Issue.find(12)
601 assert issue.recipients.include?(issue.author.mail)
603 assert issue.recipients.include?(issue.author.mail)
602 # move the issue to a private project
604 # move the issue to a private project
603 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
605 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
604 # author is not a member of project anymore
606 # author is not a member of project anymore
605 assert !copy.recipients.include?(copy.author.mail)
607 assert !copy.recipients.include?(copy.author.mail)
606 end
608 end
607
609
608 def test_recipients_should_include_the_assigned_group_members
610 def test_recipients_should_include_the_assigned_group_members
609 group_member = User.generate_with_protected!
611 group_member = User.generate_with_protected!
610 group = Group.generate!
612 group = Group.generate!
611 group.users << group_member
613 group.users << group_member
612
614
613 issue = Issue.find(12)
615 issue = Issue.find(12)
614 issue.assigned_to = group
616 issue.assigned_to = group
615 assert issue.recipients.include?(group_member.mail)
617 assert issue.recipients.include?(group_member.mail)
616 end
618 end
617
619
618 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
620 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
619 user = User.find(3)
621 user = User.find(3)
620 issue = Issue.find(9)
622 issue = Issue.find(9)
621 Watcher.create!(:user => user, :watchable => issue)
623 Watcher.create!(:user => user, :watchable => issue)
622 assert issue.watched_by?(user)
624 assert issue.watched_by?(user)
623 assert !issue.watcher_recipients.include?(user.mail)
625 assert !issue.watcher_recipients.include?(user.mail)
624 end
626 end
625
627
626 def test_issue_destroy
628 def test_issue_destroy
627 Issue.find(1).destroy
629 Issue.find(1).destroy
628 assert_nil Issue.find_by_id(1)
630 assert_nil Issue.find_by_id(1)
629 assert_nil TimeEntry.find_by_issue_id(1)
631 assert_nil TimeEntry.find_by_issue_id(1)
630 end
632 end
631
633
632 def test_blocked
634 def test_blocked
633 blocked_issue = Issue.find(9)
635 blocked_issue = Issue.find(9)
634 blocking_issue = Issue.find(10)
636 blocking_issue = Issue.find(10)
635
637
636 assert blocked_issue.blocked?
638 assert blocked_issue.blocked?
637 assert !blocking_issue.blocked?
639 assert !blocking_issue.blocked?
638 end
640 end
639
641
640 def test_blocked_issues_dont_allow_closed_statuses
642 def test_blocked_issues_dont_allow_closed_statuses
641 blocked_issue = Issue.find(9)
643 blocked_issue = Issue.find(9)
642
644
643 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
645 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
644 assert !allowed_statuses.empty?
646 assert !allowed_statuses.empty?
645 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
647 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
646 assert closed_statuses.empty?
648 assert closed_statuses.empty?
647 end
649 end
648
650
649 def test_unblocked_issues_allow_closed_statuses
651 def test_unblocked_issues_allow_closed_statuses
650 blocking_issue = Issue.find(10)
652 blocking_issue = Issue.find(10)
651
653
652 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
654 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
653 assert !allowed_statuses.empty?
655 assert !allowed_statuses.empty?
654 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
656 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
655 assert !closed_statuses.empty?
657 assert !closed_statuses.empty?
656 end
658 end
657
659
658 def test_rescheduling_an_issue_should_reschedule_following_issue
660 def test_rescheduling_an_issue_should_reschedule_following_issue
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)
661 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)
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)
662 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)
661 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
663 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
662 assert_equal issue1.due_date + 1, issue2.reload.start_date
664 assert_equal issue1.due_date + 1, issue2.reload.start_date
663
665
664 issue1.due_date = Date.today + 5
666 issue1.due_date = Date.today + 5
665 issue1.save!
667 issue1.save!
666 assert_equal issue1.due_date + 1, issue2.reload.start_date
668 assert_equal issue1.due_date + 1, issue2.reload.start_date
667 end
669 end
668
670
669 def test_overdue
671 def test_overdue
670 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
672 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
671 assert !Issue.new(:due_date => Date.today).overdue?
673 assert !Issue.new(:due_date => Date.today).overdue?
672 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
674 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
673 assert !Issue.new(:due_date => nil).overdue?
675 assert !Issue.new(:due_date => nil).overdue?
674 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
676 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
675 end
677 end
676
678
677 context "#behind_schedule?" do
679 context "#behind_schedule?" do
678 should "be false if the issue has no start_date" do
680 should "be false if the issue has no start_date" do
679 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
681 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
680 end
682 end
681
683
682 should "be false if the issue has no end_date" do
684 should "be false if the issue has no end_date" do
683 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
685 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
684 end
686 end
685
687
686 should "be false if the issue has more done than it's calendar time" do
688 should "be false if the issue has more done than it's calendar time" do
687 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
689 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
688 end
690 end
689
691
690 should "be true if the issue hasn't been started at all" do
692 should "be true if the issue hasn't been started at all" do
691 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
693 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
692 end
694 end
693
695
694 should "be true if the issue has used more calendar time than it's done ratio" do
696 should "be true if the issue has used more calendar time than it's done ratio" do
695 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
697 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
696 end
698 end
697 end
699 end
698
700
699 context "#assignable_users" do
701 context "#assignable_users" do
700 should "be Users" do
702 should "be Users" do
701 assert_kind_of User, Issue.find(1).assignable_users.first
703 assert_kind_of User, Issue.find(1).assignable_users.first
702 end
704 end
703
705
704 should "include the issue author" do
706 should "include the issue author" do
705 project = Project.find(1)
707 project = Project.find(1)
706 non_project_member = User.generate!
708 non_project_member = User.generate!
707 issue = Issue.generate_for_project!(project, :author => non_project_member)
709 issue = Issue.generate_for_project!(project, :author => non_project_member)
708
710
709 assert issue.assignable_users.include?(non_project_member)
711 assert issue.assignable_users.include?(non_project_member)
710 end
712 end
711
713
712 should "include the current assignee" do
714 should "include the current assignee" do
713 project = Project.find(1)
715 project = Project.find(1)
714 user = User.generate!
716 user = User.generate!
715 issue = Issue.generate_for_project!(project, :assigned_to => user)
717 issue = Issue.generate_for_project!(project, :assigned_to => user)
716 user.lock!
718 user.lock!
717
719
718 assert Issue.find(issue.id).assignable_users.include?(user)
720 assert Issue.find(issue.id).assignable_users.include?(user)
719 end
721 end
720
722
721 should "not show the issue author twice" do
723 should "not show the issue author twice" do
722 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
724 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
723 assert_equal 2, assignable_user_ids.length
725 assert_equal 2, assignable_user_ids.length
724
726
725 assignable_user_ids.each do |user_id|
727 assignable_user_ids.each do |user_id|
726 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
728 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
727 end
729 end
728 end
730 end
729
731
730 context "with issue_group_assignment" do
732 context "with issue_group_assignment" do
731 should "include groups" do
733 should "include groups" do
732 issue = Issue.new(:project => Project.find(2))
734 issue = Issue.new(:project => Project.find(2))
733
735
734 with_settings :issue_group_assignment => '1' do
736 with_settings :issue_group_assignment => '1' do
735 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
737 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
736 assert issue.assignable_users.include?(Group.find(11))
738 assert issue.assignable_users.include?(Group.find(11))
737 end
739 end
738 end
740 end
739 end
741 end
740
742
741 context "without issue_group_assignment" do
743 context "without issue_group_assignment" do
742 should "not include groups" do
744 should "not include groups" do
743 issue = Issue.new(:project => Project.find(2))
745 issue = Issue.new(:project => Project.find(2))
744
746
745 with_settings :issue_group_assignment => '0' do
747 with_settings :issue_group_assignment => '0' do
746 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
748 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
747 assert !issue.assignable_users.include?(Group.find(11))
749 assert !issue.assignable_users.include?(Group.find(11))
748 end
750 end
749 end
751 end
750 end
752 end
751 end
753 end
752
754
753 def test_create_should_send_email_notification
755 def test_create_should_send_email_notification
754 ActionMailer::Base.deliveries.clear
756 ActionMailer::Base.deliveries.clear
755 issue = Issue.new(:project_id => 1, :tracker_id => 1,
757 issue = Issue.new(:project_id => 1, :tracker_id => 1,
756 :author_id => 3, :status_id => 1,
758 :author_id => 3, :status_id => 1,
757 :priority => IssuePriority.all.first,
759 :priority => IssuePriority.all.first,
758 :subject => 'test_create', :estimated_hours => '1:30')
760 :subject => 'test_create', :estimated_hours => '1:30')
759
761
760 assert issue.save
762 assert issue.save
761 assert_equal 1, ActionMailer::Base.deliveries.size
763 assert_equal 1, ActionMailer::Base.deliveries.size
762 end
764 end
763
765
764 def test_stale_issue_should_not_send_email_notification
766 def test_stale_issue_should_not_send_email_notification
765 ActionMailer::Base.deliveries.clear
767 ActionMailer::Base.deliveries.clear
766 issue = Issue.find(1)
768 issue = Issue.find(1)
767 stale = Issue.find(1)
769 stale = Issue.find(1)
768
770
769 issue.init_journal(User.find(1))
771 issue.init_journal(User.find(1))
770 issue.subject = 'Subjet update'
772 issue.subject = 'Subjet update'
771 assert issue.save
773 assert issue.save
772 assert_equal 1, ActionMailer::Base.deliveries.size
774 assert_equal 1, ActionMailer::Base.deliveries.size
773 ActionMailer::Base.deliveries.clear
775 ActionMailer::Base.deliveries.clear
774
776
775 stale.init_journal(User.find(1))
777 stale.init_journal(User.find(1))
776 stale.subject = 'Another subjet update'
778 stale.subject = 'Another subjet update'
777 assert_raise ActiveRecord::StaleObjectError do
779 assert_raise ActiveRecord::StaleObjectError do
778 stale.save
780 stale.save
779 end
781 end
780 assert ActionMailer::Base.deliveries.empty?
782 assert ActionMailer::Base.deliveries.empty?
781 end
783 end
782
784
783 def test_journalized_description
785 def test_journalized_description
784 IssueCustomField.delete_all
786 IssueCustomField.delete_all
785
787
786 i = Issue.first
788 i = Issue.first
787 old_description = i.description
789 old_description = i.description
788 new_description = "This is the new description"
790 new_description = "This is the new description"
789
791
790 i.init_journal(User.find(2))
792 i.init_journal(User.find(2))
791 i.description = new_description
793 i.description = new_description
792 assert_difference 'Journal.count', 1 do
794 assert_difference 'Journal.count', 1 do
793 assert_difference 'JournalDetail.count', 1 do
795 assert_difference 'JournalDetail.count', 1 do
794 i.save!
796 i.save!
795 end
797 end
796 end
798 end
797
799
798 detail = JournalDetail.first(:order => 'id DESC')
800 detail = JournalDetail.first(:order => 'id DESC')
799 assert_equal i, detail.journal.journalized
801 assert_equal i, detail.journal.journalized
800 assert_equal 'attr', detail.property
802 assert_equal 'attr', detail.property
801 assert_equal 'description', detail.prop_key
803 assert_equal 'description', detail.prop_key
802 assert_equal old_description, detail.old_value
804 assert_equal old_description, detail.old_value
803 assert_equal new_description, detail.value
805 assert_equal new_description, detail.value
804 end
806 end
805
807
806 def test_blank_descriptions_should_not_be_journalized
808 def test_blank_descriptions_should_not_be_journalized
807 IssueCustomField.delete_all
809 IssueCustomField.delete_all
808 Issue.update_all("description = NULL", "id=1")
810 Issue.update_all("description = NULL", "id=1")
809
811
810 i = Issue.find(1)
812 i = Issue.find(1)
811 i.init_journal(User.find(2))
813 i.init_journal(User.find(2))
812 i.subject = "blank description"
814 i.subject = "blank description"
813 i.description = "\r\n"
815 i.description = "\r\n"
814
816
815 assert_difference 'Journal.count', 1 do
817 assert_difference 'Journal.count', 1 do
816 assert_difference 'JournalDetail.count', 1 do
818 assert_difference 'JournalDetail.count', 1 do
817 i.save!
819 i.save!
818 end
820 end
819 end
821 end
820 end
822 end
821
823
822 def test_description_eol_should_be_normalized
824 def test_description_eol_should_be_normalized
823 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
825 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
824 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
826 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
825 end
827 end
826
828
827 def test_saving_twice_should_not_duplicate_journal_details
829 def test_saving_twice_should_not_duplicate_journal_details
828 i = Issue.find(:first)
830 i = Issue.find(:first)
829 i.init_journal(User.find(2), 'Some notes')
831 i.init_journal(User.find(2), 'Some notes')
830 # initial changes
832 # initial changes
831 i.subject = 'New subject'
833 i.subject = 'New subject'
832 i.done_ratio = i.done_ratio + 10
834 i.done_ratio = i.done_ratio + 10
833 assert_difference 'Journal.count' do
835 assert_difference 'Journal.count' do
834 assert i.save
836 assert i.save
835 end
837 end
836 # 1 more change
838 # 1 more change
837 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
839 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
838 assert_no_difference 'Journal.count' do
840 assert_no_difference 'Journal.count' do
839 assert_difference 'JournalDetail.count', 1 do
841 assert_difference 'JournalDetail.count', 1 do
840 i.save
842 i.save
841 end
843 end
842 end
844 end
843 # no more change
845 # no more change
844 assert_no_difference 'Journal.count' do
846 assert_no_difference 'Journal.count' do
845 assert_no_difference 'JournalDetail.count' do
847 assert_no_difference 'JournalDetail.count' do
846 i.save
848 i.save
847 end
849 end
848 end
850 end
849 end
851 end
850
852
851 def test_all_dependent_issues
853 def test_all_dependent_issues
852 IssueRelation.delete_all
854 IssueRelation.delete_all
853 assert IssueRelation.create!(:issue_from => Issue.find(1),
855 assert IssueRelation.create!(:issue_from => Issue.find(1),
854 :issue_to => Issue.find(2),
856 :issue_to => Issue.find(2),
855 :relation_type => IssueRelation::TYPE_PRECEDES)
857 :relation_type => IssueRelation::TYPE_PRECEDES)
856 assert IssueRelation.create!(:issue_from => Issue.find(2),
858 assert IssueRelation.create!(:issue_from => Issue.find(2),
857 :issue_to => Issue.find(3),
859 :issue_to => Issue.find(3),
858 :relation_type => IssueRelation::TYPE_PRECEDES)
860 :relation_type => IssueRelation::TYPE_PRECEDES)
859 assert IssueRelation.create!(:issue_from => Issue.find(3),
861 assert IssueRelation.create!(:issue_from => Issue.find(3),
860 :issue_to => Issue.find(8),
862 :issue_to => Issue.find(8),
861 :relation_type => IssueRelation::TYPE_PRECEDES)
863 :relation_type => IssueRelation::TYPE_PRECEDES)
862
864
863 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
865 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
864 end
866 end
865
867
866 def test_all_dependent_issues_with_persistent_circular_dependency
868 def test_all_dependent_issues_with_persistent_circular_dependency
867 IssueRelation.delete_all
869 IssueRelation.delete_all
868 assert IssueRelation.create!(:issue_from => Issue.find(1),
870 assert IssueRelation.create!(:issue_from => Issue.find(1),
869 :issue_to => Issue.find(2),
871 :issue_to => Issue.find(2),
870 :relation_type => IssueRelation::TYPE_PRECEDES)
872 :relation_type => IssueRelation::TYPE_PRECEDES)
871 assert IssueRelation.create!(:issue_from => Issue.find(2),
873 assert IssueRelation.create!(:issue_from => Issue.find(2),
872 :issue_to => Issue.find(3),
874 :issue_to => Issue.find(3),
873 :relation_type => IssueRelation::TYPE_PRECEDES)
875 :relation_type => IssueRelation::TYPE_PRECEDES)
874 # Validation skipping
876 # Validation skipping
875 assert IssueRelation.new(:issue_from => Issue.find(3),
877 assert IssueRelation.new(:issue_from => Issue.find(3),
876 :issue_to => Issue.find(1),
878 :issue_to => Issue.find(1),
877 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
879 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
878
880
879 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
881 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
880 end
882 end
881
883
882 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
884 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
883 IssueRelation.delete_all
885 IssueRelation.delete_all
884 assert IssueRelation.create!(:issue_from => Issue.find(1),
886 assert IssueRelation.create!(:issue_from => Issue.find(1),
885 :issue_to => Issue.find(2),
887 :issue_to => Issue.find(2),
886 :relation_type => IssueRelation::TYPE_RELATES)
888 :relation_type => IssueRelation::TYPE_RELATES)
887 assert IssueRelation.create!(:issue_from => Issue.find(2),
889 assert IssueRelation.create!(:issue_from => Issue.find(2),
888 :issue_to => Issue.find(3),
890 :issue_to => Issue.find(3),
889 :relation_type => IssueRelation::TYPE_RELATES)
891 :relation_type => IssueRelation::TYPE_RELATES)
890 assert IssueRelation.create!(:issue_from => Issue.find(3),
892 assert IssueRelation.create!(:issue_from => Issue.find(3),
891 :issue_to => Issue.find(8),
893 :issue_to => Issue.find(8),
892 :relation_type => IssueRelation::TYPE_RELATES)
894 :relation_type => IssueRelation::TYPE_RELATES)
893 # Validation skipping
895 # Validation skipping
894 assert IssueRelation.new(:issue_from => Issue.find(8),
896 assert IssueRelation.new(:issue_from => Issue.find(8),
895 :issue_to => Issue.find(2),
897 :issue_to => Issue.find(2),
896 :relation_type => IssueRelation::TYPE_RELATES).save(false)
898 :relation_type => IssueRelation::TYPE_RELATES).save(false)
897 assert IssueRelation.new(:issue_from => Issue.find(3),
899 assert IssueRelation.new(:issue_from => Issue.find(3),
898 :issue_to => Issue.find(1),
900 :issue_to => Issue.find(1),
899 :relation_type => IssueRelation::TYPE_RELATES).save(false)
901 :relation_type => IssueRelation::TYPE_RELATES).save(false)
900
902
901 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
903 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
902 end
904 end
903
905
904 context "#done_ratio" do
906 context "#done_ratio" do
905 setup do
907 setup do
906 @issue = Issue.find(1)
908 @issue = Issue.find(1)
907 @issue_status = IssueStatus.find(1)
909 @issue_status = IssueStatus.find(1)
908 @issue_status.update_attribute(:default_done_ratio, 50)
910 @issue_status.update_attribute(:default_done_ratio, 50)
909 @issue2 = Issue.find(2)
911 @issue2 = Issue.find(2)
910 @issue_status2 = IssueStatus.find(2)
912 @issue_status2 = IssueStatus.find(2)
911 @issue_status2.update_attribute(:default_done_ratio, 0)
913 @issue_status2.update_attribute(:default_done_ratio, 0)
912 end
914 end
913
915
914 context "with Setting.issue_done_ratio using the issue_field" do
916 context "with Setting.issue_done_ratio using the issue_field" do
915 setup do
917 setup do
916 Setting.issue_done_ratio = 'issue_field'
918 Setting.issue_done_ratio = 'issue_field'
917 end
919 end
918
920
919 should "read the issue's field" do
921 should "read the issue's field" do
920 assert_equal 0, @issue.done_ratio
922 assert_equal 0, @issue.done_ratio
921 assert_equal 30, @issue2.done_ratio
923 assert_equal 30, @issue2.done_ratio
922 end
924 end
923 end
925 end
924
926
925 context "with Setting.issue_done_ratio using the issue_status" do
927 context "with Setting.issue_done_ratio using the issue_status" do
926 setup do
928 setup do
927 Setting.issue_done_ratio = 'issue_status'
929 Setting.issue_done_ratio = 'issue_status'
928 end
930 end
929
931
930 should "read the Issue Status's default done ratio" do
932 should "read the Issue Status's default done ratio" do
931 assert_equal 50, @issue.done_ratio
933 assert_equal 50, @issue.done_ratio
932 assert_equal 0, @issue2.done_ratio
934 assert_equal 0, @issue2.done_ratio
933 end
935 end
934 end
936 end
935 end
937 end
936
938
937 context "#update_done_ratio_from_issue_status" do
939 context "#update_done_ratio_from_issue_status" do
938 setup do
940 setup do
939 @issue = Issue.find(1)
941 @issue = Issue.find(1)
940 @issue_status = IssueStatus.find(1)
942 @issue_status = IssueStatus.find(1)
941 @issue_status.update_attribute(:default_done_ratio, 50)
943 @issue_status.update_attribute(:default_done_ratio, 50)
942 @issue2 = Issue.find(2)
944 @issue2 = Issue.find(2)
943 @issue_status2 = IssueStatus.find(2)
945 @issue_status2 = IssueStatus.find(2)
944 @issue_status2.update_attribute(:default_done_ratio, 0)
946 @issue_status2.update_attribute(:default_done_ratio, 0)
945 end
947 end
946
948
947 context "with Setting.issue_done_ratio using the issue_field" do
949 context "with Setting.issue_done_ratio using the issue_field" do
948 setup do
950 setup do
949 Setting.issue_done_ratio = 'issue_field'
951 Setting.issue_done_ratio = 'issue_field'
950 end
952 end
951
953
952 should "not change the issue" do
954 should "not change the issue" do
953 @issue.update_done_ratio_from_issue_status
955 @issue.update_done_ratio_from_issue_status
954 @issue2.update_done_ratio_from_issue_status
956 @issue2.update_done_ratio_from_issue_status
955
957
956 assert_equal 0, @issue.read_attribute(:done_ratio)
958 assert_equal 0, @issue.read_attribute(:done_ratio)
957 assert_equal 30, @issue2.read_attribute(:done_ratio)
959 assert_equal 30, @issue2.read_attribute(:done_ratio)
958 end
960 end
959 end
961 end
960
962
961 context "with Setting.issue_done_ratio using the issue_status" do
963 context "with Setting.issue_done_ratio using the issue_status" do
962 setup do
964 setup do
963 Setting.issue_done_ratio = 'issue_status'
965 Setting.issue_done_ratio = 'issue_status'
964 end
966 end
965
967
966 should "change the issue's done ratio" do
968 should "change the issue's done ratio" do
967 @issue.update_done_ratio_from_issue_status
969 @issue.update_done_ratio_from_issue_status
968 @issue2.update_done_ratio_from_issue_status
970 @issue2.update_done_ratio_from_issue_status
969
971
970 assert_equal 50, @issue.read_attribute(:done_ratio)
972 assert_equal 50, @issue.read_attribute(:done_ratio)
971 assert_equal 0, @issue2.read_attribute(:done_ratio)
973 assert_equal 0, @issue2.read_attribute(:done_ratio)
972 end
974 end
973 end
975 end
974 end
976 end
975
977
976 test "#by_tracker" do
978 test "#by_tracker" do
977 User.current = User.anonymous
979 User.current = User.anonymous
978 groups = Issue.by_tracker(Project.find(1))
980 groups = Issue.by_tracker(Project.find(1))
979 assert_equal 3, groups.size
981 assert_equal 3, groups.size
980 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
982 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
981 end
983 end
982
984
983 test "#by_version" do
985 test "#by_version" do
984 User.current = User.anonymous
986 User.current = User.anonymous
985 groups = Issue.by_version(Project.find(1))
987 groups = Issue.by_version(Project.find(1))
986 assert_equal 3, groups.size
988 assert_equal 3, groups.size
987 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
989 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
988 end
990 end
989
991
990 test "#by_priority" do
992 test "#by_priority" do
991 User.current = User.anonymous
993 User.current = User.anonymous
992 groups = Issue.by_priority(Project.find(1))
994 groups = Issue.by_priority(Project.find(1))
993 assert_equal 4, groups.size
995 assert_equal 4, groups.size
994 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
996 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
995 end
997 end
996
998
997 test "#by_category" do
999 test "#by_category" do
998 User.current = User.anonymous
1000 User.current = User.anonymous
999 groups = Issue.by_category(Project.find(1))
1001 groups = Issue.by_category(Project.find(1))
1000 assert_equal 2, groups.size
1002 assert_equal 2, groups.size
1001 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1003 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1002 end
1004 end
1003
1005
1004 test "#by_assigned_to" do
1006 test "#by_assigned_to" do
1005 User.current = User.anonymous
1007 User.current = User.anonymous
1006 groups = Issue.by_assigned_to(Project.find(1))
1008 groups = Issue.by_assigned_to(Project.find(1))
1007 assert_equal 2, groups.size
1009 assert_equal 2, groups.size
1008 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1010 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1009 end
1011 end
1010
1012
1011 test "#by_author" do
1013 test "#by_author" do
1012 User.current = User.anonymous
1014 User.current = User.anonymous
1013 groups = Issue.by_author(Project.find(1))
1015 groups = Issue.by_author(Project.find(1))
1014 assert_equal 4, groups.size
1016 assert_equal 4, groups.size
1015 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1017 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1016 end
1018 end
1017
1019
1018 test "#by_subproject" do
1020 test "#by_subproject" do
1019 User.current = User.anonymous
1021 User.current = User.anonymous
1020 groups = Issue.by_subproject(Project.find(1))
1022 groups = Issue.by_subproject(Project.find(1))
1021 # Private descendant not visible
1023 # Private descendant not visible
1022 assert_equal 1, groups.size
1024 assert_equal 1, groups.size
1023 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1025 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1024 end
1026 end
1025
1027
1026 context ".allowed_target_projects_on_move" do
1028 context ".allowed_target_projects_on_move" do
1027 should "return all active projects for admin users" do
1029 should "return all active projects for admin users" do
1028 User.current = User.find(1)
1030 User.current = User.find(1)
1029 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1031 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1030 end
1032 end
1031
1033
1032 should "return allowed projects for non admin users" do
1034 should "return allowed projects for non admin users" do
1033 User.current = User.find(2)
1035 User.current = User.find(2)
1034 Role.non_member.remove_permission! :move_issues
1036 Role.non_member.remove_permission! :move_issues
1035 assert_equal 3, Issue.allowed_target_projects_on_move.size
1037 assert_equal 3, Issue.allowed_target_projects_on_move.size
1036
1038
1037 Role.non_member.add_permission! :move_issues
1039 Role.non_member.add_permission! :move_issues
1038 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1040 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
1039 end
1041 end
1040 end
1042 end
1041
1043
1042 def test_recently_updated_with_limit_scopes
1044 def test_recently_updated_with_limit_scopes
1043 #should return the last updated issue
1045 #should return the last updated issue
1044 assert_equal 1, Issue.recently_updated.with_limit(1).length
1046 assert_equal 1, Issue.recently_updated.with_limit(1).length
1045 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1047 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
1046 end
1048 end
1047
1049
1048 def test_on_active_projects_scope
1050 def test_on_active_projects_scope
1049 assert Project.find(2).archive
1051 assert Project.find(2).archive
1050
1052
1051 before = Issue.on_active_project.length
1053 before = Issue.on_active_project.length
1052 # test inclusion to results
1054 # test inclusion to results
1053 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1055 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
1054 assert_equal before + 1, Issue.on_active_project.length
1056 assert_equal before + 1, Issue.on_active_project.length
1055
1057
1056 # Move to an archived project
1058 # Move to an archived project
1057 issue.project = Project.find(2)
1059 issue.project = Project.find(2)
1058 assert issue.save
1060 assert issue.save
1059 assert_equal before, Issue.on_active_project.length
1061 assert_equal before, Issue.on_active_project.length
1060 end
1062 end
1061
1063
1062 context "Issue#recipients" do
1064 context "Issue#recipients" do
1063 setup do
1065 setup do
1064 @project = Project.find(1)
1066 @project = Project.find(1)
1065 @author = User.generate_with_protected!
1067 @author = User.generate_with_protected!
1066 @assignee = User.generate_with_protected!
1068 @assignee = User.generate_with_protected!
1067 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1069 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
1068 end
1070 end
1069
1071
1070 should "include project recipients" do
1072 should "include project recipients" do
1071 assert @project.recipients.present?
1073 assert @project.recipients.present?
1072 @project.recipients.each do |project_recipient|
1074 @project.recipients.each do |project_recipient|
1073 assert @issue.recipients.include?(project_recipient)
1075 assert @issue.recipients.include?(project_recipient)
1074 end
1076 end
1075 end
1077 end
1076
1078
1077 should "include the author if the author is active" do
1079 should "include the author if the author is active" do
1078 assert @issue.author, "No author set for Issue"
1080 assert @issue.author, "No author set for Issue"
1079 assert @issue.recipients.include?(@issue.author.mail)
1081 assert @issue.recipients.include?(@issue.author.mail)
1080 end
1082 end
1081
1083
1082 should "include the assigned to user if the assigned to user is active" do
1084 should "include the assigned to user if the assigned to user is active" do
1083 assert @issue.assigned_to, "No assigned_to set for Issue"
1085 assert @issue.assigned_to, "No assigned_to set for Issue"
1084 assert @issue.recipients.include?(@issue.assigned_to.mail)
1086 assert @issue.recipients.include?(@issue.assigned_to.mail)
1085 end
1087 end
1086
1088
1087 should "not include users who opt out of all email" do
1089 should "not include users who opt out of all email" do
1088 @author.update_attribute(:mail_notification, :none)
1090 @author.update_attribute(:mail_notification, :none)
1089
1091
1090 assert !@issue.recipients.include?(@issue.author.mail)
1092 assert !@issue.recipients.include?(@issue.author.mail)
1091 end
1093 end
1092
1094
1093 should "not include the issue author if they are only notified of assigned issues" do
1095 should "not include the issue author if they are only notified of assigned issues" do
1094 @author.update_attribute(:mail_notification, :only_assigned)
1096 @author.update_attribute(:mail_notification, :only_assigned)
1095
1097
1096 assert !@issue.recipients.include?(@issue.author.mail)
1098 assert !@issue.recipients.include?(@issue.author.mail)
1097 end
1099 end
1098
1100
1099 should "not include the assigned user if they are only notified of owned issues" do
1101 should "not include the assigned user if they are only notified of owned issues" do
1100 @assignee.update_attribute(:mail_notification, :only_owner)
1102 @assignee.update_attribute(:mail_notification, :only_owner)
1101
1103
1102 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1104 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1103 end
1105 end
1104
1106
1105 end
1107 end
1106 end
1108 end
General Comments 0
You need to be logged in to leave comments. Login now