##// END OF EJS Templates
Merged r13921 (#18894)....
Jean-Philippe Lang -
r13638:a5a7c62b69f1
parent child
Show More
@@ -1,47 +1,47
1 1 <%= form_tag({}) do -%>
2 2 <%= hidden_field_tag 'back_url', url_for(params), :id => nil %>
3 3 <div class="autoscroll">
4 4 <table class="list issues <%= sort_css_classes %>">
5 5 <thead>
6 6 <tr>
7 7 <th class="checkbox hide-when-print">
8 8 <%= link_to image_tag('toggle_check.png'), {},
9 9 :onclick => 'toggleIssuesSelection(this); return false;',
10 10 :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %>
11 11 </th>
12 12 <% query.inline_columns.each do |column| %>
13 13 <%= column_header(column) %>
14 14 <% end %>
15 15 </tr>
16 16 </thead>
17 17 <% previous_group = false %>
18 18 <tbody>
19 19 <% issue_list(issues) do |issue, level| -%>
20 20 <% if @query.grouped? && (group = @query.group_by_column.value(issue)) != previous_group %>
21 21 <% reset_cycle %>
22 22 <tr class="group open">
23 23 <td colspan="<%= query.inline_columns.size + 2 %>">
24 24 <span class="expander" onclick="toggleRowGroup(this);">&nbsp;</span>
25 <%= group.blank? ? l(:label_none) : column_content(@query.group_by_column, issue) %> <span class="count"><%= @issue_count_by_group[group] %></span>
25 <%= (group.blank? && group != false) ? l(:label_none) : column_content(@query.group_by_column, issue) %> <span class="count"><%= @issue_count_by_group[group] %></span>
26 26 <%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}",
27 27 "toggleAllRowGroups(this)", :class => 'toggle-all') %>
28 28 </td>
29 29 </tr>
30 30 <% previous_group = group %>
31 31 <% end %>
32 32 <tr id="issue-<%= issue.id %>" class="hascontextmenu <%= cycle('odd', 'even') %> <%= issue.css_classes %> <%= level > 0 ? "idnt idnt-#{level}" : nil %>">
33 33 <td class="checkbox hide-when-print"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
34 34 <%= raw query.inline_columns.map {|column| "<td class=\"#{column.css_classes}\">#{column_content(column, issue)}</td>"}.join %>
35 35 </tr>
36 36 <% @query.block_columns.each do |column|
37 37 if (text = column_content(column, issue)) && text.present? -%>
38 38 <tr class="<%= current_cycle %>">
39 39 <td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>"><%= text %></td>
40 40 </tr>
41 41 <% end -%>
42 42 <% end -%>
43 43 <% end -%>
44 44 </tbody>
45 45 </table>
46 46 </div>
47 47 <% end -%>
@@ -1,4034 +1,4050
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 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
20 20 class IssuesControllerTest < ActionController::TestCase
21 21 fixtures :projects,
22 22 :users,
23 23 :roles,
24 24 :members,
25 25 :member_roles,
26 26 :issues,
27 27 :issue_statuses,
28 28 :issue_relations,
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 User.current = nil
52 52 end
53 53
54 54 def test_index
55 55 with_settings :default_language => "en" do
56 56 get :index
57 57 assert_response :success
58 58 assert_template 'index'
59 59 assert_not_nil assigns(:issues)
60 60 assert_nil assigns(:project)
61 61
62 62 # links to visible issues
63 63 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
64 64 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
65 65 # private projects hidden
66 66 assert_select 'a[href=/issues/6]', 0
67 67 assert_select 'a[href=/issues/4]', 0
68 68 # project column
69 69 assert_select 'th', :text => /Project/
70 70 end
71 71 end
72 72
73 73 def test_index_should_not_list_issues_when_module_disabled
74 74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
75 75 get :index
76 76 assert_response :success
77 77 assert_template 'index'
78 78 assert_not_nil assigns(:issues)
79 79 assert_nil assigns(:project)
80 80
81 81 assert_select 'a[href=/issues/1]', 0
82 82 assert_select 'a[href=/issues/5]', :text => /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
99 99 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
100 100 assert_select 'a[href=/issues/5]', 0
101 101 end
102 102
103 103 def test_index_with_project_and_subprojects
104 104 Setting.display_subprojects_issues = 1
105 105 get :index, :project_id => 1
106 106 assert_response :success
107 107 assert_template 'index'
108 108 assert_not_nil assigns(:issues)
109 109
110 110 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
111 111 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
112 112 assert_select 'a[href=/issues/6]', 0
113 113 end
114 114
115 115 def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
116 116 @request.session[:user_id] = 2
117 117 Setting.display_subprojects_issues = 1
118 118 get :index, :project_id => 1
119 119 assert_response :success
120 120 assert_template 'index'
121 121 assert_not_nil assigns(:issues)
122 122
123 123 assert_select 'a[href=/issues/1]', :text => /#{ESCAPED_UCANT} print recipes/
124 124 assert_select 'a[href=/issues/5]', :text => /Subproject issue/
125 125 assert_select 'a[href=/issues/6]', :text => /Issue of a private subproject/
126 126 end
127 127
128 128 def test_index_with_project_and_default_filter
129 129 get :index, :project_id => 1, :set_filter => 1
130 130 assert_response :success
131 131 assert_template 'index'
132 132 assert_not_nil assigns(:issues)
133 133
134 134 query = assigns(:query)
135 135 assert_not_nil query
136 136 # default filter
137 137 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
138 138 end
139 139
140 140 def test_index_with_project_and_filter
141 141 get :index, :project_id => 1, :set_filter => 1,
142 142 :f => ['tracker_id'],
143 143 :op => {'tracker_id' => '='},
144 144 :v => {'tracker_id' => ['1']}
145 145 assert_response :success
146 146 assert_template 'index'
147 147 assert_not_nil assigns(:issues)
148 148
149 149 query = assigns(:query)
150 150 assert_not_nil query
151 151 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
152 152 end
153 153
154 154 def test_index_with_short_filters
155 155 to_test = {
156 156 'status_id' => {
157 157 'o' => { :op => 'o', :values => [''] },
158 158 'c' => { :op => 'c', :values => [''] },
159 159 '7' => { :op => '=', :values => ['7'] },
160 160 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
161 161 '=7' => { :op => '=', :values => ['7'] },
162 162 '!3' => { :op => '!', :values => ['3'] },
163 163 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
164 164 'subject' => {
165 165 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
166 166 'o' => { :op => '=', :values => ['o'] },
167 167 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
168 168 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
169 169 'tracker_id' => {
170 170 '3' => { :op => '=', :values => ['3'] },
171 171 '=3' => { :op => '=', :values => ['3'] }},
172 172 'start_date' => {
173 173 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
174 174 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
175 175 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
176 176 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
177 177 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
178 178 '<t+2' => { :op => '<t+', :values => ['2'] },
179 179 '>t+2' => { :op => '>t+', :values => ['2'] },
180 180 't+2' => { :op => 't+', :values => ['2'] },
181 181 't' => { :op => 't', :values => [''] },
182 182 'w' => { :op => 'w', :values => [''] },
183 183 '>t-2' => { :op => '>t-', :values => ['2'] },
184 184 '<t-2' => { :op => '<t-', :values => ['2'] },
185 185 't-2' => { :op => 't-', :values => ['2'] }},
186 186 'created_on' => {
187 187 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
188 188 '<t-2' => { :op => '<t-', :values => ['2'] },
189 189 '>t-2' => { :op => '>t-', :values => ['2'] },
190 190 't-2' => { :op => 't-', :values => ['2'] }},
191 191 'cf_1' => {
192 192 'c' => { :op => '=', :values => ['c'] },
193 193 '!c' => { :op => '!', :values => ['c'] },
194 194 '!*' => { :op => '!*', :values => [''] },
195 195 '*' => { :op => '*', :values => [''] }},
196 196 'estimated_hours' => {
197 197 '=13.4' => { :op => '=', :values => ['13.4'] },
198 198 '>=45' => { :op => '>=', :values => ['45'] },
199 199 '<=125' => { :op => '<=', :values => ['125'] },
200 200 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
201 201 '!*' => { :op => '!*', :values => [''] },
202 202 '*' => { :op => '*', :values => [''] }}
203 203 }
204 204
205 205 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
206 206
207 207 to_test.each do |field, expression_and_expected|
208 208 expression_and_expected.each do |filter_expression, expected|
209 209
210 210 get :index, :set_filter => 1, field => filter_expression
211 211
212 212 assert_response :success
213 213 assert_template 'index'
214 214 assert_not_nil assigns(:issues)
215 215
216 216 query = assigns(:query)
217 217 assert_not_nil query
218 218 assert query.has_filter?(field)
219 219 assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
220 220 end
221 221 end
222 222 end
223 223
224 224 def test_index_with_project_and_empty_filters
225 225 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
226 226 assert_response :success
227 227 assert_template 'index'
228 228 assert_not_nil assigns(:issues)
229 229
230 230 query = assigns(:query)
231 231 assert_not_nil query
232 232 # no filter
233 233 assert_equal({}, query.filters)
234 234 end
235 235
236 236 def test_index_with_project_custom_field_filter
237 237 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
238 238 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
239 239 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
240 240 filter_name = "project.cf_#{field.id}"
241 241 @request.session[:user_id] = 1
242 242
243 243 get :index, :set_filter => 1,
244 244 :f => [filter_name],
245 245 :op => {filter_name => '='},
246 246 :v => {filter_name => ['Foo']}
247 247 assert_response :success
248 248 assert_template 'index'
249 249 assert_equal [3, 5], assigns(:issues).map(&:project_id).uniq.sort
250 250 end
251 251
252 252 def test_index_with_query
253 253 get :index, :project_id => 1, :query_id => 5
254 254 assert_response :success
255 255 assert_template 'index'
256 256 assert_not_nil assigns(:issues)
257 257 assert_nil assigns(:issue_count_by_group)
258 258 end
259 259
260 260 def test_index_with_query_grouped_by_tracker
261 261 get :index, :project_id => 1, :query_id => 6
262 262 assert_response :success
263 263 assert_template 'index'
264 264 assert_not_nil assigns(:issues)
265 265 assert_not_nil assigns(:issue_count_by_group)
266 266 end
267 267
268 268 def test_index_with_query_grouped_by_list_custom_field
269 269 get :index, :project_id => 1, :query_id => 9
270 270 assert_response :success
271 271 assert_template 'index'
272 272 assert_not_nil assigns(:issues)
273 273 assert_not_nil assigns(:issue_count_by_group)
274 274 end
275 275
276 276 def test_index_with_query_grouped_by_user_custom_field
277 277 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
278 278 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
279 279 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
280 280 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
281 281 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
282 282
283 283 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
284 284 assert_response :success
285 285
286 286 assert_select 'tr.group', 3
287 287 assert_select 'tr.group' do
288 288 assert_select 'a', :text => 'John Smith'
289 289 assert_select 'span.count', :text => '1'
290 290 end
291 291 assert_select 'tr.group' do
292 292 assert_select 'a', :text => 'Dave Lopper'
293 293 assert_select 'span.count', :text => '2'
294 294 end
295 295 end
296 296
297 def test_index_grouped_by_boolean_custom_field_should_distinguish_blank_and_false_values
298 cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool')
299 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '1')
300 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
301 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '')
302
303 with_settings :default_language => 'en' do
304 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
305 assert_response :success
306 end
307
308 assert_select 'tr.group', :text => /Yes/
309 assert_select 'tr.group', :text => /No/
310 assert_select 'tr.group', :text => /none/
311 end
312
297 313 def test_index_with_query_grouped_by_tracker_in_normal_order
298 314 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
299 315
300 316 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
301 317 assert_response :success
302 318
303 319 trackers = assigns(:issues).map(&:tracker).uniq
304 320 assert_equal [1, 2, 3], trackers.map(&:id)
305 321 end
306 322
307 323 def test_index_with_query_grouped_by_tracker_in_reverse_order
308 324 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
309 325
310 326 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
311 327 assert_response :success
312 328
313 329 trackers = assigns(:issues).map(&:tracker).uniq
314 330 assert_equal [3, 2, 1], trackers.map(&:id)
315 331 end
316 332
317 333 def test_index_with_query_id_and_project_id_should_set_session_query
318 334 get :index, :project_id => 1, :query_id => 4
319 335 assert_response :success
320 336 assert_kind_of Hash, session[:query]
321 337 assert_equal 4, session[:query][:id]
322 338 assert_equal 1, session[:query][:project_id]
323 339 end
324 340
325 341 def test_index_with_invalid_query_id_should_respond_404
326 342 get :index, :project_id => 1, :query_id => 999
327 343 assert_response 404
328 344 end
329 345
330 346 def test_index_with_cross_project_query_in_session_should_show_project_issues
331 347 q = IssueQuery.create!(:name => "test", :user_id => 2, :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
332 348 @request.session[:query] = {:id => q.id, :project_id => 1}
333 349
334 350 with_settings :display_subprojects_issues => '0' do
335 351 get :index, :project_id => 1
336 352 end
337 353 assert_response :success
338 354 assert_not_nil assigns(:query)
339 355 assert_equal q.id, assigns(:query).id
340 356 assert_equal 1, assigns(:query).project_id
341 357 assert_equal [1], assigns(:issues).map(&:project_id).uniq
342 358 end
343 359
344 360 def test_private_query_should_not_be_available_to_other_users
345 361 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
346 362 @request.session[:user_id] = 3
347 363
348 364 get :index, :query_id => q.id
349 365 assert_response 403
350 366 end
351 367
352 368 def test_private_query_should_be_available_to_its_user
353 369 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
354 370 @request.session[:user_id] = 2
355 371
356 372 get :index, :query_id => q.id
357 373 assert_response :success
358 374 end
359 375
360 376 def test_public_query_should_be_available_to_other_users
361 377 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
362 378 @request.session[:user_id] = 3
363 379
364 380 get :index, :query_id => q.id
365 381 assert_response :success
366 382 end
367 383
368 384 def test_index_should_omit_page_param_in_export_links
369 385 get :index, :page => 2
370 386 assert_response :success
371 387 assert_select 'a.atom[href=/issues.atom]'
372 388 assert_select 'a.csv[href=/issues.csv]'
373 389 assert_select 'a.pdf[href=/issues.pdf]'
374 390 assert_select 'form#csv-export-form[action=/issues.csv]'
375 391 end
376 392
377 393 def test_index_should_not_warn_when_not_exceeding_export_limit
378 394 with_settings :issues_export_limit => 200 do
379 395 get :index
380 396 assert_select '#csv-export-options p.icon-warning', 0
381 397 end
382 398 end
383 399
384 400 def test_index_should_warn_when_exceeding_export_limit
385 401 with_settings :issues_export_limit => 2 do
386 402 get :index
387 403 assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
388 404 end
389 405 end
390 406
391 407 def test_index_csv
392 408 get :index, :format => 'csv'
393 409 assert_response :success
394 410 assert_not_nil assigns(:issues)
395 411 assert_equal 'text/csv; header=present', @response.content_type
396 412 assert @response.body.starts_with?("#,")
397 413 lines = @response.body.chomp.split("\n")
398 414 assert_equal assigns(:query).columns.size, lines[0].split(',').size
399 415 end
400 416
401 417 def test_index_csv_with_project
402 418 get :index, :project_id => 1, :format => 'csv'
403 419 assert_response :success
404 420 assert_not_nil assigns(:issues)
405 421 assert_equal 'text/csv; header=present', @response.content_type
406 422 end
407 423
408 424 def test_index_csv_with_description
409 425 Issue.generate!(:description => 'test_index_csv_with_description')
410 426
411 427 with_settings :default_language => 'en' do
412 428 get :index, :format => 'csv', :description => '1'
413 429 assert_response :success
414 430 assert_not_nil assigns(:issues)
415 431 end
416 432
417 433 assert_equal 'text/csv; header=present', response.content_type
418 434 headers = response.body.chomp.split("\n").first.split(',')
419 435 assert_include 'Description', headers
420 436 assert_include 'test_index_csv_with_description', response.body
421 437 end
422 438
423 439 def test_index_csv_with_spent_time_column
424 440 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
425 441 TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
426 442
427 443 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
428 444 assert_response :success
429 445 assert_equal 'text/csv; header=present', @response.content_type
430 446 lines = @response.body.chomp.split("\n")
431 447 assert_include "#{issue.id},#{issue.subject},7.33", lines
432 448 end
433 449
434 450 def test_index_csv_with_all_columns
435 451 get :index, :format => 'csv', :columns => 'all'
436 452 assert_response :success
437 453 assert_not_nil assigns(:issues)
438 454 assert_equal 'text/csv; header=present', @response.content_type
439 455 assert_match /\A#,/, response.body
440 456 lines = response.body.chomp.split("\n")
441 457 assert_equal assigns(:query).available_inline_columns.size, lines[0].split(',').size
442 458 end
443 459
444 460 def test_index_csv_with_multi_column_field
445 461 CustomField.find(1).update_attribute :multiple, true
446 462 issue = Issue.find(1)
447 463 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
448 464 issue.save!
449 465
450 466 get :index, :format => 'csv', :columns => 'all'
451 467 assert_response :success
452 468 lines = @response.body.chomp.split("\n")
453 469 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
454 470 end
455 471
456 472 def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
457 473 field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
458 474 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
459 475
460 476 with_settings :default_language => 'fr' do
461 477 get :index, :format => 'csv', :columns => 'all'
462 478 assert_response :success
463 479 issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
464 480 assert_include '185,60', issue_line
465 481 end
466 482
467 483 with_settings :default_language => 'en' do
468 484 get :index, :format => 'csv', :columns => 'all'
469 485 assert_response :success
470 486 issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
471 487 assert_include '185.60', issue_line
472 488 end
473 489 end
474 490
475 491 def test_index_csv_should_fill_parent_column_with_parent_id
476 492 Issue.delete_all
477 493 parent = Issue.generate!
478 494 child = Issue.generate!(:parent_issue_id => parent.id)
479 495
480 496 with_settings :default_language => 'en' do
481 497 get :index, :format => 'csv', :c => %w(parent)
482 498 end
483 499 lines = response.body.split
484 500 assert_include "#{child.id},#{parent.id}", lines
485 501 end
486 502
487 503 def test_index_csv_big_5
488 504 with_settings :default_language => "zh-TW" do
489 505 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
490 506 str_big5 = "\xa4@\xa4\xeb"
491 507 if str_utf8.respond_to?(:force_encoding)
492 508 str_utf8.force_encoding('UTF-8')
493 509 str_big5.force_encoding('Big5')
494 510 end
495 511 issue = Issue.generate!(:subject => str_utf8)
496 512
497 513 get :index, :project_id => 1,
498 514 :f => ['subject'],
499 515 :op => '=', :values => [str_utf8],
500 516 :format => 'csv'
501 517 assert_equal 'text/csv; header=present', @response.content_type
502 518 lines = @response.body.chomp.split("\n")
503 519 s1 = "\xaa\xac\xbaA"
504 520 if str_utf8.respond_to?(:force_encoding)
505 521 s1.force_encoding('Big5')
506 522 end
507 523 assert_include s1, lines[0]
508 524 assert_include str_big5, lines[1]
509 525 end
510 526 end
511 527
512 528 def test_index_csv_cannot_convert_should_be_replaced_big_5
513 529 with_settings :default_language => "zh-TW" do
514 530 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
515 531 if str_utf8.respond_to?(:force_encoding)
516 532 str_utf8.force_encoding('UTF-8')
517 533 end
518 534 issue = Issue.generate!(:subject => str_utf8)
519 535
520 536 get :index, :project_id => 1,
521 537 :f => ['subject'],
522 538 :op => '=', :values => [str_utf8],
523 539 :c => ['status', 'subject'],
524 540 :format => 'csv',
525 541 :set_filter => 1
526 542 assert_equal 'text/csv; header=present', @response.content_type
527 543 lines = @response.body.chomp.split("\n")
528 544 s1 = "\xaa\xac\xbaA" # status
529 545 if str_utf8.respond_to?(:force_encoding)
530 546 s1.force_encoding('Big5')
531 547 end
532 548 assert lines[0].include?(s1)
533 549 s2 = lines[1].split(",")[2]
534 550 if s1.respond_to?(:force_encoding)
535 551 s3 = "\xa5H?" # subject
536 552 s3.force_encoding('Big5')
537 553 assert_equal s3, s2
538 554 elsif RUBY_PLATFORM == 'java'
539 555 assert_equal "??", s2
540 556 else
541 557 assert_equal "\xa5H???", s2
542 558 end
543 559 end
544 560 end
545 561
546 562 def test_index_csv_tw
547 563 with_settings :default_language => "zh-TW" do
548 564 str1 = "test_index_csv_tw"
549 565 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
550 566
551 567 get :index, :project_id => 1,
552 568 :f => ['subject'],
553 569 :op => '=', :values => [str1],
554 570 :c => ['estimated_hours', 'subject'],
555 571 :format => 'csv',
556 572 :set_filter => 1
557 573 assert_equal 'text/csv; header=present', @response.content_type
558 574 lines = @response.body.chomp.split("\n")
559 575 assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
560 576 end
561 577 end
562 578
563 579 def test_index_csv_fr
564 580 with_settings :default_language => "fr" do
565 581 str1 = "test_index_csv_fr"
566 582 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
567 583
568 584 get :index, :project_id => 1,
569 585 :f => ['subject'],
570 586 :op => '=', :values => [str1],
571 587 :c => ['estimated_hours', 'subject'],
572 588 :format => 'csv',
573 589 :set_filter => 1
574 590 assert_equal 'text/csv; header=present', @response.content_type
575 591 lines = @response.body.chomp.split("\n")
576 592 assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
577 593 end
578 594 end
579 595
580 596 def test_index_pdf
581 597 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
582 598 with_settings :default_language => lang do
583 599
584 600 get :index
585 601 assert_response :success
586 602 assert_template 'index'
587 603
588 604 get :index, :format => 'pdf'
589 605 assert_response :success
590 606 assert_not_nil assigns(:issues)
591 607 assert_equal 'application/pdf', @response.content_type
592 608
593 609 get :index, :project_id => 1, :format => 'pdf'
594 610 assert_response :success
595 611 assert_not_nil assigns(:issues)
596 612 assert_equal 'application/pdf', @response.content_type
597 613
598 614 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
599 615 assert_response :success
600 616 assert_not_nil assigns(:issues)
601 617 assert_equal 'application/pdf', @response.content_type
602 618 end
603 619 end
604 620 end
605 621
606 622 def test_index_pdf_with_query_grouped_by_list_custom_field
607 623 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
608 624 assert_response :success
609 625 assert_not_nil assigns(:issues)
610 626 assert_not_nil assigns(:issue_count_by_group)
611 627 assert_equal 'application/pdf', @response.content_type
612 628 end
613 629
614 630 def test_index_atom
615 631 get :index, :project_id => 'ecookbook', :format => 'atom'
616 632 assert_response :success
617 633 assert_template 'common/feed'
618 634 assert_equal 'application/atom+xml', response.content_type
619 635
620 636 assert_select 'feed' do
621 637 assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
622 638 assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
623 639 assert_select 'entry link[href=?]', 'http://test.host/issues/1'
624 640 end
625 641 end
626 642
627 643 def test_index_sort
628 644 get :index, :sort => 'tracker,id:desc'
629 645 assert_response :success
630 646
631 647 sort_params = @request.session['issues_index_sort']
632 648 assert sort_params.is_a?(String)
633 649 assert_equal 'tracker,id:desc', sort_params
634 650
635 651 issues = assigns(:issues)
636 652 assert_not_nil issues
637 653 assert !issues.empty?
638 654 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
639 655 assert_select 'table.issues.sort-by-tracker.sort-asc'
640 656 end
641 657
642 658 def test_index_sort_by_field_not_included_in_columns
643 659 Setting.issue_list_default_columns = %w(subject author)
644 660 get :index, :sort => 'tracker'
645 661 end
646 662
647 663 def test_index_sort_by_assigned_to
648 664 get :index, :sort => 'assigned_to'
649 665 assert_response :success
650 666 assignees = assigns(:issues).collect(&:assigned_to).compact
651 667 assert_equal assignees.sort, assignees
652 668 assert_select 'table.issues.sort-by-assigned-to.sort-asc'
653 669 end
654 670
655 671 def test_index_sort_by_assigned_to_desc
656 672 get :index, :sort => 'assigned_to:desc'
657 673 assert_response :success
658 674 assignees = assigns(:issues).collect(&:assigned_to).compact
659 675 assert_equal assignees.sort.reverse, assignees
660 676 assert_select 'table.issues.sort-by-assigned-to.sort-desc'
661 677 end
662 678
663 679 def test_index_group_by_assigned_to
664 680 get :index, :group_by => 'assigned_to', :sort => 'priority'
665 681 assert_response :success
666 682 end
667 683
668 684 def test_index_sort_by_author
669 685 get :index, :sort => 'author'
670 686 assert_response :success
671 687 authors = assigns(:issues).collect(&:author)
672 688 assert_equal authors.sort, authors
673 689 end
674 690
675 691 def test_index_sort_by_author_desc
676 692 get :index, :sort => 'author:desc'
677 693 assert_response :success
678 694 authors = assigns(:issues).collect(&:author)
679 695 assert_equal authors.sort.reverse, authors
680 696 end
681 697
682 698 def test_index_group_by_author
683 699 get :index, :group_by => 'author', :sort => 'priority'
684 700 assert_response :success
685 701 end
686 702
687 703 def test_index_sort_by_spent_hours
688 704 get :index, :sort => 'spent_hours:desc'
689 705 assert_response :success
690 706 hours = assigns(:issues).collect(&:spent_hours)
691 707 assert_equal hours.sort.reverse, hours
692 708 end
693 709
694 710 def test_index_sort_by_user_custom_field
695 711 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
696 712 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
697 713 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
698 714 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
699 715 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
700 716
701 717 get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
702 718 assert_response :success
703 719
704 720 assert_equal [2, 3, 1], assigns(:issues).select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
705 721 end
706 722
707 723 def test_index_with_columns
708 724 columns = ['tracker', 'subject', 'assigned_to']
709 725 get :index, :set_filter => 1, :c => columns
710 726 assert_response :success
711 727
712 728 # query should use specified columns
713 729 query = assigns(:query)
714 730 assert_kind_of IssueQuery, query
715 731 assert_equal columns, query.column_names.map(&:to_s)
716 732
717 733 # columns should be stored in session
718 734 assert_kind_of Hash, session[:query]
719 735 assert_kind_of Array, session[:query][:column_names]
720 736 assert_equal columns, session[:query][:column_names].map(&:to_s)
721 737
722 738 # ensure only these columns are kept in the selected columns list
723 739 assert_select 'select#selected_columns option' do
724 740 assert_select 'option', 3
725 741 assert_select 'option[value=tracker]'
726 742 assert_select 'option[value=project]', 0
727 743 end
728 744 end
729 745
730 746 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
731 747 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
732 748 get :index, :set_filter => 1
733 749
734 750 # query should use specified columns
735 751 query = assigns(:query)
736 752 assert_kind_of IssueQuery, query
737 753 assert_equal [:id, :project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
738 754 end
739 755
740 756 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
741 757 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
742 758 columns = ['id', 'tracker', 'subject', 'assigned_to']
743 759 get :index, :set_filter => 1, :c => columns
744 760
745 761 # query should use specified columns
746 762 query = assigns(:query)
747 763 assert_kind_of IssueQuery, query
748 764 assert_equal columns.map(&:to_sym), query.columns.map(&:name)
749 765 end
750 766
751 767 def test_index_with_custom_field_column
752 768 columns = %w(tracker subject cf_2)
753 769 get :index, :set_filter => 1, :c => columns
754 770 assert_response :success
755 771
756 772 # query should use specified columns
757 773 query = assigns(:query)
758 774 assert_kind_of IssueQuery, query
759 775 assert_equal columns, query.column_names.map(&:to_s)
760 776
761 777 assert_select 'table.issues td.cf_2.string'
762 778 end
763 779
764 780 def test_index_with_multi_custom_field_column
765 781 field = CustomField.find(1)
766 782 field.update_attribute :multiple, true
767 783 issue = Issue.find(1)
768 784 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
769 785 issue.save!
770 786
771 787 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
772 788 assert_response :success
773 789
774 790 assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
775 791 end
776 792
777 793 def test_index_with_multi_user_custom_field_column
778 794 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
779 795 :tracker_ids => [1], :is_for_all => true)
780 796 issue = Issue.find(1)
781 797 issue.custom_field_values = {field.id => ['2', '3']}
782 798 issue.save!
783 799
784 800 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
785 801 assert_response :success
786 802
787 803 assert_select "table.issues td.cf_#{field.id}" do
788 804 assert_select 'a', 2
789 805 assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
790 806 assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
791 807 end
792 808 end
793 809
794 810 def test_index_with_date_column
795 811 with_settings :date_format => '%d/%m/%Y' do
796 812 Issue.find(1).update_attribute :start_date, '1987-08-24'
797 813 get :index, :set_filter => 1, :c => %w(start_date)
798 814 assert_select "table.issues td.start_date", :text => '24/08/1987'
799 815 end
800 816 end
801 817
802 818 def test_index_with_done_ratio_column
803 819 Issue.find(1).update_attribute :done_ratio, 40
804 820 get :index, :set_filter => 1, :c => %w(done_ratio)
805 821 assert_select 'table.issues td.done_ratio' do
806 822 assert_select 'table.progress' do
807 823 assert_select 'td.closed[style=?]', 'width: 40%;'
808 824 end
809 825 end
810 826 end
811 827
812 828 def test_index_with_spent_hours_column
813 829 get :index, :set_filter => 1, :c => %w(subject spent_hours)
814 830 assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
815 831 end
816 832
817 833 def test_index_should_not_show_spent_hours_column_without_permission
818 834 Role.anonymous.remove_permission! :view_time_entries
819 835 get :index, :set_filter => 1, :c => %w(subject spent_hours)
820 836 assert_select 'td.spent_hours', 0
821 837 end
822 838
823 839 def test_index_with_fixed_version_column
824 840 get :index, :set_filter => 1, :c => %w(fixed_version)
825 841 assert_select 'table.issues td.fixed_version' do
826 842 assert_select 'a[href=?]', '/versions/2', :text => '1.0'
827 843 end
828 844 end
829 845
830 846 def test_index_with_relations_column
831 847 IssueRelation.delete_all
832 848 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
833 849 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
834 850 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
835 851 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
836 852
837 853 get :index, :set_filter => 1, :c => %w(subject relations)
838 854 assert_response :success
839 855 assert_select "tr#issue-1 td.relations" do
840 856 assert_select "span", 3
841 857 assert_select "span", :text => "Related to #7"
842 858 assert_select "span", :text => "Related to #8"
843 859 assert_select "span", :text => "Blocks #11"
844 860 end
845 861 assert_select "tr#issue-2 td.relations" do
846 862 assert_select "span", 1
847 863 assert_select "span", :text => "Blocked by #12"
848 864 end
849 865 assert_select "tr#issue-3 td.relations" do
850 866 assert_select "span", 0
851 867 end
852 868
853 869 get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
854 870 assert_response :success
855 871 assert_equal 'text/csv; header=present', response.content_type
856 872 lines = response.body.chomp.split("\n")
857 873 assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
858 874 assert_include '2,Blocked by #12', lines
859 875 assert_include '3,""', lines
860 876
861 877 get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
862 878 assert_response :success
863 879 assert_equal 'application/pdf', response.content_type
864 880 end
865 881
866 882 def test_index_with_description_column
867 883 get :index, :set_filter => 1, :c => %w(subject description)
868 884
869 885 assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
870 886 assert_select 'td.description[colspan=3]', :text => 'Unable to print recipes'
871 887
872 888 get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
873 889 assert_response :success
874 890 assert_equal 'application/pdf', response.content_type
875 891 end
876 892
877 893 def test_index_with_parent_column
878 894 Issue.delete_all
879 895 parent = Issue.generate!
880 896 child = Issue.generate!(:parent_issue_id => parent.id)
881 897
882 898 get :index, :c => %w(parent)
883 899
884 900 assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
885 901 assert_select 'td.parent a[title=?]', parent.subject
886 902 end
887 903
888 904 def test_index_send_html_if_query_is_invalid
889 905 get :index, :f => ['start_date'], :op => {:start_date => '='}
890 906 assert_equal 'text/html', @response.content_type
891 907 assert_template 'index'
892 908 end
893 909
894 910 def test_index_send_nothing_if_query_is_invalid
895 911 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
896 912 assert_equal 'text/csv', @response.content_type
897 913 assert @response.body.blank?
898 914 end
899 915
900 916 def test_show_by_anonymous
901 917 get :show, :id => 1
902 918 assert_response :success
903 919 assert_template 'show'
904 920 assert_equal Issue.find(1), assigns(:issue)
905 921 assert_select 'div.issue div.description', :text => /Unable to print recipes/
906 922 # anonymous role is allowed to add a note
907 923 assert_select 'form#issue-form' do
908 924 assert_select 'fieldset' do
909 925 assert_select 'legend', :text => 'Notes'
910 926 assert_select 'textarea[name=?]', 'issue[notes]'
911 927 end
912 928 end
913 929 assert_select 'title', :text => "Bug #1: #{ESCAPED_UCANT} print recipes - eCookbook - Redmine"
914 930 end
915 931
916 932 def test_show_by_manager
917 933 @request.session[:user_id] = 2
918 934 get :show, :id => 1
919 935 assert_response :success
920 936 assert_select 'a', :text => /Quote/
921 937 assert_select 'form#issue-form' do
922 938 assert_select 'fieldset' do
923 939 assert_select 'legend', :text => 'Change properties'
924 940 assert_select 'input[name=?]', 'issue[subject]'
925 941 end
926 942 assert_select 'fieldset' do
927 943 assert_select 'legend', :text => 'Log time'
928 944 assert_select 'input[name=?]', 'time_entry[hours]'
929 945 end
930 946 assert_select 'fieldset' do
931 947 assert_select 'legend', :text => 'Notes'
932 948 assert_select 'textarea[name=?]', 'issue[notes]'
933 949 end
934 950 end
935 951 end
936 952
937 953 def test_show_should_display_update_form
938 954 @request.session[:user_id] = 2
939 955 get :show, :id => 1
940 956 assert_response :success
941 957
942 958 assert_select 'form#issue-form' do
943 959 assert_select 'input[name=?]', 'issue[is_private]'
944 960 assert_select 'select[name=?]', 'issue[project_id]'
945 961 assert_select 'select[name=?]', 'issue[tracker_id]'
946 962 assert_select 'input[name=?]', 'issue[subject]'
947 963 assert_select 'textarea[name=?]', 'issue[description]'
948 964 assert_select 'select[name=?]', 'issue[status_id]'
949 965 assert_select 'select[name=?]', 'issue[priority_id]'
950 966 assert_select 'select[name=?]', 'issue[assigned_to_id]'
951 967 assert_select 'select[name=?]', 'issue[category_id]'
952 968 assert_select 'select[name=?]', 'issue[fixed_version_id]'
953 969 assert_select 'input[name=?]', 'issue[parent_issue_id]'
954 970 assert_select 'input[name=?]', 'issue[start_date]'
955 971 assert_select 'input[name=?]', 'issue[due_date]'
956 972 assert_select 'select[name=?]', 'issue[done_ratio]'
957 973 assert_select 'input[name=?]', 'issue[custom_field_values][2]'
958 974 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
959 975 assert_select 'textarea[name=?]', 'issue[notes]'
960 976 end
961 977 end
962 978
963 979 def test_show_should_display_update_form_with_minimal_permissions
964 980 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
965 981 WorkflowTransition.delete_all :role_id => 1
966 982
967 983 @request.session[:user_id] = 2
968 984 get :show, :id => 1
969 985 assert_response :success
970 986
971 987 assert_select 'form#issue-form' do
972 988 assert_select 'input[name=?]', 'issue[is_private]', 0
973 989 assert_select 'select[name=?]', 'issue[project_id]', 0
974 990 assert_select 'select[name=?]', 'issue[tracker_id]', 0
975 991 assert_select 'input[name=?]', 'issue[subject]', 0
976 992 assert_select 'textarea[name=?]', 'issue[description]', 0
977 993 assert_select 'select[name=?]', 'issue[status_id]', 0
978 994 assert_select 'select[name=?]', 'issue[priority_id]', 0
979 995 assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
980 996 assert_select 'select[name=?]', 'issue[category_id]', 0
981 997 assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
982 998 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
983 999 assert_select 'input[name=?]', 'issue[start_date]', 0
984 1000 assert_select 'input[name=?]', 'issue[due_date]', 0
985 1001 assert_select 'select[name=?]', 'issue[done_ratio]', 0
986 1002 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
987 1003 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
988 1004 assert_select 'textarea[name=?]', 'issue[notes]'
989 1005 end
990 1006 end
991 1007
992 1008 def test_show_should_display_update_form_with_workflow_permissions
993 1009 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
994 1010
995 1011 @request.session[:user_id] = 2
996 1012 get :show, :id => 1
997 1013 assert_response :success
998 1014
999 1015 assert_select 'form#issue-form' do
1000 1016 assert_select 'input[name=?]', 'issue[is_private]', 0
1001 1017 assert_select 'select[name=?]', 'issue[project_id]', 0
1002 1018 assert_select 'select[name=?]', 'issue[tracker_id]', 0
1003 1019 assert_select 'input[name=?]', 'issue[subject]', 0
1004 1020 assert_select 'textarea[name=?]', 'issue[description]', 0
1005 1021 assert_select 'select[name=?]', 'issue[status_id]'
1006 1022 assert_select 'select[name=?]', 'issue[priority_id]', 0
1007 1023 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1008 1024 assert_select 'select[name=?]', 'issue[category_id]', 0
1009 1025 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1010 1026 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1011 1027 assert_select 'input[name=?]', 'issue[start_date]', 0
1012 1028 assert_select 'input[name=?]', 'issue[due_date]', 0
1013 1029 assert_select 'select[name=?]', 'issue[done_ratio]'
1014 1030 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
1015 1031 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1016 1032 assert_select 'textarea[name=?]', 'issue[notes]'
1017 1033 end
1018 1034 end
1019 1035
1020 1036 def test_show_should_not_display_update_form_without_permissions
1021 1037 Role.find(1).update_attribute :permissions, [:view_issues]
1022 1038
1023 1039 @request.session[:user_id] = 2
1024 1040 get :show, :id => 1
1025 1041 assert_response :success
1026 1042
1027 1043 assert_select 'form#issue-form', 0
1028 1044 end
1029 1045
1030 1046 def test_update_form_should_not_display_inactive_enumerations
1031 1047 assert !IssuePriority.find(15).active?
1032 1048
1033 1049 @request.session[:user_id] = 2
1034 1050 get :show, :id => 1
1035 1051 assert_response :success
1036 1052
1037 1053 assert_select 'form#issue-form' do
1038 1054 assert_select 'select[name=?]', 'issue[priority_id]' do
1039 1055 assert_select 'option[value=4]'
1040 1056 assert_select 'option[value=15]', 0
1041 1057 end
1042 1058 end
1043 1059 end
1044 1060
1045 1061 def test_update_form_should_allow_attachment_upload
1046 1062 @request.session[:user_id] = 2
1047 1063 get :show, :id => 1
1048 1064
1049 1065 assert_select 'form#issue-form[method=post][enctype=multipart/form-data]' do
1050 1066 assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
1051 1067 end
1052 1068 end
1053 1069
1054 1070 def test_show_should_deny_anonymous_access_without_permission
1055 1071 Role.anonymous.remove_permission!(:view_issues)
1056 1072 get :show, :id => 1
1057 1073 assert_response :redirect
1058 1074 end
1059 1075
1060 1076 def test_show_should_deny_anonymous_access_to_private_issue
1061 1077 Issue.where(:id => 1).update_all(["is_private = ?", true])
1062 1078 get :show, :id => 1
1063 1079 assert_response :redirect
1064 1080 end
1065 1081
1066 1082 def test_show_should_deny_non_member_access_without_permission
1067 1083 Role.non_member.remove_permission!(:view_issues)
1068 1084 @request.session[:user_id] = 9
1069 1085 get :show, :id => 1
1070 1086 assert_response 403
1071 1087 end
1072 1088
1073 1089 def test_show_should_deny_non_member_access_to_private_issue
1074 1090 Issue.where(:id => 1).update_all(["is_private = ?", true])
1075 1091 @request.session[:user_id] = 9
1076 1092 get :show, :id => 1
1077 1093 assert_response 403
1078 1094 end
1079 1095
1080 1096 def test_show_should_deny_member_access_without_permission
1081 1097 Role.find(1).remove_permission!(:view_issues)
1082 1098 @request.session[:user_id] = 2
1083 1099 get :show, :id => 1
1084 1100 assert_response 403
1085 1101 end
1086 1102
1087 1103 def test_show_should_deny_member_access_to_private_issue_without_permission
1088 1104 Issue.where(:id => 1).update_all(["is_private = ?", true])
1089 1105 @request.session[:user_id] = 3
1090 1106 get :show, :id => 1
1091 1107 assert_response 403
1092 1108 end
1093 1109
1094 1110 def test_show_should_allow_author_access_to_private_issue
1095 1111 Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
1096 1112 @request.session[:user_id] = 3
1097 1113 get :show, :id => 1
1098 1114 assert_response :success
1099 1115 end
1100 1116
1101 1117 def test_show_should_allow_assignee_access_to_private_issue
1102 1118 Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
1103 1119 @request.session[:user_id] = 3
1104 1120 get :show, :id => 1
1105 1121 assert_response :success
1106 1122 end
1107 1123
1108 1124 def test_show_should_allow_member_access_to_private_issue_with_permission
1109 1125 Issue.where(:id => 1).update_all(["is_private = ?", true])
1110 1126 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
1111 1127 @request.session[:user_id] = 3
1112 1128 get :show, :id => 1
1113 1129 assert_response :success
1114 1130 end
1115 1131
1116 1132 def test_show_should_not_disclose_relations_to_invisible_issues
1117 1133 Setting.cross_project_issue_relations = '1'
1118 1134 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
1119 1135 # Relation to a private project issue
1120 1136 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
1121 1137
1122 1138 get :show, :id => 1
1123 1139 assert_response :success
1124 1140
1125 1141 assert_select 'div#relations' do
1126 1142 assert_select 'a', :text => /#2$/
1127 1143 assert_select 'a', :text => /#4$/, :count => 0
1128 1144 end
1129 1145 end
1130 1146
1131 1147 def test_show_should_list_subtasks
1132 1148 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1133 1149
1134 1150 get :show, :id => 1
1135 1151 assert_response :success
1136 1152
1137 1153 assert_select 'div#issue_tree' do
1138 1154 assert_select 'td.subject', :text => /Child Issue/
1139 1155 end
1140 1156 end
1141 1157
1142 1158 def test_show_should_list_parents
1143 1159 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1144 1160
1145 1161 get :show, :id => issue.id
1146 1162 assert_response :success
1147 1163
1148 1164 assert_select 'div.subject' do
1149 1165 assert_select 'h3', 'Child Issue'
1150 1166 assert_select 'a[href=/issues/1]'
1151 1167 end
1152 1168 end
1153 1169
1154 1170 def test_show_should_not_display_prev_next_links_without_query_in_session
1155 1171 get :show, :id => 1
1156 1172 assert_response :success
1157 1173 assert_nil assigns(:prev_issue_id)
1158 1174 assert_nil assigns(:next_issue_id)
1159 1175
1160 1176 assert_select 'div.next-prev-links', 0
1161 1177 end
1162 1178
1163 1179 def test_show_should_display_prev_next_links_with_query_in_session
1164 1180 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1165 1181 @request.session['issues_index_sort'] = 'id'
1166 1182
1167 1183 with_settings :display_subprojects_issues => '0' do
1168 1184 get :show, :id => 3
1169 1185 end
1170 1186
1171 1187 assert_response :success
1172 1188 # Previous and next issues for all projects
1173 1189 assert_equal 2, assigns(:prev_issue_id)
1174 1190 assert_equal 5, assigns(:next_issue_id)
1175 1191
1176 1192 count = Issue.open.visible.count
1177 1193
1178 1194 assert_select 'div.next-prev-links' do
1179 1195 assert_select 'a[href=/issues/2]', :text => /Previous/
1180 1196 assert_select 'a[href=/issues/5]', :text => /Next/
1181 1197 assert_select 'span.position', :text => "3 of #{count}"
1182 1198 end
1183 1199 end
1184 1200
1185 1201 def test_show_should_display_prev_next_links_with_saved_query_in_session
1186 1202 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1,
1187 1203 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1188 1204 :sort_criteria => [['id', 'asc']])
1189 1205 @request.session[:query] = {:id => query.id, :project_id => nil}
1190 1206
1191 1207 get :show, :id => 11
1192 1208
1193 1209 assert_response :success
1194 1210 assert_equal query, assigns(:query)
1195 1211 # Previous and next issues for all projects
1196 1212 assert_equal 8, assigns(:prev_issue_id)
1197 1213 assert_equal 12, assigns(:next_issue_id)
1198 1214
1199 1215 assert_select 'div.next-prev-links' do
1200 1216 assert_select 'a[href=/issues/8]', :text => /Previous/
1201 1217 assert_select 'a[href=/issues/12]', :text => /Next/
1202 1218 end
1203 1219 end
1204 1220
1205 1221 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1206 1222 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1207 1223
1208 1224 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1209 1225 @request.session['issues_index_sort'] = assoc_sort
1210 1226
1211 1227 get :show, :id => 3
1212 1228 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1213 1229
1214 1230 assert_select 'div.next-prev-links' do
1215 1231 assert_select 'a', :text => /(Previous|Next)/
1216 1232 end
1217 1233 end
1218 1234 end
1219 1235
1220 1236 def test_show_should_display_prev_next_links_with_project_query_in_session
1221 1237 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1222 1238 @request.session['issues_index_sort'] = 'id'
1223 1239
1224 1240 with_settings :display_subprojects_issues => '0' do
1225 1241 get :show, :id => 3
1226 1242 end
1227 1243
1228 1244 assert_response :success
1229 1245 # Previous and next issues inside project
1230 1246 assert_equal 2, assigns(:prev_issue_id)
1231 1247 assert_equal 7, assigns(:next_issue_id)
1232 1248
1233 1249 assert_select 'div.next-prev-links' do
1234 1250 assert_select 'a[href=/issues/2]', :text => /Previous/
1235 1251 assert_select 'a[href=/issues/7]', :text => /Next/
1236 1252 end
1237 1253 end
1238 1254
1239 1255 def test_show_should_not_display_prev_link_for_first_issue
1240 1256 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1241 1257 @request.session['issues_index_sort'] = 'id'
1242 1258
1243 1259 with_settings :display_subprojects_issues => '0' do
1244 1260 get :show, :id => 1
1245 1261 end
1246 1262
1247 1263 assert_response :success
1248 1264 assert_nil assigns(:prev_issue_id)
1249 1265 assert_equal 2, assigns(:next_issue_id)
1250 1266
1251 1267 assert_select 'div.next-prev-links' do
1252 1268 assert_select 'a', :text => /Previous/, :count => 0
1253 1269 assert_select 'a[href=/issues/2]', :text => /Next/
1254 1270 end
1255 1271 end
1256 1272
1257 1273 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1258 1274 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1259 1275 @request.session['issues_index_sort'] = 'id'
1260 1276
1261 1277 get :show, :id => 1
1262 1278
1263 1279 assert_response :success
1264 1280 assert_nil assigns(:prev_issue_id)
1265 1281 assert_nil assigns(:next_issue_id)
1266 1282
1267 1283 assert_select 'a', :text => /Previous/, :count => 0
1268 1284 assert_select 'a', :text => /Next/, :count => 0
1269 1285 end
1270 1286
1271 1287 def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
1272 1288 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
1273 1289 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
1274 1290 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
1275 1291 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
1276 1292 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
1277 1293
1278 1294 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1, :filters => {},
1279 1295 :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
1280 1296 @request.session[:query] = {:id => query.id, :project_id => nil}
1281 1297
1282 1298 get :show, :id => 3
1283 1299 assert_response :success
1284 1300
1285 1301 assert_equal 2, assigns(:prev_issue_id)
1286 1302 assert_equal 1, assigns(:next_issue_id)
1287 1303
1288 1304 assert_select 'div.next-prev-links' do
1289 1305 assert_select 'a[href=/issues/2]', :text => /Previous/
1290 1306 assert_select 'a[href=/issues/1]', :text => /Next/
1291 1307 end
1292 1308 end
1293 1309
1294 1310 def test_show_should_display_link_to_the_assignee
1295 1311 get :show, :id => 2
1296 1312 assert_response :success
1297 1313 assert_select '.assigned-to' do
1298 1314 assert_select 'a[href=/users/3]'
1299 1315 end
1300 1316 end
1301 1317
1302 1318 def test_show_should_display_visible_changesets_from_other_projects
1303 1319 project = Project.find(2)
1304 1320 issue = project.issues.first
1305 1321 issue.changeset_ids = [102]
1306 1322 issue.save!
1307 1323 # changesets from other projects should be displayed even if repository
1308 1324 # is disabled on issue's project
1309 1325 project.disable_module! :repository
1310 1326
1311 1327 @request.session[:user_id] = 2
1312 1328 get :show, :id => issue.id
1313 1329
1314 1330 assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
1315 1331 end
1316 1332
1317 1333 def test_show_should_display_watchers
1318 1334 @request.session[:user_id] = 2
1319 1335 Issue.find(1).add_watcher User.find(2)
1320 1336
1321 1337 get :show, :id => 1
1322 1338 assert_select 'div#watchers ul' do
1323 1339 assert_select 'li' do
1324 1340 assert_select 'a[href=/users/2]'
1325 1341 assert_select 'a img[alt=Delete]'
1326 1342 end
1327 1343 end
1328 1344 end
1329 1345
1330 1346 def test_show_should_display_watchers_with_gravatars
1331 1347 @request.session[:user_id] = 2
1332 1348 Issue.find(1).add_watcher User.find(2)
1333 1349
1334 1350 with_settings :gravatar_enabled => '1' do
1335 1351 get :show, :id => 1
1336 1352 end
1337 1353
1338 1354 assert_select 'div#watchers ul' do
1339 1355 assert_select 'li' do
1340 1356 assert_select 'img.gravatar'
1341 1357 assert_select 'a[href=/users/2]'
1342 1358 assert_select 'a img[alt=Delete]'
1343 1359 end
1344 1360 end
1345 1361 end
1346 1362
1347 1363 def test_show_with_thumbnails_enabled_should_display_thumbnails
1348 1364 @request.session[:user_id] = 2
1349 1365
1350 1366 with_settings :thumbnails_enabled => '1' do
1351 1367 get :show, :id => 14
1352 1368 assert_response :success
1353 1369 end
1354 1370
1355 1371 assert_select 'div.thumbnails' do
1356 1372 assert_select 'a[href=/attachments/16/testfile.png]' do
1357 1373 assert_select 'img[src=/attachments/thumbnail/16]'
1358 1374 end
1359 1375 end
1360 1376 end
1361 1377
1362 1378 def test_show_with_thumbnails_disabled_should_not_display_thumbnails
1363 1379 @request.session[:user_id] = 2
1364 1380
1365 1381 with_settings :thumbnails_enabled => '0' do
1366 1382 get :show, :id => 14
1367 1383 assert_response :success
1368 1384 end
1369 1385
1370 1386 assert_select 'div.thumbnails', 0
1371 1387 end
1372 1388
1373 1389 def test_show_with_multi_custom_field
1374 1390 field = CustomField.find(1)
1375 1391 field.update_attribute :multiple, true
1376 1392 issue = Issue.find(1)
1377 1393 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1378 1394 issue.save!
1379 1395
1380 1396 get :show, :id => 1
1381 1397 assert_response :success
1382 1398
1383 1399 assert_select 'td', :text => 'MySQL, Oracle'
1384 1400 end
1385 1401
1386 1402 def test_show_with_multi_user_custom_field
1387 1403 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1388 1404 :tracker_ids => [1], :is_for_all => true)
1389 1405 issue = Issue.find(1)
1390 1406 issue.custom_field_values = {field.id => ['2', '3']}
1391 1407 issue.save!
1392 1408
1393 1409 get :show, :id => 1
1394 1410 assert_response :success
1395 1411
1396 1412 assert_select "td.cf_#{field.id}", :text => 'Dave Lopper, John Smith' do
1397 1413 assert_select 'a', :text => 'Dave Lopper'
1398 1414 assert_select 'a', :text => 'John Smith'
1399 1415 end
1400 1416 end
1401 1417
1402 1418 def test_show_should_display_private_notes_with_permission_only
1403 1419 journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
1404 1420 @request.session[:user_id] = 2
1405 1421
1406 1422 get :show, :id => 2
1407 1423 assert_response :success
1408 1424 assert_include journal, assigns(:journals)
1409 1425
1410 1426 Role.find(1).remove_permission! :view_private_notes
1411 1427 get :show, :id => 2
1412 1428 assert_response :success
1413 1429 assert_not_include journal, assigns(:journals)
1414 1430 end
1415 1431
1416 1432 def test_show_atom
1417 1433 get :show, :id => 2, :format => 'atom'
1418 1434 assert_response :success
1419 1435 assert_template 'journals/index'
1420 1436 # Inline image
1421 1437 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1422 1438 end
1423 1439
1424 1440 def test_show_export_to_pdf
1425 1441 issue = Issue.find(3)
1426 1442 assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1427 1443 get :show, :id => 3, :format => 'pdf'
1428 1444 assert_response :success
1429 1445 assert_equal 'application/pdf', @response.content_type
1430 1446 assert @response.body.starts_with?('%PDF')
1431 1447 assert_not_nil assigns(:issue)
1432 1448 end
1433 1449
1434 1450 def test_export_to_pdf_with_utf8_u_fffd
1435 1451 # U+FFFD
1436 1452 s = "\xef\xbf\xbd"
1437 1453 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
1438 1454 issue = Issue.generate!(:subject => s)
1439 1455 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
1440 1456 with_settings :default_language => lang do
1441 1457 get :show, :id => issue.id, :format => 'pdf'
1442 1458 assert_response :success
1443 1459 assert_equal 'application/pdf', @response.content_type
1444 1460 assert @response.body.starts_with?('%PDF')
1445 1461 assert_not_nil assigns(:issue)
1446 1462 end
1447 1463 end
1448 1464 end
1449 1465
1450 1466 def test_show_export_to_pdf_with_ancestors
1451 1467 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1452 1468
1453 1469 get :show, :id => issue.id, :format => 'pdf'
1454 1470 assert_response :success
1455 1471 assert_equal 'application/pdf', @response.content_type
1456 1472 assert @response.body.starts_with?('%PDF')
1457 1473 end
1458 1474
1459 1475 def test_show_export_to_pdf_with_descendants
1460 1476 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1461 1477 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1462 1478 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1463 1479
1464 1480 get :show, :id => 1, :format => 'pdf'
1465 1481 assert_response :success
1466 1482 assert_equal 'application/pdf', @response.content_type
1467 1483 assert @response.body.starts_with?('%PDF')
1468 1484 end
1469 1485
1470 1486 def test_show_export_to_pdf_with_journals
1471 1487 get :show, :id => 1, :format => 'pdf'
1472 1488 assert_response :success
1473 1489 assert_equal 'application/pdf', @response.content_type
1474 1490 assert @response.body.starts_with?('%PDF')
1475 1491 end
1476 1492
1477 1493 def test_show_export_to_pdf_with_changesets
1478 1494 [[100], [100, 101], [100, 101, 102]].each do |cs|
1479 1495 issue1 = Issue.find(3)
1480 1496 issue1.changesets = Changeset.find(cs)
1481 1497 issue1.save!
1482 1498 issue = Issue.find(3)
1483 1499 assert_equal issue.changesets.count, cs.size
1484 1500 get :show, :id => 3, :format => 'pdf'
1485 1501 assert_response :success
1486 1502 assert_equal 'application/pdf', @response.content_type
1487 1503 assert @response.body.starts_with?('%PDF')
1488 1504 end
1489 1505 end
1490 1506
1491 1507 def test_show_invalid_should_respond_with_404
1492 1508 get :show, :id => 999
1493 1509 assert_response 404
1494 1510 end
1495 1511
1496 1512 def test_get_new
1497 1513 @request.session[:user_id] = 2
1498 1514 get :new, :project_id => 1, :tracker_id => 1
1499 1515 assert_response :success
1500 1516 assert_template 'new'
1501 1517
1502 1518 assert_select 'form#issue-form' do
1503 1519 assert_select 'input[name=?]', 'issue[is_private]'
1504 1520 assert_select 'select[name=?]', 'issue[project_id]', 0
1505 1521 assert_select 'select[name=?]', 'issue[tracker_id]'
1506 1522 assert_select 'input[name=?]', 'issue[subject]'
1507 1523 assert_select 'textarea[name=?]', 'issue[description]'
1508 1524 assert_select 'select[name=?]', 'issue[status_id]'
1509 1525 assert_select 'select[name=?]', 'issue[priority_id]'
1510 1526 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1511 1527 assert_select 'select[name=?]', 'issue[category_id]'
1512 1528 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1513 1529 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1514 1530 assert_select 'input[name=?]', 'issue[start_date]'
1515 1531 assert_select 'input[name=?]', 'issue[due_date]'
1516 1532 assert_select 'select[name=?]', 'issue[done_ratio]'
1517 1533 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1518 1534 assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
1519 1535 end
1520 1536
1521 1537 # Be sure we don't display inactive IssuePriorities
1522 1538 assert ! IssuePriority.find(15).active?
1523 1539 assert_select 'select[name=?]', 'issue[priority_id]' do
1524 1540 assert_select 'option[value=15]', 0
1525 1541 end
1526 1542 end
1527 1543
1528 1544 def test_get_new_with_minimal_permissions
1529 1545 Role.find(1).update_attribute :permissions, [:add_issues]
1530 1546 WorkflowTransition.delete_all :role_id => 1
1531 1547
1532 1548 @request.session[:user_id] = 2
1533 1549 get :new, :project_id => 1, :tracker_id => 1
1534 1550 assert_response :success
1535 1551 assert_template 'new'
1536 1552
1537 1553 assert_select 'form#issue-form' do
1538 1554 assert_select 'input[name=?]', 'issue[is_private]', 0
1539 1555 assert_select 'select[name=?]', 'issue[project_id]', 0
1540 1556 assert_select 'select[name=?]', 'issue[tracker_id]'
1541 1557 assert_select 'input[name=?]', 'issue[subject]'
1542 1558 assert_select 'textarea[name=?]', 'issue[description]'
1543 1559 assert_select 'select[name=?]', 'issue[status_id]'
1544 1560 assert_select 'select[name=?]', 'issue[priority_id]'
1545 1561 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1546 1562 assert_select 'select[name=?]', 'issue[category_id]'
1547 1563 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1548 1564 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1549 1565 assert_select 'input[name=?]', 'issue[start_date]'
1550 1566 assert_select 'input[name=?]', 'issue[due_date]'
1551 1567 assert_select 'select[name=?]', 'issue[done_ratio]'
1552 1568 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1553 1569 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1554 1570 end
1555 1571 end
1556 1572
1557 1573 def test_get_new_with_list_custom_field
1558 1574 @request.session[:user_id] = 2
1559 1575 get :new, :project_id => 1, :tracker_id => 1
1560 1576 assert_response :success
1561 1577 assert_template 'new'
1562 1578
1563 1579 assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
1564 1580 assert_select 'option', 4
1565 1581 assert_select 'option[value=MySQL]', :text => 'MySQL'
1566 1582 end
1567 1583 end
1568 1584
1569 1585 def test_get_new_with_multi_custom_field
1570 1586 field = IssueCustomField.find(1)
1571 1587 field.update_attribute :multiple, true
1572 1588
1573 1589 @request.session[:user_id] = 2
1574 1590 get :new, :project_id => 1, :tracker_id => 1
1575 1591 assert_response :success
1576 1592 assert_template 'new'
1577 1593
1578 1594 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
1579 1595 assert_select 'option', 3
1580 1596 assert_select 'option[value=MySQL]', :text => 'MySQL'
1581 1597 end
1582 1598 assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
1583 1599 end
1584 1600
1585 1601 def test_get_new_with_multi_user_custom_field
1586 1602 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1587 1603 :tracker_ids => [1], :is_for_all => true)
1588 1604
1589 1605 @request.session[:user_id] = 2
1590 1606 get :new, :project_id => 1, :tracker_id => 1
1591 1607 assert_response :success
1592 1608 assert_template 'new'
1593 1609
1594 1610 assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
1595 1611 assert_select 'option', Project.find(1).users.count
1596 1612 assert_select 'option[value=2]', :text => 'John Smith'
1597 1613 end
1598 1614 assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
1599 1615 end
1600 1616
1601 1617 def test_get_new_with_date_custom_field
1602 1618 field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
1603 1619
1604 1620 @request.session[:user_id] = 2
1605 1621 get :new, :project_id => 1, :tracker_id => 1
1606 1622 assert_response :success
1607 1623
1608 1624 assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
1609 1625 end
1610 1626
1611 1627 def test_get_new_with_text_custom_field
1612 1628 field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
1613 1629
1614 1630 @request.session[:user_id] = 2
1615 1631 get :new, :project_id => 1, :tracker_id => 1
1616 1632 assert_response :success
1617 1633
1618 1634 assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
1619 1635 end
1620 1636
1621 1637 def test_get_new_without_default_start_date_is_creation_date
1622 1638 with_settings :default_issue_start_date_to_creation_date => 0 do
1623 1639 @request.session[:user_id] = 2
1624 1640 get :new, :project_id => 1, :tracker_id => 1
1625 1641 assert_response :success
1626 1642 assert_template 'new'
1627 1643 assert_select 'input[name=?]', 'issue[start_date]'
1628 1644 assert_select 'input[name=?][value]', 'issue[start_date]', 0
1629 1645 end
1630 1646 end
1631 1647
1632 1648 def test_get_new_with_default_start_date_is_creation_date
1633 1649 with_settings :default_issue_start_date_to_creation_date => 1 do
1634 1650 @request.session[:user_id] = 2
1635 1651 get :new, :project_id => 1, :tracker_id => 1
1636 1652 assert_response :success
1637 1653 assert_template 'new'
1638 1654 assert_select 'input[name=?][value=?]', 'issue[start_date]',
1639 1655 Date.today.to_s
1640 1656 end
1641 1657 end
1642 1658
1643 1659 def test_get_new_form_should_allow_attachment_upload
1644 1660 @request.session[:user_id] = 2
1645 1661 get :new, :project_id => 1, :tracker_id => 1
1646 1662
1647 1663 assert_select 'form[id=issue-form][method=post][enctype=multipart/form-data]' do
1648 1664 assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
1649 1665 end
1650 1666 end
1651 1667
1652 1668 def test_get_new_should_prefill_the_form_from_params
1653 1669 @request.session[:user_id] = 2
1654 1670 get :new, :project_id => 1,
1655 1671 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
1656 1672
1657 1673 issue = assigns(:issue)
1658 1674 assert_equal 3, issue.tracker_id
1659 1675 assert_equal 'Prefilled', issue.description
1660 1676 assert_equal 'Custom field value', issue.custom_field_value(2)
1661 1677
1662 1678 assert_select 'select[name=?]', 'issue[tracker_id]' do
1663 1679 assert_select 'option[value=3][selected=selected]'
1664 1680 end
1665 1681 assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
1666 1682 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
1667 1683 end
1668 1684
1669 1685 def test_get_new_should_mark_required_fields
1670 1686 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1671 1687 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1672 1688 WorkflowPermission.delete_all
1673 1689 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1674 1690 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1675 1691 @request.session[:user_id] = 2
1676 1692
1677 1693 get :new, :project_id => 1
1678 1694 assert_response :success
1679 1695 assert_template 'new'
1680 1696
1681 1697 assert_select 'label[for=issue_start_date]' do
1682 1698 assert_select 'span[class=required]', 0
1683 1699 end
1684 1700 assert_select 'label[for=issue_due_date]' do
1685 1701 assert_select 'span[class=required]'
1686 1702 end
1687 1703 assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
1688 1704 assert_select 'span[class=required]', 0
1689 1705 end
1690 1706 assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
1691 1707 assert_select 'span[class=required]'
1692 1708 end
1693 1709 end
1694 1710
1695 1711 def test_get_new_should_not_display_readonly_fields
1696 1712 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1697 1713 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1698 1714 WorkflowPermission.delete_all
1699 1715 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1700 1716 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1701 1717 @request.session[:user_id] = 2
1702 1718
1703 1719 get :new, :project_id => 1
1704 1720 assert_response :success
1705 1721 assert_template 'new'
1706 1722
1707 1723 assert_select 'input[name=?]', 'issue[start_date]'
1708 1724 assert_select 'input[name=?]', 'issue[due_date]', 0
1709 1725 assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
1710 1726 assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
1711 1727 end
1712 1728
1713 1729 def test_get_new_without_tracker_id
1714 1730 @request.session[:user_id] = 2
1715 1731 get :new, :project_id => 1
1716 1732 assert_response :success
1717 1733 assert_template 'new'
1718 1734
1719 1735 issue = assigns(:issue)
1720 1736 assert_not_nil issue
1721 1737 assert_equal Project.find(1).trackers.first, issue.tracker
1722 1738 end
1723 1739
1724 1740 def test_get_new_with_no_default_status_should_display_an_error
1725 1741 @request.session[:user_id] = 2
1726 1742 IssueStatus.delete_all
1727 1743
1728 1744 get :new, :project_id => 1
1729 1745 assert_response 500
1730 1746 assert_error_tag :content => /No default issue/
1731 1747 end
1732 1748
1733 1749 def test_get_new_with_no_tracker_should_display_an_error
1734 1750 @request.session[:user_id] = 2
1735 1751 Tracker.delete_all
1736 1752
1737 1753 get :new, :project_id => 1
1738 1754 assert_response 500
1739 1755 assert_error_tag :content => /No tracker/
1740 1756 end
1741 1757
1742 1758 def test_update_form_for_new_issue
1743 1759 @request.session[:user_id] = 2
1744 1760 xhr :post, :update_form, :project_id => 1,
1745 1761 :issue => {:tracker_id => 2,
1746 1762 :subject => 'This is the test_new issue',
1747 1763 :description => 'This is the description',
1748 1764 :priority_id => 5}
1749 1765 assert_response :success
1750 1766 assert_template 'update_form'
1751 1767 assert_template :partial => '_form'
1752 1768 assert_equal 'text/javascript', response.content_type
1753 1769
1754 1770 issue = assigns(:issue)
1755 1771 assert_kind_of Issue, issue
1756 1772 assert_equal 1, issue.project_id
1757 1773 assert_equal 2, issue.tracker_id
1758 1774 assert_equal 'This is the test_new issue', issue.subject
1759 1775 end
1760 1776
1761 1777 def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
1762 1778 @request.session[:user_id] = 2
1763 1779 WorkflowTransition.delete_all
1764 1780 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
1765 1781 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
1766 1782 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
1767 1783
1768 1784 xhr :post, :update_form, :project_id => 1,
1769 1785 :issue => {:tracker_id => 1,
1770 1786 :status_id => 5,
1771 1787 :subject => 'This is an issue'}
1772 1788
1773 1789 assert_equal 5, assigns(:issue).status_id
1774 1790 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
1775 1791 end
1776 1792
1777 1793 def test_post_create
1778 1794 @request.session[:user_id] = 2
1779 1795 assert_difference 'Issue.count' do
1780 1796 post :create, :project_id => 1,
1781 1797 :issue => {:tracker_id => 3,
1782 1798 :status_id => 2,
1783 1799 :subject => 'This is the test_new issue',
1784 1800 :description => 'This is the description',
1785 1801 :priority_id => 5,
1786 1802 :start_date => '2010-11-07',
1787 1803 :estimated_hours => '',
1788 1804 :custom_field_values => {'2' => 'Value for field 2'}}
1789 1805 end
1790 1806 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1791 1807
1792 1808 issue = Issue.find_by_subject('This is the test_new issue')
1793 1809 assert_not_nil issue
1794 1810 assert_equal 2, issue.author_id
1795 1811 assert_equal 3, issue.tracker_id
1796 1812 assert_equal 2, issue.status_id
1797 1813 assert_equal Date.parse('2010-11-07'), issue.start_date
1798 1814 assert_nil issue.estimated_hours
1799 1815 v = issue.custom_values.where(:custom_field_id => 2).first
1800 1816 assert_not_nil v
1801 1817 assert_equal 'Value for field 2', v.value
1802 1818 end
1803 1819
1804 1820 def test_post_new_with_group_assignment
1805 1821 group = Group.find(11)
1806 1822 project = Project.find(1)
1807 1823 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
1808 1824
1809 1825 with_settings :issue_group_assignment => '1' do
1810 1826 @request.session[:user_id] = 2
1811 1827 assert_difference 'Issue.count' do
1812 1828 post :create, :project_id => project.id,
1813 1829 :issue => {:tracker_id => 3,
1814 1830 :status_id => 1,
1815 1831 :subject => 'This is the test_new_with_group_assignment issue',
1816 1832 :assigned_to_id => group.id}
1817 1833 end
1818 1834 end
1819 1835 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1820 1836
1821 1837 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
1822 1838 assert_not_nil issue
1823 1839 assert_equal group, issue.assigned_to
1824 1840 end
1825 1841
1826 1842 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
1827 1843 with_settings :default_issue_start_date_to_creation_date => 0 do
1828 1844 @request.session[:user_id] = 2
1829 1845 assert_difference 'Issue.count' do
1830 1846 post :create, :project_id => 1,
1831 1847 :issue => {:tracker_id => 3,
1832 1848 :status_id => 2,
1833 1849 :subject => 'This is the test_new issue',
1834 1850 :description => 'This is the description',
1835 1851 :priority_id => 5,
1836 1852 :estimated_hours => '',
1837 1853 :custom_field_values => {'2' => 'Value for field 2'}}
1838 1854 end
1839 1855 assert_redirected_to :controller => 'issues', :action => 'show',
1840 1856 :id => Issue.last.id
1841 1857 issue = Issue.find_by_subject('This is the test_new issue')
1842 1858 assert_not_nil issue
1843 1859 assert_nil issue.start_date
1844 1860 end
1845 1861 end
1846 1862
1847 1863 def test_post_create_without_start_date_and_default_start_date_is_creation_date
1848 1864 with_settings :default_issue_start_date_to_creation_date => 1 do
1849 1865 @request.session[:user_id] = 2
1850 1866 assert_difference 'Issue.count' do
1851 1867 post :create, :project_id => 1,
1852 1868 :issue => {:tracker_id => 3,
1853 1869 :status_id => 2,
1854 1870 :subject => 'This is the test_new issue',
1855 1871 :description => 'This is the description',
1856 1872 :priority_id => 5,
1857 1873 :estimated_hours => '',
1858 1874 :custom_field_values => {'2' => 'Value for field 2'}}
1859 1875 end
1860 1876 assert_redirected_to :controller => 'issues', :action => 'show',
1861 1877 :id => Issue.last.id
1862 1878 issue = Issue.find_by_subject('This is the test_new issue')
1863 1879 assert_not_nil issue
1864 1880 assert_equal Date.today, issue.start_date
1865 1881 end
1866 1882 end
1867 1883
1868 1884 def test_post_create_and_continue
1869 1885 @request.session[:user_id] = 2
1870 1886 assert_difference 'Issue.count' do
1871 1887 post :create, :project_id => 1,
1872 1888 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
1873 1889 :continue => ''
1874 1890 end
1875 1891
1876 1892 issue = Issue.order('id DESC').first
1877 1893 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
1878 1894 assert_not_nil flash[:notice], "flash was not set"
1879 1895 assert_include %|<a href="/issues/#{issue.id}" title="This is first issue">##{issue.id}</a>|, flash[:notice], "issue link not found in the flash message"
1880 1896 end
1881 1897
1882 1898 def test_post_create_without_custom_fields_param
1883 1899 @request.session[:user_id] = 2
1884 1900 assert_difference 'Issue.count' do
1885 1901 post :create, :project_id => 1,
1886 1902 :issue => {:tracker_id => 1,
1887 1903 :subject => 'This is the test_new issue',
1888 1904 :description => 'This is the description',
1889 1905 :priority_id => 5}
1890 1906 end
1891 1907 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
1892 1908 end
1893 1909
1894 1910 def test_post_create_with_multi_custom_field
1895 1911 field = IssueCustomField.find_by_name('Database')
1896 1912 field.update_attribute(:multiple, true)
1897 1913
1898 1914 @request.session[:user_id] = 2
1899 1915 assert_difference 'Issue.count' do
1900 1916 post :create, :project_id => 1,
1901 1917 :issue => {:tracker_id => 1,
1902 1918 :subject => 'This is the test_new issue',
1903 1919 :description => 'This is the description',
1904 1920 :priority_id => 5,
1905 1921 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
1906 1922 end
1907 1923 assert_response 302
1908 1924 issue = Issue.order('id DESC').first
1909 1925 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
1910 1926 end
1911 1927
1912 1928 def test_post_create_with_empty_multi_custom_field
1913 1929 field = IssueCustomField.find_by_name('Database')
1914 1930 field.update_attribute(:multiple, true)
1915 1931
1916 1932 @request.session[:user_id] = 2
1917 1933 assert_difference 'Issue.count' do
1918 1934 post :create, :project_id => 1,
1919 1935 :issue => {:tracker_id => 1,
1920 1936 :subject => 'This is the test_new issue',
1921 1937 :description => 'This is the description',
1922 1938 :priority_id => 5,
1923 1939 :custom_field_values => {'1' => ['']}}
1924 1940 end
1925 1941 assert_response 302
1926 1942 issue = Issue.order('id DESC').first
1927 1943 assert_equal [''], issue.custom_field_value(1).sort
1928 1944 end
1929 1945
1930 1946 def test_post_create_with_multi_user_custom_field
1931 1947 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1932 1948 :tracker_ids => [1], :is_for_all => true)
1933 1949
1934 1950 @request.session[:user_id] = 2
1935 1951 assert_difference 'Issue.count' do
1936 1952 post :create, :project_id => 1,
1937 1953 :issue => {:tracker_id => 1,
1938 1954 :subject => 'This is the test_new issue',
1939 1955 :description => 'This is the description',
1940 1956 :priority_id => 5,
1941 1957 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
1942 1958 end
1943 1959 assert_response 302
1944 1960 issue = Issue.order('id DESC').first
1945 1961 assert_equal ['2', '3'], issue.custom_field_value(field).sort
1946 1962 end
1947 1963
1948 1964 def test_post_create_with_required_custom_field_and_without_custom_fields_param
1949 1965 field = IssueCustomField.find_by_name('Database')
1950 1966 field.update_attribute(:is_required, true)
1951 1967
1952 1968 @request.session[:user_id] = 2
1953 1969 assert_no_difference 'Issue.count' do
1954 1970 post :create, :project_id => 1,
1955 1971 :issue => {:tracker_id => 1,
1956 1972 :subject => 'This is the test_new issue',
1957 1973 :description => 'This is the description',
1958 1974 :priority_id => 5}
1959 1975 end
1960 1976 assert_response :success
1961 1977 assert_template 'new'
1962 1978 issue = assigns(:issue)
1963 1979 assert_not_nil issue
1964 1980 assert_error_tag :content => /Database #{ESCAPED_CANT} be blank/
1965 1981 end
1966 1982
1967 1983 def test_create_should_validate_required_fields
1968 1984 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1969 1985 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1970 1986 WorkflowPermission.delete_all
1971 1987 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1972 1988 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1973 1989 @request.session[:user_id] = 2
1974 1990
1975 1991 assert_no_difference 'Issue.count' do
1976 1992 post :create, :project_id => 1, :issue => {
1977 1993 :tracker_id => 2,
1978 1994 :status_id => 1,
1979 1995 :subject => 'Test',
1980 1996 :start_date => '',
1981 1997 :due_date => '',
1982 1998 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
1983 1999 }
1984 2000 assert_response :success
1985 2001 assert_template 'new'
1986 2002 end
1987 2003
1988 2004 assert_error_tag :content => /Due date #{ESCAPED_CANT} be blank/i
1989 2005 assert_error_tag :content => /Bar #{ESCAPED_CANT} be blank/i
1990 2006 end
1991 2007
1992 2008 def test_create_should_ignore_readonly_fields
1993 2009 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1994 2010 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1995 2011 WorkflowPermission.delete_all
1996 2012 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1997 2013 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1998 2014 @request.session[:user_id] = 2
1999 2015
2000 2016 assert_difference 'Issue.count' do
2001 2017 post :create, :project_id => 1, :issue => {
2002 2018 :tracker_id => 2,
2003 2019 :status_id => 1,
2004 2020 :subject => 'Test',
2005 2021 :start_date => '2012-07-14',
2006 2022 :due_date => '2012-07-16',
2007 2023 :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
2008 2024 }
2009 2025 assert_response 302
2010 2026 end
2011 2027
2012 2028 issue = Issue.order('id DESC').first
2013 2029 assert_equal Date.parse('2012-07-14'), issue.start_date
2014 2030 assert_nil issue.due_date
2015 2031 assert_equal 'value1', issue.custom_field_value(cf1)
2016 2032 assert_nil issue.custom_field_value(cf2)
2017 2033 end
2018 2034
2019 2035 def test_post_create_with_watchers
2020 2036 @request.session[:user_id] = 2
2021 2037 ActionMailer::Base.deliveries.clear
2022 2038
2023 2039 assert_difference 'Watcher.count', 2 do
2024 2040 post :create, :project_id => 1,
2025 2041 :issue => {:tracker_id => 1,
2026 2042 :subject => 'This is a new issue with watchers',
2027 2043 :description => 'This is the description',
2028 2044 :priority_id => 5,
2029 2045 :watcher_user_ids => ['2', '3']}
2030 2046 end
2031 2047 issue = Issue.find_by_subject('This is a new issue with watchers')
2032 2048 assert_not_nil issue
2033 2049 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2034 2050
2035 2051 # Watchers added
2036 2052 assert_equal [2, 3], issue.watcher_user_ids.sort
2037 2053 assert issue.watched_by?(User.find(3))
2038 2054 # Watchers notified
2039 2055 mail = ActionMailer::Base.deliveries.last
2040 2056 assert_not_nil mail
2041 2057 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
2042 2058 end
2043 2059
2044 2060 def test_post_create_subissue
2045 2061 @request.session[:user_id] = 2
2046 2062
2047 2063 assert_difference 'Issue.count' do
2048 2064 post :create, :project_id => 1,
2049 2065 :issue => {:tracker_id => 1,
2050 2066 :subject => 'This is a child issue',
2051 2067 :parent_issue_id => '2'}
2052 2068 assert_response 302
2053 2069 end
2054 2070 issue = Issue.order('id DESC').first
2055 2071 assert_equal Issue.find(2), issue.parent
2056 2072 end
2057 2073
2058 2074 def test_post_create_subissue_with_sharp_parent_id
2059 2075 @request.session[:user_id] = 2
2060 2076
2061 2077 assert_difference 'Issue.count' do
2062 2078 post :create, :project_id => 1,
2063 2079 :issue => {:tracker_id => 1,
2064 2080 :subject => 'This is a child issue',
2065 2081 :parent_issue_id => '#2'}
2066 2082 assert_response 302
2067 2083 end
2068 2084 issue = Issue.order('id DESC').first
2069 2085 assert_equal Issue.find(2), issue.parent
2070 2086 end
2071 2087
2072 2088 def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
2073 2089 @request.session[:user_id] = 2
2074 2090
2075 2091 assert_no_difference 'Issue.count' do
2076 2092 post :create, :project_id => 1,
2077 2093 :issue => {:tracker_id => 1,
2078 2094 :subject => 'This is a child issue',
2079 2095 :parent_issue_id => '4'}
2080 2096
2081 2097 assert_response :success
2082 2098 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
2083 2099 assert_error_tag :content => /Parent task is invalid/i
2084 2100 end
2085 2101 end
2086 2102
2087 2103 def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
2088 2104 @request.session[:user_id] = 2
2089 2105
2090 2106 assert_no_difference 'Issue.count' do
2091 2107 post :create, :project_id => 1,
2092 2108 :issue => {:tracker_id => 1,
2093 2109 :subject => 'This is a child issue',
2094 2110 :parent_issue_id => '01ABC'}
2095 2111
2096 2112 assert_response :success
2097 2113 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
2098 2114 assert_error_tag :content => /Parent task is invalid/i
2099 2115 end
2100 2116 end
2101 2117
2102 2118 def test_post_create_private
2103 2119 @request.session[:user_id] = 2
2104 2120
2105 2121 assert_difference 'Issue.count' do
2106 2122 post :create, :project_id => 1,
2107 2123 :issue => {:tracker_id => 1,
2108 2124 :subject => 'This is a private issue',
2109 2125 :is_private => '1'}
2110 2126 end
2111 2127 issue = Issue.order('id DESC').first
2112 2128 assert issue.is_private?
2113 2129 end
2114 2130
2115 2131 def test_post_create_private_with_set_own_issues_private_permission
2116 2132 role = Role.find(1)
2117 2133 role.remove_permission! :set_issues_private
2118 2134 role.add_permission! :set_own_issues_private
2119 2135
2120 2136 @request.session[:user_id] = 2
2121 2137
2122 2138 assert_difference 'Issue.count' do
2123 2139 post :create, :project_id => 1,
2124 2140 :issue => {:tracker_id => 1,
2125 2141 :subject => 'This is a private issue',
2126 2142 :is_private => '1'}
2127 2143 end
2128 2144 issue = Issue.order('id DESC').first
2129 2145 assert issue.is_private?
2130 2146 end
2131 2147
2132 2148 def test_post_create_should_send_a_notification
2133 2149 ActionMailer::Base.deliveries.clear
2134 2150 @request.session[:user_id] = 2
2135 2151 assert_difference 'Issue.count' do
2136 2152 post :create, :project_id => 1,
2137 2153 :issue => {:tracker_id => 3,
2138 2154 :subject => 'This is the test_new issue',
2139 2155 :description => 'This is the description',
2140 2156 :priority_id => 5,
2141 2157 :estimated_hours => '',
2142 2158 :custom_field_values => {'2' => 'Value for field 2'}}
2143 2159 end
2144 2160 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2145 2161
2146 2162 assert_equal 1, ActionMailer::Base.deliveries.size
2147 2163 end
2148 2164
2149 2165 def test_post_create_should_preserve_fields_values_on_validation_failure
2150 2166 @request.session[:user_id] = 2
2151 2167 post :create, :project_id => 1,
2152 2168 :issue => {:tracker_id => 1,
2153 2169 # empty subject
2154 2170 :subject => '',
2155 2171 :description => 'This is a description',
2156 2172 :priority_id => 6,
2157 2173 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
2158 2174 assert_response :success
2159 2175 assert_template 'new'
2160 2176
2161 2177 assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
2162 2178 assert_select 'select[name=?]', 'issue[priority_id]' do
2163 2179 assert_select 'option[value=6][selected=selected]', :text => 'High'
2164 2180 end
2165 2181 # Custom fields
2166 2182 assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
2167 2183 assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
2168 2184 end
2169 2185 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
2170 2186 end
2171 2187
2172 2188 def test_post_create_with_failure_should_preserve_watchers
2173 2189 assert !User.find(8).member_of?(Project.find(1))
2174 2190
2175 2191 @request.session[:user_id] = 2
2176 2192 post :create, :project_id => 1,
2177 2193 :issue => {:tracker_id => 1,
2178 2194 :watcher_user_ids => ['3', '8']}
2179 2195 assert_response :success
2180 2196 assert_template 'new'
2181 2197
2182 2198 assert_select 'input[name=?][value=2]:not(checked)', 'issue[watcher_user_ids][]'
2183 2199 assert_select 'input[name=?][value=3][checked=checked]', 'issue[watcher_user_ids][]'
2184 2200 assert_select 'input[name=?][value=8][checked=checked]', 'issue[watcher_user_ids][]'
2185 2201 end
2186 2202
2187 2203 def test_post_create_should_ignore_non_safe_attributes
2188 2204 @request.session[:user_id] = 2
2189 2205 assert_nothing_raised do
2190 2206 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
2191 2207 end
2192 2208 end
2193 2209
2194 2210 def test_post_create_with_attachment
2195 2211 set_tmp_attachments_directory
2196 2212 @request.session[:user_id] = 2
2197 2213
2198 2214 assert_difference 'Issue.count' do
2199 2215 assert_difference 'Attachment.count' do
2200 2216 post :create, :project_id => 1,
2201 2217 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2202 2218 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2203 2219 end
2204 2220 end
2205 2221
2206 2222 issue = Issue.order('id DESC').first
2207 2223 attachment = Attachment.order('id DESC').first
2208 2224
2209 2225 assert_equal issue, attachment.container
2210 2226 assert_equal 2, attachment.author_id
2211 2227 assert_equal 'testfile.txt', attachment.filename
2212 2228 assert_equal 'text/plain', attachment.content_type
2213 2229 assert_equal 'test file', attachment.description
2214 2230 assert_equal 59, attachment.filesize
2215 2231 assert File.exists?(attachment.diskfile)
2216 2232 assert_equal 59, File.size(attachment.diskfile)
2217 2233 end
2218 2234
2219 2235 def test_post_create_with_attachment_should_notify_with_attachments
2220 2236 ActionMailer::Base.deliveries.clear
2221 2237 set_tmp_attachments_directory
2222 2238 @request.session[:user_id] = 2
2223 2239
2224 2240 with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
2225 2241 assert_difference 'Issue.count' do
2226 2242 post :create, :project_id => 1,
2227 2243 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2228 2244 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2229 2245 end
2230 2246 end
2231 2247
2232 2248 assert_not_nil ActionMailer::Base.deliveries.last
2233 2249 assert_select_email do
2234 2250 assert_select 'a[href^=?]', 'http://mydomain.foo/attachments/download', 'testfile.txt'
2235 2251 end
2236 2252 end
2237 2253
2238 2254 def test_post_create_with_failure_should_save_attachments
2239 2255 set_tmp_attachments_directory
2240 2256 @request.session[:user_id] = 2
2241 2257
2242 2258 assert_no_difference 'Issue.count' do
2243 2259 assert_difference 'Attachment.count' do
2244 2260 post :create, :project_id => 1,
2245 2261 :issue => { :tracker_id => '1', :subject => '' },
2246 2262 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2247 2263 assert_response :success
2248 2264 assert_template 'new'
2249 2265 end
2250 2266 end
2251 2267
2252 2268 attachment = Attachment.order('id DESC').first
2253 2269 assert_equal 'testfile.txt', attachment.filename
2254 2270 assert File.exists?(attachment.diskfile)
2255 2271 assert_nil attachment.container
2256 2272
2257 2273 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2258 2274 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2259 2275 end
2260 2276
2261 2277 def test_post_create_with_failure_should_keep_saved_attachments
2262 2278 set_tmp_attachments_directory
2263 2279 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2264 2280 @request.session[:user_id] = 2
2265 2281
2266 2282 assert_no_difference 'Issue.count' do
2267 2283 assert_no_difference 'Attachment.count' do
2268 2284 post :create, :project_id => 1,
2269 2285 :issue => { :tracker_id => '1', :subject => '' },
2270 2286 :attachments => {'p0' => {'token' => attachment.token}}
2271 2287 assert_response :success
2272 2288 assert_template 'new'
2273 2289 end
2274 2290 end
2275 2291
2276 2292 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2277 2293 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2278 2294 end
2279 2295
2280 2296 def test_post_create_should_attach_saved_attachments
2281 2297 set_tmp_attachments_directory
2282 2298 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2283 2299 @request.session[:user_id] = 2
2284 2300
2285 2301 assert_difference 'Issue.count' do
2286 2302 assert_no_difference 'Attachment.count' do
2287 2303 post :create, :project_id => 1,
2288 2304 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
2289 2305 :attachments => {'p0' => {'token' => attachment.token}}
2290 2306 assert_response 302
2291 2307 end
2292 2308 end
2293 2309
2294 2310 issue = Issue.order('id DESC').first
2295 2311 assert_equal 1, issue.attachments.count
2296 2312
2297 2313 attachment.reload
2298 2314 assert_equal issue, attachment.container
2299 2315 end
2300 2316
2301 2317 def setup_without_workflow_privilege
2302 2318 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2303 2319 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2304 2320 end
2305 2321 private :setup_without_workflow_privilege
2306 2322
2307 2323 test "without workflow privilege #new should propose default status only" do
2308 2324 setup_without_workflow_privilege
2309 2325 get :new, :project_id => 1
2310 2326 assert_response :success
2311 2327 assert_template 'new'
2312 2328 assert_select 'select[name=?]', 'issue[status_id]' do
2313 2329 assert_select 'option', 1
2314 2330 assert_select 'option[value=?]', IssueStatus.default.id.to_s
2315 2331 end
2316 2332 end
2317 2333
2318 2334 test "without workflow privilege #new should accept default status" do
2319 2335 setup_without_workflow_privilege
2320 2336 assert_difference 'Issue.count' do
2321 2337 post :create, :project_id => 1,
2322 2338 :issue => {:tracker_id => 1,
2323 2339 :subject => 'This is an issue',
2324 2340 :status_id => 1}
2325 2341 end
2326 2342 issue = Issue.order('id').last
2327 2343 assert_equal IssueStatus.default, issue.status
2328 2344 end
2329 2345
2330 2346 test "without workflow privilege #new should ignore unauthorized status" do
2331 2347 setup_without_workflow_privilege
2332 2348 assert_difference 'Issue.count' do
2333 2349 post :create, :project_id => 1,
2334 2350 :issue => {:tracker_id => 1,
2335 2351 :subject => 'This is an issue',
2336 2352 :status_id => 3}
2337 2353 end
2338 2354 issue = Issue.order('id').last
2339 2355 assert_equal IssueStatus.default, issue.status
2340 2356 end
2341 2357
2342 2358 test "without workflow privilege #update should ignore status change" do
2343 2359 setup_without_workflow_privilege
2344 2360 assert_difference 'Journal.count' do
2345 2361 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2346 2362 end
2347 2363 assert_equal 1, Issue.find(1).status_id
2348 2364 end
2349 2365
2350 2366 test "without workflow privilege #update ignore attributes changes" do
2351 2367 setup_without_workflow_privilege
2352 2368 assert_difference 'Journal.count' do
2353 2369 put :update, :id => 1,
2354 2370 :issue => {:subject => 'changed', :assigned_to_id => 2,
2355 2371 :notes => 'just trying'}
2356 2372 end
2357 2373 issue = Issue.find(1)
2358 2374 assert_equal "Can't print recipes", issue.subject
2359 2375 assert_nil issue.assigned_to
2360 2376 end
2361 2377
2362 2378 def setup_with_workflow_privilege
2363 2379 WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
2364 2380 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2365 2381 :old_status_id => 1, :new_status_id => 3)
2366 2382 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2367 2383 :old_status_id => 1, :new_status_id => 4)
2368 2384 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2369 2385 end
2370 2386 private :setup_with_workflow_privilege
2371 2387
2372 2388 test "with workflow privilege #update should accept authorized status" do
2373 2389 setup_with_workflow_privilege
2374 2390 assert_difference 'Journal.count' do
2375 2391 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2376 2392 end
2377 2393 assert_equal 3, Issue.find(1).status_id
2378 2394 end
2379 2395
2380 2396 test "with workflow privilege #update should ignore unauthorized status" do
2381 2397 setup_with_workflow_privilege
2382 2398 assert_difference 'Journal.count' do
2383 2399 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2384 2400 end
2385 2401 assert_equal 1, Issue.find(1).status_id
2386 2402 end
2387 2403
2388 2404 test "with workflow privilege #update should accept authorized attributes changes" do
2389 2405 setup_with_workflow_privilege
2390 2406 assert_difference 'Journal.count' do
2391 2407 put :update, :id => 1, :issue => {:assigned_to_id => 2, :notes => 'just trying'}
2392 2408 end
2393 2409 issue = Issue.find(1)
2394 2410 assert_equal 2, issue.assigned_to_id
2395 2411 end
2396 2412
2397 2413 test "with workflow privilege #update should ignore unauthorized attributes changes" do
2398 2414 setup_with_workflow_privilege
2399 2415 assert_difference 'Journal.count' do
2400 2416 put :update, :id => 1, :issue => {:subject => 'changed', :notes => 'just trying'}
2401 2417 end
2402 2418 issue = Issue.find(1)
2403 2419 assert_equal "Can't print recipes", issue.subject
2404 2420 end
2405 2421
2406 2422 def setup_with_workflow_privilege_and_edit_issues_permission
2407 2423 setup_with_workflow_privilege
2408 2424 Role.anonymous.add_permission! :add_issues, :edit_issues
2409 2425 end
2410 2426 private :setup_with_workflow_privilege_and_edit_issues_permission
2411 2427
2412 2428 test "with workflow privilege and :edit_issues permission should accept authorized status" do
2413 2429 setup_with_workflow_privilege_and_edit_issues_permission
2414 2430 assert_difference 'Journal.count' do
2415 2431 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2416 2432 end
2417 2433 assert_equal 3, Issue.find(1).status_id
2418 2434 end
2419 2435
2420 2436 test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
2421 2437 setup_with_workflow_privilege_and_edit_issues_permission
2422 2438 assert_difference 'Journal.count' do
2423 2439 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2424 2440 end
2425 2441 assert_equal 1, Issue.find(1).status_id
2426 2442 end
2427 2443
2428 2444 test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
2429 2445 setup_with_workflow_privilege_and_edit_issues_permission
2430 2446 assert_difference 'Journal.count' do
2431 2447 put :update, :id => 1,
2432 2448 :issue => {:subject => 'changed', :assigned_to_id => 2,
2433 2449 :notes => 'just trying'}
2434 2450 end
2435 2451 issue = Issue.find(1)
2436 2452 assert_equal "changed", issue.subject
2437 2453 assert_equal 2, issue.assigned_to_id
2438 2454 end
2439 2455
2440 2456 def test_new_as_copy
2441 2457 @request.session[:user_id] = 2
2442 2458 get :new, :project_id => 1, :copy_from => 1
2443 2459
2444 2460 assert_response :success
2445 2461 assert_template 'new'
2446 2462
2447 2463 assert_not_nil assigns(:issue)
2448 2464 orig = Issue.find(1)
2449 2465 assert_equal 1, assigns(:issue).project_id
2450 2466 assert_equal orig.subject, assigns(:issue).subject
2451 2467 assert assigns(:issue).copy?
2452 2468
2453 2469 assert_select 'form[id=issue-form][action=/projects/ecookbook/issues]' do
2454 2470 assert_select 'select[name=?]', 'issue[project_id]' do
2455 2471 assert_select 'option[value=1][selected=selected]', :text => 'eCookbook'
2456 2472 assert_select 'option[value=2]:not([selected])', :text => 'OnlineStore'
2457 2473 end
2458 2474 assert_select 'input[name=copy_from][value=1]'
2459 2475 end
2460 2476
2461 2477 # "New issue" menu item should not link to copy
2462 2478 assert_select '#main-menu a.new-issue[href=/projects/ecookbook/issues/new]'
2463 2479 end
2464 2480
2465 2481 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2466 2482 @request.session[:user_id] = 2
2467 2483 issue = Issue.find(3)
2468 2484 assert issue.attachments.count > 0
2469 2485 get :new, :project_id => 1, :copy_from => 3
2470 2486
2471 2487 assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value=1]'
2472 2488 end
2473 2489
2474 2490 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2475 2491 @request.session[:user_id] = 2
2476 2492 issue = Issue.find(3)
2477 2493 issue.attachments.delete_all
2478 2494 get :new, :project_id => 1, :copy_from => 3
2479 2495
2480 2496 assert_select 'input[name=copy_attachments]', 0
2481 2497 end
2482 2498
2483 2499 def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
2484 2500 @request.session[:user_id] = 2
2485 2501 issue = Issue.generate_with_descendants!
2486 2502 get :new, :project_id => 1, :copy_from => issue.id
2487 2503
2488 2504 assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value=1]'
2489 2505 end
2490 2506
2491 2507 def test_new_as_copy_with_invalid_issue_should_respond_with_404
2492 2508 @request.session[:user_id] = 2
2493 2509 get :new, :project_id => 1, :copy_from => 99999
2494 2510 assert_response 404
2495 2511 end
2496 2512
2497 2513 def test_create_as_copy_on_different_project
2498 2514 @request.session[:user_id] = 2
2499 2515 assert_difference 'Issue.count' do
2500 2516 post :create, :project_id => 1, :copy_from => 1,
2501 2517 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2502 2518
2503 2519 assert_not_nil assigns(:issue)
2504 2520 assert assigns(:issue).copy?
2505 2521 end
2506 2522 issue = Issue.order('id DESC').first
2507 2523 assert_redirected_to "/issues/#{issue.id}"
2508 2524
2509 2525 assert_equal 2, issue.project_id
2510 2526 assert_equal 3, issue.tracker_id
2511 2527 assert_equal 'Copy', issue.subject
2512 2528 end
2513 2529
2514 2530 def test_create_as_copy_should_copy_attachments
2515 2531 @request.session[:user_id] = 2
2516 2532 issue = Issue.find(3)
2517 2533 count = issue.attachments.count
2518 2534 assert count > 0
2519 2535 assert_difference 'Issue.count' do
2520 2536 assert_difference 'Attachment.count', count do
2521 2537 assert_difference 'Journal.count', 2 do
2522 2538 post :create, :project_id => 1, :copy_from => 3,
2523 2539 :issue => {:project_id => '1', :tracker_id => '3',
2524 2540 :status_id => '1', :subject => 'Copy with attachments'},
2525 2541 :copy_attachments => '1'
2526 2542 end
2527 2543 end
2528 2544 end
2529 2545 copy = Issue.order('id DESC').first
2530 2546 assert_equal count, copy.attachments.count
2531 2547 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
2532 2548 end
2533 2549
2534 2550 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
2535 2551 @request.session[:user_id] = 2
2536 2552 issue = Issue.find(3)
2537 2553 count = issue.attachments.count
2538 2554 assert count > 0
2539 2555 assert_difference 'Issue.count' do
2540 2556 assert_no_difference 'Attachment.count' do
2541 2557 assert_difference 'Journal.count', 2 do
2542 2558 post :create, :project_id => 1, :copy_from => 3,
2543 2559 :issue => {:project_id => '1', :tracker_id => '3',
2544 2560 :status_id => '1', :subject => 'Copy with attachments'}
2545 2561 end
2546 2562 end
2547 2563 end
2548 2564 copy = Issue.order('id DESC').first
2549 2565 assert_equal 0, copy.attachments.count
2550 2566 end
2551 2567
2552 2568 def test_create_as_copy_with_attachments_should_add_new_files
2553 2569 @request.session[:user_id] = 2
2554 2570 issue = Issue.find(3)
2555 2571 count = issue.attachments.count
2556 2572 assert count > 0
2557 2573 assert_difference 'Issue.count' do
2558 2574 assert_difference 'Attachment.count', count + 1 do
2559 2575 assert_difference 'Journal.count', 2 do
2560 2576 post :create, :project_id => 1, :copy_from => 3,
2561 2577 :issue => {:project_id => '1', :tracker_id => '3',
2562 2578 :status_id => '1', :subject => 'Copy with attachments'},
2563 2579 :copy_attachments => '1',
2564 2580 :attachments => {'1' =>
2565 2581 {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
2566 2582 'description' => 'test file'}}
2567 2583 end
2568 2584 end
2569 2585 end
2570 2586 copy = Issue.order('id DESC').first
2571 2587 assert_equal count + 1, copy.attachments.count
2572 2588 end
2573 2589
2574 2590 def test_create_as_copy_should_add_relation_with_copied_issue
2575 2591 @request.session[:user_id] = 2
2576 2592 assert_difference 'Issue.count' do
2577 2593 assert_difference 'IssueRelation.count' do
2578 2594 post :create, :project_id => 1, :copy_from => 1,
2579 2595 :issue => {:project_id => '1', :tracker_id => '3',
2580 2596 :status_id => '1', :subject => 'Copy'}
2581 2597 end
2582 2598 end
2583 2599 copy = Issue.order('id DESC').first
2584 2600 assert_equal 1, copy.relations.size
2585 2601 end
2586 2602
2587 2603 def test_create_as_copy_should_copy_subtasks
2588 2604 @request.session[:user_id] = 2
2589 2605 issue = Issue.generate_with_descendants!
2590 2606 count = issue.descendants.count
2591 2607 assert_difference 'Issue.count', count + 1 do
2592 2608 assert_difference 'Journal.count', (count + 1) * 2 do
2593 2609 post :create, :project_id => 1, :copy_from => issue.id,
2594 2610 :issue => {:project_id => '1', :tracker_id => '3',
2595 2611 :status_id => '1', :subject => 'Copy with subtasks'},
2596 2612 :copy_subtasks => '1'
2597 2613 end
2598 2614 end
2599 2615 copy = Issue.where(:parent_id => nil).order('id DESC').first
2600 2616 assert_equal count, copy.descendants.count
2601 2617 assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
2602 2618 end
2603 2619
2604 2620 def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
2605 2621 @request.session[:user_id] = 2
2606 2622 issue = Issue.generate_with_descendants!
2607 2623 assert_difference 'Issue.count', 1 do
2608 2624 assert_difference 'Journal.count', 2 do
2609 2625 post :create, :project_id => 1, :copy_from => 3,
2610 2626 :issue => {:project_id => '1', :tracker_id => '3',
2611 2627 :status_id => '1', :subject => 'Copy with subtasks'}
2612 2628 end
2613 2629 end
2614 2630 copy = Issue.where(:parent_id => nil).order('id DESC').first
2615 2631 assert_equal 0, copy.descendants.count
2616 2632 end
2617 2633
2618 2634 def test_create_as_copy_with_failure
2619 2635 @request.session[:user_id] = 2
2620 2636 post :create, :project_id => 1, :copy_from => 1,
2621 2637 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
2622 2638
2623 2639 assert_response :success
2624 2640 assert_template 'new'
2625 2641
2626 2642 assert_not_nil assigns(:issue)
2627 2643 assert assigns(:issue).copy?
2628 2644
2629 2645 assert_select 'form#issue-form[action=/projects/ecookbook/issues]' do
2630 2646 assert_select 'select[name=?]', 'issue[project_id]' do
2631 2647 assert_select 'option[value=1]:not([selected])', :text => 'eCookbook'
2632 2648 assert_select 'option[value=2][selected=selected]', :text => 'OnlineStore'
2633 2649 end
2634 2650 assert_select 'input[name=copy_from][value=1]'
2635 2651 end
2636 2652 end
2637 2653
2638 2654 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
2639 2655 @request.session[:user_id] = 2
2640 2656 assert !User.find(2).member_of?(Project.find(4))
2641 2657
2642 2658 assert_difference 'Issue.count' do
2643 2659 post :create, :project_id => 1, :copy_from => 1,
2644 2660 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2645 2661 end
2646 2662 issue = Issue.order('id DESC').first
2647 2663 assert_equal 1, issue.project_id
2648 2664 end
2649 2665
2650 2666 def test_get_edit
2651 2667 @request.session[:user_id] = 2
2652 2668 get :edit, :id => 1
2653 2669 assert_response :success
2654 2670 assert_template 'edit'
2655 2671 assert_not_nil assigns(:issue)
2656 2672 assert_equal Issue.find(1), assigns(:issue)
2657 2673
2658 2674 # Be sure we don't display inactive IssuePriorities
2659 2675 assert ! IssuePriority.find(15).active?
2660 2676 assert_select 'select[name=?]', 'issue[priority_id]' do
2661 2677 assert_select 'option[value=15]', 0
2662 2678 end
2663 2679 end
2664 2680
2665 2681 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
2666 2682 @request.session[:user_id] = 2
2667 2683 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
2668 2684
2669 2685 get :edit, :id => 1
2670 2686 assert_select 'input[name=?]', 'time_entry[hours]'
2671 2687 end
2672 2688
2673 2689 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
2674 2690 @request.session[:user_id] = 2
2675 2691 Role.find_by_name('Manager').remove_permission! :log_time
2676 2692
2677 2693 get :edit, :id => 1
2678 2694 assert_select 'input[name=?]', 'time_entry[hours]', 0
2679 2695 end
2680 2696
2681 2697 def test_get_edit_with_params
2682 2698 @request.session[:user_id] = 2
2683 2699 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
2684 2700 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
2685 2701 assert_response :success
2686 2702 assert_template 'edit'
2687 2703
2688 2704 issue = assigns(:issue)
2689 2705 assert_not_nil issue
2690 2706
2691 2707 assert_equal 5, issue.status_id
2692 2708 assert_select 'select[name=?]', 'issue[status_id]' do
2693 2709 assert_select 'option[value=5][selected=selected]', :text => 'Closed'
2694 2710 end
2695 2711
2696 2712 assert_equal 7, issue.priority_id
2697 2713 assert_select 'select[name=?]', 'issue[priority_id]' do
2698 2714 assert_select 'option[value=7][selected=selected]', :text => 'Urgent'
2699 2715 end
2700 2716
2701 2717 assert_select 'input[name=?][value=2.5]', 'time_entry[hours]'
2702 2718 assert_select 'select[name=?]', 'time_entry[activity_id]' do
2703 2719 assert_select 'option[value=10][selected=selected]', :text => 'Development'
2704 2720 end
2705 2721 assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
2706 2722 end
2707 2723
2708 2724 def test_get_edit_with_multi_custom_field
2709 2725 field = CustomField.find(1)
2710 2726 field.update_attribute :multiple, true
2711 2727 issue = Issue.find(1)
2712 2728 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2713 2729 issue.save!
2714 2730
2715 2731 @request.session[:user_id] = 2
2716 2732 get :edit, :id => 1
2717 2733 assert_response :success
2718 2734 assert_template 'edit'
2719 2735
2720 2736 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
2721 2737 assert_select 'option', 3
2722 2738 assert_select 'option[value=MySQL][selected=selected]'
2723 2739 assert_select 'option[value=Oracle][selected=selected]'
2724 2740 assert_select 'option[value=PostgreSQL]:not([selected])'
2725 2741 end
2726 2742 end
2727 2743
2728 2744 def test_update_form_for_existing_issue
2729 2745 @request.session[:user_id] = 2
2730 2746 xhr :put, :update_form, :project_id => 1,
2731 2747 :id => 1,
2732 2748 :issue => {:tracker_id => 2,
2733 2749 :subject => 'This is the test_new issue',
2734 2750 :description => 'This is the description',
2735 2751 :priority_id => 5}
2736 2752 assert_response :success
2737 2753 assert_equal 'text/javascript', response.content_type
2738 2754 assert_template 'update_form'
2739 2755 assert_template :partial => '_form'
2740 2756
2741 2757 issue = assigns(:issue)
2742 2758 assert_kind_of Issue, issue
2743 2759 assert_equal 1, issue.id
2744 2760 assert_equal 1, issue.project_id
2745 2761 assert_equal 2, issue.tracker_id
2746 2762 assert_equal 'This is the test_new issue', issue.subject
2747 2763 end
2748 2764
2749 2765 def test_update_form_for_existing_issue_should_keep_issue_author
2750 2766 @request.session[:user_id] = 3
2751 2767 xhr :put, :update_form, :project_id => 1, :id => 1, :issue => {:subject => 'Changed'}
2752 2768 assert_response :success
2753 2769 assert_equal 'text/javascript', response.content_type
2754 2770
2755 2771 issue = assigns(:issue)
2756 2772 assert_equal User.find(2), issue.author
2757 2773 assert_equal 2, issue.author_id
2758 2774 assert_not_equal User.current, issue.author
2759 2775 end
2760 2776
2761 2777 def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
2762 2778 @request.session[:user_id] = 2
2763 2779 WorkflowTransition.delete_all
2764 2780 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
2765 2781 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
2766 2782 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
2767 2783
2768 2784 xhr :put, :update_form, :project_id => 1,
2769 2785 :id => 2,
2770 2786 :issue => {:tracker_id => 2,
2771 2787 :status_id => 5,
2772 2788 :subject => 'This is an issue'}
2773 2789
2774 2790 assert_equal 5, assigns(:issue).status_id
2775 2791 assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
2776 2792 end
2777 2793
2778 2794 def test_update_form_for_existing_issue_with_project_change
2779 2795 @request.session[:user_id] = 2
2780 2796 xhr :put, :update_form, :project_id => 1,
2781 2797 :id => 1,
2782 2798 :issue => {:project_id => 2,
2783 2799 :tracker_id => 2,
2784 2800 :subject => 'This is the test_new issue',
2785 2801 :description => 'This is the description',
2786 2802 :priority_id => 5}
2787 2803 assert_response :success
2788 2804 assert_template :partial => '_form'
2789 2805
2790 2806 issue = assigns(:issue)
2791 2807 assert_kind_of Issue, issue
2792 2808 assert_equal 1, issue.id
2793 2809 assert_equal 2, issue.project_id
2794 2810 assert_equal 2, issue.tracker_id
2795 2811 assert_equal 'This is the test_new issue', issue.subject
2796 2812 end
2797 2813
2798 2814 def test_update_form_should_propose_default_status_for_existing_issue
2799 2815 @request.session[:user_id] = 2
2800 2816 WorkflowTransition.delete_all
2801 2817 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
2802 2818
2803 2819 xhr :put, :update_form, :project_id => 1, :id => 2
2804 2820 assert_response :success
2805 2821 assert_equal [2,3], assigns(:allowed_statuses).map(&:id).sort
2806 2822 end
2807 2823
2808 2824 def test_put_update_without_custom_fields_param
2809 2825 @request.session[:user_id] = 2
2810 2826 ActionMailer::Base.deliveries.clear
2811 2827
2812 2828 issue = Issue.find(1)
2813 2829 assert_equal '125', issue.custom_value_for(2).value
2814 2830 old_subject = issue.subject
2815 2831 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
2816 2832
2817 2833 assert_difference('Journal.count') do
2818 2834 assert_difference('JournalDetail.count', 2) do
2819 2835 put :update, :id => 1, :issue => {:subject => new_subject,
2820 2836 :priority_id => '6',
2821 2837 :category_id => '1' # no change
2822 2838 }
2823 2839 end
2824 2840 end
2825 2841 assert_redirected_to :action => 'show', :id => '1'
2826 2842 issue.reload
2827 2843 assert_equal new_subject, issue.subject
2828 2844 # Make sure custom fields were not cleared
2829 2845 assert_equal '125', issue.custom_value_for(2).value
2830 2846
2831 2847 mail = ActionMailer::Base.deliveries.last
2832 2848 assert_not_nil mail
2833 2849 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2834 2850 assert_mail_body_match "Subject changed from #{old_subject} to #{new_subject}", mail
2835 2851 end
2836 2852
2837 2853 def test_put_update_with_project_change
2838 2854 @request.session[:user_id] = 2
2839 2855 ActionMailer::Base.deliveries.clear
2840 2856
2841 2857 assert_difference('Journal.count') do
2842 2858 assert_difference('JournalDetail.count', 3) do
2843 2859 put :update, :id => 1, :issue => {:project_id => '2',
2844 2860 :tracker_id => '1', # no change
2845 2861 :priority_id => '6',
2846 2862 :category_id => '3'
2847 2863 }
2848 2864 end
2849 2865 end
2850 2866 assert_redirected_to :action => 'show', :id => '1'
2851 2867 issue = Issue.find(1)
2852 2868 assert_equal 2, issue.project_id
2853 2869 assert_equal 1, issue.tracker_id
2854 2870 assert_equal 6, issue.priority_id
2855 2871 assert_equal 3, issue.category_id
2856 2872
2857 2873 mail = ActionMailer::Base.deliveries.last
2858 2874 assert_not_nil mail
2859 2875 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2860 2876 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
2861 2877 end
2862 2878
2863 2879 def test_put_update_with_tracker_change
2864 2880 @request.session[:user_id] = 2
2865 2881 ActionMailer::Base.deliveries.clear
2866 2882
2867 2883 assert_difference('Journal.count') do
2868 2884 assert_difference('JournalDetail.count', 2) do
2869 2885 put :update, :id => 1, :issue => {:project_id => '1',
2870 2886 :tracker_id => '2',
2871 2887 :priority_id => '6'
2872 2888 }
2873 2889 end
2874 2890 end
2875 2891 assert_redirected_to :action => 'show', :id => '1'
2876 2892 issue = Issue.find(1)
2877 2893 assert_equal 1, issue.project_id
2878 2894 assert_equal 2, issue.tracker_id
2879 2895 assert_equal 6, issue.priority_id
2880 2896 assert_equal 1, issue.category_id
2881 2897
2882 2898 mail = ActionMailer::Base.deliveries.last
2883 2899 assert_not_nil mail
2884 2900 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
2885 2901 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
2886 2902 end
2887 2903
2888 2904 def test_put_update_with_custom_field_change
2889 2905 @request.session[:user_id] = 2
2890 2906 issue = Issue.find(1)
2891 2907 assert_equal '125', issue.custom_value_for(2).value
2892 2908
2893 2909 assert_difference('Journal.count') do
2894 2910 assert_difference('JournalDetail.count', 3) do
2895 2911 put :update, :id => 1, :issue => {:subject => 'Custom field change',
2896 2912 :priority_id => '6',
2897 2913 :category_id => '1', # no change
2898 2914 :custom_field_values => { '2' => 'New custom value' }
2899 2915 }
2900 2916 end
2901 2917 end
2902 2918 assert_redirected_to :action => 'show', :id => '1'
2903 2919 issue.reload
2904 2920 assert_equal 'New custom value', issue.custom_value_for(2).value
2905 2921
2906 2922 mail = ActionMailer::Base.deliveries.last
2907 2923 assert_not_nil mail
2908 2924 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
2909 2925 end
2910 2926
2911 2927 def test_put_update_with_multi_custom_field_change
2912 2928 field = CustomField.find(1)
2913 2929 field.update_attribute :multiple, true
2914 2930 issue = Issue.find(1)
2915 2931 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
2916 2932 issue.save!
2917 2933
2918 2934 @request.session[:user_id] = 2
2919 2935 assert_difference('Journal.count') do
2920 2936 assert_difference('JournalDetail.count', 3) do
2921 2937 put :update, :id => 1,
2922 2938 :issue => {
2923 2939 :subject => 'Custom field change',
2924 2940 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
2925 2941 }
2926 2942 end
2927 2943 end
2928 2944 assert_redirected_to :action => 'show', :id => '1'
2929 2945 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
2930 2946 end
2931 2947
2932 2948 def test_put_update_with_status_and_assignee_change
2933 2949 issue = Issue.find(1)
2934 2950 assert_equal 1, issue.status_id
2935 2951 @request.session[:user_id] = 2
2936 2952 assert_difference('TimeEntry.count', 0) do
2937 2953 put :update,
2938 2954 :id => 1,
2939 2955 :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
2940 2956 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
2941 2957 end
2942 2958 assert_redirected_to :action => 'show', :id => '1'
2943 2959 issue.reload
2944 2960 assert_equal 2, issue.status_id
2945 2961 j = Journal.order('id DESC').first
2946 2962 assert_equal 'Assigned to dlopper', j.notes
2947 2963 assert_equal 2, j.details.size
2948 2964
2949 2965 mail = ActionMailer::Base.deliveries.last
2950 2966 assert_mail_body_match "Status changed from New to Assigned", mail
2951 2967 # subject should contain the new status
2952 2968 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
2953 2969 end
2954 2970
2955 2971 def test_put_update_with_note_only
2956 2972 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
2957 2973 # anonymous user
2958 2974 put :update,
2959 2975 :id => 1,
2960 2976 :issue => { :notes => notes }
2961 2977 assert_redirected_to :action => 'show', :id => '1'
2962 2978 j = Journal.order('id DESC').first
2963 2979 assert_equal notes, j.notes
2964 2980 assert_equal 0, j.details.size
2965 2981 assert_equal User.anonymous, j.user
2966 2982
2967 2983 mail = ActionMailer::Base.deliveries.last
2968 2984 assert_mail_body_match notes, mail
2969 2985 end
2970 2986
2971 2987 def test_put_update_with_private_note_only
2972 2988 notes = 'Private note'
2973 2989 @request.session[:user_id] = 2
2974 2990
2975 2991 assert_difference 'Journal.count' do
2976 2992 put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
2977 2993 assert_redirected_to :action => 'show', :id => '1'
2978 2994 end
2979 2995
2980 2996 j = Journal.order('id DESC').first
2981 2997 assert_equal notes, j.notes
2982 2998 assert_equal true, j.private_notes
2983 2999 end
2984 3000
2985 3001 def test_put_update_with_private_note_and_changes
2986 3002 notes = 'Private note'
2987 3003 @request.session[:user_id] = 2
2988 3004
2989 3005 assert_difference 'Journal.count', 2 do
2990 3006 put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
2991 3007 assert_redirected_to :action => 'show', :id => '1'
2992 3008 end
2993 3009
2994 3010 j = Journal.order('id DESC').first
2995 3011 assert_equal notes, j.notes
2996 3012 assert_equal true, j.private_notes
2997 3013 assert_equal 0, j.details.count
2998 3014
2999 3015 j = Journal.order('id DESC').offset(1).first
3000 3016 assert_nil j.notes
3001 3017 assert_equal false, j.private_notes
3002 3018 assert_equal 1, j.details.count
3003 3019 end
3004 3020
3005 3021 def test_put_update_with_note_and_spent_time
3006 3022 @request.session[:user_id] = 2
3007 3023 spent_hours_before = Issue.find(1).spent_hours
3008 3024 assert_difference('TimeEntry.count') do
3009 3025 put :update,
3010 3026 :id => 1,
3011 3027 :issue => { :notes => '2.5 hours added' },
3012 3028 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
3013 3029 end
3014 3030 assert_redirected_to :action => 'show', :id => '1'
3015 3031
3016 3032 issue = Issue.find(1)
3017 3033
3018 3034 j = Journal.order('id DESC').first
3019 3035 assert_equal '2.5 hours added', j.notes
3020 3036 assert_equal 0, j.details.size
3021 3037
3022 3038 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
3023 3039 assert_not_nil t
3024 3040 assert_equal 2.5, t.hours
3025 3041 assert_equal spent_hours_before + 2.5, issue.spent_hours
3026 3042 end
3027 3043
3028 3044 def test_put_update_should_preserve_parent_issue_even_if_not_visible
3029 3045 parent = Issue.generate!(:project_id => 1, :is_private => true)
3030 3046 issue = Issue.generate!(:parent_issue_id => parent.id)
3031 3047 assert !parent.visible?(User.find(3))
3032 3048 @request.session[:user_id] = 3
3033 3049
3034 3050 get :edit, :id => issue.id
3035 3051 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
3036 3052
3037 3053 put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
3038 3054 assert_response 302
3039 3055 assert_equal parent, issue.parent
3040 3056 end
3041 3057
3042 3058 def test_put_update_with_attachment_only
3043 3059 set_tmp_attachments_directory
3044 3060
3045 3061 # Delete all fixtured journals, a race condition can occur causing the wrong
3046 3062 # journal to get fetched in the next find.
3047 3063 Journal.delete_all
3048 3064
3049 3065 # anonymous user
3050 3066 assert_difference 'Attachment.count' do
3051 3067 put :update, :id => 1,
3052 3068 :issue => {:notes => ''},
3053 3069 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3054 3070 end
3055 3071
3056 3072 assert_redirected_to :action => 'show', :id => '1'
3057 3073 j = Issue.find(1).journals.reorder('id DESC').first
3058 3074 assert j.notes.blank?
3059 3075 assert_equal 1, j.details.size
3060 3076 assert_equal 'testfile.txt', j.details.first.value
3061 3077 assert_equal User.anonymous, j.user
3062 3078
3063 3079 attachment = Attachment.order('id DESC').first
3064 3080 assert_equal Issue.find(1), attachment.container
3065 3081 assert_equal User.anonymous, attachment.author
3066 3082 assert_equal 'testfile.txt', attachment.filename
3067 3083 assert_equal 'text/plain', attachment.content_type
3068 3084 assert_equal 'test file', attachment.description
3069 3085 assert_equal 59, attachment.filesize
3070 3086 assert File.exists?(attachment.diskfile)
3071 3087 assert_equal 59, File.size(attachment.diskfile)
3072 3088
3073 3089 mail = ActionMailer::Base.deliveries.last
3074 3090 assert_mail_body_match 'testfile.txt', mail
3075 3091 end
3076 3092
3077 3093 def test_put_update_with_failure_should_save_attachments
3078 3094 set_tmp_attachments_directory
3079 3095 @request.session[:user_id] = 2
3080 3096
3081 3097 assert_no_difference 'Journal.count' do
3082 3098 assert_difference 'Attachment.count' do
3083 3099 put :update, :id => 1,
3084 3100 :issue => { :subject => '' },
3085 3101 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3086 3102 assert_response :success
3087 3103 assert_template 'edit'
3088 3104 end
3089 3105 end
3090 3106
3091 3107 attachment = Attachment.order('id DESC').first
3092 3108 assert_equal 'testfile.txt', attachment.filename
3093 3109 assert File.exists?(attachment.diskfile)
3094 3110 assert_nil attachment.container
3095 3111
3096 3112 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3097 3113 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3098 3114 end
3099 3115
3100 3116 def test_put_update_with_failure_should_keep_saved_attachments
3101 3117 set_tmp_attachments_directory
3102 3118 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3103 3119 @request.session[:user_id] = 2
3104 3120
3105 3121 assert_no_difference 'Journal.count' do
3106 3122 assert_no_difference 'Attachment.count' do
3107 3123 put :update, :id => 1,
3108 3124 :issue => { :subject => '' },
3109 3125 :attachments => {'p0' => {'token' => attachment.token}}
3110 3126 assert_response :success
3111 3127 assert_template 'edit'
3112 3128 end
3113 3129 end
3114 3130
3115 3131 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3116 3132 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3117 3133 end
3118 3134
3119 3135 def test_put_update_should_attach_saved_attachments
3120 3136 set_tmp_attachments_directory
3121 3137 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3122 3138 @request.session[:user_id] = 2
3123 3139
3124 3140 assert_difference 'Journal.count' do
3125 3141 assert_difference 'JournalDetail.count' do
3126 3142 assert_no_difference 'Attachment.count' do
3127 3143 put :update, :id => 1,
3128 3144 :issue => {:notes => 'Attachment added'},
3129 3145 :attachments => {'p0' => {'token' => attachment.token}}
3130 3146 assert_redirected_to '/issues/1'
3131 3147 end
3132 3148 end
3133 3149 end
3134 3150
3135 3151 attachment.reload
3136 3152 assert_equal Issue.find(1), attachment.container
3137 3153
3138 3154 journal = Journal.order('id DESC').first
3139 3155 assert_equal 1, journal.details.size
3140 3156 assert_equal 'testfile.txt', journal.details.first.value
3141 3157 end
3142 3158
3143 3159 def test_put_update_with_attachment_that_fails_to_save
3144 3160 set_tmp_attachments_directory
3145 3161
3146 3162 # Delete all fixtured journals, a race condition can occur causing the wrong
3147 3163 # journal to get fetched in the next find.
3148 3164 Journal.delete_all
3149 3165
3150 3166 # Mock out the unsaved attachment
3151 3167 Attachment.any_instance.stubs(:create).returns(Attachment.new)
3152 3168
3153 3169 # anonymous user
3154 3170 put :update,
3155 3171 :id => 1,
3156 3172 :issue => {:notes => ''},
3157 3173 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
3158 3174 assert_redirected_to :action => 'show', :id => '1'
3159 3175 assert_equal '1 file(s) could not be saved.', flash[:warning]
3160 3176 end
3161 3177
3162 3178 def test_put_update_with_no_change
3163 3179 issue = Issue.find(1)
3164 3180 issue.journals.clear
3165 3181 ActionMailer::Base.deliveries.clear
3166 3182
3167 3183 put :update,
3168 3184 :id => 1,
3169 3185 :issue => {:notes => ''}
3170 3186 assert_redirected_to :action => 'show', :id => '1'
3171 3187
3172 3188 issue.reload
3173 3189 assert issue.journals.empty?
3174 3190 # No email should be sent
3175 3191 assert ActionMailer::Base.deliveries.empty?
3176 3192 end
3177 3193
3178 3194 def test_put_update_should_send_a_notification
3179 3195 @request.session[:user_id] = 2
3180 3196 ActionMailer::Base.deliveries.clear
3181 3197 issue = Issue.find(1)
3182 3198 old_subject = issue.subject
3183 3199 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
3184 3200
3185 3201 put :update, :id => 1, :issue => {:subject => new_subject,
3186 3202 :priority_id => '6',
3187 3203 :category_id => '1' # no change
3188 3204 }
3189 3205 assert_equal 1, ActionMailer::Base.deliveries.size
3190 3206 end
3191 3207
3192 3208 def test_put_update_with_invalid_spent_time_hours_only
3193 3209 @request.session[:user_id] = 2
3194 3210 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3195 3211
3196 3212 assert_no_difference('Journal.count') do
3197 3213 put :update,
3198 3214 :id => 1,
3199 3215 :issue => {:notes => notes},
3200 3216 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
3201 3217 end
3202 3218 assert_response :success
3203 3219 assert_template 'edit'
3204 3220
3205 3221 assert_error_tag :descendant => {:content => /Activity #{ESCAPED_CANT} be blank/}
3206 3222 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3207 3223 assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
3208 3224 end
3209 3225
3210 3226 def test_put_update_with_invalid_spent_time_comments_only
3211 3227 @request.session[:user_id] = 2
3212 3228 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3213 3229
3214 3230 assert_no_difference('Journal.count') do
3215 3231 put :update,
3216 3232 :id => 1,
3217 3233 :issue => {:notes => notes},
3218 3234 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
3219 3235 end
3220 3236 assert_response :success
3221 3237 assert_template 'edit'
3222 3238
3223 3239 assert_error_tag :descendant => {:content => /Activity #{ESCAPED_CANT} be blank/}
3224 3240 assert_error_tag :descendant => {:content => /Hours #{ESCAPED_CANT} be blank/}
3225 3241 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3226 3242 assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
3227 3243 end
3228 3244
3229 3245 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
3230 3246 issue = Issue.find(2)
3231 3247 @request.session[:user_id] = 2
3232 3248
3233 3249 put :update,
3234 3250 :id => issue.id,
3235 3251 :issue => {
3236 3252 :fixed_version_id => 4
3237 3253 }
3238 3254
3239 3255 assert_response :redirect
3240 3256 issue.reload
3241 3257 assert_equal 4, issue.fixed_version_id
3242 3258 assert_not_equal issue.project_id, issue.fixed_version.project_id
3243 3259 end
3244 3260
3245 3261 def test_put_update_should_redirect_back_using_the_back_url_parameter
3246 3262 issue = Issue.find(2)
3247 3263 @request.session[:user_id] = 2
3248 3264
3249 3265 put :update,
3250 3266 :id => issue.id,
3251 3267 :issue => {
3252 3268 :fixed_version_id => 4
3253 3269 },
3254 3270 :back_url => '/issues'
3255 3271
3256 3272 assert_response :redirect
3257 3273 assert_redirected_to '/issues'
3258 3274 end
3259 3275
3260 3276 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3261 3277 issue = Issue.find(2)
3262 3278 @request.session[:user_id] = 2
3263 3279
3264 3280 put :update,
3265 3281 :id => issue.id,
3266 3282 :issue => {
3267 3283 :fixed_version_id => 4
3268 3284 },
3269 3285 :back_url => 'http://google.com'
3270 3286
3271 3287 assert_response :redirect
3272 3288 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3273 3289 end
3274 3290
3275 3291 def test_get_bulk_edit
3276 3292 @request.session[:user_id] = 2
3277 3293 get :bulk_edit, :ids => [1, 2]
3278 3294 assert_response :success
3279 3295 assert_template 'bulk_edit'
3280 3296
3281 3297 assert_select 'ul#bulk-selection' do
3282 3298 assert_select 'li', 2
3283 3299 assert_select 'li a', :text => 'Bug #1'
3284 3300 end
3285 3301
3286 3302 assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
3287 3303 assert_select 'input[name=?]', 'ids[]', 2
3288 3304 assert_select 'input[name=?][value=1][type=hidden]', 'ids[]'
3289 3305
3290 3306 assert_select 'select[name=?]', 'issue[project_id]'
3291 3307 assert_select 'input[name=?]', 'issue[parent_issue_id]'
3292 3308
3293 3309 # Project specific custom field, date type
3294 3310 field = CustomField.find(9)
3295 3311 assert !field.is_for_all?
3296 3312 assert_equal 'date', field.field_format
3297 3313 assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3298 3314
3299 3315 # System wide custom field
3300 3316 assert CustomField.find(1).is_for_all?
3301 3317 assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3302 3318
3303 3319 # Be sure we don't display inactive IssuePriorities
3304 3320 assert ! IssuePriority.find(15).active?
3305 3321 assert_select 'select[name=?]', 'issue[priority_id]' do
3306 3322 assert_select 'option[value=15]', 0
3307 3323 end
3308 3324 end
3309 3325 end
3310 3326
3311 3327 def test_get_bulk_edit_on_different_projects
3312 3328 @request.session[:user_id] = 2
3313 3329 get :bulk_edit, :ids => [1, 2, 6]
3314 3330 assert_response :success
3315 3331 assert_template 'bulk_edit'
3316 3332
3317 3333 # Can not set issues from different projects as children of an issue
3318 3334 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
3319 3335
3320 3336 # Project specific custom field, date type
3321 3337 field = CustomField.find(9)
3322 3338 assert !field.is_for_all?
3323 3339 assert !field.project_ids.include?(Issue.find(6).project_id)
3324 3340 assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
3325 3341 end
3326 3342
3327 3343 def test_get_bulk_edit_with_user_custom_field
3328 3344 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
3329 3345
3330 3346 @request.session[:user_id] = 2
3331 3347 get :bulk_edit, :ids => [1, 2]
3332 3348 assert_response :success
3333 3349 assert_template 'bulk_edit'
3334 3350
3335 3351 assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3336 3352 assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
3337 3353 end
3338 3354 end
3339 3355
3340 3356 def test_get_bulk_edit_with_version_custom_field
3341 3357 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
3342 3358
3343 3359 @request.session[:user_id] = 2
3344 3360 get :bulk_edit, :ids => [1, 2]
3345 3361 assert_response :success
3346 3362 assert_template 'bulk_edit'
3347 3363
3348 3364 assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3349 3365 assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
3350 3366 end
3351 3367 end
3352 3368
3353 3369 def test_get_bulk_edit_with_multi_custom_field
3354 3370 field = CustomField.find(1)
3355 3371 field.update_attribute :multiple, true
3356 3372
3357 3373 @request.session[:user_id] = 2
3358 3374 get :bulk_edit, :ids => [1, 2]
3359 3375 assert_response :success
3360 3376 assert_template 'bulk_edit'
3361 3377
3362 3378 assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
3363 3379 assert_select 'option', field.possible_values.size + 1 # "none" options
3364 3380 end
3365 3381 end
3366 3382
3367 3383 def test_bulk_edit_should_propose_to_clear_text_custom_fields
3368 3384 @request.session[:user_id] = 2
3369 3385 get :bulk_edit, :ids => [1, 3]
3370 3386 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
3371 3387 end
3372 3388
3373 3389 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
3374 3390 WorkflowTransition.delete_all
3375 3391 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3376 3392 :old_status_id => 1, :new_status_id => 1)
3377 3393 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3378 3394 :old_status_id => 1, :new_status_id => 3)
3379 3395 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3380 3396 :old_status_id => 1, :new_status_id => 4)
3381 3397 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3382 3398 :old_status_id => 2, :new_status_id => 1)
3383 3399 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3384 3400 :old_status_id => 2, :new_status_id => 3)
3385 3401 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3386 3402 :old_status_id => 2, :new_status_id => 5)
3387 3403 @request.session[:user_id] = 2
3388 3404 get :bulk_edit, :ids => [1, 2]
3389 3405
3390 3406 assert_response :success
3391 3407 statuses = assigns(:available_statuses)
3392 3408 assert_not_nil statuses
3393 3409 assert_equal [1, 3], statuses.map(&:id).sort
3394 3410
3395 3411 assert_select 'select[name=?]', 'issue[status_id]' do
3396 3412 assert_select 'option', 3 # 2 statuses + "no change" option
3397 3413 end
3398 3414 end
3399 3415
3400 3416 def test_bulk_edit_should_propose_target_project_open_shared_versions
3401 3417 @request.session[:user_id] = 2
3402 3418 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3403 3419 assert_response :success
3404 3420 assert_template 'bulk_edit'
3405 3421 assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
3406 3422
3407 3423 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
3408 3424 assert_select 'option', :text => '2.0'
3409 3425 end
3410 3426 end
3411 3427
3412 3428 def test_bulk_edit_should_propose_target_project_categories
3413 3429 @request.session[:user_id] = 2
3414 3430 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3415 3431 assert_response :success
3416 3432 assert_template 'bulk_edit'
3417 3433 assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
3418 3434
3419 3435 assert_select 'select[name=?]', 'issue[category_id]' do
3420 3436 assert_select 'option', :text => 'Recipes'
3421 3437 end
3422 3438 end
3423 3439
3424 3440 def test_bulk_update
3425 3441 @request.session[:user_id] = 2
3426 3442 # update issues priority
3427 3443 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
3428 3444 :issue => {:priority_id => 7,
3429 3445 :assigned_to_id => '',
3430 3446 :custom_field_values => {'2' => ''}}
3431 3447
3432 3448 assert_response 302
3433 3449 # check that the issues were updated
3434 3450 assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
3435 3451
3436 3452 issue = Issue.find(1)
3437 3453 journal = issue.journals.reorder('created_on DESC').first
3438 3454 assert_equal '125', issue.custom_value_for(2).value
3439 3455 assert_equal 'Bulk editing', journal.notes
3440 3456 assert_equal 1, journal.details.size
3441 3457 end
3442 3458
3443 3459 def test_bulk_update_with_group_assignee
3444 3460 group = Group.find(11)
3445 3461 project = Project.find(1)
3446 3462 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
3447 3463
3448 3464 @request.session[:user_id] = 2
3449 3465 # update issues assignee
3450 3466 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
3451 3467 :issue => {:priority_id => '',
3452 3468 :assigned_to_id => group.id,
3453 3469 :custom_field_values => {'2' => ''}}
3454 3470
3455 3471 assert_response 302
3456 3472 assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
3457 3473 end
3458 3474
3459 3475 def test_bulk_update_on_different_projects
3460 3476 @request.session[:user_id] = 2
3461 3477 # update issues priority
3462 3478 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
3463 3479 :issue => {:priority_id => 7,
3464 3480 :assigned_to_id => '',
3465 3481 :custom_field_values => {'2' => ''}}
3466 3482
3467 3483 assert_response 302
3468 3484 # check that the issues were updated
3469 3485 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
3470 3486
3471 3487 issue = Issue.find(1)
3472 3488 journal = issue.journals.reorder('created_on DESC').first
3473 3489 assert_equal '125', issue.custom_value_for(2).value
3474 3490 assert_equal 'Bulk editing', journal.notes
3475 3491 assert_equal 1, journal.details.size
3476 3492 end
3477 3493
3478 3494 def test_bulk_update_on_different_projects_without_rights
3479 3495 @request.session[:user_id] = 3
3480 3496 user = User.find(3)
3481 3497 action = { :controller => "issues", :action => "bulk_update" }
3482 3498 assert user.allowed_to?(action, Issue.find(1).project)
3483 3499 assert ! user.allowed_to?(action, Issue.find(6).project)
3484 3500 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
3485 3501 :issue => {:priority_id => 7,
3486 3502 :assigned_to_id => '',
3487 3503 :custom_field_values => {'2' => ''}}
3488 3504 assert_response 403
3489 3505 assert_not_equal "Bulk should fail", Journal.last.notes
3490 3506 end
3491 3507
3492 3508 def test_bullk_update_should_send_a_notification
3493 3509 @request.session[:user_id] = 2
3494 3510 ActionMailer::Base.deliveries.clear
3495 3511 post(:bulk_update,
3496 3512 {
3497 3513 :ids => [1, 2],
3498 3514 :notes => 'Bulk editing',
3499 3515 :issue => {
3500 3516 :priority_id => 7,
3501 3517 :assigned_to_id => '',
3502 3518 :custom_field_values => {'2' => ''}
3503 3519 }
3504 3520 })
3505 3521
3506 3522 assert_response 302
3507 3523 assert_equal 2, ActionMailer::Base.deliveries.size
3508 3524 end
3509 3525
3510 3526 def test_bulk_update_project
3511 3527 @request.session[:user_id] = 2
3512 3528 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
3513 3529 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3514 3530 # Issues moved to project 2
3515 3531 assert_equal 2, Issue.find(1).project_id
3516 3532 assert_equal 2, Issue.find(2).project_id
3517 3533 # No tracker change
3518 3534 assert_equal 1, Issue.find(1).tracker_id
3519 3535 assert_equal 2, Issue.find(2).tracker_id
3520 3536 end
3521 3537
3522 3538 def test_bulk_update_project_on_single_issue_should_follow_when_needed
3523 3539 @request.session[:user_id] = 2
3524 3540 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
3525 3541 assert_redirected_to '/issues/1'
3526 3542 end
3527 3543
3528 3544 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
3529 3545 @request.session[:user_id] = 2
3530 3546 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
3531 3547 assert_redirected_to '/projects/onlinestore/issues'
3532 3548 end
3533 3549
3534 3550 def test_bulk_update_tracker
3535 3551 @request.session[:user_id] = 2
3536 3552 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
3537 3553 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3538 3554 assert_equal 2, Issue.find(1).tracker_id
3539 3555 assert_equal 2, Issue.find(2).tracker_id
3540 3556 end
3541 3557
3542 3558 def test_bulk_update_status
3543 3559 @request.session[:user_id] = 2
3544 3560 # update issues priority
3545 3561 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
3546 3562 :issue => {:priority_id => '',
3547 3563 :assigned_to_id => '',
3548 3564 :status_id => '5'}
3549 3565
3550 3566 assert_response 302
3551 3567 issue = Issue.find(1)
3552 3568 assert issue.closed?
3553 3569 end
3554 3570
3555 3571 def test_bulk_update_priority
3556 3572 @request.session[:user_id] = 2
3557 3573 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
3558 3574
3559 3575 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3560 3576 assert_equal 6, Issue.find(1).priority_id
3561 3577 assert_equal 6, Issue.find(2).priority_id
3562 3578 end
3563 3579
3564 3580 def test_bulk_update_with_notes
3565 3581 @request.session[:user_id] = 2
3566 3582 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
3567 3583
3568 3584 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3569 3585 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
3570 3586 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
3571 3587 end
3572 3588
3573 3589 def test_bulk_update_parent_id
3574 3590 IssueRelation.delete_all
3575 3591 @request.session[:user_id] = 2
3576 3592 post :bulk_update, :ids => [1, 3],
3577 3593 :notes => 'Bulk editing parent',
3578 3594 :issue => {:priority_id => '', :assigned_to_id => '',
3579 3595 :status_id => '', :parent_issue_id => '2'}
3580 3596 assert_response 302
3581 3597 parent = Issue.find(2)
3582 3598 assert_equal parent.id, Issue.find(1).parent_id
3583 3599 assert_equal parent.id, Issue.find(3).parent_id
3584 3600 assert_equal [1, 3], parent.children.collect(&:id).sort
3585 3601 end
3586 3602
3587 3603 def test_bulk_update_custom_field
3588 3604 @request.session[:user_id] = 2
3589 3605 # update issues priority
3590 3606 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
3591 3607 :issue => {:priority_id => '',
3592 3608 :assigned_to_id => '',
3593 3609 :custom_field_values => {'2' => '777'}}
3594 3610
3595 3611 assert_response 302
3596 3612
3597 3613 issue = Issue.find(1)
3598 3614 journal = issue.journals.reorder('created_on DESC').first
3599 3615 assert_equal '777', issue.custom_value_for(2).value
3600 3616 assert_equal 1, journal.details.size
3601 3617 assert_equal '125', journal.details.first.old_value
3602 3618 assert_equal '777', journal.details.first.value
3603 3619 end
3604 3620
3605 3621 def test_bulk_update_custom_field_to_blank
3606 3622 @request.session[:user_id] = 2
3607 3623 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
3608 3624 :issue => {:priority_id => '',
3609 3625 :assigned_to_id => '',
3610 3626 :custom_field_values => {'1' => '__none__'}}
3611 3627 assert_response 302
3612 3628 assert_equal '', Issue.find(1).custom_field_value(1)
3613 3629 assert_equal '', Issue.find(3).custom_field_value(1)
3614 3630 end
3615 3631
3616 3632 def test_bulk_update_multi_custom_field
3617 3633 field = CustomField.find(1)
3618 3634 field.update_attribute :multiple, true
3619 3635
3620 3636 @request.session[:user_id] = 2
3621 3637 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
3622 3638 :issue => {:priority_id => '',
3623 3639 :assigned_to_id => '',
3624 3640 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
3625 3641
3626 3642 assert_response 302
3627 3643
3628 3644 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
3629 3645 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
3630 3646 # the custom field is not associated with the issue tracker
3631 3647 assert_nil Issue.find(2).custom_field_value(1)
3632 3648 end
3633 3649
3634 3650 def test_bulk_update_multi_custom_field_to_blank
3635 3651 field = CustomField.find(1)
3636 3652 field.update_attribute :multiple, true
3637 3653
3638 3654 @request.session[:user_id] = 2
3639 3655 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
3640 3656 :issue => {:priority_id => '',
3641 3657 :assigned_to_id => '',
3642 3658 :custom_field_values => {'1' => ['__none__']}}
3643 3659 assert_response 302
3644 3660 assert_equal [''], Issue.find(1).custom_field_value(1)
3645 3661 assert_equal [''], Issue.find(3).custom_field_value(1)
3646 3662 end
3647 3663
3648 3664 def test_bulk_update_unassign
3649 3665 assert_not_nil Issue.find(2).assigned_to
3650 3666 @request.session[:user_id] = 2
3651 3667 # unassign issues
3652 3668 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
3653 3669 assert_response 302
3654 3670 # check that the issues were updated
3655 3671 assert_nil Issue.find(2).assigned_to
3656 3672 end
3657 3673
3658 3674 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
3659 3675 @request.session[:user_id] = 2
3660 3676
3661 3677 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
3662 3678
3663 3679 assert_response :redirect
3664 3680 issues = Issue.find([1,2])
3665 3681 issues.each do |issue|
3666 3682 assert_equal 4, issue.fixed_version_id
3667 3683 assert_not_equal issue.project_id, issue.fixed_version.project_id
3668 3684 end
3669 3685 end
3670 3686
3671 3687 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
3672 3688 @request.session[:user_id] = 2
3673 3689 post :bulk_update, :ids => [1,2], :back_url => '/issues'
3674 3690
3675 3691 assert_response :redirect
3676 3692 assert_redirected_to '/issues'
3677 3693 end
3678 3694
3679 3695 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3680 3696 @request.session[:user_id] = 2
3681 3697 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
3682 3698
3683 3699 assert_response :redirect
3684 3700 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
3685 3701 end
3686 3702
3687 3703 def test_bulk_update_with_all_failures_should_show_errors
3688 3704 @request.session[:user_id] = 2
3689 3705 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
3690 3706
3691 3707 assert_response :success
3692 3708 assert_template 'bulk_edit'
3693 3709 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
3694 3710 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
3695 3711
3696 3712 assert_equal [1, 2], assigns[:issues].map(&:id)
3697 3713 end
3698 3714
3699 3715 def test_bulk_update_with_some_failures_should_show_errors
3700 3716 issue1 = Issue.generate!(:start_date => '2013-05-12')
3701 3717 issue2 = Issue.generate!(:start_date => '2013-05-15')
3702 3718 issue3 = Issue.generate!
3703 3719 @request.session[:user_id] = 2
3704 3720 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
3705 3721 :issue => {:due_date => '2013-05-01'}
3706 3722 assert_response :success
3707 3723 assert_template 'bulk_edit'
3708 3724 assert_select '#errorExplanation span',
3709 3725 :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
3710 3726 assert_select '#errorExplanation ul li',
3711 3727 :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
3712 3728 assert_equal [issue1.id, issue2.id], assigns[:issues].map(&:id)
3713 3729 end
3714 3730
3715 3731 def test_bulk_update_with_failure_should_preserved_form_values
3716 3732 @request.session[:user_id] = 2
3717 3733 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
3718 3734
3719 3735 assert_response :success
3720 3736 assert_template 'bulk_edit'
3721 3737 assert_select 'select[name=?]', 'issue[tracker_id]' do
3722 3738 assert_select 'option[value=2][selected=selected]'
3723 3739 end
3724 3740 assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
3725 3741 end
3726 3742
3727 3743 def test_get_bulk_copy
3728 3744 @request.session[:user_id] = 2
3729 3745 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
3730 3746 assert_response :success
3731 3747 assert_template 'bulk_edit'
3732 3748
3733 3749 issues = assigns(:issues)
3734 3750 assert_not_nil issues
3735 3751 assert_equal [1, 2, 3], issues.map(&:id).sort
3736 3752
3737 3753 assert_select 'input[name=copy_attachments]'
3738 3754 end
3739 3755
3740 3756 def test_bulk_copy_to_another_project
3741 3757 @request.session[:user_id] = 2
3742 3758 assert_difference 'Issue.count', 2 do
3743 3759 assert_no_difference 'Project.find(1).issues.count' do
3744 3760 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
3745 3761 end
3746 3762 end
3747 3763 assert_redirected_to '/projects/ecookbook/issues'
3748 3764
3749 3765 copies = Issue.order('id DESC').limit(issues.size)
3750 3766 copies.each do |copy|
3751 3767 assert_equal 2, copy.project_id
3752 3768 end
3753 3769 end
3754 3770
3755 3771 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
3756 3772 @request.session[:user_id] = 2
3757 3773 issues = [
3758 3774 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
3759 3775 :priority_id => 2, :subject => 'issue 1', :author_id => 1,
3760 3776 :assigned_to_id => nil),
3761 3777 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
3762 3778 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
3763 3779 :assigned_to_id => 3)
3764 3780 ]
3765 3781 assert_difference 'Issue.count', issues.size do
3766 3782 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
3767 3783 :issue => {
3768 3784 :project_id => '', :tracker_id => '', :assigned_to_id => '',
3769 3785 :status_id => '', :start_date => '', :due_date => ''
3770 3786 }
3771 3787 end
3772 3788
3773 3789 copies = Issue.order('id DESC').limit(issues.size)
3774 3790 issues.each do |orig|
3775 3791 copy = copies.detect {|c| c.subject == orig.subject}
3776 3792 assert_not_nil copy
3777 3793 assert_equal orig.project_id, copy.project_id
3778 3794 assert_equal orig.tracker_id, copy.tracker_id
3779 3795 assert_equal orig.status_id, copy.status_id
3780 3796 assert_equal orig.assigned_to_id, copy.assigned_to_id
3781 3797 assert_equal orig.priority_id, copy.priority_id
3782 3798 end
3783 3799 end
3784 3800
3785 3801 def test_bulk_copy_should_allow_changing_the_issue_attributes
3786 3802 # Fixes random test failure with Mysql
3787 3803 # where Issue.where(:project_id => 2).limit(2).order('id desc')
3788 3804 # doesn't return the expected results
3789 3805 Issue.delete_all("project_id=2")
3790 3806
3791 3807 @request.session[:user_id] = 2
3792 3808 assert_difference 'Issue.count', 2 do
3793 3809 assert_no_difference 'Project.find(1).issues.count' do
3794 3810 post :bulk_update, :ids => [1, 2], :copy => '1',
3795 3811 :issue => {
3796 3812 :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
3797 3813 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
3798 3814 }
3799 3815 end
3800 3816 end
3801 3817
3802 3818 copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
3803 3819 assert_equal 2, copied_issues.size
3804 3820 copied_issues.each do |issue|
3805 3821 assert_equal 2, issue.project_id, "Project is incorrect"
3806 3822 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
3807 3823 assert_equal 1, issue.status_id, "Status is incorrect"
3808 3824 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
3809 3825 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
3810 3826 end
3811 3827 end
3812 3828
3813 3829 def test_bulk_copy_should_allow_adding_a_note
3814 3830 @request.session[:user_id] = 2
3815 3831 assert_difference 'Issue.count', 1 do
3816 3832 post :bulk_update, :ids => [1], :copy => '1',
3817 3833 :notes => 'Copying one issue',
3818 3834 :issue => {
3819 3835 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
3820 3836 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
3821 3837 }
3822 3838 end
3823 3839 issue = Issue.order('id DESC').first
3824 3840 assert_equal 1, issue.journals.size
3825 3841 journal = issue.journals.first
3826 3842 assert_equal 1, journal.details.size
3827 3843 assert_equal 'Copying one issue', journal.notes
3828 3844 end
3829 3845
3830 3846 def test_bulk_copy_should_allow_not_copying_the_attachments
3831 3847 attachment_count = Issue.find(3).attachments.size
3832 3848 assert attachment_count > 0
3833 3849 @request.session[:user_id] = 2
3834 3850
3835 3851 assert_difference 'Issue.count', 1 do
3836 3852 assert_no_difference 'Attachment.count' do
3837 3853 post :bulk_update, :ids => [3], :copy => '1',
3838 3854 :issue => {
3839 3855 :project_id => ''
3840 3856 }
3841 3857 end
3842 3858 end
3843 3859 end
3844 3860
3845 3861 def test_bulk_copy_should_allow_copying_the_attachments
3846 3862 attachment_count = Issue.find(3).attachments.size
3847 3863 assert attachment_count > 0
3848 3864 @request.session[:user_id] = 2
3849 3865
3850 3866 assert_difference 'Issue.count', 1 do
3851 3867 assert_difference 'Attachment.count', attachment_count do
3852 3868 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
3853 3869 :issue => {
3854 3870 :project_id => ''
3855 3871 }
3856 3872 end
3857 3873 end
3858 3874 end
3859 3875
3860 3876 def test_bulk_copy_should_add_relations_with_copied_issues
3861 3877 @request.session[:user_id] = 2
3862 3878
3863 3879 assert_difference 'Issue.count', 2 do
3864 3880 assert_difference 'IssueRelation.count', 2 do
3865 3881 post :bulk_update, :ids => [1, 3], :copy => '1',
3866 3882 :issue => {
3867 3883 :project_id => '1'
3868 3884 }
3869 3885 end
3870 3886 end
3871 3887 end
3872 3888
3873 3889 def test_bulk_copy_should_allow_not_copying_the_subtasks
3874 3890 issue = Issue.generate_with_descendants!
3875 3891 @request.session[:user_id] = 2
3876 3892
3877 3893 assert_difference 'Issue.count', 1 do
3878 3894 post :bulk_update, :ids => [issue.id], :copy => '1',
3879 3895 :issue => {
3880 3896 :project_id => ''
3881 3897 }
3882 3898 end
3883 3899 end
3884 3900
3885 3901 def test_bulk_copy_should_allow_copying_the_subtasks
3886 3902 issue = Issue.generate_with_descendants!
3887 3903 count = issue.descendants.count
3888 3904 @request.session[:user_id] = 2
3889 3905
3890 3906 assert_difference 'Issue.count', count+1 do
3891 3907 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
3892 3908 :issue => {
3893 3909 :project_id => ''
3894 3910 }
3895 3911 end
3896 3912 copy = Issue.where(:parent_id => nil).order("id DESC").first
3897 3913 assert_equal count, copy.descendants.count
3898 3914 end
3899 3915
3900 3916 def test_bulk_copy_should_not_copy_selected_subtasks_twice
3901 3917 issue = Issue.generate_with_descendants!
3902 3918 count = issue.descendants.count
3903 3919 @request.session[:user_id] = 2
3904 3920
3905 3921 assert_difference 'Issue.count', count+1 do
3906 3922 post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
3907 3923 :issue => {
3908 3924 :project_id => ''
3909 3925 }
3910 3926 end
3911 3927 copy = Issue.where(:parent_id => nil).order("id DESC").first
3912 3928 assert_equal count, copy.descendants.count
3913 3929 end
3914 3930
3915 3931 def test_bulk_copy_to_another_project_should_follow_when_needed
3916 3932 @request.session[:user_id] = 2
3917 3933 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
3918 3934 issue = Issue.order('id DESC').first
3919 3935 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
3920 3936 end
3921 3937
3922 3938 def test_bulk_copy_with_all_failures_should_display_errors
3923 3939 @request.session[:user_id] = 2
3924 3940 post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
3925 3941
3926 3942 assert_response :success
3927 3943 end
3928 3944
3929 3945 def test_destroy_issue_with_no_time_entries
3930 3946 assert_nil TimeEntry.find_by_issue_id(2)
3931 3947 @request.session[:user_id] = 2
3932 3948
3933 3949 assert_difference 'Issue.count', -1 do
3934 3950 delete :destroy, :id => 2
3935 3951 end
3936 3952 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3937 3953 assert_nil Issue.find_by_id(2)
3938 3954 end
3939 3955
3940 3956 def test_destroy_issues_with_time_entries
3941 3957 @request.session[:user_id] = 2
3942 3958
3943 3959 assert_no_difference 'Issue.count' do
3944 3960 delete :destroy, :ids => [1, 3]
3945 3961 end
3946 3962 assert_response :success
3947 3963 assert_template 'destroy'
3948 3964 assert_not_nil assigns(:hours)
3949 3965 assert Issue.find_by_id(1) && Issue.find_by_id(3)
3950 3966
3951 3967 assert_select 'form' do
3952 3968 assert_select 'input[name=_method][value=delete]'
3953 3969 end
3954 3970 end
3955 3971
3956 3972 def test_destroy_issues_and_destroy_time_entries
3957 3973 @request.session[:user_id] = 2
3958 3974
3959 3975 assert_difference 'Issue.count', -2 do
3960 3976 assert_difference 'TimeEntry.count', -3 do
3961 3977 delete :destroy, :ids => [1, 3], :todo => 'destroy'
3962 3978 end
3963 3979 end
3964 3980 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3965 3981 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3966 3982 assert_nil TimeEntry.find_by_id([1, 2])
3967 3983 end
3968 3984
3969 3985 def test_destroy_issues_and_assign_time_entries_to_project
3970 3986 @request.session[:user_id] = 2
3971 3987
3972 3988 assert_difference 'Issue.count', -2 do
3973 3989 assert_no_difference 'TimeEntry.count' do
3974 3990 delete :destroy, :ids => [1, 3], :todo => 'nullify'
3975 3991 end
3976 3992 end
3977 3993 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3978 3994 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3979 3995 assert_nil TimeEntry.find(1).issue_id
3980 3996 assert_nil TimeEntry.find(2).issue_id
3981 3997 end
3982 3998
3983 3999 def test_destroy_issues_and_reassign_time_entries_to_another_issue
3984 4000 @request.session[:user_id] = 2
3985 4001
3986 4002 assert_difference 'Issue.count', -2 do
3987 4003 assert_no_difference 'TimeEntry.count' do
3988 4004 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
3989 4005 end
3990 4006 end
3991 4007 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
3992 4008 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
3993 4009 assert_equal 2, TimeEntry.find(1).issue_id
3994 4010 assert_equal 2, TimeEntry.find(2).issue_id
3995 4011 end
3996 4012
3997 4013 def test_destroy_issues_from_different_projects
3998 4014 @request.session[:user_id] = 2
3999 4015
4000 4016 assert_difference 'Issue.count', -3 do
4001 4017 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
4002 4018 end
4003 4019 assert_redirected_to :controller => 'issues', :action => 'index'
4004 4020 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
4005 4021 end
4006 4022
4007 4023 def test_destroy_parent_and_child_issues
4008 4024 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
4009 4025 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
4010 4026 assert child.is_descendant_of?(parent.reload)
4011 4027
4012 4028 @request.session[:user_id] = 2
4013 4029 assert_difference 'Issue.count', -2 do
4014 4030 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
4015 4031 end
4016 4032 assert_response 302
4017 4033 end
4018 4034
4019 4035 def test_destroy_invalid_should_respond_with_404
4020 4036 @request.session[:user_id] = 2
4021 4037 assert_no_difference 'Issue.count' do
4022 4038 delete :destroy, :id => 999
4023 4039 end
4024 4040 assert_response 404
4025 4041 end
4026 4042
4027 4043 def test_default_search_scope
4028 4044 get :index
4029 4045
4030 4046 assert_select 'div#quick-search form' do
4031 4047 assert_select 'input[name=issues][value=1][type=hidden]'
4032 4048 end
4033 4049 end
4034 4050 end
General Comments 0
You need to be logged in to leave comments. Login now