##// END OF EJS Templates
Merged r9700 from trunk....
Jean-Philippe Lang -
r9521:7cd7b1bd8b99
parent child
Show More
@@ -1,76 +1,80
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2012 Jean-Philippe Lang
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; either version 2
9 9 # of the License, or (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 20 module WatchersHelper
21 21
22 22 def watcher_tag(object, user, options={})
23 23 content_tag("span", watcher_link(object, user), :class => watcher_css(object))
24 24 end
25 25
26 26 def watcher_link(object, user)
27 27 return '' unless user && user.logged? && object.respond_to?('watched_by?')
28 28 watched = object.watched_by?(user)
29 29 url = {:controller => 'watchers',
30 30 :action => (watched ? 'unwatch' : 'watch'),
31 31 :object_type => object.class.to_s.underscore,
32 32 :object_id => object.id}
33 33 link_to_remote((watched ? l(:button_unwatch) : l(:button_watch)),
34 34 {:url => url},
35 35 :href => url_for(url),
36 36 :class => (watched ? 'icon icon-fav' : 'icon icon-fav-off'))
37 37
38 38 end
39 39
40 40 # Returns the css class used to identify watch links for a given +object+
41 41 def watcher_css(object)
42 42 "#{object.class.to_s.underscore}-#{object.id}-watcher"
43 43 end
44 44
45 45 # Returns a comma separated list of users watching the given object
46 46 def watchers_list(object)
47 47 remove_allowed = User.current.allowed_to?("delete_#{object.class.name.underscore}_watchers".to_sym, object.project)
48 content = ''.html_safe
48 49 lis = object.watcher_users.collect do |user|
49 s = avatar(user, :size => "16").to_s + link_to_user(user, :class => 'user').to_s
50 s = ''.html_safe
51 s << avatar(user, :size => "16").to_s
52 s << link_to_user(user, :class => 'user')
50 53 if remove_allowed
51 54 url = {:controller => 'watchers',
52 55 :action => 'destroy',
53 56 :object_type => object.class.to_s.underscore,
54 57 :object_id => object.id,
55 58 :user_id => user}
56 s += ' ' + link_to_remote(image_tag('delete.png'),
59 s << ' '
60 s << link_to_remote(image_tag('delete.png'),
57 61 {:url => url},
58 62 :href => url_for(url),
59 63 :style => "vertical-align: middle",
60 64 :class => "delete")
61 65 end
62 content_tag :li, s.html_safe
66 content << content_tag('li', s)
63 67 end
64 (lis.empty? ? "" : "<ul>#{ lis.join("\n") }</ul>").html_safe
68 content.present? ? content_tag('ul', content) : content
65 69 end
66 70
67 71 def watchers_checkboxes(object, users, checked=nil)
68 72 users.map do |user|
69 73 c = checked.nil? ? object.watched_by?(user) : checked
70 74 tag = check_box_tag 'issue[watcher_user_ids][]', user.id, c, :id => nil
71 75 content_tag 'label', "#{tag} #{h(user)}".html_safe,
72 76 :id => "issue_watcher_user_ids_#{user.id}",
73 77 :class => "floating"
74 78 end.join.html_safe
75 79 end
76 80 end
@@ -1,3328 +1,3358
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19 require 'issues_controller'
20 20
21 21 class IssuesControllerTest < ActionController::TestCase
22 22 fixtures :projects,
23 23 :users,
24 24 :roles,
25 25 :members,
26 26 :member_roles,
27 27 :issues,
28 28 :issue_statuses,
29 29 :versions,
30 30 :trackers,
31 31 :projects_trackers,
32 32 :issue_categories,
33 33 :enabled_modules,
34 34 :enumerations,
35 35 :attachments,
36 36 :workflows,
37 37 :custom_fields,
38 38 :custom_values,
39 39 :custom_fields_projects,
40 40 :custom_fields_trackers,
41 41 :time_entries,
42 42 :journals,
43 43 :journal_details,
44 44 :queries,
45 45 :repositories,
46 46 :changesets
47 47
48 48 include Redmine::I18n
49 49
50 50 def setup
51 51 @controller = IssuesController.new
52 52 @request = ActionController::TestRequest.new
53 53 @response = ActionController::TestResponse.new
54 54 User.current = nil
55 55 end
56 56
57 57 def test_index
58 58 with_settings :default_language => "en" do
59 59 get :index
60 60 assert_response :success
61 61 assert_template 'index'
62 62 assert_not_nil assigns(:issues)
63 63 assert_nil assigns(:project)
64 64 assert_tag :tag => 'a', :content => /Can't print recipes/
65 65 assert_tag :tag => 'a', :content => /Subproject issue/
66 66 # private projects hidden
67 67 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
68 68 assert_no_tag :tag => 'a', :content => /Issue on project 2/
69 69 # project column
70 70 assert_tag :tag => 'th', :content => /Project/
71 71 end
72 72 end
73 73
74 74 def test_index_should_not_list_issues_when_module_disabled
75 75 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
76 76 get :index
77 77 assert_response :success
78 78 assert_template 'index'
79 79 assert_not_nil assigns(:issues)
80 80 assert_nil assigns(:project)
81 81 assert_no_tag :tag => 'a', :content => /Can't print recipes/
82 82 assert_tag :tag => 'a', :content => /Subproject issue/
83 83 end
84 84
85 85 def test_index_should_list_visible_issues_only
86 86 get :index, :per_page => 100
87 87 assert_response :success
88 88 assert_not_nil assigns(:issues)
89 89 assert_nil assigns(:issues).detect {|issue| !issue.visible?}
90 90 end
91 91
92 92 def test_index_with_project
93 93 Setting.display_subprojects_issues = 0
94 94 get :index, :project_id => 1
95 95 assert_response :success
96 96 assert_template 'index'
97 97 assert_not_nil assigns(:issues)
98 98 assert_tag :tag => 'a', :content => /Can't print recipes/
99 99 assert_no_tag :tag => 'a', :content => /Subproject issue/
100 100 end
101 101
102 102 def test_index_with_project_and_subprojects
103 103 Setting.display_subprojects_issues = 1
104 104 get :index, :project_id => 1
105 105 assert_response :success
106 106 assert_template 'index'
107 107 assert_not_nil assigns(:issues)
108 108 assert_tag :tag => 'a', :content => /Can't print recipes/
109 109 assert_tag :tag => 'a', :content => /Subproject issue/
110 110 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
111 111 end
112 112
113 113 def test_index_with_project_and_subprojects_should_show_private_subprojects
114 114 @request.session[:user_id] = 2
115 115 Setting.display_subprojects_issues = 1
116 116 get :index, :project_id => 1
117 117 assert_response :success
118 118 assert_template 'index'
119 119 assert_not_nil assigns(:issues)
120 120 assert_tag :tag => 'a', :content => /Can't print recipes/
121 121 assert_tag :tag => 'a', :content => /Subproject issue/
122 122 assert_tag :tag => 'a', :content => /Issue of a private subproject/
123 123 end
124 124
125 125 def test_index_with_project_and_default_filter
126 126 get :index, :project_id => 1, :set_filter => 1
127 127 assert_response :success
128 128 assert_template 'index'
129 129 assert_not_nil assigns(:issues)
130 130
131 131 query = assigns(:query)
132 132 assert_not_nil query
133 133 # default filter
134 134 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
135 135 end
136 136
137 137 def test_index_with_project_and_filter
138 138 get :index, :project_id => 1, :set_filter => 1,
139 139 :f => ['tracker_id'],
140 140 :op => {'tracker_id' => '='},
141 141 :v => {'tracker_id' => ['1']}
142 142 assert_response :success
143 143 assert_template 'index'
144 144 assert_not_nil assigns(:issues)
145 145
146 146 query = assigns(:query)
147 147 assert_not_nil query
148 148 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
149 149 end
150 150
151 151 def test_index_with_short_filters
152 152 to_test = {
153 153 'status_id' => {
154 154 'o' => { :op => 'o', :values => [''] },
155 155 'c' => { :op => 'c', :values => [''] },
156 156 '7' => { :op => '=', :values => ['7'] },
157 157 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
158 158 '=7' => { :op => '=', :values => ['7'] },
159 159 '!3' => { :op => '!', :values => ['3'] },
160 160 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
161 161 'subject' => {
162 162 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
163 163 'o' => { :op => '=', :values => ['o'] },
164 164 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
165 165 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
166 166 'tracker_id' => {
167 167 '3' => { :op => '=', :values => ['3'] },
168 168 '=3' => { :op => '=', :values => ['3'] }},
169 169 'start_date' => {
170 170 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
171 171 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
172 172 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
173 173 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
174 174 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
175 175 '<t+2' => { :op => '<t+', :values => ['2'] },
176 176 '>t+2' => { :op => '>t+', :values => ['2'] },
177 177 't+2' => { :op => 't+', :values => ['2'] },
178 178 't' => { :op => 't', :values => [''] },
179 179 'w' => { :op => 'w', :values => [''] },
180 180 '>t-2' => { :op => '>t-', :values => ['2'] },
181 181 '<t-2' => { :op => '<t-', :values => ['2'] },
182 182 't-2' => { :op => 't-', :values => ['2'] }},
183 183 'created_on' => {
184 184 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
185 185 '<t-2' => { :op => '<t-', :values => ['2'] },
186 186 '>t-2' => { :op => '>t-', :values => ['2'] },
187 187 't-2' => { :op => 't-', :values => ['2'] }},
188 188 'cf_1' => {
189 189 'c' => { :op => '=', :values => ['c'] },
190 190 '!c' => { :op => '!', :values => ['c'] },
191 191 '!*' => { :op => '!*', :values => [''] },
192 192 '*' => { :op => '*', :values => [''] }},
193 193 'estimated_hours' => {
194 194 '=13.4' => { :op => '=', :values => ['13.4'] },
195 195 '>=45' => { :op => '>=', :values => ['45'] },
196 196 '<=125' => { :op => '<=', :values => ['125'] },
197 197 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
198 198 '!*' => { :op => '!*', :values => [''] },
199 199 '*' => { :op => '*', :values => [''] }}
200 200 }
201 201
202 202 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
203 203
204 204 to_test.each do |field, expression_and_expected|
205 205 expression_and_expected.each do |filter_expression, expected|
206 206
207 207 get :index, :set_filter => 1, field => filter_expression
208 208
209 209 assert_response :success
210 210 assert_template 'index'
211 211 assert_not_nil assigns(:issues)
212 212
213 213 query = assigns(:query)
214 214 assert_not_nil query
215 215 assert query.has_filter?(field)
216 216 assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
217 217 end
218 218 end
219 219 end
220 220
221 221 def test_index_with_project_and_empty_filters
222 222 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
223 223 assert_response :success
224 224 assert_template 'index'
225 225 assert_not_nil assigns(:issues)
226 226
227 227 query = assigns(:query)
228 228 assert_not_nil query
229 229 # no filter
230 230 assert_equal({}, query.filters)
231 231 end
232 232
233 233 def test_index_with_query
234 234 get :index, :project_id => 1, :query_id => 5
235 235 assert_response :success
236 236 assert_template 'index'
237 237 assert_not_nil assigns(:issues)
238 238 assert_nil assigns(:issue_count_by_group)
239 239 end
240 240
241 241 def test_index_with_query_grouped_by_tracker
242 242 get :index, :project_id => 1, :query_id => 6
243 243 assert_response :success
244 244 assert_template 'index'
245 245 assert_not_nil assigns(:issues)
246 246 assert_not_nil assigns(:issue_count_by_group)
247 247 end
248 248
249 249 def test_index_with_query_grouped_by_list_custom_field
250 250 get :index, :project_id => 1, :query_id => 9
251 251 assert_response :success
252 252 assert_template 'index'
253 253 assert_not_nil assigns(:issues)
254 254 assert_not_nil assigns(:issue_count_by_group)
255 255 end
256 256
257 257 def test_index_with_query_id_and_project_id_should_set_session_query
258 258 get :index, :project_id => 1, :query_id => 4
259 259 assert_response :success
260 260 assert_kind_of Hash, session[:query]
261 261 assert_equal 4, session[:query][:id]
262 262 assert_equal 1, session[:query][:project_id]
263 263 end
264 264
265 265 def test_index_with_invalid_query_id_should_respond_404
266 266 get :index, :project_id => 1, :query_id => 999
267 267 assert_response 404
268 268 end
269 269
270 270 def test_index_with_cross_project_query_in_session_should_show_project_issues
271 271 q = Query.create!(:name => "test", :user_id => 2, :is_public => false, :project => nil)
272 272 @request.session[:query] = {:id => q.id, :project_id => 1}
273 273
274 274 with_settings :display_subprojects_issues => '0' do
275 275 get :index, :project_id => 1
276 276 end
277 277 assert_response :success
278 278 assert_not_nil assigns(:query)
279 279 assert_equal q.id, assigns(:query).id
280 280 assert_equal 1, assigns(:query).project_id
281 281 assert_equal [1], assigns(:issues).map(&:project_id).uniq
282 282 end
283 283
284 284 def test_private_query_should_not_be_available_to_other_users
285 285 q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
286 286 @request.session[:user_id] = 3
287 287
288 288 get :index, :query_id => q.id
289 289 assert_response 403
290 290 end
291 291
292 292 def test_private_query_should_be_available_to_its_user
293 293 q = Query.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
294 294 @request.session[:user_id] = 2
295 295
296 296 get :index, :query_id => q.id
297 297 assert_response :success
298 298 end
299 299
300 300 def test_public_query_should_be_available_to_other_users
301 301 q = Query.create!(:name => "private", :user => User.find(2), :is_public => true, :project => nil)
302 302 @request.session[:user_id] = 3
303 303
304 304 get :index, :query_id => q.id
305 305 assert_response :success
306 306 end
307 307
308 308 def test_index_should_omit_page_param_in_export_links
309 309 get :index, :page => 2
310 310 assert_response :success
311 311 assert_select 'a.atom[href=/issues.atom]'
312 312 assert_select 'a.csv[href=/issues.csv]'
313 313 assert_select 'a.pdf[href=/issues.pdf]'
314 314 assert_select 'form#csv-export-form[action=/issues.csv]'
315 315 end
316 316
317 317 def test_index_csv
318 318 get :index, :format => 'csv'
319 319 assert_response :success
320 320 assert_not_nil assigns(:issues)
321 321 assert_equal 'text/csv; header=present', @response.content_type
322 322 assert @response.body.starts_with?("#,")
323 323 lines = @response.body.chomp.split("\n")
324 324 assert_equal assigns(:query).columns.size + 1, lines[0].split(',').size
325 325 end
326 326
327 327 def test_index_csv_with_project
328 328 get :index, :project_id => 1, :format => 'csv'
329 329 assert_response :success
330 330 assert_not_nil assigns(:issues)
331 331 assert_equal 'text/csv; header=present', @response.content_type
332 332 end
333 333
334 334 def test_index_csv_with_description
335 335 get :index, :format => 'csv', :description => '1'
336 336 assert_response :success
337 337 assert_not_nil assigns(:issues)
338 338 assert_equal 'text/csv; header=present', @response.content_type
339 339 assert @response.body.starts_with?("#,")
340 340 lines = @response.body.chomp.split("\n")
341 341 assert_equal assigns(:query).columns.size + 2, lines[0].split(',').size
342 342 end
343 343
344 344 def test_index_csv_with_spent_time_column
345 345 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
346 346 TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
347 347
348 348 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
349 349 assert_response :success
350 350 assert_equal 'text/csv; header=present', @response.content_type
351 351 lines = @response.body.chomp.split("\n")
352 352 assert_include "#{issue.id},#{issue.subject},7.33", lines
353 353 end
354 354
355 355 def test_index_csv_with_all_columns
356 356 get :index, :format => 'csv', :columns => 'all'
357 357 assert_response :success
358 358 assert_not_nil assigns(:issues)
359 359 assert_equal 'text/csv; header=present', @response.content_type
360 360 assert @response.body.starts_with?("#,")
361 361 lines = @response.body.chomp.split("\n")
362 362 assert_equal assigns(:query).available_columns.size + 1, lines[0].split(',').size
363 363 end
364 364
365 365 def test_index_csv_with_multi_column_field
366 366 CustomField.find(1).update_attribute :multiple, true
367 367 issue = Issue.find(1)
368 368 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
369 369 issue.save!
370 370
371 371 get :index, :format => 'csv', :columns => 'all'
372 372 assert_response :success
373 373 lines = @response.body.chomp.split("\n")
374 374 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
375 375 end
376 376
377 377 def test_index_csv_big_5
378 378 with_settings :default_language => "zh-TW" do
379 379 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
380 380 str_big5 = "\xa4@\xa4\xeb"
381 381 if str_utf8.respond_to?(:force_encoding)
382 382 str_utf8.force_encoding('UTF-8')
383 383 str_big5.force_encoding('Big5')
384 384 end
385 385 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
386 386 :status_id => 1, :priority => IssuePriority.all.first,
387 387 :subject => str_utf8)
388 388 assert issue.save
389 389
390 390 get :index, :project_id => 1,
391 391 :f => ['subject'],
392 392 :op => '=', :values => [str_utf8],
393 393 :format => 'csv'
394 394 assert_equal 'text/csv; header=present', @response.content_type
395 395 lines = @response.body.chomp.split("\n")
396 396 s1 = "\xaa\xac\xbaA"
397 397 if str_utf8.respond_to?(:force_encoding)
398 398 s1.force_encoding('Big5')
399 399 end
400 400 assert lines[0].include?(s1)
401 401 assert lines[1].include?(str_big5)
402 402 end
403 403 end
404 404
405 405 def test_index_csv_cannot_convert_should_be_replaced_big_5
406 406 with_settings :default_language => "zh-TW" do
407 407 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
408 408 if str_utf8.respond_to?(:force_encoding)
409 409 str_utf8.force_encoding('UTF-8')
410 410 end
411 411 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
412 412 :status_id => 1, :priority => IssuePriority.all.first,
413 413 :subject => str_utf8)
414 414 assert issue.save
415 415
416 416 get :index, :project_id => 1,
417 417 :f => ['subject'],
418 418 :op => '=', :values => [str_utf8],
419 419 :c => ['status', 'subject'],
420 420 :format => 'csv',
421 421 :set_filter => 1
422 422 assert_equal 'text/csv; header=present', @response.content_type
423 423 lines = @response.body.chomp.split("\n")
424 424 s1 = "\xaa\xac\xbaA" # status
425 425 if str_utf8.respond_to?(:force_encoding)
426 426 s1.force_encoding('Big5')
427 427 end
428 428 assert lines[0].include?(s1)
429 429 s2 = lines[1].split(",")[2]
430 430 if s1.respond_to?(:force_encoding)
431 431 s3 = "\xa5H?" # subject
432 432 s3.force_encoding('Big5')
433 433 assert_equal s3, s2
434 434 elsif RUBY_PLATFORM == 'java'
435 435 assert_equal "??", s2
436 436 else
437 437 assert_equal "\xa5H???", s2
438 438 end
439 439 end
440 440 end
441 441
442 442 def test_index_csv_tw
443 443 with_settings :default_language => "zh-TW" do
444 444 str1 = "test_index_csv_tw"
445 445 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
446 446 :status_id => 1, :priority => IssuePriority.all.first,
447 447 :subject => str1, :estimated_hours => '1234.5')
448 448 assert issue.save
449 449 assert_equal 1234.5, issue.estimated_hours
450 450
451 451 get :index, :project_id => 1,
452 452 :f => ['subject'],
453 453 :op => '=', :values => [str1],
454 454 :c => ['estimated_hours', 'subject'],
455 455 :format => 'csv',
456 456 :set_filter => 1
457 457 assert_equal 'text/csv; header=present', @response.content_type
458 458 lines = @response.body.chomp.split("\n")
459 459 assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
460 460
461 461 str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)"
462 462 if str_tw.respond_to?(:force_encoding)
463 463 str_tw.force_encoding('UTF-8')
464 464 end
465 465 assert_equal str_tw, l(:general_lang_name)
466 466 assert_equal ',', l(:general_csv_separator)
467 467 assert_equal '.', l(:general_csv_decimal_separator)
468 468 end
469 469 end
470 470
471 471 def test_index_csv_fr
472 472 with_settings :default_language => "fr" do
473 473 str1 = "test_index_csv_fr"
474 474 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
475 475 :status_id => 1, :priority => IssuePriority.all.first,
476 476 :subject => str1, :estimated_hours => '1234.5')
477 477 assert issue.save
478 478 assert_equal 1234.5, issue.estimated_hours
479 479
480 480 get :index, :project_id => 1,
481 481 :f => ['subject'],
482 482 :op => '=', :values => [str1],
483 483 :c => ['estimated_hours', 'subject'],
484 484 :format => 'csv',
485 485 :set_filter => 1
486 486 assert_equal 'text/csv; header=present', @response.content_type
487 487 lines = @response.body.chomp.split("\n")
488 488 assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
489 489
490 490 str_fr = "Fran\xc3\xa7ais"
491 491 if str_fr.respond_to?(:force_encoding)
492 492 str_fr.force_encoding('UTF-8')
493 493 end
494 494 assert_equal str_fr, l(:general_lang_name)
495 495 assert_equal ';', l(:general_csv_separator)
496 496 assert_equal ',', l(:general_csv_decimal_separator)
497 497 end
498 498 end
499 499
500 500 def test_index_pdf
501 501 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
502 502 with_settings :default_language => lang do
503 503
504 504 get :index
505 505 assert_response :success
506 506 assert_template 'index'
507 507
508 508 if lang == "ja"
509 509 if RUBY_PLATFORM != 'java'
510 510 assert_equal "CP932", l(:general_pdf_encoding)
511 511 end
512 512 if RUBY_PLATFORM == 'java' && l(:general_pdf_encoding) == "CP932"
513 513 next
514 514 end
515 515 end
516 516
517 517 get :index, :format => 'pdf'
518 518 assert_response :success
519 519 assert_not_nil assigns(:issues)
520 520 assert_equal 'application/pdf', @response.content_type
521 521
522 522 get :index, :project_id => 1, :format => 'pdf'
523 523 assert_response :success
524 524 assert_not_nil assigns(:issues)
525 525 assert_equal 'application/pdf', @response.content_type
526 526
527 527 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
528 528 assert_response :success
529 529 assert_not_nil assigns(:issues)
530 530 assert_equal 'application/pdf', @response.content_type
531 531 end
532 532 end
533 533 end
534 534
535 535 def test_index_pdf_with_query_grouped_by_list_custom_field
536 536 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
537 537 assert_response :success
538 538 assert_not_nil assigns(:issues)
539 539 assert_not_nil assigns(:issue_count_by_group)
540 540 assert_equal 'application/pdf', @response.content_type
541 541 end
542 542
543 543 def test_index_atom
544 544 get :index, :project_id => 'ecookbook', :format => 'atom'
545 545 assert_response :success
546 546 assert_template 'common/feed'
547 547
548 548 assert_tag :tag => 'link', :parent => {:tag => 'feed', :parent => nil },
549 549 :attributes => {:rel => 'self', :href => 'http://test.host/projects/ecookbook/issues.atom'}
550 550 assert_tag :tag => 'link', :parent => {:tag => 'feed', :parent => nil },
551 551 :attributes => {:rel => 'alternate', :href => 'http://test.host/projects/ecookbook/issues'}
552 552
553 553 assert_tag :tag => 'entry', :child => {
554 554 :tag => 'link',
555 555 :attributes => {:href => 'http://test.host/issues/1'}}
556 556 end
557 557
558 558 def test_index_sort
559 559 get :index, :sort => 'tracker,id:desc'
560 560 assert_response :success
561 561
562 562 sort_params = @request.session['issues_index_sort']
563 563 assert sort_params.is_a?(String)
564 564 assert_equal 'tracker,id:desc', sort_params
565 565
566 566 issues = assigns(:issues)
567 567 assert_not_nil issues
568 568 assert !issues.empty?
569 569 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
570 570 end
571 571
572 572 def test_index_sort_by_field_not_included_in_columns
573 573 Setting.issue_list_default_columns = %w(subject author)
574 574 get :index, :sort => 'tracker'
575 575 end
576 576
577 577 def test_index_sort_by_assigned_to
578 578 get :index, :sort => 'assigned_to'
579 579 assert_response :success
580 580 assignees = assigns(:issues).collect(&:assigned_to).compact
581 581 assert_equal assignees.sort, assignees
582 582 end
583 583
584 584 def test_index_sort_by_assigned_to_desc
585 585 get :index, :sort => 'assigned_to:desc'
586 586 assert_response :success
587 587 assignees = assigns(:issues).collect(&:assigned_to).compact
588 588 assert_equal assignees.sort.reverse, assignees
589 589 end
590 590
591 591 def test_index_group_by_assigned_to
592 592 get :index, :group_by => 'assigned_to', :sort => 'priority'
593 593 assert_response :success
594 594 end
595 595
596 596 def test_index_sort_by_author
597 597 get :index, :sort => 'author'
598 598 assert_response :success
599 599 authors = assigns(:issues).collect(&:author)
600 600 assert_equal authors.sort, authors
601 601 end
602 602
603 603 def test_index_sort_by_author_desc
604 604 get :index, :sort => 'author:desc'
605 605 assert_response :success
606 606 authors = assigns(:issues).collect(&:author)
607 607 assert_equal authors.sort.reverse, authors
608 608 end
609 609
610 610 def test_index_group_by_author
611 611 get :index, :group_by => 'author', :sort => 'priority'
612 612 assert_response :success
613 613 end
614 614
615 615 def test_index_sort_by_spent_hours
616 616 get :index, :sort => 'spent_hours:desc'
617 617 assert_response :success
618 618 hours = assigns(:issues).collect(&:spent_hours)
619 619 assert_equal hours.sort.reverse, hours
620 620 end
621 621
622 622 def test_index_with_columns
623 623 columns = ['tracker', 'subject', 'assigned_to']
624 624 get :index, :set_filter => 1, :c => columns
625 625 assert_response :success
626 626
627 627 # query should use specified columns
628 628 query = assigns(:query)
629 629 assert_kind_of Query, query
630 630 assert_equal columns, query.column_names.map(&:to_s)
631 631
632 632 # columns should be stored in session
633 633 assert_kind_of Hash, session[:query]
634 634 assert_kind_of Array, session[:query][:column_names]
635 635 assert_equal columns, session[:query][:column_names].map(&:to_s)
636 636
637 637 # ensure only these columns are kept in the selected columns list
638 638 assert_tag :tag => 'select', :attributes => { :id => 'selected_columns' },
639 639 :children => { :count => 3 }
640 640 assert_no_tag :tag => 'option', :attributes => { :value => 'project' },
641 641 :parent => { :tag => 'select', :attributes => { :id => "selected_columns" } }
642 642 end
643 643
644 644 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
645 645 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
646 646 get :index, :set_filter => 1
647 647
648 648 # query should use specified columns
649 649 query = assigns(:query)
650 650 assert_kind_of Query, query
651 651 assert_equal [:project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
652 652 end
653 653
654 654 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
655 655 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
656 656 columns = ['tracker', 'subject', 'assigned_to']
657 657 get :index, :set_filter => 1, :c => columns
658 658
659 659 # query should use specified columns
660 660 query = assigns(:query)
661 661 assert_kind_of Query, query
662 662 assert_equal columns.map(&:to_sym), query.columns.map(&:name)
663 663 end
664 664
665 665 def test_index_with_custom_field_column
666 666 columns = %w(tracker subject cf_2)
667 667 get :index, :set_filter => 1, :c => columns
668 668 assert_response :success
669 669
670 670 # query should use specified columns
671 671 query = assigns(:query)
672 672 assert_kind_of Query, query
673 673 assert_equal columns, query.column_names.map(&:to_s)
674 674
675 675 assert_tag :td,
676 676 :attributes => {:class => 'cf_2 string'},
677 677 :ancestor => {:tag => 'table', :attributes => {:class => /issues/}}
678 678 end
679 679
680 680 def test_index_with_multi_custom_field_column
681 681 field = CustomField.find(1)
682 682 field.update_attribute :multiple, true
683 683 issue = Issue.find(1)
684 684 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
685 685 issue.save!
686 686
687 687 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
688 688 assert_response :success
689 689
690 690 assert_tag :td,
691 691 :attributes => {:class => /cf_1/},
692 692 :content => 'MySQL, Oracle'
693 693 end
694 694
695 695 def test_index_with_multi_user_custom_field_column
696 696 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
697 697 :tracker_ids => [1], :is_for_all => true)
698 698 issue = Issue.find(1)
699 699 issue.custom_field_values = {field.id => ['2', '3']}
700 700 issue.save!
701 701
702 702 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
703 703 assert_response :success
704 704
705 705 assert_tag :td,
706 706 :attributes => {:class => /cf_#{field.id}/},
707 707 :child => {:tag => 'a', :content => 'John Smith'}
708 708 end
709 709
710 710 def test_index_with_date_column
711 711 Issue.find(1).update_attribute :start_date, '1987-08-24'
712 712
713 713 with_settings :date_format => '%d/%m/%Y' do
714 714 get :index, :set_filter => 1, :c => %w(start_date)
715 715 assert_tag 'td', :attributes => {:class => /start_date/}, :content => '24/08/1987'
716 716 end
717 717 end
718 718
719 719 def test_index_with_done_ratio
720 720 Issue.find(1).update_attribute :done_ratio, 40
721 721
722 722 get :index, :set_filter => 1, :c => %w(done_ratio)
723 723 assert_tag 'td', :attributes => {:class => /done_ratio/},
724 724 :child => {:tag => 'table', :attributes => {:class => 'progress'},
725 725 :descendant => {:tag => 'td', :attributes => {:class => 'closed', :style => 'width: 40%;'}}
726 726 }
727 727 end
728 728
729 729 def test_index_with_spent_hours_column
730 730 get :index, :set_filter => 1, :c => %w(subject spent_hours)
731 731
732 732 assert_tag 'tr', :attributes => {:id => 'issue-3'},
733 733 :child => {
734 734 :tag => 'td', :attributes => {:class => /spent_hours/}, :content => '1.00'
735 735 }
736 736 end
737 737
738 738 def test_index_should_not_show_spent_hours_column_without_permission
739 739 Role.anonymous.remove_permission! :view_time_entries
740 740 get :index, :set_filter => 1, :c => %w(subject spent_hours)
741 741
742 742 assert_no_tag 'td', :attributes => {:class => /spent_hours/}
743 743 end
744 744
745 745 def test_index_with_fixed_version
746 746 get :index, :set_filter => 1, :c => %w(fixed_version)
747 747 assert_tag 'td', :attributes => {:class => /fixed_version/},
748 748 :child => {:tag => 'a', :content => '1.0', :attributes => {:href => '/versions/2'}}
749 749 end
750 750
751 751 def test_index_send_html_if_query_is_invalid
752 752 get :index, :f => ['start_date'], :op => {:start_date => '='}
753 753 assert_equal 'text/html', @response.content_type
754 754 assert_template 'index'
755 755 end
756 756
757 757 def test_index_send_nothing_if_query_is_invalid
758 758 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
759 759 assert_equal 'text/csv', @response.content_type
760 760 assert @response.body.blank?
761 761 end
762 762
763 763 def test_show_by_anonymous
764 764 get :show, :id => 1
765 765 assert_response :success
766 766 assert_template 'show'
767 767 assert_not_nil assigns(:issue)
768 768 assert_equal Issue.find(1), assigns(:issue)
769 769
770 770 # anonymous role is allowed to add a note
771 771 assert_tag :tag => 'form',
772 772 :descendant => { :tag => 'fieldset',
773 773 :child => { :tag => 'legend',
774 774 :content => /Notes/ } }
775 775 assert_tag :tag => 'title',
776 776 :content => "Bug #1: Can't print recipes - eCookbook - Redmine"
777 777 end
778 778
779 779 def test_show_by_manager
780 780 @request.session[:user_id] = 2
781 781 get :show, :id => 1
782 782 assert_response :success
783 783
784 784 assert_tag :tag => 'a',
785 785 :content => /Quote/
786 786
787 787 assert_tag :tag => 'form',
788 788 :descendant => { :tag => 'fieldset',
789 789 :child => { :tag => 'legend',
790 790 :content => /Change properties/ } },
791 791 :descendant => { :tag => 'fieldset',
792 792 :child => { :tag => 'legend',
793 793 :content => /Log time/ } },
794 794 :descendant => { :tag => 'fieldset',
795 795 :child => { :tag => 'legend',
796 796 :content => /Notes/ } }
797 797 end
798 798
799 799 def test_show_should_display_update_form
800 800 @request.session[:user_id] = 2
801 801 get :show, :id => 1
802 802 assert_response :success
803 803
804 804 assert_tag 'form', :attributes => {:id => 'issue-form'}
805 805 assert_tag 'input', :attributes => {:name => 'issue[is_private]'}
806 806 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
807 807 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
808 808 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
809 809 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
810 810 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
811 811 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
812 812 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
813 813 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
814 814 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
815 815 assert_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
816 816 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
817 817 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
818 818 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
819 819 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
820 820 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
821 821 assert_tag 'textarea', :attributes => {:name => 'notes'}
822 822 end
823 823
824 824 def test_show_should_display_update_form_with_minimal_permissions
825 825 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
826 826 Workflow.delete_all :role_id => 1
827 827
828 828 @request.session[:user_id] = 2
829 829 get :show, :id => 1
830 830 assert_response :success
831 831
832 832 assert_tag 'form', :attributes => {:id => 'issue-form'}
833 833 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
834 834 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
835 835 assert_no_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
836 836 assert_no_tag 'input', :attributes => {:name => 'issue[subject]'}
837 837 assert_no_tag 'textarea', :attributes => {:name => 'issue[description]'}
838 838 assert_no_tag 'select', :attributes => {:name => 'issue[status_id]'}
839 839 assert_no_tag 'select', :attributes => {:name => 'issue[priority_id]'}
840 840 assert_no_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
841 841 assert_no_tag 'select', :attributes => {:name => 'issue[category_id]'}
842 842 assert_no_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
843 843 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
844 844 assert_no_tag 'input', :attributes => {:name => 'issue[start_date]'}
845 845 assert_no_tag 'input', :attributes => {:name => 'issue[due_date]'}
846 846 assert_no_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
847 847 assert_no_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
848 848 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
849 849 assert_tag 'textarea', :attributes => {:name => 'notes'}
850 850 end
851 851
852 852 def test_show_should_display_update_form_with_workflow_permissions
853 853 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
854 854
855 855 @request.session[:user_id] = 2
856 856 get :show, :id => 1
857 857 assert_response :success
858 858
859 859 assert_tag 'form', :attributes => {:id => 'issue-form'}
860 860 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
861 861 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
862 862 assert_no_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
863 863 assert_no_tag 'input', :attributes => {:name => 'issue[subject]'}
864 864 assert_no_tag 'textarea', :attributes => {:name => 'issue[description]'}
865 865 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
866 866 assert_no_tag 'select', :attributes => {:name => 'issue[priority_id]'}
867 867 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
868 868 assert_no_tag 'select', :attributes => {:name => 'issue[category_id]'}
869 869 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
870 870 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
871 871 assert_no_tag 'input', :attributes => {:name => 'issue[start_date]'}
872 872 assert_no_tag 'input', :attributes => {:name => 'issue[due_date]'}
873 873 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
874 874 assert_no_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]' }
875 875 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
876 876 assert_tag 'textarea', :attributes => {:name => 'notes'}
877 877 end
878 878
879 879 def test_show_should_not_display_update_form_without_permissions
880 880 Role.find(1).update_attribute :permissions, [:view_issues]
881 881
882 882 @request.session[:user_id] = 2
883 883 get :show, :id => 1
884 884 assert_response :success
885 885
886 886 assert_no_tag 'form', :attributes => {:id => 'issue-form'}
887 887 end
888 888
889 889 def test_update_form_should_not_display_inactive_enumerations
890 890 @request.session[:user_id] = 2
891 891 get :show, :id => 1
892 892 assert_response :success
893 893
894 894 assert ! IssuePriority.find(15).active?
895 895 assert_no_tag :option, :attributes => {:value => '15'},
896 896 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
897 897 end
898 898
899 899 def test_update_form_should_allow_attachment_upload
900 900 @request.session[:user_id] = 2
901 901 get :show, :id => 1
902 902
903 903 assert_tag :tag => 'form',
904 904 :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'},
905 905 :descendant => {
906 906 :tag => 'input',
907 907 :attributes => {:type => 'file', :name => 'attachments[1][file]'}
908 908 }
909 909 end
910 910
911 911 def test_show_should_deny_anonymous_access_without_permission
912 912 Role.anonymous.remove_permission!(:view_issues)
913 913 get :show, :id => 1
914 914 assert_response :redirect
915 915 end
916 916
917 917 def test_show_should_deny_anonymous_access_to_private_issue
918 918 Issue.update_all(["is_private = ?", true], "id = 1")
919 919 get :show, :id => 1
920 920 assert_response :redirect
921 921 end
922 922
923 923 def test_show_should_deny_non_member_access_without_permission
924 924 Role.non_member.remove_permission!(:view_issues)
925 925 @request.session[:user_id] = 9
926 926 get :show, :id => 1
927 927 assert_response 403
928 928 end
929 929
930 930 def test_show_should_deny_non_member_access_to_private_issue
931 931 Issue.update_all(["is_private = ?", true], "id = 1")
932 932 @request.session[:user_id] = 9
933 933 get :show, :id => 1
934 934 assert_response 403
935 935 end
936 936
937 937 def test_show_should_deny_member_access_without_permission
938 938 Role.find(1).remove_permission!(:view_issues)
939 939 @request.session[:user_id] = 2
940 940 get :show, :id => 1
941 941 assert_response 403
942 942 end
943 943
944 944 def test_show_should_deny_member_access_to_private_issue_without_permission
945 945 Issue.update_all(["is_private = ?", true], "id = 1")
946 946 @request.session[:user_id] = 3
947 947 get :show, :id => 1
948 948 assert_response 403
949 949 end
950 950
951 951 def test_show_should_allow_author_access_to_private_issue
952 952 Issue.update_all(["is_private = ?, author_id = 3", true], "id = 1")
953 953 @request.session[:user_id] = 3
954 954 get :show, :id => 1
955 955 assert_response :success
956 956 end
957 957
958 958 def test_show_should_allow_assignee_access_to_private_issue
959 959 Issue.update_all(["is_private = ?, assigned_to_id = 3", true], "id = 1")
960 960 @request.session[:user_id] = 3
961 961 get :show, :id => 1
962 962 assert_response :success
963 963 end
964 964
965 965 def test_show_should_allow_member_access_to_private_issue_with_permission
966 966 Issue.update_all(["is_private = ?", true], "id = 1")
967 967 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
968 968 @request.session[:user_id] = 3
969 969 get :show, :id => 1
970 970 assert_response :success
971 971 end
972 972
973 973 def test_show_should_not_disclose_relations_to_invisible_issues
974 974 Setting.cross_project_issue_relations = '1'
975 975 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
976 976 # Relation to a private project issue
977 977 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
978 978
979 979 get :show, :id => 1
980 980 assert_response :success
981 981
982 982 assert_tag :div, :attributes => { :id => 'relations' },
983 983 :descendant => { :tag => 'a', :content => /#2$/ }
984 984 assert_no_tag :div, :attributes => { :id => 'relations' },
985 985 :descendant => { :tag => 'a', :content => /#4$/ }
986 986 end
987 987
988 988 def test_show_should_list_subtasks
989 989 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
990 990
991 991 get :show, :id => 1
992 992 assert_response :success
993 993 assert_tag 'div', :attributes => {:id => 'issue_tree'},
994 994 :descendant => {:tag => 'td', :content => /Child Issue/, :attributes => {:class => /subject/}}
995 995 end
996 996
997 997 def test_show_should_list_parents
998 998 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
999 999
1000 1000 get :show, :id => issue.id
1001 1001 assert_response :success
1002 1002 assert_tag 'div', :attributes => {:class => 'subject'},
1003 1003 :descendant => {:tag => 'h3', :content => 'Child Issue'}
1004 1004 assert_tag 'div', :attributes => {:class => 'subject'},
1005 1005 :descendant => {:tag => 'a', :attributes => {:href => '/issues/1'}}
1006 1006 end
1007 1007
1008 1008 def test_show_should_not_display_prev_next_links_without_query_in_session
1009 1009 get :show, :id => 1
1010 1010 assert_response :success
1011 1011 assert_nil assigns(:prev_issue_id)
1012 1012 assert_nil assigns(:next_issue_id)
1013 1013
1014 1014 assert_no_tag 'div', :attributes => {:class => /next-prev-links/}
1015 1015 end
1016 1016
1017 1017 def test_show_should_display_prev_next_links_with_query_in_session
1018 1018 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1019 1019 @request.session['issues_index_sort'] = 'id'
1020 1020
1021 1021 with_settings :display_subprojects_issues => '0' do
1022 1022 get :show, :id => 3
1023 1023 end
1024 1024
1025 1025 assert_response :success
1026 1026 # Previous and next issues for all projects
1027 1027 assert_equal 2, assigns(:prev_issue_id)
1028 1028 assert_equal 5, assigns(:next_issue_id)
1029 1029
1030 1030 assert_tag 'div', :attributes => {:class => /next-prev-links/}
1031 1031 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Previous/
1032 1032 assert_tag 'a', :attributes => {:href => '/issues/5'}, :content => /Next/
1033 1033
1034 1034 count = Issue.open.visible.count
1035 1035 assert_tag 'span', :attributes => {:class => 'position'}, :content => "3 of #{count}"
1036 1036 end
1037 1037
1038 1038 def test_show_should_display_prev_next_links_with_saved_query_in_session
1039 1039 query = Query.create!(:name => 'test', :is_public => true, :user_id => 1,
1040 1040 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1041 1041 :sort_criteria => [['id', 'asc']])
1042 1042 @request.session[:query] = {:id => query.id, :project_id => nil}
1043 1043
1044 1044 get :show, :id => 11
1045 1045
1046 1046 assert_response :success
1047 1047 assert_equal query, assigns(:query)
1048 1048 # Previous and next issues for all projects
1049 1049 assert_equal 8, assigns(:prev_issue_id)
1050 1050 assert_equal 12, assigns(:next_issue_id)
1051 1051
1052 1052 assert_tag 'a', :attributes => {:href => '/issues/8'}, :content => /Previous/
1053 1053 assert_tag 'a', :attributes => {:href => '/issues/12'}, :content => /Next/
1054 1054 end
1055 1055
1056 1056 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1057 1057 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1058 1058
1059 1059 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1060 1060 @request.session['issues_index_sort'] = assoc_sort
1061 1061
1062 1062 get :show, :id => 3
1063 1063 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1064 1064
1065 1065 assert_tag 'div', :attributes => {:class => /next-prev-links/}, :content => /Previous/
1066 1066 assert_tag 'div', :attributes => {:class => /next-prev-links/}, :content => /Next/
1067 1067 end
1068 1068 end
1069 1069
1070 1070 def test_show_should_display_prev_next_links_with_project_query_in_session
1071 1071 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1072 1072 @request.session['issues_index_sort'] = 'id'
1073 1073
1074 1074 with_settings :display_subprojects_issues => '0' do
1075 1075 get :show, :id => 3
1076 1076 end
1077 1077
1078 1078 assert_response :success
1079 1079 # Previous and next issues inside project
1080 1080 assert_equal 2, assigns(:prev_issue_id)
1081 1081 assert_equal 7, assigns(:next_issue_id)
1082 1082
1083 1083 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Previous/
1084 1084 assert_tag 'a', :attributes => {:href => '/issues/7'}, :content => /Next/
1085 1085 end
1086 1086
1087 1087 def test_show_should_not_display_prev_link_for_first_issue
1088 1088 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1089 1089 @request.session['issues_index_sort'] = 'id'
1090 1090
1091 1091 with_settings :display_subprojects_issues => '0' do
1092 1092 get :show, :id => 1
1093 1093 end
1094 1094
1095 1095 assert_response :success
1096 1096 assert_nil assigns(:prev_issue_id)
1097 1097 assert_equal 2, assigns(:next_issue_id)
1098 1098
1099 1099 assert_no_tag 'a', :content => /Previous/
1100 1100 assert_tag 'a', :attributes => {:href => '/issues/2'}, :content => /Next/
1101 1101 end
1102 1102
1103 1103 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1104 1104 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1105 1105 @request.session['issues_index_sort'] = 'id'
1106 1106
1107 1107 get :show, :id => 1
1108 1108
1109 1109 assert_response :success
1110 1110 assert_nil assigns(:prev_issue_id)
1111 1111 assert_nil assigns(:next_issue_id)
1112 1112
1113 1113 assert_no_tag 'a', :content => /Previous/
1114 1114 assert_no_tag 'a', :content => /Next/
1115 1115 end
1116 1116
1117 1117 def test_show_should_display_visible_changesets_from_other_projects
1118 1118 project = Project.find(2)
1119 1119 issue = project.issues.first
1120 1120 issue.changeset_ids = [102]
1121 1121 issue.save!
1122 1122 project.disable_module! :repository
1123 1123
1124 1124 @request.session[:user_id] = 2
1125 1125 get :show, :id => issue.id
1126 1126 assert_tag 'a', :attributes => {:href => "/projects/ecookbook/repository/revisions/3"}
1127 1127 end
1128 1128
1129 def test_show_should_display_watchers
1130 @request.session[:user_id] = 2
1131 Issue.find(1).add_watcher User.find(2)
1132
1133 get :show, :id => 1
1134 assert_select 'div#watchers ul' do
1135 assert_select 'li' do
1136 assert_select 'a[href=/users/2]'
1137 assert_select 'a img[alt=Delete]'
1138 end
1139 end
1140 end
1141
1142 def test_show_should_display_watchers_with_gravatars
1143 @request.session[:user_id] = 2
1144 Issue.find(1).add_watcher User.find(2)
1145
1146 with_settings :gravatar_enabled => '1' do
1147 get :show, :id => 1
1148 end
1149
1150 assert_select 'div#watchers ul' do
1151 assert_select 'li' do
1152 assert_select 'img.gravatar'
1153 assert_select 'a[href=/users/2]'
1154 assert_select 'a img[alt=Delete]'
1155 end
1156 end
1157 end
1158
1129 1159 def test_show_with_multi_custom_field
1130 1160 field = CustomField.find(1)
1131 1161 field.update_attribute :multiple, true
1132 1162 issue = Issue.find(1)
1133 1163 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1134 1164 issue.save!
1135 1165
1136 1166 get :show, :id => 1
1137 1167 assert_response :success
1138 1168
1139 1169 assert_tag :td, :content => 'MySQL, Oracle'
1140 1170 end
1141 1171
1142 1172 def test_show_with_multi_user_custom_field
1143 1173 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1144 1174 :tracker_ids => [1], :is_for_all => true)
1145 1175 issue = Issue.find(1)
1146 1176 issue.custom_field_values = {field.id => ['2', '3']}
1147 1177 issue.save!
1148 1178
1149 1179 get :show, :id => 1
1150 1180 assert_response :success
1151 1181
1152 1182 # TODO: should display links
1153 1183 assert_tag :td, :content => 'Dave Lopper, John Smith'
1154 1184 end
1155 1185
1156 1186 def test_show_atom
1157 1187 get :show, :id => 2, :format => 'atom'
1158 1188 assert_response :success
1159 1189 assert_template 'journals/index'
1160 1190 # Inline image
1161 1191 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1162 1192 end
1163 1193
1164 1194 def test_show_export_to_pdf
1165 1195 get :show, :id => 3, :format => 'pdf'
1166 1196 assert_response :success
1167 1197 assert_equal 'application/pdf', @response.content_type
1168 1198 assert @response.body.starts_with?('%PDF')
1169 1199 assert_not_nil assigns(:issue)
1170 1200 end
1171 1201
1172 1202 def test_show_export_to_pdf_with_ancestors
1173 1203 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1174 1204
1175 1205 get :show, :id => issue.id, :format => 'pdf'
1176 1206 assert_response :success
1177 1207 assert_equal 'application/pdf', @response.content_type
1178 1208 assert @response.body.starts_with?('%PDF')
1179 1209 end
1180 1210
1181 1211 def test_show_export_to_pdf_with_descendants
1182 1212 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1183 1213 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1184 1214 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1185 1215
1186 1216 get :show, :id => 1, :format => 'pdf'
1187 1217 assert_response :success
1188 1218 assert_equal 'application/pdf', @response.content_type
1189 1219 assert @response.body.starts_with?('%PDF')
1190 1220 end
1191 1221
1192 1222 def test_show_export_to_pdf_with_journals
1193 1223 get :show, :id => 1, :format => 'pdf'
1194 1224 assert_response :success
1195 1225 assert_equal 'application/pdf', @response.content_type
1196 1226 assert @response.body.starts_with?('%PDF')
1197 1227 end
1198 1228
1199 1229 def test_show_export_to_pdf_with_changesets
1200 1230 Issue.find(3).changesets = Changeset.find_all_by_id(100, 101, 102)
1201 1231
1202 1232 get :show, :id => 3, :format => 'pdf'
1203 1233 assert_response :success
1204 1234 assert_equal 'application/pdf', @response.content_type
1205 1235 assert @response.body.starts_with?('%PDF')
1206 1236 end
1207 1237
1208 1238 def test_get_new
1209 1239 @request.session[:user_id] = 2
1210 1240 get :new, :project_id => 1, :tracker_id => 1
1211 1241 assert_response :success
1212 1242 assert_template 'new'
1213 1243
1214 1244 assert_tag 'input', :attributes => {:name => 'issue[is_private]'}
1215 1245 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
1216 1246 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
1217 1247 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
1218 1248 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
1219 1249 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
1220 1250 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
1221 1251 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
1222 1252 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
1223 1253 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
1224 1254 assert_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
1225 1255 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
1226 1256 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
1227 1257 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
1228 1258 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]', :value => 'Default string' }
1229 1259 assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
1230 1260
1231 1261 # Be sure we don't display inactive IssuePriorities
1232 1262 assert ! IssuePriority.find(15).active?
1233 1263 assert_no_tag :option, :attributes => {:value => '15'},
1234 1264 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
1235 1265 end
1236 1266
1237 1267 def test_get_new_with_minimal_permissions
1238 1268 Role.find(1).update_attribute :permissions, [:add_issues]
1239 1269 Workflow.delete_all :role_id => 1
1240 1270
1241 1271 @request.session[:user_id] = 2
1242 1272 get :new, :project_id => 1, :tracker_id => 1
1243 1273 assert_response :success
1244 1274 assert_template 'new'
1245 1275
1246 1276 assert_no_tag 'input', :attributes => {:name => 'issue[is_private]'}
1247 1277 assert_no_tag 'select', :attributes => {:name => 'issue[project_id]'}
1248 1278 assert_tag 'select', :attributes => {:name => 'issue[tracker_id]'}
1249 1279 assert_tag 'input', :attributes => {:name => 'issue[subject]'}
1250 1280 assert_tag 'textarea', :attributes => {:name => 'issue[description]'}
1251 1281 assert_tag 'select', :attributes => {:name => 'issue[status_id]'}
1252 1282 assert_tag 'select', :attributes => {:name => 'issue[priority_id]'}
1253 1283 assert_tag 'select', :attributes => {:name => 'issue[assigned_to_id]'}
1254 1284 assert_tag 'select', :attributes => {:name => 'issue[category_id]'}
1255 1285 assert_tag 'select', :attributes => {:name => 'issue[fixed_version_id]'}
1256 1286 assert_no_tag 'input', :attributes => {:name => 'issue[parent_issue_id]'}
1257 1287 assert_tag 'input', :attributes => {:name => 'issue[start_date]'}
1258 1288 assert_tag 'input', :attributes => {:name => 'issue[due_date]'}
1259 1289 assert_tag 'select', :attributes => {:name => 'issue[done_ratio]'}
1260 1290 assert_tag 'input', :attributes => { :name => 'issue[custom_field_values][2]', :value => 'Default string' }
1261 1291 assert_no_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]'}
1262 1292 end
1263 1293
1264 1294 def test_get_new_with_list_custom_field
1265 1295 @request.session[:user_id] = 2
1266 1296 get :new, :project_id => 1, :tracker_id => 1
1267 1297 assert_response :success
1268 1298 assert_template 'new'
1269 1299
1270 1300 assert_tag 'select',
1271 1301 :attributes => {:name => 'issue[custom_field_values][1]', :class => 'list_cf'},
1272 1302 :children => {:count => 4},
1273 1303 :child => {:tag => 'option', :attributes => {:value => 'MySQL'}, :content => 'MySQL'}
1274 1304 end
1275 1305
1276 1306 def test_get_new_with_multi_custom_field
1277 1307 field = IssueCustomField.find(1)
1278 1308 field.update_attribute :multiple, true
1279 1309
1280 1310 @request.session[:user_id] = 2
1281 1311 get :new, :project_id => 1, :tracker_id => 1
1282 1312 assert_response :success
1283 1313 assert_template 'new'
1284 1314
1285 1315 assert_tag 'select',
1286 1316 :attributes => {:name => 'issue[custom_field_values][1][]', :multiple => 'multiple'},
1287 1317 :children => {:count => 3},
1288 1318 :child => {:tag => 'option', :attributes => {:value => 'MySQL'}, :content => 'MySQL'}
1289 1319 assert_tag 'input',
1290 1320 :attributes => {:name => 'issue[custom_field_values][1][]', :value => ''}
1291 1321 end
1292 1322
1293 1323 def test_get_new_with_multi_user_custom_field
1294 1324 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1295 1325 :tracker_ids => [1], :is_for_all => true)
1296 1326
1297 1327 @request.session[:user_id] = 2
1298 1328 get :new, :project_id => 1, :tracker_id => 1
1299 1329 assert_response :success
1300 1330 assert_template 'new'
1301 1331
1302 1332 assert_tag 'select',
1303 1333 :attributes => {:name => "issue[custom_field_values][#{field.id}][]", :multiple => 'multiple'},
1304 1334 :children => {:count => Project.find(1).users.count},
1305 1335 :child => {:tag => 'option', :attributes => {:value => '2'}, :content => 'John Smith'}
1306 1336 assert_tag 'input',
1307 1337 :attributes => {:name => "issue[custom_field_values][#{field.id}][]", :value => ''}
1308 1338 end
1309 1339
1310 1340 def test_get_new_without_default_start_date_is_creation_date
1311 1341 Setting.default_issue_start_date_to_creation_date = 0
1312 1342
1313 1343 @request.session[:user_id] = 2
1314 1344 get :new, :project_id => 1, :tracker_id => 1
1315 1345 assert_response :success
1316 1346 assert_template 'new'
1317 1347
1318 1348 assert_tag :tag => 'input', :attributes => { :name => 'issue[start_date]',
1319 1349 :value => nil }
1320 1350 end
1321 1351
1322 1352 def test_get_new_with_default_start_date_is_creation_date
1323 1353 Setting.default_issue_start_date_to_creation_date = 1
1324 1354
1325 1355 @request.session[:user_id] = 2
1326 1356 get :new, :project_id => 1, :tracker_id => 1
1327 1357 assert_response :success
1328 1358 assert_template 'new'
1329 1359
1330 1360 assert_tag :tag => 'input', :attributes => { :name => 'issue[start_date]',
1331 1361 :value => Date.today.to_s }
1332 1362 end
1333 1363
1334 1364 def test_get_new_form_should_allow_attachment_upload
1335 1365 @request.session[:user_id] = 2
1336 1366 get :new, :project_id => 1, :tracker_id => 1
1337 1367
1338 1368 assert_tag :tag => 'form',
1339 1369 :attributes => {:id => 'issue-form', :method => 'post', :enctype => 'multipart/form-data'},
1340 1370 :descendant => {
1341 1371 :tag => 'input',
1342 1372 :attributes => {:type => 'file', :name => 'attachments[1][file]'}
1343 1373 }
1344 1374 end
1345 1375
1346 1376 def test_get_new_should_prefill_the_form_from_params
1347 1377 @request.session[:user_id] = 2
1348 1378 get :new, :project_id => 1,
1349 1379 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
1350 1380
1351 1381 issue = assigns(:issue)
1352 1382 assert_equal 3, issue.tracker_id
1353 1383 assert_equal 'Prefilled', issue.description
1354 1384 assert_equal 'Custom field value', issue.custom_field_value(2)
1355 1385
1356 1386 assert_tag 'select',
1357 1387 :attributes => {:name => 'issue[tracker_id]'},
1358 1388 :child => {:tag => 'option', :attributes => {:value => '3', :selected => 'selected'}}
1359 1389 assert_tag 'textarea',
1360 1390 :attributes => {:name => 'issue[description]'}, :content => "\nPrefilled"
1361 1391 assert_tag 'input',
1362 1392 :attributes => {:name => 'issue[custom_field_values][2]', :value => 'Custom field value'}
1363 1393 end
1364 1394
1365 1395 def test_get_new_without_tracker_id
1366 1396 @request.session[:user_id] = 2
1367 1397 get :new, :project_id => 1
1368 1398 assert_response :success
1369 1399 assert_template 'new'
1370 1400
1371 1401 issue = assigns(:issue)
1372 1402 assert_not_nil issue
1373 1403 assert_equal Project.find(1).trackers.first, issue.tracker
1374 1404 end
1375 1405
1376 1406 def test_get_new_with_no_default_status_should_display_an_error
1377 1407 @request.session[:user_id] = 2
1378 1408 IssueStatus.delete_all
1379 1409
1380 1410 get :new, :project_id => 1
1381 1411 assert_response 500
1382 1412 assert_error_tag :content => /No default issue/
1383 1413 end
1384 1414
1385 1415 def test_get_new_with_no_tracker_should_display_an_error
1386 1416 @request.session[:user_id] = 2
1387 1417 Tracker.delete_all
1388 1418
1389 1419 get :new, :project_id => 1
1390 1420 assert_response 500
1391 1421 assert_error_tag :content => /No tracker/
1392 1422 end
1393 1423
1394 1424 def test_update_new_form
1395 1425 @request.session[:user_id] = 2
1396 1426 xhr :post, :new, :project_id => 1,
1397 1427 :issue => {:tracker_id => 2,
1398 1428 :subject => 'This is the test_new issue',
1399 1429 :description => 'This is the description',
1400 1430 :priority_id => 5}
1401 1431 assert_response :success
1402 1432 assert_template 'attributes'
1403 1433
1404 1434 issue = assigns(:issue)
1405 1435 assert_kind_of Issue, issue
1406 1436 assert_equal 1, issue.project_id
1407 1437 assert_equal 2, issue.tracker_id
1408 1438 assert_equal 'This is the test_new issue', issue.subject
1409 1439 end
1410 1440
1411 1441 def test_update_new_form_should_propose_transitions_based_on_initial_status
1412 1442 @request.session[:user_id] = 2
1413 1443 Workflow.delete_all
1414 1444 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
1415 1445 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
1416 1446 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
1417 1447
1418 1448 xhr :post, :new, :project_id => 1,
1419 1449 :issue => {:tracker_id => 1,
1420 1450 :status_id => 5,
1421 1451 :subject => 'This is an issue'}
1422 1452
1423 1453 assert_equal 5, assigns(:issue).status_id
1424 1454 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
1425 1455 end
1426 1456
1427 1457 def test_post_create
1428 1458 @request.session[:user_id] = 2
1429 1459 assert_difference 'Issue.count' do
1430 1460 post :create, :project_id => 1,
1431 1461 :issue => {:tracker_id => 3,
1432 1462 :status_id => 2,
1433 1463 :subject => 'This is the test_new issue',
1434 1464 :description => 'This is the description',
1435 1465 :priority_id => 5,
1436 1466 :start_date => '2010-11-07',
1437 1467 :estimated_hours => '',
1438 1468 :custom_field_values => {'2' => 'Value for field 2'}}
1439 1469 end
1440 1470 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1441 1471
1442 1472 issue = Issue.find_by_subject('This is the test_new issue')
1443 1473 assert_not_nil issue
1444 1474 assert_equal 2, issue.author_id
1445 1475 assert_equal 3, issue.tracker_id
1446 1476 assert_equal 2, issue.status_id
1447 1477 assert_equal Date.parse('2010-11-07'), issue.start_date
1448 1478 assert_nil issue.estimated_hours
1449 1479 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
1450 1480 assert_not_nil v
1451 1481 assert_equal 'Value for field 2', v.value
1452 1482 end
1453 1483
1454 1484 def test_post_new_with_group_assignment
1455 1485 group = Group.find(11)
1456 1486 project = Project.find(1)
1457 1487 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
1458 1488
1459 1489 with_settings :issue_group_assignment => '1' do
1460 1490 @request.session[:user_id] = 2
1461 1491 assert_difference 'Issue.count' do
1462 1492 post :create, :project_id => project.id,
1463 1493 :issue => {:tracker_id => 3,
1464 1494 :status_id => 1,
1465 1495 :subject => 'This is the test_new_with_group_assignment issue',
1466 1496 :assigned_to_id => group.id}
1467 1497 end
1468 1498 end
1469 1499 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1470 1500
1471 1501 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
1472 1502 assert_not_nil issue
1473 1503 assert_equal group, issue.assigned_to
1474 1504 end
1475 1505
1476 1506 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
1477 1507 Setting.default_issue_start_date_to_creation_date = 0
1478 1508
1479 1509 @request.session[:user_id] = 2
1480 1510 assert_difference 'Issue.count' do
1481 1511 post :create, :project_id => 1,
1482 1512 :issue => {:tracker_id => 3,
1483 1513 :status_id => 2,
1484 1514 :subject => 'This is the test_new issue',
1485 1515 :description => 'This is the description',
1486 1516 :priority_id => 5,
1487 1517 :estimated_hours => '',
1488 1518 :custom_field_values => {'2' => 'Value for field 2'}}
1489 1519 end
1490 1520 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1491 1521
1492 1522 issue = Issue.find_by_subject('This is the test_new issue')
1493 1523 assert_not_nil issue
1494 1524 assert_nil issue.start_date
1495 1525 end
1496 1526
1497 1527 def test_post_create_without_start_date_and_default_start_date_is_creation_date
1498 1528 Setting.default_issue_start_date_to_creation_date = 1
1499 1529
1500 1530 @request.session[:user_id] = 2
1501 1531 assert_difference 'Issue.count' do
1502 1532 post :create, :project_id => 1,
1503 1533 :issue => {:tracker_id => 3,
1504 1534 :status_id => 2,
1505 1535 :subject => 'This is the test_new issue',
1506 1536 :description => 'This is the description',
1507 1537 :priority_id => 5,
1508 1538 :estimated_hours => '',
1509 1539 :custom_field_values => {'2' => 'Value for field 2'}}
1510 1540 end
1511 1541 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1512 1542
1513 1543 issue = Issue.find_by_subject('This is the test_new issue')
1514 1544 assert_not_nil issue
1515 1545 assert_equal Date.today, issue.start_date
1516 1546 end
1517 1547
1518 1548 def test_post_create_and_continue
1519 1549 @request.session[:user_id] = 2
1520 1550 assert_difference 'Issue.count' do
1521 1551 post :create, :project_id => 1,
1522 1552 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
1523 1553 :continue => ''
1524 1554 end
1525 1555
1526 1556 issue = Issue.first(:order => 'id DESC')
1527 1557 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
1528 1558 assert_not_nil flash[:notice], "flash was not set"
1529 1559 assert flash[:notice].include?("<a href='/issues/#{issue.id}'>##{issue.id}</a>"), "issue link not found in flash: #{flash[:notice]}"
1530 1560 end
1531 1561
1532 1562 def test_post_create_without_custom_fields_param
1533 1563 @request.session[:user_id] = 2
1534 1564 assert_difference 'Issue.count' do
1535 1565 post :create, :project_id => 1,
1536 1566 :issue => {:tracker_id => 1,
1537 1567 :subject => 'This is the test_new issue',
1538 1568 :description => 'This is the description',
1539 1569 :priority_id => 5}
1540 1570 end
1541 1571 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1542 1572 end
1543 1573
1544 1574 def test_post_create_with_multi_custom_field
1545 1575 field = IssueCustomField.find_by_name('Database')
1546 1576 field.update_attribute(:multiple, true)
1547 1577
1548 1578 @request.session[:user_id] = 2
1549 1579 assert_difference 'Issue.count' do
1550 1580 post :create, :project_id => 1,
1551 1581 :issue => {:tracker_id => 1,
1552 1582 :subject => 'This is the test_new issue',
1553 1583 :description => 'This is the description',
1554 1584 :priority_id => 5,
1555 1585 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
1556 1586 end
1557 1587 assert_response 302
1558 1588 issue = Issue.first(:order => 'id DESC')
1559 1589 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
1560 1590 end
1561 1591
1562 1592 def test_post_create_with_empty_multi_custom_field
1563 1593 field = IssueCustomField.find_by_name('Database')
1564 1594 field.update_attribute(:multiple, true)
1565 1595
1566 1596 @request.session[:user_id] = 2
1567 1597 assert_difference 'Issue.count' do
1568 1598 post :create, :project_id => 1,
1569 1599 :issue => {:tracker_id => 1,
1570 1600 :subject => 'This is the test_new issue',
1571 1601 :description => 'This is the description',
1572 1602 :priority_id => 5,
1573 1603 :custom_field_values => {'1' => ['']}}
1574 1604 end
1575 1605 assert_response 302
1576 1606 issue = Issue.first(:order => 'id DESC')
1577 1607 assert_equal [''], issue.custom_field_value(1).sort
1578 1608 end
1579 1609
1580 1610 def test_post_create_with_multi_user_custom_field
1581 1611 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1582 1612 :tracker_ids => [1], :is_for_all => true)
1583 1613
1584 1614 @request.session[:user_id] = 2
1585 1615 assert_difference 'Issue.count' do
1586 1616 post :create, :project_id => 1,
1587 1617 :issue => {:tracker_id => 1,
1588 1618 :subject => 'This is the test_new issue',
1589 1619 :description => 'This is the description',
1590 1620 :priority_id => 5,
1591 1621 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
1592 1622 end
1593 1623 assert_response 302
1594 1624 issue = Issue.first(:order => 'id DESC')
1595 1625 assert_equal ['2', '3'], issue.custom_field_value(field).sort
1596 1626 end
1597 1627
1598 1628 def test_post_create_with_required_custom_field_and_without_custom_fields_param
1599 1629 field = IssueCustomField.find_by_name('Database')
1600 1630 field.update_attribute(:is_required, true)
1601 1631
1602 1632 @request.session[:user_id] = 2
1603 1633 assert_no_difference 'Issue.count' do
1604 1634 post :create, :project_id => 1,
1605 1635 :issue => {:tracker_id => 1,
1606 1636 :subject => 'This is the test_new issue',
1607 1637 :description => 'This is the description',
1608 1638 :priority_id => 5}
1609 1639 end
1610 1640 assert_response :success
1611 1641 assert_template 'new'
1612 1642 issue = assigns(:issue)
1613 1643 assert_not_nil issue
1614 1644 assert_error_tag :content => /Database can't be blank/
1615 1645 end
1616 1646
1617 1647 def test_post_create_with_watchers
1618 1648 @request.session[:user_id] = 2
1619 1649 ActionMailer::Base.deliveries.clear
1620 1650
1621 1651 assert_difference 'Watcher.count', 2 do
1622 1652 post :create, :project_id => 1,
1623 1653 :issue => {:tracker_id => 1,
1624 1654 :subject => 'This is a new issue with watchers',
1625 1655 :description => 'This is the description',
1626 1656 :priority_id => 5,
1627 1657 :watcher_user_ids => ['2', '3']}
1628 1658 end
1629 1659 issue = Issue.find_by_subject('This is a new issue with watchers')
1630 1660 assert_not_nil issue
1631 1661 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1632 1662
1633 1663 # Watchers added
1634 1664 assert_equal [2, 3], issue.watcher_user_ids.sort
1635 1665 assert issue.watched_by?(User.find(3))
1636 1666 # Watchers notified
1637 1667 mail = ActionMailer::Base.deliveries.last
1638 1668 assert_not_nil mail
1639 1669 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
1640 1670 end
1641 1671
1642 1672 def test_post_create_subissue
1643 1673 @request.session[:user_id] = 2
1644 1674
1645 1675 assert_difference 'Issue.count' do
1646 1676 post :create, :project_id => 1,
1647 1677 :issue => {:tracker_id => 1,
1648 1678 :subject => 'This is a child issue',
1649 1679 :parent_issue_id => 2}
1650 1680 end
1651 1681 issue = Issue.find_by_subject('This is a child issue')
1652 1682 assert_not_nil issue
1653 1683 assert_equal Issue.find(2), issue.parent
1654 1684 end
1655 1685
1656 1686 def test_post_create_subissue_with_non_numeric_parent_id
1657 1687 @request.session[:user_id] = 2
1658 1688
1659 1689 assert_difference 'Issue.count' do
1660 1690 post :create, :project_id => 1,
1661 1691 :issue => {:tracker_id => 1,
1662 1692 :subject => 'This is a child issue',
1663 1693 :parent_issue_id => 'ABC'}
1664 1694 end
1665 1695 issue = Issue.find_by_subject('This is a child issue')
1666 1696 assert_not_nil issue
1667 1697 assert_nil issue.parent
1668 1698 end
1669 1699
1670 1700 def test_post_create_private
1671 1701 @request.session[:user_id] = 2
1672 1702
1673 1703 assert_difference 'Issue.count' do
1674 1704 post :create, :project_id => 1,
1675 1705 :issue => {:tracker_id => 1,
1676 1706 :subject => 'This is a private issue',
1677 1707 :is_private => '1'}
1678 1708 end
1679 1709 issue = Issue.first(:order => 'id DESC')
1680 1710 assert issue.is_private?
1681 1711 end
1682 1712
1683 1713 def test_post_create_private_with_set_own_issues_private_permission
1684 1714 role = Role.find(1)
1685 1715 role.remove_permission! :set_issues_private
1686 1716 role.add_permission! :set_own_issues_private
1687 1717
1688 1718 @request.session[:user_id] = 2
1689 1719
1690 1720 assert_difference 'Issue.count' do
1691 1721 post :create, :project_id => 1,
1692 1722 :issue => {:tracker_id => 1,
1693 1723 :subject => 'This is a private issue',
1694 1724 :is_private => '1'}
1695 1725 end
1696 1726 issue = Issue.first(:order => 'id DESC')
1697 1727 assert issue.is_private?
1698 1728 end
1699 1729
1700 1730 def test_post_create_should_send_a_notification
1701 1731 ActionMailer::Base.deliveries.clear
1702 1732 @request.session[:user_id] = 2
1703 1733 assert_difference 'Issue.count' do
1704 1734 post :create, :project_id => 1,
1705 1735 :issue => {:tracker_id => 3,
1706 1736 :subject => 'This is the test_new issue',
1707 1737 :description => 'This is the description',
1708 1738 :priority_id => 5,
1709 1739 :estimated_hours => '',
1710 1740 :custom_field_values => {'2' => 'Value for field 2'}}
1711 1741 end
1712 1742 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1713 1743
1714 1744 assert_equal 1, ActionMailer::Base.deliveries.size
1715 1745 end
1716 1746
1717 1747 def test_post_create_should_preserve_fields_values_on_validation_failure
1718 1748 @request.session[:user_id] = 2
1719 1749 post :create, :project_id => 1,
1720 1750 :issue => {:tracker_id => 1,
1721 1751 # empty subject
1722 1752 :subject => '',
1723 1753 :description => 'This is a description',
1724 1754 :priority_id => 6,
1725 1755 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
1726 1756 assert_response :success
1727 1757 assert_template 'new'
1728 1758
1729 1759 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
1730 1760 :content => "\nThis is a description"
1731 1761 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
1732 1762 :child => { :tag => 'option', :attributes => { :selected => 'selected',
1733 1763 :value => '6' },
1734 1764 :content => 'High' }
1735 1765 # Custom fields
1736 1766 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
1737 1767 :child => { :tag => 'option', :attributes => { :selected => 'selected',
1738 1768 :value => 'Oracle' },
1739 1769 :content => 'Oracle' }
1740 1770 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
1741 1771 :value => 'Value for field 2'}
1742 1772 end
1743 1773
1744 1774 def test_post_create_with_failure_should_preserve_watchers
1745 1775 assert !User.find(8).member_of?(Project.find(1))
1746 1776
1747 1777 @request.session[:user_id] = 2
1748 1778 post :create, :project_id => 1,
1749 1779 :issue => {:tracker_id => 1,
1750 1780 :watcher_user_ids => ['3', '8']}
1751 1781 assert_response :success
1752 1782 assert_template 'new'
1753 1783
1754 1784 assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '2', :checked => nil}
1755 1785 assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '3', :checked => 'checked'}
1756 1786 assert_tag 'input', :attributes => {:name => 'issue[watcher_user_ids][]', :value => '8', :checked => 'checked'}
1757 1787 end
1758 1788
1759 1789 def test_post_create_should_ignore_non_safe_attributes
1760 1790 @request.session[:user_id] = 2
1761 1791 assert_nothing_raised do
1762 1792 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
1763 1793 end
1764 1794 end
1765 1795
1766 1796 def test_post_create_with_attachment
1767 1797 set_tmp_attachments_directory
1768 1798 @request.session[:user_id] = 2
1769 1799
1770 1800 assert_difference 'Issue.count' do
1771 1801 assert_difference 'Attachment.count' do
1772 1802 post :create, :project_id => 1,
1773 1803 :issue => { :tracker_id => '1', :subject => 'With attachment' },
1774 1804 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
1775 1805 end
1776 1806 end
1777 1807
1778 1808 issue = Issue.first(:order => 'id DESC')
1779 1809 attachment = Attachment.first(:order => 'id DESC')
1780 1810
1781 1811 assert_equal issue, attachment.container
1782 1812 assert_equal 2, attachment.author_id
1783 1813 assert_equal 'testfile.txt', attachment.filename
1784 1814 assert_equal 'text/plain', attachment.content_type
1785 1815 assert_equal 'test file', attachment.description
1786 1816 assert_equal 59, attachment.filesize
1787 1817 assert File.exists?(attachment.diskfile)
1788 1818 assert_equal 59, File.size(attachment.diskfile)
1789 1819 end
1790 1820
1791 1821 def test_post_create_with_failure_should_save_attachments
1792 1822 set_tmp_attachments_directory
1793 1823 @request.session[:user_id] = 2
1794 1824
1795 1825 assert_no_difference 'Issue.count' do
1796 1826 assert_difference 'Attachment.count' do
1797 1827 post :create, :project_id => 1,
1798 1828 :issue => { :tracker_id => '1', :subject => '' },
1799 1829 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
1800 1830 assert_response :success
1801 1831 assert_template 'new'
1802 1832 end
1803 1833 end
1804 1834
1805 1835 attachment = Attachment.first(:order => 'id DESC')
1806 1836 assert_equal 'testfile.txt', attachment.filename
1807 1837 assert File.exists?(attachment.diskfile)
1808 1838 assert_nil attachment.container
1809 1839
1810 1840 assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
1811 1841 assert_tag 'span', :content => /testfile.txt/
1812 1842 end
1813 1843
1814 1844 def test_post_create_with_failure_should_keep_saved_attachments
1815 1845 set_tmp_attachments_directory
1816 1846 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
1817 1847 @request.session[:user_id] = 2
1818 1848
1819 1849 assert_no_difference 'Issue.count' do
1820 1850 assert_no_difference 'Attachment.count' do
1821 1851 post :create, :project_id => 1,
1822 1852 :issue => { :tracker_id => '1', :subject => '' },
1823 1853 :attachments => {'p0' => {'token' => attachment.token}}
1824 1854 assert_response :success
1825 1855 assert_template 'new'
1826 1856 end
1827 1857 end
1828 1858
1829 1859 assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
1830 1860 assert_tag 'span', :content => /testfile.txt/
1831 1861 end
1832 1862
1833 1863 def test_post_create_should_attach_saved_attachments
1834 1864 set_tmp_attachments_directory
1835 1865 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
1836 1866 @request.session[:user_id] = 2
1837 1867
1838 1868 assert_difference 'Issue.count' do
1839 1869 assert_no_difference 'Attachment.count' do
1840 1870 post :create, :project_id => 1,
1841 1871 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
1842 1872 :attachments => {'p0' => {'token' => attachment.token}}
1843 1873 assert_response 302
1844 1874 end
1845 1875 end
1846 1876
1847 1877 issue = Issue.first(:order => 'id DESC')
1848 1878 assert_equal 1, issue.attachments.count
1849 1879
1850 1880 attachment.reload
1851 1881 assert_equal issue, attachment.container
1852 1882 end
1853 1883
1854 1884 context "without workflow privilege" do
1855 1885 setup do
1856 1886 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
1857 1887 Role.anonymous.add_permission! :add_issues, :add_issue_notes
1858 1888 end
1859 1889
1860 1890 context "#new" do
1861 1891 should "propose default status only" do
1862 1892 get :new, :project_id => 1
1863 1893 assert_response :success
1864 1894 assert_template 'new'
1865 1895 assert_tag :tag => 'select',
1866 1896 :attributes => {:name => 'issue[status_id]'},
1867 1897 :children => {:count => 1},
1868 1898 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
1869 1899 end
1870 1900
1871 1901 should "accept default status" do
1872 1902 assert_difference 'Issue.count' do
1873 1903 post :create, :project_id => 1,
1874 1904 :issue => {:tracker_id => 1,
1875 1905 :subject => 'This is an issue',
1876 1906 :status_id => 1}
1877 1907 end
1878 1908 issue = Issue.last(:order => 'id')
1879 1909 assert_equal IssueStatus.default, issue.status
1880 1910 end
1881 1911
1882 1912 should "ignore unauthorized status" do
1883 1913 assert_difference 'Issue.count' do
1884 1914 post :create, :project_id => 1,
1885 1915 :issue => {:tracker_id => 1,
1886 1916 :subject => 'This is an issue',
1887 1917 :status_id => 3}
1888 1918 end
1889 1919 issue = Issue.last(:order => 'id')
1890 1920 assert_equal IssueStatus.default, issue.status
1891 1921 end
1892 1922 end
1893 1923
1894 1924 context "#update" do
1895 1925 should "ignore status change" do
1896 1926 assert_difference 'Journal.count' do
1897 1927 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1898 1928 end
1899 1929 assert_equal 1, Issue.find(1).status_id
1900 1930 end
1901 1931
1902 1932 should "ignore attributes changes" do
1903 1933 assert_difference 'Journal.count' do
1904 1934 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
1905 1935 end
1906 1936 issue = Issue.find(1)
1907 1937 assert_equal "Can't print recipes", issue.subject
1908 1938 assert_nil issue.assigned_to
1909 1939 end
1910 1940 end
1911 1941 end
1912 1942
1913 1943 context "with workflow privilege" do
1914 1944 setup do
1915 1945 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
1916 1946 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
1917 1947 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
1918 1948 Role.anonymous.add_permission! :add_issues, :add_issue_notes
1919 1949 end
1920 1950
1921 1951 context "#update" do
1922 1952 should "accept authorized status" do
1923 1953 assert_difference 'Journal.count' do
1924 1954 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1925 1955 end
1926 1956 assert_equal 3, Issue.find(1).status_id
1927 1957 end
1928 1958
1929 1959 should "ignore unauthorized status" do
1930 1960 assert_difference 'Journal.count' do
1931 1961 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
1932 1962 end
1933 1963 assert_equal 1, Issue.find(1).status_id
1934 1964 end
1935 1965
1936 1966 should "accept authorized attributes changes" do
1937 1967 assert_difference 'Journal.count' do
1938 1968 put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2}
1939 1969 end
1940 1970 issue = Issue.find(1)
1941 1971 assert_equal 2, issue.assigned_to_id
1942 1972 end
1943 1973
1944 1974 should "ignore unauthorized attributes changes" do
1945 1975 assert_difference 'Journal.count' do
1946 1976 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'}
1947 1977 end
1948 1978 issue = Issue.find(1)
1949 1979 assert_equal "Can't print recipes", issue.subject
1950 1980 end
1951 1981 end
1952 1982
1953 1983 context "and :edit_issues permission" do
1954 1984 setup do
1955 1985 Role.anonymous.add_permission! :add_issues, :edit_issues
1956 1986 end
1957 1987
1958 1988 should "accept authorized status" do
1959 1989 assert_difference 'Journal.count' do
1960 1990 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
1961 1991 end
1962 1992 assert_equal 3, Issue.find(1).status_id
1963 1993 end
1964 1994
1965 1995 should "ignore unauthorized status" do
1966 1996 assert_difference 'Journal.count' do
1967 1997 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
1968 1998 end
1969 1999 assert_equal 1, Issue.find(1).status_id
1970 2000 end
1971 2001
1972 2002 should "accept authorized attributes changes" do
1973 2003 assert_difference 'Journal.count' do
1974 2004 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
1975 2005 end
1976 2006 issue = Issue.find(1)
1977 2007 assert_equal "changed", issue.subject
1978 2008 assert_equal 2, issue.assigned_to_id
1979 2009 end
1980 2010 end
1981 2011 end
1982 2012
1983 2013 def test_new_as_copy
1984 2014 @request.session[:user_id] = 2
1985 2015 get :new, :project_id => 1, :copy_from => 1
1986 2016
1987 2017 assert_response :success
1988 2018 assert_template 'new'
1989 2019
1990 2020 assert_not_nil assigns(:issue)
1991 2021 orig = Issue.find(1)
1992 2022 assert_equal 1, assigns(:issue).project_id
1993 2023 assert_equal orig.subject, assigns(:issue).subject
1994 2024 assert assigns(:issue).copy?
1995 2025
1996 2026 assert_tag 'form', :attributes => {:id => 'issue-form', :action => '/projects/ecookbook/issues'}
1997 2027 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
1998 2028 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
1999 2029 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}, :content => 'eCookbook'}
2000 2030 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
2001 2031 :child => {:tag => 'option', :attributes => {:value => '2', :selected => nil}, :content => 'OnlineStore'}
2002 2032 assert_tag 'input', :attributes => {:name => 'copy_from', :value => '1'}
2003 2033 end
2004 2034
2005 2035 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2006 2036 @request.session[:user_id] = 2
2007 2037 issue = Issue.find(3)
2008 2038 assert issue.attachments.count > 0
2009 2039 get :new, :project_id => 1, :copy_from => 3
2010 2040
2011 2041 assert_tag 'input', :attributes => {:name => 'copy_attachments', :type => 'checkbox', :checked => 'checked', :value => '1'}
2012 2042 end
2013 2043
2014 2044 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2015 2045 @request.session[:user_id] = 2
2016 2046 issue = Issue.find(3)
2017 2047 issue.attachments.delete_all
2018 2048 get :new, :project_id => 1, :copy_from => 3
2019 2049
2020 2050 assert_no_tag 'input', :attributes => {:name => 'copy_attachments', :type => 'checkbox', :checked => 'checked', :value => '1'}
2021 2051 end
2022 2052
2023 2053 def test_new_as_copy_with_invalid_issue_should_respond_with_404
2024 2054 @request.session[:user_id] = 2
2025 2055 get :new, :project_id => 1, :copy_from => 99999
2026 2056 assert_response 404
2027 2057 end
2028 2058
2029 2059 def test_create_as_copy_on_different_project
2030 2060 @request.session[:user_id] = 2
2031 2061 assert_difference 'Issue.count' do
2032 2062 post :create, :project_id => 1, :copy_from => 1,
2033 2063 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2034 2064
2035 2065 assert_not_nil assigns(:issue)
2036 2066 assert assigns(:issue).copy?
2037 2067 end
2038 2068 issue = Issue.first(:order => 'id DESC')
2039 2069 assert_redirected_to "/issues/#{issue.id}"
2040 2070
2041 2071 assert_equal 2, issue.project_id
2042 2072 assert_equal 3, issue.tracker_id
2043 2073 assert_equal 'Copy', issue.subject
2044 2074 end
2045 2075
2046 2076 def test_create_as_copy_should_copy_attachments
2047 2077 @request.session[:user_id] = 2
2048 2078 issue = Issue.find(3)
2049 2079 count = issue.attachments.count
2050 2080 assert count > 0
2051 2081
2052 2082 assert_difference 'Issue.count' do
2053 2083 assert_difference 'Attachment.count', count do
2054 2084 assert_no_difference 'Journal.count' do
2055 2085 post :create, :project_id => 1, :copy_from => 3,
2056 2086 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
2057 2087 :copy_attachments => '1'
2058 2088 end
2059 2089 end
2060 2090 end
2061 2091 copy = Issue.first(:order => 'id DESC')
2062 2092 assert_equal count, copy.attachments.count
2063 2093 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
2064 2094 end
2065 2095
2066 2096 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
2067 2097 @request.session[:user_id] = 2
2068 2098 issue = Issue.find(3)
2069 2099 count = issue.attachments.count
2070 2100 assert count > 0
2071 2101
2072 2102 assert_difference 'Issue.count' do
2073 2103 assert_no_difference 'Attachment.count' do
2074 2104 assert_no_difference 'Journal.count' do
2075 2105 post :create, :project_id => 1, :copy_from => 3,
2076 2106 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'}
2077 2107 end
2078 2108 end
2079 2109 end
2080 2110 copy = Issue.first(:order => 'id DESC')
2081 2111 assert_equal 0, copy.attachments.count
2082 2112 end
2083 2113
2084 2114 def test_create_as_copy_with_attachments_should_add_new_files
2085 2115 @request.session[:user_id] = 2
2086 2116 issue = Issue.find(3)
2087 2117 count = issue.attachments.count
2088 2118 assert count > 0
2089 2119
2090 2120 assert_difference 'Issue.count' do
2091 2121 assert_difference 'Attachment.count', count + 1 do
2092 2122 assert_no_difference 'Journal.count' do
2093 2123 post :create, :project_id => 1, :copy_from => 3,
2094 2124 :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
2095 2125 :copy_attachments => '1',
2096 2126 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2097 2127 end
2098 2128 end
2099 2129 end
2100 2130 copy = Issue.first(:order => 'id DESC')
2101 2131 assert_equal count + 1, copy.attachments.count
2102 2132 end
2103 2133
2104 2134 def test_create_as_copy_with_failure
2105 2135 @request.session[:user_id] = 2
2106 2136 post :create, :project_id => 1, :copy_from => 1,
2107 2137 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
2108 2138
2109 2139 assert_response :success
2110 2140 assert_template 'new'
2111 2141
2112 2142 assert_not_nil assigns(:issue)
2113 2143 assert assigns(:issue).copy?
2114 2144
2115 2145 assert_tag 'form', :attributes => {:id => 'issue-form', :action => '/projects/ecookbook/issues'}
2116 2146 assert_tag 'select', :attributes => {:name => 'issue[project_id]'}
2117 2147 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
2118 2148 :child => {:tag => 'option', :attributes => {:value => '1', :selected => nil}, :content => 'eCookbook'}
2119 2149 assert_tag 'select', :attributes => {:name => 'issue[project_id]'},
2120 2150 :child => {:tag => 'option', :attributes => {:value => '2', :selected => 'selected'}, :content => 'OnlineStore'}
2121 2151 assert_tag 'input', :attributes => {:name => 'copy_from', :value => '1'}
2122 2152 end
2123 2153
2124 2154 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
2125 2155 @request.session[:user_id] = 2
2126 2156 assert !User.find(2).member_of?(Project.find(4))
2127 2157
2128 2158 assert_difference 'Issue.count' do
2129 2159 post :create, :project_id => 1, :copy_from => 1,
2130 2160 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2131 2161 end
2132 2162 issue = Issue.first(:order => 'id DESC')
2133 2163 assert_equal 1, issue.project_id
2134 2164 end
2135 2165
2136 2166 def test_get_edit
2137 2167 @request.session[:user_id] = 2
2138 2168 get :edit, :id => 1
2139 2169 assert_response :success
2140 2170 assert_template 'edit'
2141 2171 assert_not_nil assigns(:issue)
2142 2172 assert_equal Issue.find(1), assigns(:issue)
2143 2173
2144 2174 # Be sure we don't display inactive IssuePriorities
2145 2175 assert ! IssuePriority.find(15).active?
2146 2176 assert_no_tag :option, :attributes => {:value => '15'},
2147 2177 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
2148 2178 end
2149 2179
2150 2180 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
2151 2181 @request.session[:user_id] = 2
2152 2182 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
2153 2183
2154 2184 get :edit, :id => 1
2155 2185 assert_tag 'input', :attributes => {:name => 'time_entry[hours]'}
2156 2186 end
2157 2187
2158 2188 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
2159 2189 @request.session[:user_id] = 2
2160 2190 Role.find_by_name('Manager').remove_permission! :log_time
2161 2191
2162 2192 get :edit, :id => 1
2163 2193 assert_no_tag 'input', :attributes => {:name => 'time_entry[hours]'}
2164 2194 end
2165 2195
2166 2196 def test_get_edit_with_params
2167 2197 @request.session[:user_id] = 2
2168 2198 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
2169 2199 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => TimeEntryActivity.first.id }
2170 2200 assert_response :success
2171 2201 assert_template 'edit'
2172 2202
2173 2203 issue = assigns(:issue)
2174 2204 assert_not_nil issue
2175 2205
2176 2206 assert_equal 5, issue.status_id
2177 2207 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
2178 2208 :child => { :tag => 'option',
2179 2209 :content => 'Closed',
2180 2210 :attributes => { :selected => 'selected' } }
2181 2211
2182 2212 assert_equal 7, issue.priority_id
2183 2213 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
2184 2214 :child => { :tag => 'option',
2185 2215 :content => 'Urgent',
2186 2216 :attributes => { :selected => 'selected' } }
2187 2217
2188 2218 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => '2.5' }
2189 2219 assert_tag :select, :attributes => { :name => 'time_entry[activity_id]' },
2190 2220 :child => { :tag => 'option',
2191 2221 :attributes => { :selected => 'selected', :value => TimeEntryActivity.first.id } }
2192 2222 assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => 'test_get_edit_with_params' }
2193 2223 end
2194 2224
2195 2225 def test_get_edit_with_multi_custom_field
2196 2226 field = CustomField.find(1)
2197 2227 field.update_attribute :multiple, true
2198 2228 issue = Issue.find(1)
2199 2229 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2200 2230 issue.save!
2201 2231
2202 2232 @request.session[:user_id] = 2
2203 2233 get :edit, :id => 1
2204 2234 assert_response :success
2205 2235 assert_template 'edit'
2206 2236
2207 2237 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]', :multiple => 'multiple'}
2208 2238 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2209 2239 :child => {:tag => 'option', :attributes => {:value => 'MySQL', :selected => 'selected'}}
2210 2240 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2211 2241 :child => {:tag => 'option', :attributes => {:value => 'PostgreSQL', :selected => nil}}
2212 2242 assert_tag 'select', :attributes => {:name => 'issue[custom_field_values][1][]'},
2213 2243 :child => {:tag => 'option', :attributes => {:value => 'Oracle', :selected => 'selected'}}
2214 2244 end
2215 2245
2216 2246 def test_update_edit_form
2217 2247 @request.session[:user_id] = 2
2218 2248 xhr :put, :new, :project_id => 1,
2219 2249 :id => 1,
2220 2250 :issue => {:tracker_id => 2,
2221 2251 :subject => 'This is the test_new issue',
2222 2252 :description => 'This is the description',
2223 2253 :priority_id => 5}
2224 2254 assert_response :success
2225 2255 assert_template 'attributes'
2226 2256
2227 2257 issue = assigns(:issue)
2228 2258 assert_kind_of Issue, issue
2229 2259 assert_equal 1, issue.id
2230 2260 assert_equal 1, issue.project_id
2231 2261 assert_equal 2, issue.tracker_id
2232 2262 assert_equal 'This is the test_new issue', issue.subject
2233 2263 end
2234 2264
2235 2265 def test_update_edit_form_should_propose_transitions_based_on_initial_status
2236 2266 @request.session[:user_id] = 2
2237 2267 Workflow.delete_all
2238 2268 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
2239 2269 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
2240 2270 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
2241 2271
2242 2272 xhr :put, :new, :project_id => 1,
2243 2273 :id => 2,
2244 2274 :issue => {:tracker_id => 2,
2245 2275 :status_id => 5,
2246 2276 :subject => 'This is an issue'}
2247 2277
2248 2278 assert_equal 5, assigns(:issue).status_id
2249 2279 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
2250 2280 end
2251 2281
2252 2282 def test_update_edit_form_with_project_change
2253 2283 @request.session[:user_id] = 2
2254 2284 xhr :put, :new, :project_id => 1,
2255 2285 :id => 1,
2256 2286 :project_change => '1',
2257 2287 :issue => {:project_id => 2,
2258 2288 :tracker_id => 2,
2259 2289 :subject => 'This is the test_new issue',
2260 2290 :description => 'This is the description',
2261 2291 :priority_id => 5}
2262 2292 assert_response :success
2263 2293 assert_template 'form'
2264 2294
2265 2295 issue = assigns(:issue)
2266 2296 assert_kind_of Issue, issue
2267 2297 assert_equal 1, issue.id
2268 2298 assert_equal 2, issue.project_id
2269 2299 assert_equal 2, issue.tracker_id
2270 2300 assert_equal 'This is the test_new issue', issue.subject
2271 2301 end
2272 2302
2273 2303 def test_put_update_without_custom_fields_param
2274 2304 @request.session[:user_id] = 2
2275 2305 ActionMailer::Base.deliveries.clear
2276 2306
2277 2307 issue = Issue.find(1)
2278 2308 assert_equal '125', issue.custom_value_for(2).value
2279 2309 old_subject = issue.subject
2280 2310 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2281 2311
2282 2312 assert_difference('Journal.count') do
2283 2313 assert_difference('JournalDetail.count', 2) do
2284 2314 put :update, :id => 1, :issue => {:subject => new_subject,
2285 2315 :priority_id => '6',
2286 2316 :category_id => '1' # no change
2287 2317 }
2288 2318 end
2289 2319 end
2290 2320 assert_redirected_to :action => 'show', :id => '1'
2291 2321 issue.reload
2292 2322 assert_equal new_subject, issue.subject
2293 2323 # Make sure custom fields were not cleared
2294 2324 assert_equal '125', issue.custom_value_for(2).value
2295 2325
2296 2326 mail = ActionMailer::Base.deliveries.last
2297 2327 assert_not_nil mail
2298 2328 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2299 2329 assert_mail_body_match "Subject changed from #{old_subject} to #{new_subject}", mail
2300 2330 end
2301 2331
2302 2332 def test_put_update_with_project_change
2303 2333 @request.session[:user_id] = 2
2304 2334 ActionMailer::Base.deliveries.clear
2305 2335
2306 2336 assert_difference('Journal.count') do
2307 2337 assert_difference('JournalDetail.count', 3) do
2308 2338 put :update, :id => 1, :issue => {:project_id => '2',
2309 2339 :tracker_id => '1', # no change
2310 2340 :priority_id => '6',
2311 2341 :category_id => '3'
2312 2342 }
2313 2343 end
2314 2344 end
2315 2345 assert_redirected_to :action => 'show', :id => '1'
2316 2346 issue = Issue.find(1)
2317 2347 assert_equal 2, issue.project_id
2318 2348 assert_equal 1, issue.tracker_id
2319 2349 assert_equal 6, issue.priority_id
2320 2350 assert_equal 3, issue.category_id
2321 2351
2322 2352 mail = ActionMailer::Base.deliveries.last
2323 2353 assert_not_nil mail
2324 2354 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2325 2355 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
2326 2356 end
2327 2357
2328 2358 def test_put_update_with_tracker_change
2329 2359 @request.session[:user_id] = 2
2330 2360 ActionMailer::Base.deliveries.clear
2331 2361
2332 2362 assert_difference('Journal.count') do
2333 2363 assert_difference('JournalDetail.count', 2) do
2334 2364 put :update, :id => 1, :issue => {:project_id => '1',
2335 2365 :tracker_id => '2',
2336 2366 :priority_id => '6'
2337 2367 }
2338 2368 end
2339 2369 end
2340 2370 assert_redirected_to :action => 'show', :id => '1'
2341 2371 issue = Issue.find(1)
2342 2372 assert_equal 1, issue.project_id
2343 2373 assert_equal 2, issue.tracker_id
2344 2374 assert_equal 6, issue.priority_id
2345 2375 assert_equal 1, issue.category_id
2346 2376
2347 2377 mail = ActionMailer::Base.deliveries.last
2348 2378 assert_not_nil mail
2349 2379 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2350 2380 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
2351 2381 end
2352 2382
2353 2383 def test_put_update_with_custom_field_change
2354 2384 @request.session[:user_id] = 2
2355 2385 issue = Issue.find(1)
2356 2386 assert_equal '125', issue.custom_value_for(2).value
2357 2387
2358 2388 assert_difference('Journal.count') do
2359 2389 assert_difference('JournalDetail.count', 3) do
2360 2390 put :update, :id => 1, :issue => {:subject => 'Custom field change',
2361 2391 :priority_id => '6',
2362 2392 :category_id => '1', # no change
2363 2393 :custom_field_values => { '2' => 'New custom value' }
2364 2394 }
2365 2395 end
2366 2396 end
2367 2397 assert_redirected_to :action => 'show', :id => '1'
2368 2398 issue.reload
2369 2399 assert_equal 'New custom value', issue.custom_value_for(2).value
2370 2400
2371 2401 mail = ActionMailer::Base.deliveries.last
2372 2402 assert_not_nil mail
2373 2403 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
2374 2404 end
2375 2405
2376 2406 def test_put_update_with_multi_custom_field_change
2377 2407 field = CustomField.find(1)
2378 2408 field.update_attribute :multiple, true
2379 2409 issue = Issue.find(1)
2380 2410 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2381 2411 issue.save!
2382 2412
2383 2413 @request.session[:user_id] = 2
2384 2414 assert_difference('Journal.count') do
2385 2415 assert_difference('JournalDetail.count', 3) do
2386 2416 put :update, :id => 1,
2387 2417 :issue => {
2388 2418 :subject => 'Custom field change',
2389 2419 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
2390 2420 }
2391 2421 end
2392 2422 end
2393 2423 assert_redirected_to :action => 'show', :id => '1'
2394 2424 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
2395 2425 end
2396 2426
2397 2427 def test_put_update_with_status_and_assignee_change
2398 2428 issue = Issue.find(1)
2399 2429 assert_equal 1, issue.status_id
2400 2430 @request.session[:user_id] = 2
2401 2431 assert_difference('TimeEntry.count', 0) do
2402 2432 put :update,
2403 2433 :id => 1,
2404 2434 :issue => { :status_id => 2, :assigned_to_id => 3 },
2405 2435 :notes => 'Assigned to dlopper',
2406 2436 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
2407 2437 end
2408 2438 assert_redirected_to :action => 'show', :id => '1'
2409 2439 issue.reload
2410 2440 assert_equal 2, issue.status_id
2411 2441 j = Journal.find(:first, :order => 'id DESC')
2412 2442 assert_equal 'Assigned to dlopper', j.notes
2413 2443 assert_equal 2, j.details.size
2414 2444
2415 2445 mail = ActionMailer::Base.deliveries.last
2416 2446 assert_mail_body_match "Status changed from New to Assigned", mail
2417 2447 # subject should contain the new status
2418 2448 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
2419 2449 end
2420 2450
2421 2451 def test_put_update_with_note_only
2422 2452 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
2423 2453 # anonymous user
2424 2454 put :update,
2425 2455 :id => 1,
2426 2456 :notes => notes
2427 2457 assert_redirected_to :action => 'show', :id => '1'
2428 2458 j = Journal.find(:first, :order => 'id DESC')
2429 2459 assert_equal notes, j.notes
2430 2460 assert_equal 0, j.details.size
2431 2461 assert_equal User.anonymous, j.user
2432 2462
2433 2463 mail = ActionMailer::Base.deliveries.last
2434 2464 assert_mail_body_match notes, mail
2435 2465 end
2436 2466
2437 2467 def test_put_update_with_note_and_spent_time
2438 2468 @request.session[:user_id] = 2
2439 2469 spent_hours_before = Issue.find(1).spent_hours
2440 2470 assert_difference('TimeEntry.count') do
2441 2471 put :update,
2442 2472 :id => 1,
2443 2473 :notes => '2.5 hours added',
2444 2474 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
2445 2475 end
2446 2476 assert_redirected_to :action => 'show', :id => '1'
2447 2477
2448 2478 issue = Issue.find(1)
2449 2479
2450 2480 j = Journal.find(:first, :order => 'id DESC')
2451 2481 assert_equal '2.5 hours added', j.notes
2452 2482 assert_equal 0, j.details.size
2453 2483
2454 2484 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
2455 2485 assert_not_nil t
2456 2486 assert_equal 2.5, t.hours
2457 2487 assert_equal spent_hours_before + 2.5, issue.spent_hours
2458 2488 end
2459 2489
2460 2490 def test_put_update_with_attachment_only
2461 2491 set_tmp_attachments_directory
2462 2492
2463 2493 # Delete all fixtured journals, a race condition can occur causing the wrong
2464 2494 # journal to get fetched in the next find.
2465 2495 Journal.delete_all
2466 2496
2467 2497 # anonymous user
2468 2498 assert_difference 'Attachment.count' do
2469 2499 put :update, :id => 1,
2470 2500 :notes => '',
2471 2501 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2472 2502 end
2473 2503
2474 2504 assert_redirected_to :action => 'show', :id => '1'
2475 2505 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
2476 2506 assert j.notes.blank?
2477 2507 assert_equal 1, j.details.size
2478 2508 assert_equal 'testfile.txt', j.details.first.value
2479 2509 assert_equal User.anonymous, j.user
2480 2510
2481 2511 attachment = Attachment.first(:order => 'id DESC')
2482 2512 assert_equal Issue.find(1), attachment.container
2483 2513 assert_equal User.anonymous, attachment.author
2484 2514 assert_equal 'testfile.txt', attachment.filename
2485 2515 assert_equal 'text/plain', attachment.content_type
2486 2516 assert_equal 'test file', attachment.description
2487 2517 assert_equal 59, attachment.filesize
2488 2518 assert File.exists?(attachment.diskfile)
2489 2519 assert_equal 59, File.size(attachment.diskfile)
2490 2520
2491 2521 mail = ActionMailer::Base.deliveries.last
2492 2522 assert_mail_body_match 'testfile.txt', mail
2493 2523 end
2494 2524
2495 2525 def test_put_update_with_failure_should_save_attachments
2496 2526 set_tmp_attachments_directory
2497 2527 @request.session[:user_id] = 2
2498 2528
2499 2529 assert_no_difference 'Journal.count' do
2500 2530 assert_difference 'Attachment.count' do
2501 2531 put :update, :id => 1,
2502 2532 :issue => { :subject => '' },
2503 2533 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2504 2534 assert_response :success
2505 2535 assert_template 'edit'
2506 2536 end
2507 2537 end
2508 2538
2509 2539 attachment = Attachment.first(:order => 'id DESC')
2510 2540 assert_equal 'testfile.txt', attachment.filename
2511 2541 assert File.exists?(attachment.diskfile)
2512 2542 assert_nil attachment.container
2513 2543
2514 2544 assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
2515 2545 assert_tag 'span', :content => /testfile.txt/
2516 2546 end
2517 2547
2518 2548 def test_put_update_with_failure_should_keep_saved_attachments
2519 2549 set_tmp_attachments_directory
2520 2550 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2521 2551 @request.session[:user_id] = 2
2522 2552
2523 2553 assert_no_difference 'Journal.count' do
2524 2554 assert_no_difference 'Attachment.count' do
2525 2555 put :update, :id => 1,
2526 2556 :issue => { :subject => '' },
2527 2557 :attachments => {'p0' => {'token' => attachment.token}}
2528 2558 assert_response :success
2529 2559 assert_template 'edit'
2530 2560 end
2531 2561 end
2532 2562
2533 2563 assert_tag 'input', :attributes => {:name => 'attachments[p0][token]', :value => attachment.token}
2534 2564 assert_tag 'span', :content => /testfile.txt/
2535 2565 end
2536 2566
2537 2567 def test_put_update_should_attach_saved_attachments
2538 2568 set_tmp_attachments_directory
2539 2569 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2540 2570 @request.session[:user_id] = 2
2541 2571
2542 2572 assert_difference 'Journal.count' do
2543 2573 assert_difference 'JournalDetail.count' do
2544 2574 assert_no_difference 'Attachment.count' do
2545 2575 put :update, :id => 1,
2546 2576 :notes => 'Attachment added',
2547 2577 :attachments => {'p0' => {'token' => attachment.token}}
2548 2578 assert_redirected_to '/issues/1'
2549 2579 end
2550 2580 end
2551 2581 end
2552 2582
2553 2583 attachment.reload
2554 2584 assert_equal Issue.find(1), attachment.container
2555 2585
2556 2586 journal = Journal.first(:order => 'id DESC')
2557 2587 assert_equal 1, journal.details.size
2558 2588 assert_equal 'testfile.txt', journal.details.first.value
2559 2589 end
2560 2590
2561 2591 def test_put_update_with_attachment_that_fails_to_save
2562 2592 set_tmp_attachments_directory
2563 2593
2564 2594 # Delete all fixtured journals, a race condition can occur causing the wrong
2565 2595 # journal to get fetched in the next find.
2566 2596 Journal.delete_all
2567 2597
2568 2598 # Mock out the unsaved attachment
2569 2599 Attachment.any_instance.stubs(:create).returns(Attachment.new)
2570 2600
2571 2601 # anonymous user
2572 2602 put :update,
2573 2603 :id => 1,
2574 2604 :notes => '',
2575 2605 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
2576 2606 assert_redirected_to :action => 'show', :id => '1'
2577 2607 assert_equal '1 file(s) could not be saved.', flash[:warning]
2578 2608 end
2579 2609
2580 2610 def test_put_update_with_no_change
2581 2611 issue = Issue.find(1)
2582 2612 issue.journals.clear
2583 2613 ActionMailer::Base.deliveries.clear
2584 2614
2585 2615 put :update,
2586 2616 :id => 1,
2587 2617 :notes => ''
2588 2618 assert_redirected_to :action => 'show', :id => '1'
2589 2619
2590 2620 issue.reload
2591 2621 assert issue.journals.empty?
2592 2622 # No email should be sent
2593 2623 assert ActionMailer::Base.deliveries.empty?
2594 2624 end
2595 2625
2596 2626 def test_put_update_should_send_a_notification
2597 2627 @request.session[:user_id] = 2
2598 2628 ActionMailer::Base.deliveries.clear
2599 2629 issue = Issue.find(1)
2600 2630 old_subject = issue.subject
2601 2631 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2602 2632
2603 2633 put :update, :id => 1, :issue => {:subject => new_subject,
2604 2634 :priority_id => '6',
2605 2635 :category_id => '1' # no change
2606 2636 }
2607 2637 assert_equal 1, ActionMailer::Base.deliveries.size
2608 2638 end
2609 2639
2610 2640 def test_put_update_with_invalid_spent_time_hours_only
2611 2641 @request.session[:user_id] = 2
2612 2642 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
2613 2643
2614 2644 assert_no_difference('Journal.count') do
2615 2645 put :update,
2616 2646 :id => 1,
2617 2647 :notes => notes,
2618 2648 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
2619 2649 end
2620 2650 assert_response :success
2621 2651 assert_template 'edit'
2622 2652
2623 2653 assert_error_tag :descendant => {:content => /Activity can't be blank/}
2624 2654 assert_tag :textarea, :attributes => { :name => 'notes' }, :content => "\n"+notes
2625 2655 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
2626 2656 end
2627 2657
2628 2658 def test_put_update_with_invalid_spent_time_comments_only
2629 2659 @request.session[:user_id] = 2
2630 2660 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
2631 2661
2632 2662 assert_no_difference('Journal.count') do
2633 2663 put :update,
2634 2664 :id => 1,
2635 2665 :notes => notes,
2636 2666 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
2637 2667 end
2638 2668 assert_response :success
2639 2669 assert_template 'edit'
2640 2670
2641 2671 assert_error_tag :descendant => {:content => /Activity can't be blank/}
2642 2672 assert_error_tag :descendant => {:content => /Hours can't be blank/}
2643 2673 assert_tag :textarea, :attributes => { :name => 'notes' }, :content => "\n"+notes
2644 2674 assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => "this is my comment" }
2645 2675 end
2646 2676
2647 2677 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
2648 2678 issue = Issue.find(2)
2649 2679 @request.session[:user_id] = 2
2650 2680
2651 2681 put :update,
2652 2682 :id => issue.id,
2653 2683 :issue => {
2654 2684 :fixed_version_id => 4
2655 2685 }
2656 2686
2657 2687 assert_response :redirect
2658 2688 issue.reload
2659 2689 assert_equal 4, issue.fixed_version_id
2660 2690 assert_not_equal issue.project_id, issue.fixed_version.project_id
2661 2691 end
2662 2692
2663 2693 def test_put_update_should_redirect_back_using_the_back_url_parameter
2664 2694 issue = Issue.find(2)
2665 2695 @request.session[:user_id] = 2
2666 2696
2667 2697 put :update,
2668 2698 :id => issue.id,
2669 2699 :issue => {
2670 2700 :fixed_version_id => 4
2671 2701 },
2672 2702 :back_url => '/issues'
2673 2703
2674 2704 assert_response :redirect
2675 2705 assert_redirected_to '/issues'
2676 2706 end
2677 2707
2678 2708 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
2679 2709 issue = Issue.find(2)
2680 2710 @request.session[:user_id] = 2
2681 2711
2682 2712 put :update,
2683 2713 :id => issue.id,
2684 2714 :issue => {
2685 2715 :fixed_version_id => 4
2686 2716 },
2687 2717 :back_url => 'http://google.com'
2688 2718
2689 2719 assert_response :redirect
2690 2720 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
2691 2721 end
2692 2722
2693 2723 def test_get_bulk_edit
2694 2724 @request.session[:user_id] = 2
2695 2725 get :bulk_edit, :ids => [1, 2]
2696 2726 assert_response :success
2697 2727 assert_template 'bulk_edit'
2698 2728
2699 2729 assert_tag :select, :attributes => {:name => 'issue[project_id]'}
2700 2730 assert_tag :input, :attributes => {:name => 'issue[parent_issue_id]'}
2701 2731
2702 2732 # Project specific custom field, date type
2703 2733 field = CustomField.find(9)
2704 2734 assert !field.is_for_all?
2705 2735 assert_equal 'date', field.field_format
2706 2736 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
2707 2737
2708 2738 # System wide custom field
2709 2739 assert CustomField.find(1).is_for_all?
2710 2740 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
2711 2741
2712 2742 # Be sure we don't display inactive IssuePriorities
2713 2743 assert ! IssuePriority.find(15).active?
2714 2744 assert_no_tag :option, :attributes => {:value => '15'},
2715 2745 :parent => {:tag => 'select', :attributes => {:id => 'issue_priority_id'} }
2716 2746 end
2717 2747
2718 2748 def test_get_bulk_edit_on_different_projects
2719 2749 @request.session[:user_id] = 2
2720 2750 get :bulk_edit, :ids => [1, 2, 6]
2721 2751 assert_response :success
2722 2752 assert_template 'bulk_edit'
2723 2753
2724 2754 # Can not set issues from different projects as children of an issue
2725 2755 assert_no_tag :input, :attributes => {:name => 'issue[parent_issue_id]'}
2726 2756
2727 2757 # Project specific custom field, date type
2728 2758 field = CustomField.find(9)
2729 2759 assert !field.is_for_all?
2730 2760 assert !field.project_ids.include?(Issue.find(6).project_id)
2731 2761 assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
2732 2762 end
2733 2763
2734 2764 def test_get_bulk_edit_with_user_custom_field
2735 2765 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
2736 2766
2737 2767 @request.session[:user_id] = 2
2738 2768 get :bulk_edit, :ids => [1, 2]
2739 2769 assert_response :success
2740 2770 assert_template 'bulk_edit'
2741 2771
2742 2772 assert_tag :select,
2743 2773 :attributes => {:name => "issue[custom_field_values][#{field.id}]", :class => 'user_cf'},
2744 2774 :children => {
2745 2775 :only => {:tag => 'option'},
2746 2776 :count => Project.find(1).users.count + 2 # "no change" + "none" options
2747 2777 }
2748 2778 end
2749 2779
2750 2780 def test_get_bulk_edit_with_version_custom_field
2751 2781 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
2752 2782
2753 2783 @request.session[:user_id] = 2
2754 2784 get :bulk_edit, :ids => [1, 2]
2755 2785 assert_response :success
2756 2786 assert_template 'bulk_edit'
2757 2787
2758 2788 assert_tag :select,
2759 2789 :attributes => {:name => "issue[custom_field_values][#{field.id}]"},
2760 2790 :children => {
2761 2791 :only => {:tag => 'option'},
2762 2792 :count => Project.find(1).shared_versions.count + 2 # "no change" + "none" options
2763 2793 }
2764 2794 end
2765 2795
2766 2796 def test_get_bulk_edit_with_multi_custom_field
2767 2797 field = CustomField.find(1)
2768 2798 field.update_attribute :multiple, true
2769 2799
2770 2800 @request.session[:user_id] = 2
2771 2801 get :bulk_edit, :ids => [1, 2]
2772 2802 assert_response :success
2773 2803 assert_template 'bulk_edit'
2774 2804
2775 2805 assert_tag :select,
2776 2806 :attributes => {:name => "issue[custom_field_values][1][]"},
2777 2807 :children => {
2778 2808 :only => {:tag => 'option'},
2779 2809 :count => field.possible_values.size + 1 # "none" options
2780 2810 }
2781 2811 end
2782 2812
2783 2813 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
2784 2814 Workflow.delete_all
2785 2815 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 1)
2786 2816 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
2787 2817 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
2788 2818 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
2789 2819 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
2790 2820 Workflow.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
2791 2821 @request.session[:user_id] = 2
2792 2822 get :bulk_edit, :ids => [1, 2]
2793 2823
2794 2824 assert_response :success
2795 2825 statuses = assigns(:available_statuses)
2796 2826 assert_not_nil statuses
2797 2827 assert_equal [1, 3], statuses.map(&:id).sort
2798 2828
2799 2829 assert_tag 'select', :attributes => {:name => 'issue[status_id]'},
2800 2830 :children => {:count => 3} # 2 statuses + "no change" option
2801 2831 end
2802 2832
2803 2833 def test_bulk_edit_should_propose_target_project_open_shared_versions
2804 2834 @request.session[:user_id] = 2
2805 2835 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
2806 2836 assert_response :success
2807 2837 assert_template 'bulk_edit'
2808 2838 assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
2809 2839 assert_tag 'select',
2810 2840 :attributes => {:name => 'issue[fixed_version_id]'},
2811 2841 :descendant => {:tag => 'option', :content => '2.0'}
2812 2842 end
2813 2843
2814 2844 def test_bulk_edit_should_propose_target_project_categories
2815 2845 @request.session[:user_id] = 2
2816 2846 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
2817 2847 assert_response :success
2818 2848 assert_template 'bulk_edit'
2819 2849 assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
2820 2850 assert_tag 'select',
2821 2851 :attributes => {:name => 'issue[category_id]'},
2822 2852 :descendant => {:tag => 'option', :content => 'Recipes'}
2823 2853 end
2824 2854
2825 2855 def test_bulk_update
2826 2856 @request.session[:user_id] = 2
2827 2857 # update issues priority
2828 2858 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
2829 2859 :issue => {:priority_id => 7,
2830 2860 :assigned_to_id => '',
2831 2861 :custom_field_values => {'2' => ''}}
2832 2862
2833 2863 assert_response 302
2834 2864 # check that the issues were updated
2835 2865 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
2836 2866
2837 2867 issue = Issue.find(1)
2838 2868 journal = issue.journals.find(:first, :order => 'created_on DESC')
2839 2869 assert_equal '125', issue.custom_value_for(2).value
2840 2870 assert_equal 'Bulk editing', journal.notes
2841 2871 assert_equal 1, journal.details.size
2842 2872 end
2843 2873
2844 2874 def test_bulk_update_with_group_assignee
2845 2875 group = Group.find(11)
2846 2876 project = Project.find(1)
2847 2877 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
2848 2878
2849 2879 @request.session[:user_id] = 2
2850 2880 # update issues assignee
2851 2881 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
2852 2882 :issue => {:priority_id => '',
2853 2883 :assigned_to_id => group.id,
2854 2884 :custom_field_values => {'2' => ''}}
2855 2885
2856 2886 assert_response 302
2857 2887 assert_equal [group, group], Issue.find_all_by_id([1, 2]).collect {|i| i.assigned_to}
2858 2888 end
2859 2889
2860 2890 def test_bulk_update_on_different_projects
2861 2891 @request.session[:user_id] = 2
2862 2892 # update issues priority
2863 2893 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
2864 2894 :issue => {:priority_id => 7,
2865 2895 :assigned_to_id => '',
2866 2896 :custom_field_values => {'2' => ''}}
2867 2897
2868 2898 assert_response 302
2869 2899 # check that the issues were updated
2870 2900 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
2871 2901
2872 2902 issue = Issue.find(1)
2873 2903 journal = issue.journals.find(:first, :order => 'created_on DESC')
2874 2904 assert_equal '125', issue.custom_value_for(2).value
2875 2905 assert_equal 'Bulk editing', journal.notes
2876 2906 assert_equal 1, journal.details.size
2877 2907 end
2878 2908
2879 2909 def test_bulk_update_on_different_projects_without_rights
2880 2910 @request.session[:user_id] = 3
2881 2911 user = User.find(3)
2882 2912 action = { :controller => "issues", :action => "bulk_update" }
2883 2913 assert user.allowed_to?(action, Issue.find(1).project)
2884 2914 assert ! user.allowed_to?(action, Issue.find(6).project)
2885 2915 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
2886 2916 :issue => {:priority_id => 7,
2887 2917 :assigned_to_id => '',
2888 2918 :custom_field_values => {'2' => ''}}
2889 2919 assert_response 403
2890 2920 assert_not_equal "Bulk should fail", Journal.last.notes
2891 2921 end
2892 2922
2893 2923 def test_bullk_update_should_send_a_notification
2894 2924 @request.session[:user_id] = 2
2895 2925 ActionMailer::Base.deliveries.clear
2896 2926 post(:bulk_update,
2897 2927 {
2898 2928 :ids => [1, 2],
2899 2929 :notes => 'Bulk editing',
2900 2930 :issue => {
2901 2931 :priority_id => 7,
2902 2932 :assigned_to_id => '',
2903 2933 :custom_field_values => {'2' => ''}
2904 2934 }
2905 2935 })
2906 2936
2907 2937 assert_response 302
2908 2938 assert_equal 2, ActionMailer::Base.deliveries.size
2909 2939 end
2910 2940
2911 2941 def test_bulk_update_project
2912 2942 @request.session[:user_id] = 2
2913 2943 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
2914 2944 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2915 2945 # Issues moved to project 2
2916 2946 assert_equal 2, Issue.find(1).project_id
2917 2947 assert_equal 2, Issue.find(2).project_id
2918 2948 # No tracker change
2919 2949 assert_equal 1, Issue.find(1).tracker_id
2920 2950 assert_equal 2, Issue.find(2).tracker_id
2921 2951 end
2922 2952
2923 2953 def test_bulk_update_project_on_single_issue_should_follow_when_needed
2924 2954 @request.session[:user_id] = 2
2925 2955 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
2926 2956 assert_redirected_to '/issues/1'
2927 2957 end
2928 2958
2929 2959 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
2930 2960 @request.session[:user_id] = 2
2931 2961 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
2932 2962 assert_redirected_to '/projects/onlinestore/issues'
2933 2963 end
2934 2964
2935 2965 def test_bulk_update_tracker
2936 2966 @request.session[:user_id] = 2
2937 2967 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
2938 2968 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2939 2969 assert_equal 2, Issue.find(1).tracker_id
2940 2970 assert_equal 2, Issue.find(2).tracker_id
2941 2971 end
2942 2972
2943 2973 def test_bulk_update_status
2944 2974 @request.session[:user_id] = 2
2945 2975 # update issues priority
2946 2976 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
2947 2977 :issue => {:priority_id => '',
2948 2978 :assigned_to_id => '',
2949 2979 :status_id => '5'}
2950 2980
2951 2981 assert_response 302
2952 2982 issue = Issue.find(1)
2953 2983 assert issue.closed?
2954 2984 end
2955 2985
2956 2986 def test_bulk_update_priority
2957 2987 @request.session[:user_id] = 2
2958 2988 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
2959 2989
2960 2990 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2961 2991 assert_equal 6, Issue.find(1).priority_id
2962 2992 assert_equal 6, Issue.find(2).priority_id
2963 2993 end
2964 2994
2965 2995 def test_bulk_update_with_notes
2966 2996 @request.session[:user_id] = 2
2967 2997 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
2968 2998
2969 2999 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
2970 3000 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
2971 3001 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
2972 3002 end
2973 3003
2974 3004 def test_bulk_update_parent_id
2975 3005 @request.session[:user_id] = 2
2976 3006 post :bulk_update, :ids => [1, 3],
2977 3007 :notes => 'Bulk editing parent',
2978 3008 :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '', :parent_issue_id => '2'}
2979 3009
2980 3010 assert_response 302
2981 3011 parent = Issue.find(2)
2982 3012 assert_equal parent.id, Issue.find(1).parent_id
2983 3013 assert_equal parent.id, Issue.find(3).parent_id
2984 3014 assert_equal [1, 3], parent.children.collect(&:id).sort
2985 3015 end
2986 3016
2987 3017 def test_bulk_update_custom_field
2988 3018 @request.session[:user_id] = 2
2989 3019 # update issues priority
2990 3020 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
2991 3021 :issue => {:priority_id => '',
2992 3022 :assigned_to_id => '',
2993 3023 :custom_field_values => {'2' => '777'}}
2994 3024
2995 3025 assert_response 302
2996 3026
2997 3027 issue = Issue.find(1)
2998 3028 journal = issue.journals.find(:first, :order => 'created_on DESC')
2999 3029 assert_equal '777', issue.custom_value_for(2).value
3000 3030 assert_equal 1, journal.details.size
3001 3031 assert_equal '125', journal.details.first.old_value
3002 3032 assert_equal '777', journal.details.first.value
3003 3033 end
3004 3034
3005 3035 def test_bulk_update_custom_field_to_blank
3006 3036 @request.session[:user_id] = 2
3007 3037 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
3008 3038 :issue => {:priority_id => '',
3009 3039 :assigned_to_id => '',
3010 3040 :custom_field_values => {'1' => '__none__'}}
3011 3041 assert_response 302
3012 3042 assert_equal '', Issue.find(1).custom_field_value(1)
3013 3043 assert_equal '', Issue.find(3).custom_field_value(1)
3014 3044 end
3015 3045
3016 3046 def test_bulk_update_multi_custom_field
3017 3047 field = CustomField.find(1)
3018 3048 field.update_attribute :multiple, true
3019 3049
3020 3050 @request.session[:user_id] = 2
3021 3051 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
3022 3052 :issue => {:priority_id => '',
3023 3053 :assigned_to_id => '',
3024 3054 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
3025 3055
3026 3056 assert_response 302
3027 3057
3028 3058 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
3029 3059 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
3030 3060 # the custom field is not associated with the issue tracker
3031 3061 assert_nil Issue.find(2).custom_field_value(1)
3032 3062 end
3033 3063
3034 3064 def test_bulk_update_multi_custom_field_to_blank
3035 3065 field = CustomField.find(1)
3036 3066 field.update_attribute :multiple, true
3037 3067
3038 3068 @request.session[:user_id] = 2
3039 3069 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
3040 3070 :issue => {:priority_id => '',
3041 3071 :assigned_to_id => '',
3042 3072 :custom_field_values => {'1' => ['__none__']}}
3043 3073 assert_response 302
3044 3074 assert_equal [''], Issue.find(1).custom_field_value(1)
3045 3075 assert_equal [''], Issue.find(3).custom_field_value(1)
3046 3076 end
3047 3077
3048 3078 def test_bulk_update_unassign
3049 3079 assert_not_nil Issue.find(2).assigned_to
3050 3080 @request.session[:user_id] = 2
3051 3081 # unassign issues
3052 3082 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
3053 3083 assert_response 302
3054 3084 # check that the issues were updated
3055 3085 assert_nil Issue.find(2).assigned_to
3056 3086 end
3057 3087
3058 3088 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
3059 3089 @request.session[:user_id] = 2
3060 3090
3061 3091 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
3062 3092
3063 3093 assert_response :redirect
3064 3094 issues = Issue.find([1,2])
3065 3095 issues.each do |issue|
3066 3096 assert_equal 4, issue.fixed_version_id
3067 3097 assert_not_equal issue.project_id, issue.fixed_version.project_id
3068 3098 end
3069 3099 end
3070 3100
3071 3101 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
3072 3102 @request.session[:user_id] = 2
3073 3103 post :bulk_update, :ids => [1,2], :back_url => '/issues'
3074 3104
3075 3105 assert_response :redirect
3076 3106 assert_redirected_to '/issues'
3077 3107 end
3078 3108
3079 3109 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3080 3110 @request.session[:user_id] = 2
3081 3111 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
3082 3112
3083 3113 assert_response :redirect
3084 3114 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
3085 3115 end
3086 3116
3087 3117 def test_bulk_update_with_failure_should_set_flash
3088 3118 @request.session[:user_id] = 2
3089 3119 Issue.update_all("subject = ''", "id = 2") # Make it invalid
3090 3120 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
3091 3121
3092 3122 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3093 3123 assert_equal 'Failed to save 1 issue(s) on 2 selected: #2.', flash[:error]
3094 3124 end
3095 3125
3096 3126 def test_get_bulk_copy
3097 3127 @request.session[:user_id] = 2
3098 3128 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
3099 3129 assert_response :success
3100 3130 assert_template 'bulk_edit'
3101 3131
3102 3132 issues = assigns(:issues)
3103 3133 assert_not_nil issues
3104 3134 assert_equal [1, 2, 3], issues.map(&:id).sort
3105 3135
3106 3136 assert_select 'input[name=copy_attachments]'
3107 3137 end
3108 3138
3109 3139 def test_bulk_copy_to_another_project
3110 3140 @request.session[:user_id] = 2
3111 3141 assert_difference 'Issue.count', 2 do
3112 3142 assert_no_difference 'Project.find(1).issues.count' do
3113 3143 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
3114 3144 end
3115 3145 end
3116 3146 assert_redirected_to '/projects/ecookbook/issues'
3117 3147
3118 3148 copies = Issue.all(:order => 'id DESC', :limit => issues.size)
3119 3149 copies.each do |copy|
3120 3150 assert_equal 2, copy.project_id
3121 3151 end
3122 3152 end
3123 3153
3124 3154 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
3125 3155 @request.session[:user_id] = 2
3126 3156 issues = [
3127 3157 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1, :priority_id => 2, :subject => 'issue 1', :author_id => 1, :assigned_to_id => nil),
3128 3158 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2, :priority_id => 1, :subject => 'issue 2', :author_id => 2, :assigned_to_id => 3)
3129 3159 ]
3130 3160
3131 3161 assert_difference 'Issue.count', issues.size do
3132 3162 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
3133 3163 :issue => {
3134 3164 :project_id => '', :tracker_id => '', :assigned_to_id => '',
3135 3165 :status_id => '', :start_date => '', :due_date => ''
3136 3166 }
3137 3167 end
3138 3168
3139 3169 copies = Issue.all(:order => 'id DESC', :limit => issues.size)
3140 3170 issues.each do |orig|
3141 3171 copy = copies.detect {|c| c.subject == orig.subject}
3142 3172 assert_not_nil copy
3143 3173 assert_equal orig.project_id, copy.project_id
3144 3174 assert_equal orig.tracker_id, copy.tracker_id
3145 3175 assert_equal orig.status_id, copy.status_id
3146 3176 assert_equal orig.assigned_to_id, copy.assigned_to_id
3147 3177 assert_equal orig.priority_id, copy.priority_id
3148 3178 end
3149 3179 end
3150 3180
3151 3181 def test_bulk_copy_should_allow_changing_the_issue_attributes
3152 3182 # Fixes random test failure with Mysql
3153 3183 # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
3154 3184 # doesn't return the expected results
3155 3185 Issue.delete_all("project_id=2")
3156 3186
3157 3187 @request.session[:user_id] = 2
3158 3188 assert_difference 'Issue.count', 2 do
3159 3189 assert_no_difference 'Project.find(1).issues.count' do
3160 3190 post :bulk_update, :ids => [1, 2], :copy => '1',
3161 3191 :issue => {
3162 3192 :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
3163 3193 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
3164 3194 }
3165 3195 end
3166 3196 end
3167 3197
3168 3198 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
3169 3199 assert_equal 2, copied_issues.size
3170 3200 copied_issues.each do |issue|
3171 3201 assert_equal 2, issue.project_id, "Project is incorrect"
3172 3202 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
3173 3203 assert_equal 1, issue.status_id, "Status is incorrect"
3174 3204 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
3175 3205 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
3176 3206 end
3177 3207 end
3178 3208
3179 3209 def test_bulk_copy_should_allow_adding_a_note
3180 3210 @request.session[:user_id] = 2
3181 3211 assert_difference 'Issue.count', 1 do
3182 3212 post :bulk_update, :ids => [1], :copy => '1',
3183 3213 :notes => 'Copying one issue',
3184 3214 :issue => {
3185 3215 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
3186 3216 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
3187 3217 }
3188 3218 end
3189 3219
3190 3220 issue = Issue.first(:order => 'id DESC')
3191 3221 assert_equal 1, issue.journals.size
3192 3222 journal = issue.journals.first
3193 3223 assert_equal 0, journal.details.size
3194 3224 assert_equal 'Copying one issue', journal.notes
3195 3225 end
3196 3226
3197 3227 def test_bulk_copy_should_allow_not_copying_the_attachments
3198 3228 attachment_count = Issue.find(3).attachments.size
3199 3229 assert attachment_count > 0
3200 3230 @request.session[:user_id] = 2
3201 3231
3202 3232 assert_difference 'Issue.count', 1 do
3203 3233 assert_no_difference 'Attachment.count' do
3204 3234 post :bulk_update, :ids => [3], :copy => '1',
3205 3235 :issue => {
3206 3236 :project_id => ''
3207 3237 }
3208 3238 end
3209 3239 end
3210 3240 end
3211 3241
3212 3242 def test_bulk_copy_should_allow_copying_the_attachments
3213 3243 attachment_count = Issue.find(3).attachments.size
3214 3244 assert attachment_count > 0
3215 3245 @request.session[:user_id] = 2
3216 3246
3217 3247 assert_difference 'Issue.count', 1 do
3218 3248 assert_difference 'Attachment.count', attachment_count do
3219 3249 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
3220 3250 :issue => {
3221 3251 :project_id => ''
3222 3252 }
3223 3253 end
3224 3254 end
3225 3255 end
3226 3256
3227 3257 def test_bulk_copy_to_another_project_should_follow_when_needed
3228 3258 @request.session[:user_id] = 2
3229 3259 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
3230 3260 issue = Issue.first(:order => 'id DESC')
3231 3261 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
3232 3262 end
3233 3263
3234 3264 def test_destroy_issue_with_no_time_entries
3235 3265 assert_nil TimeEntry.find_by_issue_id(2)
3236 3266 @request.session[:user_id] = 2
3237 3267
3238 3268 assert_difference 'Issue.count', -1 do
3239 3269 delete :destroy, :id => 2
3240 3270 end
3241 3271 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3242 3272 assert_nil Issue.find_by_id(2)
3243 3273 end
3244 3274
3245 3275 def test_destroy_issues_with_time_entries
3246 3276 @request.session[:user_id] = 2
3247 3277
3248 3278 assert_no_difference 'Issue.count' do
3249 3279 delete :destroy, :ids => [1, 3]
3250 3280 end
3251 3281 assert_response :success
3252 3282 assert_template 'destroy'
3253 3283 assert_not_nil assigns(:hours)
3254 3284 assert Issue.find_by_id(1) && Issue.find_by_id(3)
3255 3285 assert_tag 'form',
3256 3286 :descendant => {:tag => 'input', :attributes => {:name => '_method', :value => 'delete'}}
3257 3287 end
3258 3288
3259 3289 def test_destroy_issues_and_destroy_time_entries
3260 3290 @request.session[:user_id] = 2
3261 3291
3262 3292 assert_difference 'Issue.count', -2 do
3263 3293 assert_difference 'TimeEntry.count', -3 do
3264 3294 delete :destroy, :ids => [1, 3], :todo => 'destroy'
3265 3295 end
3266 3296 end
3267 3297 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3268 3298 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3269 3299 assert_nil TimeEntry.find_by_id([1, 2])
3270 3300 end
3271 3301
3272 3302 def test_destroy_issues_and_assign_time_entries_to_project
3273 3303 @request.session[:user_id] = 2
3274 3304
3275 3305 assert_difference 'Issue.count', -2 do
3276 3306 assert_no_difference 'TimeEntry.count' do
3277 3307 delete :destroy, :ids => [1, 3], :todo => 'nullify'
3278 3308 end
3279 3309 end
3280 3310 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3281 3311 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3282 3312 assert_nil TimeEntry.find(1).issue_id
3283 3313 assert_nil TimeEntry.find(2).issue_id
3284 3314 end
3285 3315
3286 3316 def test_destroy_issues_and_reassign_time_entries_to_another_issue
3287 3317 @request.session[:user_id] = 2
3288 3318
3289 3319 assert_difference 'Issue.count', -2 do
3290 3320 assert_no_difference 'TimeEntry.count' do
3291 3321 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
3292 3322 end
3293 3323 end
3294 3324 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3295 3325 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3296 3326 assert_equal 2, TimeEntry.find(1).issue_id
3297 3327 assert_equal 2, TimeEntry.find(2).issue_id
3298 3328 end
3299 3329
3300 3330 def test_destroy_issues_from_different_projects
3301 3331 @request.session[:user_id] = 2
3302 3332
3303 3333 assert_difference 'Issue.count', -3 do
3304 3334 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
3305 3335 end
3306 3336 assert_redirected_to :controller => 'issues', :action => 'index'
3307 3337 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
3308 3338 end
3309 3339
3310 3340 def test_destroy_parent_and_child_issues
3311 3341 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
3312 3342 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
3313 3343 assert child.is_descendant_of?(parent.reload)
3314 3344
3315 3345 @request.session[:user_id] = 2
3316 3346 assert_difference 'Issue.count', -2 do
3317 3347 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
3318 3348 end
3319 3349 assert_response 302
3320 3350 end
3321 3351
3322 3352 def test_default_search_scope
3323 3353 get :index
3324 3354 assert_tag :div, :attributes => {:id => 'quick-search'},
3325 3355 :child => {:tag => 'form',
3326 3356 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
3327 3357 end
3328 3358 end
General Comments 0
You need to be logged in to leave comments. Login now