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