##// END OF EJS Templates
Bulk edit form not show fields based on target tracker and status (#23755)....
Jean-Philippe Lang -
r15433:dcf2e15b0617
parent child
Show More
@@ -1,551 +1,568
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class IssuesController < ApplicationController
18 class IssuesController < ApplicationController
19 default_search_scope :issues
19 default_search_scope :issues
20
20
21 before_action :find_issue, :only => [:show, :edit, :update]
21 before_action :find_issue, :only => [:show, :edit, :update]
22 before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
22 before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
23 before_action :authorize, :except => [:index, :new, :create]
23 before_action :authorize, :except => [:index, :new, :create]
24 before_action :find_optional_project, :only => [:index, :new, :create]
24 before_action :find_optional_project, :only => [:index, :new, :create]
25 before_action :build_new_issue_from_params, :only => [:new, :create]
25 before_action :build_new_issue_from_params, :only => [:new, :create]
26 accept_rss_auth :index, :show
26 accept_rss_auth :index, :show
27 accept_api_auth :index, :show, :create, :update, :destroy
27 accept_api_auth :index, :show, :create, :update, :destroy
28
28
29 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
29 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
30
30
31 helper :journals
31 helper :journals
32 helper :projects
32 helper :projects
33 helper :custom_fields
33 helper :custom_fields
34 helper :issue_relations
34 helper :issue_relations
35 helper :watchers
35 helper :watchers
36 helper :attachments
36 helper :attachments
37 helper :queries
37 helper :queries
38 include QueriesHelper
38 include QueriesHelper
39 helper :repositories
39 helper :repositories
40 helper :sort
40 helper :sort
41 include SortHelper
41 include SortHelper
42 helper :timelog
42 helper :timelog
43
43
44 def index
44 def index
45 retrieve_query
45 retrieve_query
46 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
46 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
47 sort_update(@query.sortable_columns)
47 sort_update(@query.sortable_columns)
48 @query.sort_criteria = sort_criteria.to_a
48 @query.sort_criteria = sort_criteria.to_a
49
49
50 if @query.valid?
50 if @query.valid?
51 case params[:format]
51 case params[:format]
52 when 'csv', 'pdf'
52 when 'csv', 'pdf'
53 @limit = Setting.issues_export_limit.to_i
53 @limit = Setting.issues_export_limit.to_i
54 if params[:columns] == 'all'
54 if params[:columns] == 'all'
55 @query.column_names = @query.available_inline_columns.map(&:name)
55 @query.column_names = @query.available_inline_columns.map(&:name)
56 end
56 end
57 when 'atom'
57 when 'atom'
58 @limit = Setting.feeds_limit.to_i
58 @limit = Setting.feeds_limit.to_i
59 when 'xml', 'json'
59 when 'xml', 'json'
60 @offset, @limit = api_offset_and_limit
60 @offset, @limit = api_offset_and_limit
61 @query.column_names = %w(author)
61 @query.column_names = %w(author)
62 else
62 else
63 @limit = per_page_option
63 @limit = per_page_option
64 end
64 end
65
65
66 @issue_count = @query.issue_count
66 @issue_count = @query.issue_count
67 @issue_pages = Paginator.new @issue_count, @limit, params['page']
67 @issue_pages = Paginator.new @issue_count, @limit, params['page']
68 @offset ||= @issue_pages.offset
68 @offset ||= @issue_pages.offset
69 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
69 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
70 :order => sort_clause,
70 :order => sort_clause,
71 :offset => @offset,
71 :offset => @offset,
72 :limit => @limit)
72 :limit => @limit)
73 @issue_count_by_group = @query.issue_count_by_group
73 @issue_count_by_group = @query.issue_count_by_group
74
74
75 respond_to do |format|
75 respond_to do |format|
76 format.html { render :template => 'issues/index', :layout => !request.xhr? }
76 format.html { render :template => 'issues/index', :layout => !request.xhr? }
77 format.api {
77 format.api {
78 Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
78 Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
79 }
79 }
80 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
80 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
81 format.csv { send_data(query_to_csv(@issues, @query, params[:csv]), :type => 'text/csv; header=present', :filename => 'issues.csv') }
81 format.csv { send_data(query_to_csv(@issues, @query, params[:csv]), :type => 'text/csv; header=present', :filename => 'issues.csv') }
82 format.pdf { send_file_headers! :type => 'application/pdf', :filename => 'issues.pdf' }
82 format.pdf { send_file_headers! :type => 'application/pdf', :filename => 'issues.pdf' }
83 end
83 end
84 else
84 else
85 respond_to do |format|
85 respond_to do |format|
86 format.html { render(:template => 'issues/index', :layout => !request.xhr?) }
86 format.html { render(:template => 'issues/index', :layout => !request.xhr?) }
87 format.any(:atom, :csv, :pdf) { head 422 }
87 format.any(:atom, :csv, :pdf) { head 422 }
88 format.api { render_validation_errors(@query) }
88 format.api { render_validation_errors(@query) }
89 end
89 end
90 end
90 end
91 rescue ActiveRecord::RecordNotFound
91 rescue ActiveRecord::RecordNotFound
92 render_404
92 render_404
93 end
93 end
94
94
95 def show
95 def show
96 @journals = @issue.journals.
96 @journals = @issue.journals.
97 preload(:details).
97 preload(:details).
98 preload(:user => :email_address).
98 preload(:user => :email_address).
99 reorder(:created_on, :id).to_a
99 reorder(:created_on, :id).to_a
100 @journals.each_with_index {|j,i| j.indice = i+1}
100 @journals.each_with_index {|j,i| j.indice = i+1}
101 @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
101 @journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
102 Journal.preload_journals_details_custom_fields(@journals)
102 Journal.preload_journals_details_custom_fields(@journals)
103 @journals.select! {|journal| journal.notes? || journal.visible_details.any?}
103 @journals.select! {|journal| journal.notes? || journal.visible_details.any?}
104 @journals.reverse! if User.current.wants_comments_in_reverse_order?
104 @journals.reverse! if User.current.wants_comments_in_reverse_order?
105
105
106 @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
106 @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
107 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
107 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
108
108
109 @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
109 @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
110 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
110 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
111 @priorities = IssuePriority.active
111 @priorities = IssuePriority.active
112 @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
112 @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
113 @relation = IssueRelation.new
113 @relation = IssueRelation.new
114
114
115 respond_to do |format|
115 respond_to do |format|
116 format.html {
116 format.html {
117 retrieve_previous_and_next_issue_ids
117 retrieve_previous_and_next_issue_ids
118 render :template => 'issues/show'
118 render :template => 'issues/show'
119 }
119 }
120 format.api
120 format.api
121 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
121 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
122 format.pdf {
122 format.pdf {
123 send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf"
123 send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf"
124 }
124 }
125 end
125 end
126 end
126 end
127
127
128 def new
128 def new
129 respond_to do |format|
129 respond_to do |format|
130 format.html { render :action => 'new', :layout => !request.xhr? }
130 format.html { render :action => 'new', :layout => !request.xhr? }
131 format.js
131 format.js
132 end
132 end
133 end
133 end
134
134
135 def create
135 def create
136 unless User.current.allowed_to?(:add_issues, @issue.project, :global => true)
136 unless User.current.allowed_to?(:add_issues, @issue.project, :global => true)
137 raise ::Unauthorized
137 raise ::Unauthorized
138 end
138 end
139 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
139 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
140 @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
140 @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
141 if @issue.save
141 if @issue.save
142 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
142 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
143 respond_to do |format|
143 respond_to do |format|
144 format.html {
144 format.html {
145 render_attachment_warning_if_needed(@issue)
145 render_attachment_warning_if_needed(@issue)
146 flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
146 flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
147 redirect_after_create
147 redirect_after_create
148 }
148 }
149 format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
149 format.api { render :action => 'show', :status => :created, :location => issue_url(@issue) }
150 end
150 end
151 return
151 return
152 else
152 else
153 respond_to do |format|
153 respond_to do |format|
154 format.html {
154 format.html {
155 if @issue.project.nil?
155 if @issue.project.nil?
156 render_error :status => 422
156 render_error :status => 422
157 else
157 else
158 render :action => 'new'
158 render :action => 'new'
159 end
159 end
160 }
160 }
161 format.api { render_validation_errors(@issue) }
161 format.api { render_validation_errors(@issue) }
162 end
162 end
163 end
163 end
164 end
164 end
165
165
166 def edit
166 def edit
167 return unless update_issue_from_params
167 return unless update_issue_from_params
168
168
169 respond_to do |format|
169 respond_to do |format|
170 format.html { }
170 format.html { }
171 format.js
171 format.js
172 end
172 end
173 end
173 end
174
174
175 def update
175 def update
176 return unless update_issue_from_params
176 return unless update_issue_from_params
177 @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
177 @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
178 saved = false
178 saved = false
179 begin
179 begin
180 saved = save_issue_with_child_records
180 saved = save_issue_with_child_records
181 rescue ActiveRecord::StaleObjectError
181 rescue ActiveRecord::StaleObjectError
182 @conflict = true
182 @conflict = true
183 if params[:last_journal_id]
183 if params[:last_journal_id]
184 @conflict_journals = @issue.journals_after(params[:last_journal_id]).to_a
184 @conflict_journals = @issue.journals_after(params[:last_journal_id]).to_a
185 @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
185 @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
186 end
186 end
187 end
187 end
188
188
189 if saved
189 if saved
190 render_attachment_warning_if_needed(@issue)
190 render_attachment_warning_if_needed(@issue)
191 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
191 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
192
192
193 respond_to do |format|
193 respond_to do |format|
194 format.html { redirect_back_or_default issue_path(@issue, previous_and_next_issue_ids_params) }
194 format.html { redirect_back_or_default issue_path(@issue, previous_and_next_issue_ids_params) }
195 format.api { render_api_ok }
195 format.api { render_api_ok }
196 end
196 end
197 else
197 else
198 respond_to do |format|
198 respond_to do |format|
199 format.html { render :action => 'edit' }
199 format.html { render :action => 'edit' }
200 format.api { render_validation_errors(@issue) }
200 format.api { render_validation_errors(@issue) }
201 end
201 end
202 end
202 end
203 end
203 end
204
204
205 # Bulk edit/copy a set of issues
205 # Bulk edit/copy a set of issues
206 def bulk_edit
206 def bulk_edit
207 @issues.sort!
207 @issues.sort!
208 @copy = params[:copy].present?
208 @copy = params[:copy].present?
209 @notes = params[:notes]
209 @notes = params[:notes]
210
210
211 if @copy
211 if @copy
212 unless User.current.allowed_to?(:copy_issues, @projects)
212 unless User.current.allowed_to?(:copy_issues, @projects)
213 raise ::Unauthorized
213 raise ::Unauthorized
214 end
214 end
215 else
215 else
216 unless @issues.all?(&:attributes_editable?)
216 unless @issues.all?(&:attributes_editable?)
217 raise ::Unauthorized
217 raise ::Unauthorized
218 end
218 end
219 end
219 end
220
220
221 edited_issues = Issue.where(:id => @issues.map(&:id)).to_a
222
221 @allowed_projects = Issue.allowed_target_projects
223 @allowed_projects = Issue.allowed_target_projects
222 if params[:issue]
224 if params[:issue]
223 @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
225 @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
224 if @target_project
226 if @target_project
225 target_projects = [@target_project]
227 target_projects = [@target_project]
228 edited_issues.each {|issue| issue.project = @target_project}
226 end
229 end
227 end
230 end
228 target_projects ||= @projects
231 target_projects ||= @projects
229
232
233 @trackers = target_projects.map {|p| Issue.allowed_target_trackers(p) }.reduce(:&)
234 if params[:issue]
235 @target_tracker = @trackers.detect {|t| t.id.to_s == params[:issue][:tracker_id].to_s}
236 if @target_tracker
237 edited_issues.each {|issue| issue.tracker = @target_tracker}
238 end
239 end
240
230 if @copy
241 if @copy
231 # Copied issues will get their default statuses
242 # Copied issues will get their default statuses
232 @available_statuses = []
243 @available_statuses = []
233 else
244 else
234 @available_statuses = @issues.map(&:new_statuses_allowed_to).reduce(:&)
245 @available_statuses = edited_issues.map(&:new_statuses_allowed_to).reduce(:&)
235 end
246 end
236 @custom_fields = @issues.map{|i|i.editable_custom_fields}.reduce(:&)
247 if params[:issue]
248 @target_status = @available_statuses.detect {|t| t.id.to_s == params[:issue][:status_id].to_s}
249 if @target_status
250 edited_issues.each {|issue| issue.status = @target_status}
251 end
252 end
253
254 @custom_fields = edited_issues.map{|i|i.editable_custom_fields}.reduce(:&)
237 @assignables = target_projects.map(&:assignable_users).reduce(:&)
255 @assignables = target_projects.map(&:assignable_users).reduce(:&)
238 @trackers = target_projects.map {|p| Issue.allowed_target_trackers(p) }.reduce(:&)
239 @versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
256 @versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
240 @categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
257 @categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
241 if @copy
258 if @copy
242 @attachments_present = @issues.detect {|i| i.attachments.any?}.present?
259 @attachments_present = @issues.detect {|i| i.attachments.any?}.present?
243 @subtasks_present = @issues.detect {|i| !i.leaf?}.present?
260 @subtasks_present = @issues.detect {|i| !i.leaf?}.present?
244 end
261 end
245
262
246 @safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
263 @safe_attributes = edited_issues.map(&:safe_attribute_names).reduce(:&)
247
264
248 @issue_params = params[:issue] || {}
265 @issue_params = params[:issue] || {}
249 @issue_params[:custom_field_values] ||= {}
266 @issue_params[:custom_field_values] ||= {}
250 end
267 end
251
268
252 def bulk_update
269 def bulk_update
253 @issues.sort!
270 @issues.sort!
254 @copy = params[:copy].present?
271 @copy = params[:copy].present?
255
272
256 attributes = parse_params_for_bulk_update(params[:issue])
273 attributes = parse_params_for_bulk_update(params[:issue])
257 copy_subtasks = (params[:copy_subtasks] == '1')
274 copy_subtasks = (params[:copy_subtasks] == '1')
258 copy_attachments = (params[:copy_attachments] == '1')
275 copy_attachments = (params[:copy_attachments] == '1')
259
276
260 if @copy
277 if @copy
261 unless User.current.allowed_to?(:copy_issues, @projects)
278 unless User.current.allowed_to?(:copy_issues, @projects)
262 raise ::Unauthorized
279 raise ::Unauthorized
263 end
280 end
264 target_projects = @projects
281 target_projects = @projects
265 if attributes['project_id'].present?
282 if attributes['project_id'].present?
266 target_projects = Project.where(:id => attributes['project_id']).to_a
283 target_projects = Project.where(:id => attributes['project_id']).to_a
267 end
284 end
268 unless User.current.allowed_to?(:add_issues, target_projects)
285 unless User.current.allowed_to?(:add_issues, target_projects)
269 raise ::Unauthorized
286 raise ::Unauthorized
270 end
287 end
271 else
288 else
272 unless @issues.all?(&:attributes_editable?)
289 unless @issues.all?(&:attributes_editable?)
273 raise ::Unauthorized
290 raise ::Unauthorized
274 end
291 end
275 end
292 end
276
293
277 unsaved_issues = []
294 unsaved_issues = []
278 saved_issues = []
295 saved_issues = []
279
296
280 if @copy && copy_subtasks
297 if @copy && copy_subtasks
281 # Descendant issues will be copied with the parent task
298 # Descendant issues will be copied with the parent task
282 # Don't copy them twice
299 # Don't copy them twice
283 @issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
300 @issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
284 end
301 end
285
302
286 @issues.each do |orig_issue|
303 @issues.each do |orig_issue|
287 orig_issue.reload
304 orig_issue.reload
288 if @copy
305 if @copy
289 issue = orig_issue.copy({},
306 issue = orig_issue.copy({},
290 :attachments => copy_attachments,
307 :attachments => copy_attachments,
291 :subtasks => copy_subtasks,
308 :subtasks => copy_subtasks,
292 :link => link_copy?(params[:link_copy])
309 :link => link_copy?(params[:link_copy])
293 )
310 )
294 else
311 else
295 issue = orig_issue
312 issue = orig_issue
296 end
313 end
297 journal = issue.init_journal(User.current, params[:notes])
314 journal = issue.init_journal(User.current, params[:notes])
298 issue.safe_attributes = attributes
315 issue.safe_attributes = attributes
299 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
316 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
300 if issue.save
317 if issue.save
301 saved_issues << issue
318 saved_issues << issue
302 else
319 else
303 unsaved_issues << orig_issue
320 unsaved_issues << orig_issue
304 end
321 end
305 end
322 end
306
323
307 if unsaved_issues.empty?
324 if unsaved_issues.empty?
308 flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
325 flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
309 if params[:follow]
326 if params[:follow]
310 if @issues.size == 1 && saved_issues.size == 1
327 if @issues.size == 1 && saved_issues.size == 1
311 redirect_to issue_path(saved_issues.first)
328 redirect_to issue_path(saved_issues.first)
312 elsif saved_issues.map(&:project).uniq.size == 1
329 elsif saved_issues.map(&:project).uniq.size == 1
313 redirect_to project_issues_path(saved_issues.map(&:project).first)
330 redirect_to project_issues_path(saved_issues.map(&:project).first)
314 end
331 end
315 else
332 else
316 redirect_back_or_default _project_issues_path(@project)
333 redirect_back_or_default _project_issues_path(@project)
317 end
334 end
318 else
335 else
319 @saved_issues = @issues
336 @saved_issues = @issues
320 @unsaved_issues = unsaved_issues
337 @unsaved_issues = unsaved_issues
321 @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).to_a
338 @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).to_a
322 bulk_edit
339 bulk_edit
323 render :action => 'bulk_edit'
340 render :action => 'bulk_edit'
324 end
341 end
325 end
342 end
326
343
327 def destroy
344 def destroy
328 raise Unauthorized unless @issues.all?(&:deletable?)
345 raise Unauthorized unless @issues.all?(&:deletable?)
329 @hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
346 @hours = TimeEntry.where(:issue_id => @issues.map(&:id)).sum(:hours).to_f
330 if @hours > 0
347 if @hours > 0
331 case params[:todo]
348 case params[:todo]
332 when 'destroy'
349 when 'destroy'
333 # nothing to do
350 # nothing to do
334 when 'nullify'
351 when 'nullify'
335 TimeEntry.where(['issue_id IN (?)', @issues]).update_all('issue_id = NULL')
352 TimeEntry.where(['issue_id IN (?)', @issues]).update_all('issue_id = NULL')
336 when 'reassign'
353 when 'reassign'
337 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
354 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
338 if reassign_to.nil?
355 if reassign_to.nil?
339 flash.now[:error] = l(:error_issue_not_found_in_project)
356 flash.now[:error] = l(:error_issue_not_found_in_project)
340 return
357 return
341 else
358 else
342 TimeEntry.where(['issue_id IN (?)', @issues]).
359 TimeEntry.where(['issue_id IN (?)', @issues]).
343 update_all("issue_id = #{reassign_to.id}")
360 update_all("issue_id = #{reassign_to.id}")
344 end
361 end
345 else
362 else
346 # display the destroy form if it's a user request
363 # display the destroy form if it's a user request
347 return unless api_request?
364 return unless api_request?
348 end
365 end
349 end
366 end
350 @issues.each do |issue|
367 @issues.each do |issue|
351 begin
368 begin
352 issue.reload.destroy
369 issue.reload.destroy
353 rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
370 rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
354 # nothing to do, issue was already deleted (eg. by a parent)
371 # nothing to do, issue was already deleted (eg. by a parent)
355 end
372 end
356 end
373 end
357 respond_to do |format|
374 respond_to do |format|
358 format.html { redirect_back_or_default _project_issues_path(@project) }
375 format.html { redirect_back_or_default _project_issues_path(@project) }
359 format.api { render_api_ok }
376 format.api { render_api_ok }
360 end
377 end
361 end
378 end
362
379
363 # Overrides Redmine::MenuManager::MenuController::ClassMethods for
380 # Overrides Redmine::MenuManager::MenuController::ClassMethods for
364 # when the "New issue" tab is enabled
381 # when the "New issue" tab is enabled
365 def current_menu_item
382 def current_menu_item
366 if Setting.new_item_menu_tab == '1' && [:new, :create].include?(action_name.to_sym)
383 if Setting.new_item_menu_tab == '1' && [:new, :create].include?(action_name.to_sym)
367 :new_issue
384 :new_issue
368 else
385 else
369 super
386 super
370 end
387 end
371 end
388 end
372
389
373 private
390 private
374
391
375 def retrieve_previous_and_next_issue_ids
392 def retrieve_previous_and_next_issue_ids
376 if params[:prev_issue_id].present? || params[:next_issue_id].present?
393 if params[:prev_issue_id].present? || params[:next_issue_id].present?
377 @prev_issue_id = params[:prev_issue_id].presence.try(:to_i)
394 @prev_issue_id = params[:prev_issue_id].presence.try(:to_i)
378 @next_issue_id = params[:next_issue_id].presence.try(:to_i)
395 @next_issue_id = params[:next_issue_id].presence.try(:to_i)
379 @issue_position = params[:issue_position].presence.try(:to_i)
396 @issue_position = params[:issue_position].presence.try(:to_i)
380 @issue_count = params[:issue_count].presence.try(:to_i)
397 @issue_count = params[:issue_count].presence.try(:to_i)
381 else
398 else
382 retrieve_query_from_session
399 retrieve_query_from_session
383 if @query
400 if @query
384 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
401 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
385 sort_update(@query.sortable_columns, 'issues_index_sort')
402 sort_update(@query.sortable_columns, 'issues_index_sort')
386 limit = 500
403 limit = 500
387 issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version])
404 issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version])
388 if (idx = issue_ids.index(@issue.id)) && idx < limit
405 if (idx = issue_ids.index(@issue.id)) && idx < limit
389 if issue_ids.size < 500
406 if issue_ids.size < 500
390 @issue_position = idx + 1
407 @issue_position = idx + 1
391 @issue_count = issue_ids.size
408 @issue_count = issue_ids.size
392 end
409 end
393 @prev_issue_id = issue_ids[idx - 1] if idx > 0
410 @prev_issue_id = issue_ids[idx - 1] if idx > 0
394 @next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
411 @next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
395 end
412 end
396 end
413 end
397 end
414 end
398 end
415 end
399
416
400 def previous_and_next_issue_ids_params
417 def previous_and_next_issue_ids_params
401 {
418 {
402 :prev_issue_id => params[:prev_issue_id],
419 :prev_issue_id => params[:prev_issue_id],
403 :next_issue_id => params[:next_issue_id],
420 :next_issue_id => params[:next_issue_id],
404 :issue_position => params[:issue_position],
421 :issue_position => params[:issue_position],
405 :issue_count => params[:issue_count]
422 :issue_count => params[:issue_count]
406 }.reject {|k,v| k.blank?}
423 }.reject {|k,v| k.blank?}
407 end
424 end
408
425
409 # Used by #edit and #update to set some common instance variables
426 # Used by #edit and #update to set some common instance variables
410 # from the params
427 # from the params
411 def update_issue_from_params
428 def update_issue_from_params
412 @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
429 @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
413 if params[:time_entry]
430 if params[:time_entry]
414 @time_entry.safe_attributes = params[:time_entry]
431 @time_entry.safe_attributes = params[:time_entry]
415 end
432 end
416
433
417 @issue.init_journal(User.current)
434 @issue.init_journal(User.current)
418
435
419 issue_attributes = params[:issue]
436 issue_attributes = params[:issue]
420 if issue_attributes && params[:conflict_resolution]
437 if issue_attributes && params[:conflict_resolution]
421 case params[:conflict_resolution]
438 case params[:conflict_resolution]
422 when 'overwrite'
439 when 'overwrite'
423 issue_attributes = issue_attributes.dup
440 issue_attributes = issue_attributes.dup
424 issue_attributes.delete(:lock_version)
441 issue_attributes.delete(:lock_version)
425 when 'add_notes'
442 when 'add_notes'
426 issue_attributes = issue_attributes.slice(:notes, :private_notes)
443 issue_attributes = issue_attributes.slice(:notes, :private_notes)
427 when 'cancel'
444 when 'cancel'
428 redirect_to issue_path(@issue)
445 redirect_to issue_path(@issue)
429 return false
446 return false
430 end
447 end
431 end
448 end
432 @issue.safe_attributes = issue_attributes
449 @issue.safe_attributes = issue_attributes
433 @priorities = IssuePriority.active
450 @priorities = IssuePriority.active
434 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
451 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
435 true
452 true
436 end
453 end
437
454
438 # Used by #new and #create to build a new issue from the params
455 # Used by #new and #create to build a new issue from the params
439 # The new issue will be copied from an existing one if copy_from parameter is given
456 # The new issue will be copied from an existing one if copy_from parameter is given
440 def build_new_issue_from_params
457 def build_new_issue_from_params
441 @issue = Issue.new
458 @issue = Issue.new
442 if params[:copy_from]
459 if params[:copy_from]
443 begin
460 begin
444 @issue.init_journal(User.current)
461 @issue.init_journal(User.current)
445 @copy_from = Issue.visible.find(params[:copy_from])
462 @copy_from = Issue.visible.find(params[:copy_from])
446 unless User.current.allowed_to?(:copy_issues, @copy_from.project)
463 unless User.current.allowed_to?(:copy_issues, @copy_from.project)
447 raise ::Unauthorized
464 raise ::Unauthorized
448 end
465 end
449 @link_copy = link_copy?(params[:link_copy]) || request.get?
466 @link_copy = link_copy?(params[:link_copy]) || request.get?
450 @copy_attachments = params[:copy_attachments].present? || request.get?
467 @copy_attachments = params[:copy_attachments].present? || request.get?
451 @copy_subtasks = params[:copy_subtasks].present? || request.get?
468 @copy_subtasks = params[:copy_subtasks].present? || request.get?
452 @issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks, :link => @link_copy)
469 @issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks, :link => @link_copy)
453 @issue.parent_issue_id = @copy_from.parent_id
470 @issue.parent_issue_id = @copy_from.parent_id
454 rescue ActiveRecord::RecordNotFound
471 rescue ActiveRecord::RecordNotFound
455 render_404
472 render_404
456 return
473 return
457 end
474 end
458 end
475 end
459 @issue.project = @project
476 @issue.project = @project
460 if request.get?
477 if request.get?
461 @issue.project ||= @issue.allowed_target_projects.first
478 @issue.project ||= @issue.allowed_target_projects.first
462 end
479 end
463 @issue.author ||= User.current
480 @issue.author ||= User.current
464 @issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
481 @issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
465
482
466 attrs = (params[:issue] || {}).deep_dup
483 attrs = (params[:issue] || {}).deep_dup
467 if action_name == 'new' && params[:was_default_status] == attrs[:status_id]
484 if action_name == 'new' && params[:was_default_status] == attrs[:status_id]
468 attrs.delete(:status_id)
485 attrs.delete(:status_id)
469 end
486 end
470 if action_name == 'new' && params[:form_update_triggered_by] == 'issue_project_id'
487 if action_name == 'new' && params[:form_update_triggered_by] == 'issue_project_id'
471 # Discard submitted version when changing the project on the issue form
488 # Discard submitted version when changing the project on the issue form
472 # so we can use the default version for the new project
489 # so we can use the default version for the new project
473 attrs.delete(:fixed_version_id)
490 attrs.delete(:fixed_version_id)
474 end
491 end
475 @issue.safe_attributes = attrs
492 @issue.safe_attributes = attrs
476
493
477 if @issue.project
494 if @issue.project
478 @issue.tracker ||= @issue.allowed_target_trackers.first
495 @issue.tracker ||= @issue.allowed_target_trackers.first
479 if @issue.tracker.nil?
496 if @issue.tracker.nil?
480 if @issue.project.trackers.any?
497 if @issue.project.trackers.any?
481 # None of the project trackers is allowed to the user
498 # None of the project trackers is allowed to the user
482 render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403
499 render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403
483 else
500 else
484 # Project has no trackers
501 # Project has no trackers
485 render_error l(:error_no_tracker_in_project)
502 render_error l(:error_no_tracker_in_project)
486 end
503 end
487 return false
504 return false
488 end
505 end
489 if @issue.status.nil?
506 if @issue.status.nil?
490 render_error l(:error_no_default_issue_status)
507 render_error l(:error_no_default_issue_status)
491 return false
508 return false
492 end
509 end
493 elsif request.get?
510 elsif request.get?
494 render_error :message => l(:error_no_projects_with_tracker_allowed_for_new_issue), :status => 403
511 render_error :message => l(:error_no_projects_with_tracker_allowed_for_new_issue), :status => 403
495 return false
512 return false
496 end
513 end
497
514
498 @priorities = IssuePriority.active
515 @priorities = IssuePriority.active
499 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
516 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
500 end
517 end
501
518
502 # Saves @issue and a time_entry from the parameters
519 # Saves @issue and a time_entry from the parameters
503 def save_issue_with_child_records
520 def save_issue_with_child_records
504 Issue.transaction do
521 Issue.transaction do
505 if params[:time_entry] && (params[:time_entry][:hours].present? || params[:time_entry][:comments].present?) && User.current.allowed_to?(:log_time, @issue.project)
522 if params[:time_entry] && (params[:time_entry][:hours].present? || params[:time_entry][:comments].present?) && User.current.allowed_to?(:log_time, @issue.project)
506 time_entry = @time_entry || TimeEntry.new
523 time_entry = @time_entry || TimeEntry.new
507 time_entry.project = @issue.project
524 time_entry.project = @issue.project
508 time_entry.issue = @issue
525 time_entry.issue = @issue
509 time_entry.user = User.current
526 time_entry.user = User.current
510 time_entry.spent_on = User.current.today
527 time_entry.spent_on = User.current.today
511 time_entry.attributes = params[:time_entry]
528 time_entry.attributes = params[:time_entry]
512 @issue.time_entries << time_entry
529 @issue.time_entries << time_entry
513 end
530 end
514
531
515 call_hook(:controller_issues_edit_before_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
532 call_hook(:controller_issues_edit_before_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
516 if @issue.save
533 if @issue.save
517 call_hook(:controller_issues_edit_after_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
534 call_hook(:controller_issues_edit_after_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
518 else
535 else
519 raise ActiveRecord::Rollback
536 raise ActiveRecord::Rollback
520 end
537 end
521 end
538 end
522 end
539 end
523
540
524 # Returns true if the issue copy should be linked
541 # Returns true if the issue copy should be linked
525 # to the original issue
542 # to the original issue
526 def link_copy?(param)
543 def link_copy?(param)
527 case Setting.link_copied_issue
544 case Setting.link_copied_issue
528 when 'yes'
545 when 'yes'
529 true
546 true
530 when 'no'
547 when 'no'
531 false
548 false
532 when 'ask'
549 when 'ask'
533 param == '1'
550 param == '1'
534 end
551 end
535 end
552 end
536
553
537 # Redirects user after a successful issue creation
554 # Redirects user after a successful issue creation
538 def redirect_after_create
555 def redirect_after_create
539 if params[:continue]
556 if params[:continue]
540 attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
557 attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
541 if params[:project_id]
558 if params[:project_id]
542 redirect_to new_project_issue_path(@issue.project, :issue => attrs)
559 redirect_to new_project_issue_path(@issue.project, :issue => attrs)
543 else
560 else
544 attrs.merge! :project_id => @issue.project_id
561 attrs.merge! :project_id => @issue.project_id
545 redirect_to new_issue_path(:issue => attrs)
562 redirect_to new_issue_path(:issue => attrs)
546 end
563 end
547 else
564 else
548 redirect_to issue_path(@issue)
565 redirect_to issue_path(@issue)
549 end
566 end
550 end
567 end
551 end
568 end
@@ -1,215 +1,217
1 <h2><%= @copy ? l(:button_copy) : l(:label_bulk_edit_selected_issues) %></h2>
1 <h2><%= @copy ? l(:button_copy) : l(:label_bulk_edit_selected_issues) %></h2>
2
2
3 <% if @saved_issues && @unsaved_issues.present? %>
3 <% if @saved_issues && @unsaved_issues.present? %>
4 <div id="errorExplanation">
4 <div id="errorExplanation">
5 <span>
5 <span>
6 <%= l(:notice_failed_to_save_issues,
6 <%= l(:notice_failed_to_save_issues,
7 :count => @unsaved_issues.size,
7 :count => @unsaved_issues.size,
8 :total => @saved_issues.size,
8 :total => @saved_issues.size,
9 :ids => @unsaved_issues.map {|i| "##{i.id}"}.join(', ')) %>
9 :ids => @unsaved_issues.map {|i| "##{i.id}"}.join(', ')) %>
10 </span>
10 </span>
11 <ul>
11 <ul>
12 <% bulk_edit_error_messages(@unsaved_issues).each do |message| %>
12 <% bulk_edit_error_messages(@unsaved_issues).each do |message| %>
13 <li><%= message %></li>
13 <li><%= message %></li>
14 <% end %>
14 <% end %>
15 </ul>
15 </ul>
16 </div>
16 </div>
17 <% end %>
17 <% end %>
18
18
19 <ul id="bulk-selection">
19 <ul id="bulk-selection">
20 <% @issues.each do |issue| %>
20 <% @issues.each do |issue| %>
21 <%= content_tag 'li', link_to_issue(issue) %>
21 <%= content_tag 'li', link_to_issue(issue) %>
22 <% end %>
22 <% end %>
23 </ul>
23 </ul>
24
24
25 <%= form_tag(bulk_update_issues_path, :id => 'bulk_edit_form') do %>
25 <%= form_tag(bulk_update_issues_path, :id => 'bulk_edit_form') do %>
26 <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id, :id => nil)}.join("\n").html_safe %>
26 <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id, :id => nil)}.join("\n").html_safe %>
27 <div class="box tabular">
27 <div class="box tabular">
28 <fieldset class="attributes">
28 <fieldset class="attributes">
29 <legend><%= l(:label_change_properties) %></legend>
29 <legend><%= l(:label_change_properties) %></legend>
30
30
31 <div class="splitcontentleft">
31 <div class="splitcontentleft">
32 <% if @allowed_projects.present? %>
32 <% if @allowed_projects.present? %>
33 <p>
33 <p>
34 <label for="issue_project_id"><%= l(:field_project) %></label>
34 <label for="issue_project_id"><%= l(:field_project) %></label>
35 <%= select_tag('issue[project_id]',
35 <%= select_tag('issue[project_id]',
36 project_tree_options_for_select(@allowed_projects,
36 project_tree_options_for_select(@allowed_projects,
37 :include_blank => ((!@copy || (@projects & @allowed_projects == @projects)) ? l(:label_no_change_option) : false),
37 :include_blank => ((!@copy || (@projects & @allowed_projects == @projects)) ? l(:label_no_change_option) : false),
38 :selected => @target_project),
38 :selected => @target_project),
39 :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')") %>
39 :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')") %>
40 </p>
40 </p>
41 <% end %>
41 <% end %>
42 <p>
42 <p>
43 <label for="issue_tracker_id"><%= l(:field_tracker) %></label>
43 <label for="issue_tracker_id"><%= l(:field_tracker) %></label>
44 <%= select_tag('issue[tracker_id]',
44 <%= select_tag('issue[tracker_id]',
45 content_tag('option', l(:label_no_change_option), :value => '') +
45 content_tag('option', l(:label_no_change_option), :value => '') +
46 options_from_collection_for_select(@trackers, :id, :name, @issue_params[:tracker_id])) %>
46 options_from_collection_for_select(@trackers, :id, :name, @issue_params[:tracker_id]),
47 :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')") %>
47 </p>
48 </p>
48 <% if @available_statuses.any? %>
49 <% if @available_statuses.any? %>
49 <p>
50 <p>
50 <label for='issue_status_id'><%= l(:field_status) %></label>
51 <label for='issue_status_id'><%= l(:field_status) %></label>
51 <%= select_tag('issue[status_id]',
52 <%= select_tag('issue[status_id]',
52 content_tag('option', l(:label_no_change_option), :value => '') +
53 content_tag('option', l(:label_no_change_option), :value => '') +
53 options_from_collection_for_select(@available_statuses, :id, :name, @issue_params[:status_id])) %>
54 options_from_collection_for_select(@available_statuses, :id, :name, @issue_params[:status_id]),
55 :onchange => "updateBulkEditFrom('#{escape_javascript url_for(:action => 'bulk_edit', :format => 'js')}')") %>
54 </p>
56 </p>
55 <% end %>
57 <% end %>
56
58
57 <% if @safe_attributes.include?('priority_id') -%>
59 <% if @safe_attributes.include?('priority_id') -%>
58 <p>
60 <p>
59 <label for='issue_priority_id'><%= l(:field_priority) %></label>
61 <label for='issue_priority_id'><%= l(:field_priority) %></label>
60 <%= select_tag('issue[priority_id]',
62 <%= select_tag('issue[priority_id]',
61 content_tag('option', l(:label_no_change_option), :value => '') +
63 content_tag('option', l(:label_no_change_option), :value => '') +
62 options_from_collection_for_select(IssuePriority.active, :id, :name, @issue_params[:priority_id])) %>
64 options_from_collection_for_select(IssuePriority.active, :id, :name, @issue_params[:priority_id])) %>
63 </p>
65 </p>
64 <% end %>
66 <% end %>
65
67
66 <% if @safe_attributes.include?('assigned_to_id') -%>
68 <% if @safe_attributes.include?('assigned_to_id') -%>
67 <p>
69 <p>
68 <label for='issue_assigned_to_id'><%= l(:field_assigned_to) %></label>
70 <label for='issue_assigned_to_id'><%= l(:field_assigned_to) %></label>
69 <%= select_tag('issue[assigned_to_id]',
71 <%= select_tag('issue[assigned_to_id]',
70 content_tag('option', l(:label_no_change_option), :value => '') +
72 content_tag('option', l(:label_no_change_option), :value => '') +
71 content_tag('option', l(:label_nobody), :value => 'none', :selected => (@issue_params[:assigned_to_id] == 'none')) +
73 content_tag('option', l(:label_nobody), :value => 'none', :selected => (@issue_params[:assigned_to_id] == 'none')) +
72 principals_options_for_select(@assignables, @issue_params[:assigned_to_id])) %>
74 principals_options_for_select(@assignables, @issue_params[:assigned_to_id])) %>
73 </p>
75 </p>
74 <% end %>
76 <% end %>
75
77
76 <% if @safe_attributes.include?('category_id') -%>
78 <% if @safe_attributes.include?('category_id') -%>
77 <p>
79 <p>
78 <label for='issue_category_id'><%= l(:field_category) %></label>
80 <label for='issue_category_id'><%= l(:field_category) %></label>
79 <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') +
81 <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') +
80 content_tag('option', l(:label_none), :value => 'none', :selected => (@issue_params[:category_id] == 'none')) +
82 content_tag('option', l(:label_none), :value => 'none', :selected => (@issue_params[:category_id] == 'none')) +
81 options_from_collection_for_select(@categories, :id, :name, @issue_params[:category_id])) %>
83 options_from_collection_for_select(@categories, :id, :name, @issue_params[:category_id])) %>
82 </p>
84 </p>
83 <% end %>
85 <% end %>
84
86
85 <% if @safe_attributes.include?('fixed_version_id') -%>
87 <% if @safe_attributes.include?('fixed_version_id') -%>
86 <p>
88 <p>
87 <label for='issue_fixed_version_id'><%= l(:field_fixed_version) %></label>
89 <label for='issue_fixed_version_id'><%= l(:field_fixed_version) %></label>
88 <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
90 <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
89 content_tag('option', l(:label_none), :value => 'none', :selected => (@issue_params[:fixed_version_id] == 'none')) +
91 content_tag('option', l(:label_none), :value => 'none', :selected => (@issue_params[:fixed_version_id] == 'none')) +
90 version_options_for_select(@versions.sort, @issue_params[:fixed_version_id])) %>
92 version_options_for_select(@versions.sort, @issue_params[:fixed_version_id])) %>
91 </p>
93 </p>
92 <% end %>
94 <% end %>
93
95
94 <% @custom_fields.each do |custom_field| %>
96 <% @custom_fields.each do |custom_field| %>
95 <p>
97 <p>
96 <label><%= custom_field.name %></label>
98 <label><%= custom_field.name %></label>
97 <%= custom_field_tag_for_bulk_edit('issue', custom_field, @issues, @issue_params[:custom_field_values][custom_field.id.to_s]) %>
99 <%= custom_field_tag_for_bulk_edit('issue', custom_field, @issues, @issue_params[:custom_field_values][custom_field.id.to_s]) %>
98 </p>
100 </p>
99 <% end %>
101 <% end %>
100
102
101 <% if @copy && Setting.link_copied_issue == 'ask' %>
103 <% if @copy && Setting.link_copied_issue == 'ask' %>
102 <p>
104 <p>
103 <label for='link_copy'><%= l(:label_link_copied_issue) %></label>
105 <label for='link_copy'><%= l(:label_link_copied_issue) %></label>
104 <%= hidden_field_tag 'link_copy', '0' %>
106 <%= hidden_field_tag 'link_copy', '0' %>
105 <%= check_box_tag 'link_copy', '1', params[:link_copy] != 0 %>
107 <%= check_box_tag 'link_copy', '1', params[:link_copy] != 0 %>
106 </p>
108 </p>
107 <% end %>
109 <% end %>
108
110
109 <% if @copy && @attachments_present %>
111 <% if @copy && @attachments_present %>
110 <%= hidden_field_tag 'copy_attachments', '0' %>
112 <%= hidden_field_tag 'copy_attachments', '0' %>
111 <p>
113 <p>
112 <label for='copy_attachments'><%= l(:label_copy_attachments) %></label>
114 <label for='copy_attachments'><%= l(:label_copy_attachments) %></label>
113 <%= check_box_tag 'copy_attachments', '1', params[:copy_attachments] != '0' %>
115 <%= check_box_tag 'copy_attachments', '1', params[:copy_attachments] != '0' %>
114 </p>
116 </p>
115 <% end %>
117 <% end %>
116
118
117 <% if @copy && @subtasks_present %>
119 <% if @copy && @subtasks_present %>
118 <%= hidden_field_tag 'copy_subtasks', '0' %>
120 <%= hidden_field_tag 'copy_subtasks', '0' %>
119 <p>
121 <p>
120 <label for='copy_subtasks'><%= l(:label_copy_subtasks) %></label>
122 <label for='copy_subtasks'><%= l(:label_copy_subtasks) %></label>
121 <%= check_box_tag 'copy_subtasks', '1', params[:copy_subtasks] != '0' %>
123 <%= check_box_tag 'copy_subtasks', '1', params[:copy_subtasks] != '0' %>
122 </p>
124 </p>
123 <% end %>
125 <% end %>
124
126
125 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
127 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
126 </div>
128 </div>
127
129
128 <div class="splitcontentright">
130 <div class="splitcontentright">
129 <% if @safe_attributes.include?('is_private') %>
131 <% if @safe_attributes.include?('is_private') %>
130 <p>
132 <p>
131 <label for='issue_is_private'><%= l(:field_is_private) %></label>
133 <label for='issue_is_private'><%= l(:field_is_private) %></label>
132 <%= select_tag('issue[is_private]', content_tag('option', l(:label_no_change_option), :value => '') +
134 <%= select_tag('issue[is_private]', content_tag('option', l(:label_no_change_option), :value => '') +
133 content_tag('option', l(:general_text_Yes), :value => '1', :selected => (@issue_params[:is_private] == '1')) +
135 content_tag('option', l(:general_text_Yes), :value => '1', :selected => (@issue_params[:is_private] == '1')) +
134 content_tag('option', l(:general_text_No), :value => '0', :selected => (@issue_params[:is_private] == '0'))) %>
136 content_tag('option', l(:general_text_No), :value => '0', :selected => (@issue_params[:is_private] == '0'))) %>
135 </p>
137 </p>
136 <% end %>
138 <% end %>
137
139
138 <% if @safe_attributes.include?('parent_issue_id') && @project %>
140 <% if @safe_attributes.include?('parent_issue_id') && @project %>
139 <p>
141 <p>
140 <label for='issue_parent_issue_id'><%= l(:field_parent_issue) %></label>
142 <label for='issue_parent_issue_id'><%= l(:field_parent_issue) %></label>
141 <%= text_field_tag 'issue[parent_issue_id]', '', :size => 10, :value => @issue_params[:parent_issue_id] %>
143 <%= text_field_tag 'issue[parent_issue_id]', '', :size => 10, :value => @issue_params[:parent_issue_id] %>
142 <label class="inline"><%= check_box_tag 'issue[parent_issue_id]', 'none', (@issue_params[:parent_issue_id] == 'none'), :id => nil, :data => {:disables => '#issue_parent_issue_id'} %><%= l(:button_clear) %></label>
144 <label class="inline"><%= check_box_tag 'issue[parent_issue_id]', 'none', (@issue_params[:parent_issue_id] == 'none'), :id => nil, :data => {:disables => '#issue_parent_issue_id'} %><%= l(:button_clear) %></label>
143 </p>
145 </p>
144 <%= javascript_tag "observeAutocompleteField('issue_parent_issue_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => Setting.cross_project_subtasks)}')" %>
146 <%= javascript_tag "observeAutocompleteField('issue_parent_issue_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => Setting.cross_project_subtasks)}')" %>
145 <% end %>
147 <% end %>
146
148
147 <% if @safe_attributes.include?('start_date') %>
149 <% if @safe_attributes.include?('start_date') %>
148 <p>
150 <p>
149 <label for='issue_start_date'><%= l(:field_start_date) %></label>
151 <label for='issue_start_date'><%= l(:field_start_date) %></label>
150 <%= date_field_tag 'issue[start_date]', '', :value => @issue_params[:start_date], :size => 10 %><%= calendar_for('issue_start_date') %>
152 <%= date_field_tag 'issue[start_date]', '', :value => @issue_params[:start_date], :size => 10 %><%= calendar_for('issue_start_date') %>
151 <label class="inline"><%= check_box_tag 'issue[start_date]', 'none', (@issue_params[:start_date] == 'none'), :id => nil, :data => {:disables => '#issue_start_date'} %><%= l(:button_clear) %></label>
153 <label class="inline"><%= check_box_tag 'issue[start_date]', 'none', (@issue_params[:start_date] == 'none'), :id => nil, :data => {:disables => '#issue_start_date'} %><%= l(:button_clear) %></label>
152 </p>
154 </p>
153 <% end %>
155 <% end %>
154
156
155 <% if @safe_attributes.include?('due_date') %>
157 <% if @safe_attributes.include?('due_date') %>
156 <p>
158 <p>
157 <label for='issue_due_date'><%= l(:field_due_date) %></label>
159 <label for='issue_due_date'><%= l(:field_due_date) %></label>
158 <%= date_field_tag 'issue[due_date]', '', :value => @issue_params[:due_date], :size => 10 %><%= calendar_for('issue_due_date') %>
160 <%= date_field_tag 'issue[due_date]', '', :value => @issue_params[:due_date], :size => 10 %><%= calendar_for('issue_due_date') %>
159 <label class="inline"><%= check_box_tag 'issue[due_date]', 'none', (@issue_params[:due_date] == 'none'), :id => nil, :data => {:disables => '#issue_due_date'} %><%= l(:button_clear) %></label>
161 <label class="inline"><%= check_box_tag 'issue[due_date]', 'none', (@issue_params[:due_date] == 'none'), :id => nil, :data => {:disables => '#issue_due_date'} %><%= l(:button_clear) %></label>
160 </p>
162 </p>
161 <% end %>
163 <% end %>
162
164
163 <% if @safe_attributes.include?('estimated_hours') %>
165 <% if @safe_attributes.include?('estimated_hours') %>
164 <p>
166 <p>
165 <label for='issue_estimated_hours'><%= l(:field_estimated_hours) %></label>
167 <label for='issue_estimated_hours'><%= l(:field_estimated_hours) %></label>
166 <%= text_field_tag 'issue[estimated_hours]', '', :value => @issue_params[:estimated_hours], :size => 10 %>
168 <%= text_field_tag 'issue[estimated_hours]', '', :value => @issue_params[:estimated_hours], :size => 10 %>
167 <label class="inline"><%= check_box_tag 'issue[estimated_hours]', 'none', (@issue_params[:estimated_hours] == 'none'), :id => nil, :data => {:disables => '#issue_estimated_hours'} %><%= l(:button_clear) %></label>
169 <label class="inline"><%= check_box_tag 'issue[estimated_hours]', 'none', (@issue_params[:estimated_hours] == 'none'), :id => nil, :data => {:disables => '#issue_estimated_hours'} %><%= l(:button_clear) %></label>
168 </p>
170 </p>
169 <% end %>
171 <% end %>
170
172
171 <% if @safe_attributes.include?('done_ratio') && Issue.use_field_for_done_ratio? %>
173 <% if @safe_attributes.include?('done_ratio') && Issue.use_field_for_done_ratio? %>
172 <p>
174 <p>
173 <label for='issue_done_ratio'><%= l(:field_done_ratio) %></label>
175 <label for='issue_done_ratio'><%= l(:field_done_ratio) %></label>
174 <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }, @issue_params[:done_ratio]) %>
176 <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }, @issue_params[:done_ratio]) %>
175 </p>
177 </p>
176 <% end %>
178 <% end %>
177 </div>
179 </div>
178 </fieldset>
180 </fieldset>
179
181
180 <fieldset>
182 <fieldset>
181 <legend><%= l(:field_notes) %></legend>
183 <legend><%= l(:field_notes) %></legend>
182 <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
184 <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
183 <%= wikitoolbar_for 'notes' %>
185 <%= wikitoolbar_for 'notes' %>
184 </fieldset>
186 </fieldset>
185 </div>
187 </div>
186
188
187 <p>
189 <p>
188 <% if @copy %>
190 <% if @copy %>
189 <%= hidden_field_tag 'copy', '1' %>
191 <%= hidden_field_tag 'copy', '1' %>
190 <%= submit_tag l(:button_copy) %>
192 <%= submit_tag l(:button_copy) %>
191 <%= submit_tag l(:button_copy_and_follow), :name => 'follow' %>
193 <%= submit_tag l(:button_copy_and_follow), :name => 'follow' %>
192 <% elsif @target_project %>
194 <% elsif @target_project %>
193 <%= submit_tag l(:button_move) %>
195 <%= submit_tag l(:button_move) %>
194 <%= submit_tag l(:button_move_and_follow), :name => 'follow' %>
196 <%= submit_tag l(:button_move_and_follow), :name => 'follow' %>
195 <% else %>
197 <% else %>
196 <%= submit_tag l(:button_submit) %>
198 <%= submit_tag l(:button_submit) %>
197 <% end %>
199 <% end %>
198 </p>
200 </p>
199
201
200 <% end %>
202 <% end %>
201
203
202 <%= javascript_tag do %>
204 <%= javascript_tag do %>
203 $(window).load(function(){
205 $(window).load(function(){
204 $(document).on('change', 'input[data-disables]', function(){
206 $(document).on('change', 'input[data-disables]', function(){
205 if ($(this).prop('checked')){
207 if ($(this).prop('checked')){
206 $($(this).data('disables')).attr('disabled', true).val('');
208 $($(this).data('disables')).attr('disabled', true).val('');
207 } else {
209 } else {
208 $($(this).data('disables')).attr('disabled', false);
210 $($(this).data('disables')).attr('disabled', false);
209 }
211 }
210 });
212 });
211 });
213 });
212 $(document).ready(function(){
214 $(document).ready(function(){
213 $('input[data-disables]').trigger('change');
215 $('input[data-disables]').trigger('change');
214 });
216 });
215 <% end %>
217 <% end %>
@@ -1,4700 +1,4714
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class IssuesControllerTest < Redmine::ControllerTest
20 class IssuesControllerTest < Redmine::ControllerTest
21 fixtures :projects,
21 fixtures :projects,
22 :users, :email_addresses, :user_preferences,
22 :users, :email_addresses, :user_preferences,
23 :roles,
23 :roles,
24 :members,
24 :members,
25 :member_roles,
25 :member_roles,
26 :issues,
26 :issues,
27 :issue_statuses,
27 :issue_statuses,
28 :issue_relations,
28 :issue_relations,
29 :versions,
29 :versions,
30 :trackers,
30 :trackers,
31 :projects_trackers,
31 :projects_trackers,
32 :issue_categories,
32 :issue_categories,
33 :enabled_modules,
33 :enabled_modules,
34 :enumerations,
34 :enumerations,
35 :attachments,
35 :attachments,
36 :workflows,
36 :workflows,
37 :custom_fields,
37 :custom_fields,
38 :custom_values,
38 :custom_values,
39 :custom_fields_projects,
39 :custom_fields_projects,
40 :custom_fields_trackers,
40 :custom_fields_trackers,
41 :time_entries,
41 :time_entries,
42 :journals,
42 :journals,
43 :journal_details,
43 :journal_details,
44 :queries,
44 :queries,
45 :repositories,
45 :repositories,
46 :changesets
46 :changesets
47
47
48 include Redmine::I18n
48 include Redmine::I18n
49
49
50 def setup
50 def setup
51 User.current = nil
51 User.current = nil
52 end
52 end
53
53
54 def test_index
54 def test_index
55 with_settings :default_language => "en" do
55 with_settings :default_language => "en" do
56 get :index
56 get :index
57 assert_response :success
57 assert_response :success
58
58
59 # links to visible issues
59 # links to visible issues
60 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
60 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
61 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
61 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
62 # private projects hidden
62 # private projects hidden
63 assert_select 'a[href="/issues/6"]', 0
63 assert_select 'a[href="/issues/6"]', 0
64 assert_select 'a[href="/issues/4"]', 0
64 assert_select 'a[href="/issues/4"]', 0
65 # project column
65 # project column
66 assert_select 'th', :text => /Project/
66 assert_select 'th', :text => /Project/
67 end
67 end
68 end
68 end
69
69
70 def test_index_should_not_list_issues_when_module_disabled
70 def test_index_should_not_list_issues_when_module_disabled
71 EnabledModule.where("name = 'issue_tracking' AND project_id = 1").delete_all
71 EnabledModule.where("name = 'issue_tracking' AND project_id = 1").delete_all
72 get :index
72 get :index
73 assert_response :success
73 assert_response :success
74
74
75 assert_select 'a[href="/issues/1"]', 0
75 assert_select 'a[href="/issues/1"]', 0
76 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
76 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
77 end
77 end
78
78
79 def test_index_should_list_visible_issues_only
79 def test_index_should_list_visible_issues_only
80 get :index, :per_page => 100
80 get :index, :per_page => 100
81 assert_response :success
81 assert_response :success
82
82
83 Issue.open.each do |issue|
83 Issue.open.each do |issue|
84 assert_select "tr#issue-#{issue.id}", issue.visible? ? 1 : 0
84 assert_select "tr#issue-#{issue.id}", issue.visible? ? 1 : 0
85 end
85 end
86 end
86 end
87
87
88 def test_index_with_project
88 def test_index_with_project
89 Setting.display_subprojects_issues = 0
89 Setting.display_subprojects_issues = 0
90 get :index, :project_id => 1
90 get :index, :project_id => 1
91 assert_response :success
91 assert_response :success
92
92
93 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
93 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
94 assert_select 'a[href="/issues/5"]', 0
94 assert_select 'a[href="/issues/5"]', 0
95 end
95 end
96
96
97 def test_index_with_project_and_subprojects
97 def test_index_with_project_and_subprojects
98 Setting.display_subprojects_issues = 1
98 Setting.display_subprojects_issues = 1
99 get :index, :project_id => 1
99 get :index, :project_id => 1
100 assert_response :success
100 assert_response :success
101
101
102 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
102 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
103 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
103 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
104 assert_select 'a[href="/issues/6"]', 0
104 assert_select 'a[href="/issues/6"]', 0
105 end
105 end
106
106
107 def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
107 def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
108 @request.session[:user_id] = 2
108 @request.session[:user_id] = 2
109 Setting.display_subprojects_issues = 1
109 Setting.display_subprojects_issues = 1
110 get :index, :project_id => 1
110 get :index, :project_id => 1
111 assert_response :success
111 assert_response :success
112
112
113 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
113 assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
114 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
114 assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
115 assert_select 'a[href="/issues/6"]', :text => /Issue of a private subproject/
115 assert_select 'a[href="/issues/6"]', :text => /Issue of a private subproject/
116 end
116 end
117
117
118 def test_index_with_project_and_default_filter
118 def test_index_with_project_and_default_filter
119 get :index, :project_id => 1, :set_filter => 1
119 get :index, :project_id => 1, :set_filter => 1
120 assert_response :success
120 assert_response :success
121
121
122 # default filter
122 # default filter
123 assert_query_filters [['status_id', 'o', '']]
123 assert_query_filters [['status_id', 'o', '']]
124 end
124 end
125
125
126 def test_index_with_project_and_filter
126 def test_index_with_project_and_filter
127 get :index, :project_id => 1, :set_filter => 1,
127 get :index, :project_id => 1, :set_filter => 1,
128 :f => ['tracker_id'],
128 :f => ['tracker_id'],
129 :op => {'tracker_id' => '='},
129 :op => {'tracker_id' => '='},
130 :v => {'tracker_id' => ['1']}
130 :v => {'tracker_id' => ['1']}
131 assert_response :success
131 assert_response :success
132
132
133 assert_query_filters [['tracker_id', '=', '1']]
133 assert_query_filters [['tracker_id', '=', '1']]
134 end
134 end
135
135
136 def test_index_with_short_filters
136 def test_index_with_short_filters
137 to_test = {
137 to_test = {
138 'status_id' => {
138 'status_id' => {
139 'o' => { :op => 'o', :values => [''] },
139 'o' => { :op => 'o', :values => [''] },
140 'c' => { :op => 'c', :values => [''] },
140 'c' => { :op => 'c', :values => [''] },
141 '7' => { :op => '=', :values => ['7'] },
141 '7' => { :op => '=', :values => ['7'] },
142 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
142 '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
143 '=7' => { :op => '=', :values => ['7'] },
143 '=7' => { :op => '=', :values => ['7'] },
144 '!3' => { :op => '!', :values => ['3'] },
144 '!3' => { :op => '!', :values => ['3'] },
145 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
145 '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
146 'subject' => {
146 'subject' => {
147 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
147 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
148 'o' => { :op => '=', :values => ['o'] },
148 'o' => { :op => '=', :values => ['o'] },
149 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
149 '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
150 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
150 '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
151 'tracker_id' => {
151 'tracker_id' => {
152 '3' => { :op => '=', :values => ['3'] },
152 '3' => { :op => '=', :values => ['3'] },
153 '=3' => { :op => '=', :values => ['3'] }},
153 '=3' => { :op => '=', :values => ['3'] }},
154 'start_date' => {
154 'start_date' => {
155 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
155 '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
156 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
156 '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
157 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
157 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
158 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
158 '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
159 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
159 '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
160 '<t+2' => { :op => '<t+', :values => ['2'] },
160 '<t+2' => { :op => '<t+', :values => ['2'] },
161 '>t+2' => { :op => '>t+', :values => ['2'] },
161 '>t+2' => { :op => '>t+', :values => ['2'] },
162 't+2' => { :op => 't+', :values => ['2'] },
162 't+2' => { :op => 't+', :values => ['2'] },
163 't' => { :op => 't', :values => [''] },
163 't' => { :op => 't', :values => [''] },
164 'w' => { :op => 'w', :values => [''] },
164 'w' => { :op => 'w', :values => [''] },
165 '>t-2' => { :op => '>t-', :values => ['2'] },
165 '>t-2' => { :op => '>t-', :values => ['2'] },
166 '<t-2' => { :op => '<t-', :values => ['2'] },
166 '<t-2' => { :op => '<t-', :values => ['2'] },
167 't-2' => { :op => 't-', :values => ['2'] }},
167 't-2' => { :op => 't-', :values => ['2'] }},
168 'created_on' => {
168 'created_on' => {
169 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
169 '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
170 '<t-2' => { :op => '<t-', :values => ['2'] },
170 '<t-2' => { :op => '<t-', :values => ['2'] },
171 '>t-2' => { :op => '>t-', :values => ['2'] },
171 '>t-2' => { :op => '>t-', :values => ['2'] },
172 't-2' => { :op => 't-', :values => ['2'] }},
172 't-2' => { :op => 't-', :values => ['2'] }},
173 'cf_1' => {
173 'cf_1' => {
174 'c' => { :op => '=', :values => ['c'] },
174 'c' => { :op => '=', :values => ['c'] },
175 '!c' => { :op => '!', :values => ['c'] },
175 '!c' => { :op => '!', :values => ['c'] },
176 '!*' => { :op => '!*', :values => [''] },
176 '!*' => { :op => '!*', :values => [''] },
177 '*' => { :op => '*', :values => [''] }},
177 '*' => { :op => '*', :values => [''] }},
178 'estimated_hours' => {
178 'estimated_hours' => {
179 '=13.4' => { :op => '=', :values => ['13.4'] },
179 '=13.4' => { :op => '=', :values => ['13.4'] },
180 '>=45' => { :op => '>=', :values => ['45'] },
180 '>=45' => { :op => '>=', :values => ['45'] },
181 '<=125' => { :op => '<=', :values => ['125'] },
181 '<=125' => { :op => '<=', :values => ['125'] },
182 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
182 '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
183 '!*' => { :op => '!*', :values => [''] },
183 '!*' => { :op => '!*', :values => [''] },
184 '*' => { :op => '*', :values => [''] }}
184 '*' => { :op => '*', :values => [''] }}
185 }
185 }
186
186
187 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
187 default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
188
188
189 to_test.each do |field, expression_and_expected|
189 to_test.each do |field, expression_and_expected|
190 expression_and_expected.each do |filter_expression, expected|
190 expression_and_expected.each do |filter_expression, expected|
191
191
192 get :index, :set_filter => 1, field => filter_expression
192 get :index, :set_filter => 1, field => filter_expression
193 assert_response :success
193 assert_response :success
194
194
195 expected_with_default = default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}})
195 expected_with_default = default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}})
196 assert_query_filters expected_with_default.map {|f, v| [f, v[:operator], v[:values]]}
196 assert_query_filters expected_with_default.map {|f, v| [f, v[:operator], v[:values]]}
197 end
197 end
198 end
198 end
199 end
199 end
200
200
201 def test_index_with_project_and_empty_filters
201 def test_index_with_project_and_empty_filters
202 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
202 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
203 assert_response :success
203 assert_response :success
204
204
205 # no filter
205 # no filter
206 assert_query_filters []
206 assert_query_filters []
207 end
207 end
208
208
209 def test_index_with_project_custom_field_filter
209 def test_index_with_project_custom_field_filter
210 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
210 field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
211 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
211 CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
212 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
212 CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
213 filter_name = "project.cf_#{field.id}"
213 filter_name = "project.cf_#{field.id}"
214 @request.session[:user_id] = 1
214 @request.session[:user_id] = 1
215
215
216 get :index, :set_filter => 1,
216 get :index, :set_filter => 1,
217 :f => [filter_name],
217 :f => [filter_name],
218 :op => {filter_name => '='},
218 :op => {filter_name => '='},
219 :v => {filter_name => ['Foo']},
219 :v => {filter_name => ['Foo']},
220 :c => ['project']
220 :c => ['project']
221 assert_response :success
221 assert_response :success
222
222
223 assert_equal [3, 5], issues_in_list.map(&:project_id).uniq.sort
223 assert_equal [3, 5], issues_in_list.map(&:project_id).uniq.sort
224 end
224 end
225
225
226 def test_index_with_query
226 def test_index_with_query
227 get :index, :project_id => 1, :query_id => 5
227 get :index, :project_id => 1, :query_id => 5
228 assert_response :success
228 assert_response :success
229 end
229 end
230
230
231 def test_index_with_query_grouped_by_tracker
231 def test_index_with_query_grouped_by_tracker
232 get :index, :project_id => 1, :query_id => 6
232 get :index, :project_id => 1, :query_id => 6
233 assert_response :success
233 assert_response :success
234 assert_select 'tr.group span.count'
234 assert_select 'tr.group span.count'
235 end
235 end
236
236
237 def test_index_with_query_grouped_and_sorted_by_category
237 def test_index_with_query_grouped_and_sorted_by_category
238 get :index, :project_id => 1, :set_filter => 1, :group_by => "category", :sort => "category"
238 get :index, :project_id => 1, :set_filter => 1, :group_by => "category", :sort => "category"
239 assert_response :success
239 assert_response :success
240 assert_select 'tr.group span.count'
240 assert_select 'tr.group span.count'
241 end
241 end
242
242
243 def test_index_with_query_grouped_and_sorted_by_fixed_version
243 def test_index_with_query_grouped_and_sorted_by_fixed_version
244 get :index, :project_id => 1, :set_filter => 1, :group_by => "fixed_version", :sort => "fixed_version"
244 get :index, :project_id => 1, :set_filter => 1, :group_by => "fixed_version", :sort => "fixed_version"
245 assert_response :success
245 assert_response :success
246 assert_select 'tr.group span.count'
246 assert_select 'tr.group span.count'
247 end
247 end
248
248
249 def test_index_with_query_grouped_and_sorted_by_fixed_version_in_reverse_order
249 def test_index_with_query_grouped_and_sorted_by_fixed_version_in_reverse_order
250 get :index, :project_id => 1, :set_filter => 1, :group_by => "fixed_version", :sort => "fixed_version:desc"
250 get :index, :project_id => 1, :set_filter => 1, :group_by => "fixed_version", :sort => "fixed_version:desc"
251 assert_response :success
251 assert_response :success
252 assert_select 'tr.group span.count'
252 assert_select 'tr.group span.count'
253 end
253 end
254
254
255 def test_index_with_query_grouped_by_list_custom_field
255 def test_index_with_query_grouped_by_list_custom_field
256 get :index, :project_id => 1, :query_id => 9
256 get :index, :project_id => 1, :query_id => 9
257 assert_response :success
257 assert_response :success
258 assert_select 'tr.group span.count'
258 assert_select 'tr.group span.count'
259 end
259 end
260
260
261 def test_index_with_query_grouped_by_key_value_custom_field
261 def test_index_with_query_grouped_by_key_value_custom_field
262 cf = IssueCustomField.create!(:name => 'Key', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'enumeration')
262 cf = IssueCustomField.create!(:name => 'Key', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'enumeration')
263 cf.enumerations << valueb = CustomFieldEnumeration.new(:name => 'Value B', :position => 1)
263 cf.enumerations << valueb = CustomFieldEnumeration.new(:name => 'Value B', :position => 1)
264 cf.enumerations << valuea = CustomFieldEnumeration.new(:name => 'Value A', :position => 2)
264 cf.enumerations << valuea = CustomFieldEnumeration.new(:name => 'Value A', :position => 2)
265 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => valueb.id)
265 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => valueb.id)
266 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => valueb.id)
266 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => valueb.id)
267 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => valuea.id)
267 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => valuea.id)
268 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
268 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
269
269
270 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
270 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
271 assert_response :success
271 assert_response :success
272
272
273 assert_select 'tr.group', 3
273 assert_select 'tr.group', 3
274 assert_select 'tr.group' do
274 assert_select 'tr.group' do
275 assert_select 'span.name', :text => 'Value B'
275 assert_select 'span.name', :text => 'Value B'
276 assert_select 'span.count', :text => '2'
276 assert_select 'span.count', :text => '2'
277 end
277 end
278 assert_select 'tr.group' do
278 assert_select 'tr.group' do
279 assert_select 'span.name', :text => 'Value A'
279 assert_select 'span.name', :text => 'Value A'
280 assert_select 'span.count', :text => '1'
280 assert_select 'span.count', :text => '1'
281 end
281 end
282 end
282 end
283
283
284 def test_index_with_query_grouped_by_user_custom_field
284 def test_index_with_query_grouped_by_user_custom_field
285 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
285 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
286 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
286 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
287 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
287 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
288 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
288 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
289 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
289 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
290
290
291 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
291 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
292 assert_response :success
292 assert_response :success
293
293
294 assert_select 'tr.group', 3
294 assert_select 'tr.group', 3
295 assert_select 'tr.group' do
295 assert_select 'tr.group' do
296 assert_select 'a', :text => 'John Smith'
296 assert_select 'a', :text => 'John Smith'
297 assert_select 'span.count', :text => '1'
297 assert_select 'span.count', :text => '1'
298 end
298 end
299 assert_select 'tr.group' do
299 assert_select 'tr.group' do
300 assert_select 'a', :text => 'Dave Lopper'
300 assert_select 'a', :text => 'Dave Lopper'
301 assert_select 'span.count', :text => '2'
301 assert_select 'span.count', :text => '2'
302 end
302 end
303 end
303 end
304
304
305 def test_index_grouped_by_boolean_custom_field_should_distinguish_blank_and_false_values
305 def test_index_grouped_by_boolean_custom_field_should_distinguish_blank_and_false_values
306 cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool')
306 cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool')
307 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '1')
307 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '1')
308 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
308 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
309 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '')
309 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '')
310
310
311 with_settings :default_language => 'en' do
311 with_settings :default_language => 'en' do
312 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
312 get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
313 assert_response :success
313 assert_response :success
314 end
314 end
315
315
316 assert_select 'tr.group', 3
316 assert_select 'tr.group', 3
317 assert_select 'tr.group', :text => /Yes/
317 assert_select 'tr.group', :text => /Yes/
318 assert_select 'tr.group', :text => /No/
318 assert_select 'tr.group', :text => /No/
319 assert_select 'tr.group', :text => /blank/
319 assert_select 'tr.group', :text => /blank/
320 end
320 end
321
321
322 def test_index_grouped_by_boolean_custom_field_with_false_group_in_first_position_should_show_the_group
322 def test_index_grouped_by_boolean_custom_field_with_false_group_in_first_position_should_show_the_group
323 cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool', :is_filter => true)
323 cf = IssueCustomField.create!(:name => 'Bool', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'bool', :is_filter => true)
324 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '0')
324 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '0')
325 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
325 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
326
326
327 with_settings :default_language => 'en' do
327 with_settings :default_language => 'en' do
328 get :index, :project_id => 1, :set_filter => 1, "cf_#{cf.id}" => "*", :group_by => "cf_#{cf.id}"
328 get :index, :project_id => 1, :set_filter => 1, "cf_#{cf.id}" => "*", :group_by => "cf_#{cf.id}"
329 assert_response :success
329 assert_response :success
330 end
330 end
331
331
332 assert_equal [1, 2], issues_in_list.map(&:id).sort
332 assert_equal [1, 2], issues_in_list.map(&:id).sort
333 assert_select 'tr.group', 1
333 assert_select 'tr.group', 1
334 assert_select 'tr.group', :text => /No/
334 assert_select 'tr.group', :text => /No/
335 end
335 end
336
336
337 def test_index_with_query_grouped_by_tracker_in_normal_order
337 def test_index_with_query_grouped_by_tracker_in_normal_order
338 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
338 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
339
339
340 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
340 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
341 assert_response :success
341 assert_response :success
342
342
343 assert_equal ["Bug", "Feature request", "Support request"],
343 assert_equal ["Bug", "Feature request", "Support request"],
344 css_select("tr.issue td.tracker").map(&:text).uniq
344 css_select("tr.issue td.tracker").map(&:text).uniq
345 end
345 end
346
346
347 def test_index_with_query_grouped_by_tracker_in_reverse_order
347 def test_index_with_query_grouped_by_tracker_in_reverse_order
348 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
348 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
349
349
350 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
350 get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
351 assert_response :success
351 assert_response :success
352
352
353 assert_equal ["Bug", "Feature request", "Support request"].reverse,
353 assert_equal ["Bug", "Feature request", "Support request"].reverse,
354 css_select("tr.issue td.tracker").map(&:text).uniq
354 css_select("tr.issue td.tracker").map(&:text).uniq
355 end
355 end
356
356
357 def test_index_with_query_id_and_project_id_should_set_session_query
357 def test_index_with_query_id_and_project_id_should_set_session_query
358 get :index, :project_id => 1, :query_id => 4
358 get :index, :project_id => 1, :query_id => 4
359 assert_response :success
359 assert_response :success
360 assert_kind_of Hash, session[:issue_query]
360 assert_kind_of Hash, session[:issue_query]
361 assert_equal 4, session[:issue_query][:id]
361 assert_equal 4, session[:issue_query][:id]
362 assert_equal 1, session[:issue_query][:project_id]
362 assert_equal 1, session[:issue_query][:project_id]
363 end
363 end
364
364
365 def test_index_with_invalid_query_id_should_respond_404
365 def test_index_with_invalid_query_id_should_respond_404
366 get :index, :project_id => 1, :query_id => 999
366 get :index, :project_id => 1, :query_id => 999
367 assert_response 404
367 assert_response 404
368 end
368 end
369
369
370 def test_index_with_cross_project_query_in_session_should_show_project_issues
370 def test_index_with_cross_project_query_in_session_should_show_project_issues
371 q = IssueQuery.create!(:name => "cross_project_query", :user_id => 2, :project => nil, :column_names => ['project'])
371 q = IssueQuery.create!(:name => "cross_project_query", :user_id => 2, :project => nil, :column_names => ['project'])
372 @request.session[:issue_query] = {:id => q.id, :project_id => 1}
372 @request.session[:issue_query] = {:id => q.id, :project_id => 1}
373
373
374 with_settings :display_subprojects_issues => '0' do
374 with_settings :display_subprojects_issues => '0' do
375 get :index, :project_id => 1
375 get :index, :project_id => 1
376 end
376 end
377 assert_response :success
377 assert_response :success
378
378
379 assert_select 'h2', :text => q.name
379 assert_select 'h2', :text => q.name
380 assert_equal ["eCookbook"], css_select("tr.issue td.project").map(&:text).uniq
380 assert_equal ["eCookbook"], css_select("tr.issue td.project").map(&:text).uniq
381 end
381 end
382
382
383 def test_private_query_should_not_be_available_to_other_users
383 def test_private_query_should_not_be_available_to_other_users
384 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
384 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
385 @request.session[:user_id] = 3
385 @request.session[:user_id] = 3
386
386
387 get :index, :query_id => q.id
387 get :index, :query_id => q.id
388 assert_response 403
388 assert_response 403
389 end
389 end
390
390
391 def test_private_query_should_be_available_to_its_user
391 def test_private_query_should_be_available_to_its_user
392 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
392 q = IssueQuery.create!(:name => "private", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PRIVATE, :project => nil)
393 @request.session[:user_id] = 2
393 @request.session[:user_id] = 2
394
394
395 get :index, :query_id => q.id
395 get :index, :query_id => q.id
396 assert_response :success
396 assert_response :success
397 end
397 end
398
398
399 def test_public_query_should_be_available_to_other_users
399 def test_public_query_should_be_available_to_other_users
400 q = IssueQuery.create!(:name => "public", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
400 q = IssueQuery.create!(:name => "public", :user => User.find(2), :visibility => IssueQuery::VISIBILITY_PUBLIC, :project => nil)
401 @request.session[:user_id] = 3
401 @request.session[:user_id] = 3
402
402
403 get :index, :query_id => q.id
403 get :index, :query_id => q.id
404 assert_response :success
404 assert_response :success
405 end
405 end
406
406
407 def test_index_should_omit_page_param_in_export_links
407 def test_index_should_omit_page_param_in_export_links
408 get :index, :page => 2
408 get :index, :page => 2
409 assert_response :success
409 assert_response :success
410 assert_select 'a.atom[href="/issues.atom"]'
410 assert_select 'a.atom[href="/issues.atom"]'
411 assert_select 'a.csv[href="/issues.csv"]'
411 assert_select 'a.csv[href="/issues.csv"]'
412 assert_select 'a.pdf[href="/issues.pdf"]'
412 assert_select 'a.pdf[href="/issues.pdf"]'
413 assert_select 'form#csv-export-form[action="/issues.csv"]'
413 assert_select 'form#csv-export-form[action="/issues.csv"]'
414 end
414 end
415
415
416 def test_index_should_not_warn_when_not_exceeding_export_limit
416 def test_index_should_not_warn_when_not_exceeding_export_limit
417 with_settings :issues_export_limit => 200 do
417 with_settings :issues_export_limit => 200 do
418 get :index
418 get :index
419 assert_select '#csv-export-options p.icon-warning', 0
419 assert_select '#csv-export-options p.icon-warning', 0
420 end
420 end
421 end
421 end
422
422
423 def test_index_should_warn_when_exceeding_export_limit
423 def test_index_should_warn_when_exceeding_export_limit
424 with_settings :issues_export_limit => 2 do
424 with_settings :issues_export_limit => 2 do
425 get :index
425 get :index
426 assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
426 assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
427 end
427 end
428 end
428 end
429
429
430 def test_index_should_include_query_params_as_hidden_fields_in_csv_export_form
430 def test_index_should_include_query_params_as_hidden_fields_in_csv_export_form
431 get :index, :project_id => 1, :set_filter => "1", :tracker_id => "2", :sort => 'status', :c => ["status", "priority"]
431 get :index, :project_id => 1, :set_filter => "1", :tracker_id => "2", :sort => 'status', :c => ["status", "priority"]
432
432
433 assert_select '#csv-export-form[action=?]', '/projects/ecookbook/issues.csv'
433 assert_select '#csv-export-form[action=?]', '/projects/ecookbook/issues.csv'
434 assert_select '#csv-export-form[method=?]', 'get'
434 assert_select '#csv-export-form[method=?]', 'get'
435
435
436 assert_select '#csv-export-form' do
436 assert_select '#csv-export-form' do
437 assert_select 'input[name=?][value=?]', 'set_filter', '1'
437 assert_select 'input[name=?][value=?]', 'set_filter', '1'
438
438
439 assert_select 'input[name=?][value=?]', 'f[]', 'tracker_id'
439 assert_select 'input[name=?][value=?]', 'f[]', 'tracker_id'
440 assert_select 'input[name=?][value=?]', 'op[tracker_id]', '='
440 assert_select 'input[name=?][value=?]', 'op[tracker_id]', '='
441 assert_select 'input[name=?][value=?]', 'v[tracker_id][]', '2'
441 assert_select 'input[name=?][value=?]', 'v[tracker_id][]', '2'
442
442
443 assert_select 'input[name=?][value=?]', 'c[]', 'status'
443 assert_select 'input[name=?][value=?]', 'c[]', 'status'
444 assert_select 'input[name=?][value=?]', 'c[]', 'priority'
444 assert_select 'input[name=?][value=?]', 'c[]', 'priority'
445
445
446 assert_select 'input[name=?][value=?]', 'sort', 'status'
446 assert_select 'input[name=?][value=?]', 'sort', 'status'
447 end
447 end
448
448
449 get :index, :project_id => 1, :set_filter => "1", :f => []
449 get :index, :project_id => 1, :set_filter => "1", :f => []
450 assert_select '#csv-export-form input[name=?][value=?]', 'f[]', ''
450 assert_select '#csv-export-form input[name=?][value=?]', 'f[]', ''
451 end
451 end
452
452
453 def test_index_csv
453 def test_index_csv
454 get :index, :format => 'csv'
454 get :index, :format => 'csv'
455 assert_response :success
455 assert_response :success
456
456
457 assert_equal 'text/csv; header=present', @response.content_type
457 assert_equal 'text/csv; header=present', @response.content_type
458 assert response.body.starts_with?("#,")
458 assert response.body.starts_with?("#,")
459 lines = response.body.chomp.split("\n")
459 lines = response.body.chomp.split("\n")
460 # default columns + id and project
460 # default columns + id and project
461 assert_equal Setting.issue_list_default_columns.size + 2, lines[0].split(',').size
461 assert_equal Setting.issue_list_default_columns.size + 2, lines[0].split(',').size
462 end
462 end
463
463
464 def test_index_csv_with_project
464 def test_index_csv_with_project
465 get :index, :project_id => 1, :format => 'csv'
465 get :index, :project_id => 1, :format => 'csv'
466 assert_response :success
466 assert_response :success
467
467
468 assert_equal 'text/csv; header=present', @response.content_type
468 assert_equal 'text/csv; header=present', @response.content_type
469 end
469 end
470
470
471 def test_index_csv_without_any_filters
471 def test_index_csv_without_any_filters
472 @request.session[:user_id] = 1
472 @request.session[:user_id] = 1
473 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5, :subject => 'Closed issue', :author_id => 1)
473 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5, :subject => 'Closed issue', :author_id => 1)
474 get :index, :set_filter => 1, :f => [], :format => 'csv'
474 get :index, :set_filter => 1, :f => [], :format => 'csv'
475 assert_response :success
475 assert_response :success
476 # -1 for headers
476 # -1 for headers
477 assert_equal Issue.count, response.body.chomp.split("\n").size - 1
477 assert_equal Issue.count, response.body.chomp.split("\n").size - 1
478 end
478 end
479
479
480 def test_index_csv_with_description
480 def test_index_csv_with_description
481 Issue.generate!(:description => 'test_index_csv_with_description')
481 Issue.generate!(:description => 'test_index_csv_with_description')
482
482
483 with_settings :default_language => 'en' do
483 with_settings :default_language => 'en' do
484 get :index, :format => 'csv', :csv => {:description => '1'}
484 get :index, :format => 'csv', :csv => {:description => '1'}
485 assert_response :success
485 assert_response :success
486 end
486 end
487
487
488 assert_equal 'text/csv; header=present', response.content_type
488 assert_equal 'text/csv; header=present', response.content_type
489 headers = response.body.chomp.split("\n").first.split(',')
489 headers = response.body.chomp.split("\n").first.split(',')
490 assert_include 'Description', headers
490 assert_include 'Description', headers
491 assert_include 'test_index_csv_with_description', response.body
491 assert_include 'test_index_csv_with_description', response.body
492 end
492 end
493
493
494 def test_index_csv_with_spent_time_column
494 def test_index_csv_with_spent_time_column
495 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
495 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
496 TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
496 TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
497
497
498 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
498 get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
499 assert_response :success
499 assert_response :success
500 assert_equal 'text/csv; header=present', @response.content_type
500 assert_equal 'text/csv; header=present', @response.content_type
501 lines = @response.body.chomp.split("\n")
501 lines = @response.body.chomp.split("\n")
502 assert_include "#{issue.id},#{issue.subject},7.33", lines
502 assert_include "#{issue.id},#{issue.subject},7.33", lines
503 end
503 end
504
504
505 def test_index_csv_with_all_columns
505 def test_index_csv_with_all_columns
506 get :index, :format => 'csv', :csv => {:columns => 'all'}
506 get :index, :format => 'csv', :csv => {:columns => 'all'}
507 assert_response :success
507 assert_response :success
508
508
509 assert_equal 'text/csv; header=present', @response.content_type
509 assert_equal 'text/csv; header=present', @response.content_type
510 assert_match /\A#,/, response.body
510 assert_match /\A#,/, response.body
511 lines = response.body.chomp.split("\n")
511 lines = response.body.chomp.split("\n")
512 assert_equal IssueQuery.new.available_inline_columns.size, lines[0].split(',').size
512 assert_equal IssueQuery.new.available_inline_columns.size, lines[0].split(',').size
513 end
513 end
514
514
515 def test_index_csv_with_multi_column_field
515 def test_index_csv_with_multi_column_field
516 CustomField.find(1).update_attribute :multiple, true
516 CustomField.find(1).update_attribute :multiple, true
517 issue = Issue.find(1)
517 issue = Issue.find(1)
518 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
518 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
519 issue.save!
519 issue.save!
520
520
521 get :index, :format => 'csv', :csv => {:columns => 'all'}
521 get :index, :format => 'csv', :csv => {:columns => 'all'}
522 assert_response :success
522 assert_response :success
523 lines = @response.body.chomp.split("\n")
523 lines = @response.body.chomp.split("\n")
524 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
524 assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
525 end
525 end
526
526
527 def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
527 def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
528 field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
528 field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
529 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
529 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
530
530
531 with_settings :default_language => 'fr' do
531 with_settings :default_language => 'fr' do
532 get :index, :format => 'csv', :csv => {:columns => 'all'}
532 get :index, :format => 'csv', :csv => {:columns => 'all'}
533 assert_response :success
533 assert_response :success
534 issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
534 issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
535 assert_include '185,60', issue_line
535 assert_include '185,60', issue_line
536 end
536 end
537
537
538 with_settings :default_language => 'en' do
538 with_settings :default_language => 'en' do
539 get :index, :format => 'csv', :csv => {:columns => 'all'}
539 get :index, :format => 'csv', :csv => {:columns => 'all'}
540 assert_response :success
540 assert_response :success
541 issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
541 issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
542 assert_include '185.60', issue_line
542 assert_include '185.60', issue_line
543 end
543 end
544 end
544 end
545
545
546 def test_index_csv_should_fill_parent_column_with_parent_id
546 def test_index_csv_should_fill_parent_column_with_parent_id
547 Issue.delete_all
547 Issue.delete_all
548 parent = Issue.generate!
548 parent = Issue.generate!
549 child = Issue.generate!(:parent_issue_id => parent.id)
549 child = Issue.generate!(:parent_issue_id => parent.id)
550
550
551 with_settings :default_language => 'en' do
551 with_settings :default_language => 'en' do
552 get :index, :format => 'csv', :c => %w(parent)
552 get :index, :format => 'csv', :c => %w(parent)
553 end
553 end
554 lines = response.body.split("\n")
554 lines = response.body.split("\n")
555 assert_include "#{child.id},#{parent.id}", lines
555 assert_include "#{child.id},#{parent.id}", lines
556 end
556 end
557
557
558 def test_index_csv_big_5
558 def test_index_csv_big_5
559 with_settings :default_language => "zh-TW" do
559 with_settings :default_language => "zh-TW" do
560 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8')
560 str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88".force_encoding('UTF-8')
561 str_big5 = "\xa4@\xa4\xeb".force_encoding('Big5')
561 str_big5 = "\xa4@\xa4\xeb".force_encoding('Big5')
562 issue = Issue.generate!(:subject => str_utf8)
562 issue = Issue.generate!(:subject => str_utf8)
563
563
564 get :index, :project_id => 1,
564 get :index, :project_id => 1,
565 :f => ['subject'],
565 :f => ['subject'],
566 :op => '=', :values => [str_utf8],
566 :op => '=', :values => [str_utf8],
567 :format => 'csv'
567 :format => 'csv'
568 assert_equal 'text/csv; header=present', @response.content_type
568 assert_equal 'text/csv; header=present', @response.content_type
569 lines = @response.body.chomp.split("\n")
569 lines = @response.body.chomp.split("\n")
570 header = lines[0]
570 header = lines[0]
571 status = "\xaa\xac\xbaA".force_encoding('Big5')
571 status = "\xaa\xac\xbaA".force_encoding('Big5')
572 assert_include status, header
572 assert_include status, header
573 issue_line = lines.find {|l| l =~ /^#{issue.id},/}
573 issue_line = lines.find {|l| l =~ /^#{issue.id},/}
574 assert_include str_big5, issue_line
574 assert_include str_big5, issue_line
575 end
575 end
576 end
576 end
577
577
578 def test_index_csv_cannot_convert_should_be_replaced_big_5
578 def test_index_csv_cannot_convert_should_be_replaced_big_5
579 with_settings :default_language => "zh-TW" do
579 with_settings :default_language => "zh-TW" do
580 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
580 str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
581 issue = Issue.generate!(:subject => str_utf8)
581 issue = Issue.generate!(:subject => str_utf8)
582
582
583 get :index, :project_id => 1,
583 get :index, :project_id => 1,
584 :f => ['subject'],
584 :f => ['subject'],
585 :op => '=', :values => [str_utf8],
585 :op => '=', :values => [str_utf8],
586 :c => ['status', 'subject'],
586 :c => ['status', 'subject'],
587 :format => 'csv',
587 :format => 'csv',
588 :set_filter => 1
588 :set_filter => 1
589 assert_equal 'text/csv; header=present', @response.content_type
589 assert_equal 'text/csv; header=present', @response.content_type
590 lines = @response.body.chomp.split("\n")
590 lines = @response.body.chomp.split("\n")
591 header = lines[0]
591 header = lines[0]
592 issue_line = lines.find {|l| l =~ /^#{issue.id},/}
592 issue_line = lines.find {|l| l =~ /^#{issue.id},/}
593 s1 = "\xaa\xac\xbaA".force_encoding('Big5') # status
593 s1 = "\xaa\xac\xbaA".force_encoding('Big5') # status
594 assert header.include?(s1)
594 assert header.include?(s1)
595 s2 = issue_line.split(",")[2]
595 s2 = issue_line.split(",")[2]
596 s3 = "\xa5H?".force_encoding('Big5') # subject
596 s3 = "\xa5H?".force_encoding('Big5') # subject
597 assert_equal s3, s2
597 assert_equal s3, s2
598 end
598 end
599 end
599 end
600
600
601 def test_index_csv_tw
601 def test_index_csv_tw
602 with_settings :default_language => "zh-TW" do
602 with_settings :default_language => "zh-TW" do
603 str1 = "test_index_csv_tw"
603 str1 = "test_index_csv_tw"
604 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
604 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
605
605
606 get :index, :project_id => 1,
606 get :index, :project_id => 1,
607 :f => ['subject'],
607 :f => ['subject'],
608 :op => '=', :values => [str1],
608 :op => '=', :values => [str1],
609 :c => ['estimated_hours', 'subject'],
609 :c => ['estimated_hours', 'subject'],
610 :format => 'csv',
610 :format => 'csv',
611 :set_filter => 1
611 :set_filter => 1
612 assert_equal 'text/csv; header=present', @response.content_type
612 assert_equal 'text/csv; header=present', @response.content_type
613 lines = @response.body.chomp.split("\n")
613 lines = @response.body.chomp.split("\n")
614 assert_include "#{issue.id},1234.50,#{str1}", lines
614 assert_include "#{issue.id},1234.50,#{str1}", lines
615 end
615 end
616 end
616 end
617
617
618 def test_index_csv_fr
618 def test_index_csv_fr
619 with_settings :default_language => "fr" do
619 with_settings :default_language => "fr" do
620 str1 = "test_index_csv_fr"
620 str1 = "test_index_csv_fr"
621 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
621 issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
622
622
623 get :index, :project_id => 1,
623 get :index, :project_id => 1,
624 :f => ['subject'],
624 :f => ['subject'],
625 :op => '=', :values => [str1],
625 :op => '=', :values => [str1],
626 :c => ['estimated_hours', 'subject'],
626 :c => ['estimated_hours', 'subject'],
627 :format => 'csv',
627 :format => 'csv',
628 :set_filter => 1
628 :set_filter => 1
629 assert_equal 'text/csv; header=present', @response.content_type
629 assert_equal 'text/csv; header=present', @response.content_type
630 lines = @response.body.chomp.split("\n")
630 lines = @response.body.chomp.split("\n")
631 assert_include "#{issue.id};1234,50;#{str1}", lines
631 assert_include "#{issue.id};1234,50;#{str1}", lines
632 end
632 end
633 end
633 end
634
634
635 def test_index_pdf
635 def test_index_pdf
636 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
636 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
637 with_settings :default_language => lang do
637 with_settings :default_language => lang do
638
638
639 get :index
639 get :index
640 assert_response :success
640 assert_response :success
641
641
642 get :index, :format => 'pdf'
642 get :index, :format => 'pdf'
643 assert_response :success
643 assert_response :success
644 assert_equal 'application/pdf', @response.content_type
644 assert_equal 'application/pdf', @response.content_type
645
645
646 get :index, :project_id => 1, :format => 'pdf'
646 get :index, :project_id => 1, :format => 'pdf'
647 assert_response :success
647 assert_response :success
648 assert_equal 'application/pdf', @response.content_type
648 assert_equal 'application/pdf', @response.content_type
649
649
650 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
650 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
651 assert_response :success
651 assert_response :success
652 assert_equal 'application/pdf', @response.content_type
652 assert_equal 'application/pdf', @response.content_type
653 end
653 end
654 end
654 end
655 end
655 end
656
656
657 def test_index_pdf_with_query_grouped_by_list_custom_field
657 def test_index_pdf_with_query_grouped_by_list_custom_field
658 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
658 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
659 assert_response :success
659 assert_response :success
660 assert_equal 'application/pdf', @response.content_type
660 assert_equal 'application/pdf', @response.content_type
661 end
661 end
662
662
663 def test_index_atom
663 def test_index_atom
664 get :index, :project_id => 'ecookbook', :format => 'atom'
664 get :index, :project_id => 'ecookbook', :format => 'atom'
665 assert_response :success
665 assert_response :success
666 assert_equal 'application/atom+xml', response.content_type
666 assert_equal 'application/atom+xml', response.content_type
667
667
668 assert_select 'feed' do
668 assert_select 'feed' do
669 assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
669 assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
670 assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
670 assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
671 assert_select 'entry link[href=?]', 'http://test.host/issues/1'
671 assert_select 'entry link[href=?]', 'http://test.host/issues/1'
672 end
672 end
673 end
673 end
674
674
675 def test_index_should_include_back_url_input
675 def test_index_should_include_back_url_input
676 get :index, :project_id => 'ecookbook', :foo => 'bar'
676 get :index, :project_id => 'ecookbook', :foo => 'bar'
677 assert_response :success
677 assert_response :success
678 assert_select 'input[name=back_url][value=?]', '/projects/ecookbook/issues?foo=bar'
678 assert_select 'input[name=back_url][value=?]', '/projects/ecookbook/issues?foo=bar'
679 end
679 end
680
680
681 def test_index_sort
681 def test_index_sort
682 get :index, :sort => 'tracker,id:desc'
682 get :index, :sort => 'tracker,id:desc'
683 assert_response :success
683 assert_response :success
684
684
685 sort_params = @request.session['issues_index_sort']
685 sort_params = @request.session['issues_index_sort']
686 assert sort_params.is_a?(String)
686 assert sort_params.is_a?(String)
687 assert_equal 'tracker,id:desc', sort_params
687 assert_equal 'tracker,id:desc', sort_params
688
688
689 assert_equal issues_in_list.sort_by {|issue| [issue.tracker.position, -issue.id]}, issues_in_list
689 assert_equal issues_in_list.sort_by {|issue| [issue.tracker.position, -issue.id]}, issues_in_list
690 assert_select 'table.issues.sort-by-tracker.sort-asc'
690 assert_select 'table.issues.sort-by-tracker.sort-asc'
691 end
691 end
692
692
693 def test_index_sort_by_field_not_included_in_columns
693 def test_index_sort_by_field_not_included_in_columns
694 Setting.issue_list_default_columns = %w(subject author)
694 Setting.issue_list_default_columns = %w(subject author)
695 get :index, :sort => 'tracker'
695 get :index, :sort => 'tracker'
696 end
696 end
697
697
698 def test_index_sort_by_assigned_to
698 def test_index_sort_by_assigned_to
699 get :index, :sort => 'assigned_to'
699 get :index, :sort => 'assigned_to'
700 assert_response :success
700 assert_response :success
701
701
702 assignees = issues_in_list.map(&:assigned_to).compact
702 assignees = issues_in_list.map(&:assigned_to).compact
703 assert_equal assignees.sort, assignees
703 assert_equal assignees.sort, assignees
704 assert_select 'table.issues.sort-by-assigned-to.sort-asc'
704 assert_select 'table.issues.sort-by-assigned-to.sort-asc'
705 end
705 end
706
706
707 def test_index_sort_by_assigned_to_desc
707 def test_index_sort_by_assigned_to_desc
708 get :index, :sort => 'assigned_to:desc'
708 get :index, :sort => 'assigned_to:desc'
709 assert_response :success
709 assert_response :success
710
710
711 assignees = issues_in_list.map(&:assigned_to).compact
711 assignees = issues_in_list.map(&:assigned_to).compact
712 assert_equal assignees.sort.reverse, assignees
712 assert_equal assignees.sort.reverse, assignees
713 assert_select 'table.issues.sort-by-assigned-to.sort-desc'
713 assert_select 'table.issues.sort-by-assigned-to.sort-desc'
714 end
714 end
715
715
716 def test_index_group_by_assigned_to
716 def test_index_group_by_assigned_to
717 get :index, :group_by => 'assigned_to', :sort => 'priority'
717 get :index, :group_by => 'assigned_to', :sort => 'priority'
718 assert_response :success
718 assert_response :success
719 end
719 end
720
720
721 def test_index_sort_by_author
721 def test_index_sort_by_author
722 get :index, :sort => 'author', :c => ['author']
722 get :index, :sort => 'author', :c => ['author']
723 assert_response :success
723 assert_response :success
724
724
725 authors = issues_in_list.map(&:author)
725 authors = issues_in_list.map(&:author)
726 assert_equal authors.sort, authors
726 assert_equal authors.sort, authors
727 end
727 end
728
728
729 def test_index_sort_by_author_desc
729 def test_index_sort_by_author_desc
730 get :index, :sort => 'author:desc'
730 get :index, :sort => 'author:desc'
731 assert_response :success
731 assert_response :success
732
732
733 authors = issues_in_list.map(&:author)
733 authors = issues_in_list.map(&:author)
734 assert_equal authors.sort.reverse, authors
734 assert_equal authors.sort.reverse, authors
735 end
735 end
736
736
737 def test_index_group_by_author
737 def test_index_group_by_author
738 get :index, :group_by => 'author', :sort => 'priority'
738 get :index, :group_by => 'author', :sort => 'priority'
739 assert_response :success
739 assert_response :success
740 end
740 end
741
741
742 def test_index_sort_by_spent_hours
742 def test_index_sort_by_spent_hours
743 get :index, :sort => 'spent_hours:desc'
743 get :index, :sort => 'spent_hours:desc'
744 assert_response :success
744 assert_response :success
745 hours = issues_in_list.map(&:spent_hours)
745 hours = issues_in_list.map(&:spent_hours)
746 assert_equal hours.sort.reverse, hours
746 assert_equal hours.sort.reverse, hours
747 end
747 end
748
748
749 def test_index_sort_by_total_spent_hours
749 def test_index_sort_by_total_spent_hours
750 get :index, :sort => 'total_spent_hours:desc'
750 get :index, :sort => 'total_spent_hours:desc'
751 assert_response :success
751 assert_response :success
752 hours = issues_in_list.map(&:total_spent_hours)
752 hours = issues_in_list.map(&:total_spent_hours)
753 assert_equal hours.sort.reverse, hours
753 assert_equal hours.sort.reverse, hours
754 end
754 end
755
755
756 def test_index_sort_by_total_estimated_hours
756 def test_index_sort_by_total_estimated_hours
757 get :index, :sort => 'total_estimated_hours:desc'
757 get :index, :sort => 'total_estimated_hours:desc'
758 assert_response :success
758 assert_response :success
759 hours = issues_in_list.map(&:total_estimated_hours)
759 hours = issues_in_list.map(&:total_estimated_hours)
760 assert_equal hours.sort.reverse, hours
760 assert_equal hours.sort.reverse, hours
761 end
761 end
762
762
763 def test_index_sort_by_user_custom_field
763 def test_index_sort_by_user_custom_field
764 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
764 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
765 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
765 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
766 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
766 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
767 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
767 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
768 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
768 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
769
769
770 get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
770 get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
771 assert_response :success
771 assert_response :success
772
772
773 assert_equal [2, 3, 1], issues_in_list.select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
773 assert_equal [2, 3, 1], issues_in_list.select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
774 end
774 end
775
775
776 def test_index_with_columns
776 def test_index_with_columns
777 columns = ['tracker', 'subject', 'assigned_to']
777 columns = ['tracker', 'subject', 'assigned_to']
778 get :index, :set_filter => 1, :c => columns
778 get :index, :set_filter => 1, :c => columns
779 assert_response :success
779 assert_response :success
780
780
781 # query should use specified columns + id and checkbox
781 # query should use specified columns + id and checkbox
782 assert_select 'table.issues thead th', columns.size + 2
782 assert_select 'table.issues thead th', columns.size + 2
783
783
784 # columns should be stored in session
784 # columns should be stored in session
785 assert_kind_of Hash, session[:issue_query]
785 assert_kind_of Hash, session[:issue_query]
786 assert_kind_of Array, session[:issue_query][:column_names]
786 assert_kind_of Array, session[:issue_query][:column_names]
787 assert_equal columns, session[:issue_query][:column_names].map(&:to_s)
787 assert_equal columns, session[:issue_query][:column_names].map(&:to_s)
788
788
789 # ensure only these columns are kept in the selected columns list
789 # ensure only these columns are kept in the selected columns list
790 assert_select 'select#selected_columns option' do
790 assert_select 'select#selected_columns option' do
791 assert_select 'option', 3
791 assert_select 'option', 3
792 assert_select 'option[value=tracker]'
792 assert_select 'option[value=tracker]'
793 assert_select 'option[value=project]', 0
793 assert_select 'option[value=project]', 0
794 end
794 end
795 end
795 end
796
796
797 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
797 def test_index_without_project_should_implicitly_add_project_column_to_default_columns
798 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
798 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
799 get :index, :set_filter => 1
799 get :index, :set_filter => 1
800
800
801 # query should use specified columns
801 # query should use specified columns
802 assert_equal ["#", "Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
802 assert_equal ["#", "Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
803 end
803 end
804
804
805 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
805 def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
806 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
806 Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
807 columns = ['id', 'tracker', 'subject', 'assigned_to']
807 columns = ['id', 'tracker', 'subject', 'assigned_to']
808 get :index, :set_filter => 1, :c => columns
808 get :index, :set_filter => 1, :c => columns
809
809
810 # query should use specified columns
810 # query should use specified columns
811 assert_equal ["#", "Tracker", "Subject", "Assignee"], columns_in_issues_list
811 assert_equal ["#", "Tracker", "Subject", "Assignee"], columns_in_issues_list
812 end
812 end
813
813
814 def test_index_with_default_columns_should_respect_default_columns_order
814 def test_index_with_default_columns_should_respect_default_columns_order
815 columns = ['assigned_to', 'subject', 'status', 'tracker']
815 columns = ['assigned_to', 'subject', 'status', 'tracker']
816 with_settings :issue_list_default_columns => columns do
816 with_settings :issue_list_default_columns => columns do
817 get :index, :project_id => 1, :set_filter => 1
817 get :index, :project_id => 1, :set_filter => 1
818
818
819 assert_equal ["#", "Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
819 assert_equal ["#", "Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
820 end
820 end
821 end
821 end
822
822
823 def test_index_with_custom_field_column
823 def test_index_with_custom_field_column
824 columns = %w(tracker subject cf_2)
824 columns = %w(tracker subject cf_2)
825 get :index, :set_filter => 1, :c => columns
825 get :index, :set_filter => 1, :c => columns
826 assert_response :success
826 assert_response :success
827
827
828 # query should use specified columns
828 # query should use specified columns
829 assert_equal ["#", "Tracker", "Subject", "Searchable field"], columns_in_issues_list
829 assert_equal ["#", "Tracker", "Subject", "Searchable field"], columns_in_issues_list
830 assert_select 'table.issues td.cf_2.string'
830 assert_select 'table.issues td.cf_2.string'
831 end
831 end
832
832
833 def test_index_with_multi_custom_field_column
833 def test_index_with_multi_custom_field_column
834 field = CustomField.find(1)
834 field = CustomField.find(1)
835 field.update_attribute :multiple, true
835 field.update_attribute :multiple, true
836 issue = Issue.find(1)
836 issue = Issue.find(1)
837 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
837 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
838 issue.save!
838 issue.save!
839
839
840 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
840 get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
841 assert_response :success
841 assert_response :success
842
842
843 assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
843 assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
844 end
844 end
845
845
846 def test_index_with_multi_user_custom_field_column
846 def test_index_with_multi_user_custom_field_column
847 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
847 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
848 :tracker_ids => [1], :is_for_all => true)
848 :tracker_ids => [1], :is_for_all => true)
849 issue = Issue.find(1)
849 issue = Issue.find(1)
850 issue.custom_field_values = {field.id => ['2', '3']}
850 issue.custom_field_values = {field.id => ['2', '3']}
851 issue.save!
851 issue.save!
852
852
853 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
853 get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
854 assert_response :success
854 assert_response :success
855
855
856 assert_select "table.issues td.cf_#{field.id}" do
856 assert_select "table.issues td.cf_#{field.id}" do
857 assert_select 'a', 2
857 assert_select 'a', 2
858 assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
858 assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
859 assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
859 assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
860 end
860 end
861 end
861 end
862
862
863 def test_index_with_date_column
863 def test_index_with_date_column
864 with_settings :date_format => '%d/%m/%Y' do
864 with_settings :date_format => '%d/%m/%Y' do
865 Issue.find(1).update_attribute :start_date, '1987-08-24'
865 Issue.find(1).update_attribute :start_date, '1987-08-24'
866 get :index, :set_filter => 1, :c => %w(start_date)
866 get :index, :set_filter => 1, :c => %w(start_date)
867 assert_select "table.issues td.start_date", :text => '24/08/1987'
867 assert_select "table.issues td.start_date", :text => '24/08/1987'
868 end
868 end
869 end
869 end
870
870
871 def test_index_with_done_ratio_column
871 def test_index_with_done_ratio_column
872 Issue.find(1).update_attribute :done_ratio, 40
872 Issue.find(1).update_attribute :done_ratio, 40
873 get :index, :set_filter => 1, :c => %w(done_ratio)
873 get :index, :set_filter => 1, :c => %w(done_ratio)
874 assert_select 'table.issues td.done_ratio' do
874 assert_select 'table.issues td.done_ratio' do
875 assert_select 'table.progress' do
875 assert_select 'table.progress' do
876 assert_select 'td.closed[style=?]', 'width: 40%;'
876 assert_select 'td.closed[style=?]', 'width: 40%;'
877 end
877 end
878 end
878 end
879 end
879 end
880
880
881 def test_index_with_spent_hours_column
881 def test_index_with_spent_hours_column
882 Issue.expects(:load_visible_spent_hours).once
882 Issue.expects(:load_visible_spent_hours).once
883 get :index, :set_filter => 1, :c => %w(subject spent_hours)
883 get :index, :set_filter => 1, :c => %w(subject spent_hours)
884 assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
884 assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
885 end
885 end
886
886
887 def test_index_with_total_spent_hours_column
887 def test_index_with_total_spent_hours_column
888 Issue.expects(:load_visible_total_spent_hours).once
888 Issue.expects(:load_visible_total_spent_hours).once
889 get :index, :set_filter => 1, :c => %w(subject total_spent_hours)
889 get :index, :set_filter => 1, :c => %w(subject total_spent_hours)
890 assert_select 'table.issues tr#issue-3 td.total_spent_hours', :text => '1.00'
890 assert_select 'table.issues tr#issue-3 td.total_spent_hours', :text => '1.00'
891 end
891 end
892
892
893 def test_index_with_total_estimated_hours_column
893 def test_index_with_total_estimated_hours_column
894 get :index, :set_filter => 1, :c => %w(subject total_estimated_hours)
894 get :index, :set_filter => 1, :c => %w(subject total_estimated_hours)
895 assert_select 'table.issues td.total_estimated_hours'
895 assert_select 'table.issues td.total_estimated_hours'
896 end
896 end
897
897
898 def test_index_should_not_show_spent_hours_column_without_permission
898 def test_index_should_not_show_spent_hours_column_without_permission
899 Role.anonymous.remove_permission! :view_time_entries
899 Role.anonymous.remove_permission! :view_time_entries
900 get :index, :set_filter => 1, :c => %w(subject spent_hours)
900 get :index, :set_filter => 1, :c => %w(subject spent_hours)
901 assert_select 'td.spent_hours', 0
901 assert_select 'td.spent_hours', 0
902 end
902 end
903
903
904 def test_index_with_fixed_version_column
904 def test_index_with_fixed_version_column
905 get :index, :set_filter => 1, :c => %w(fixed_version)
905 get :index, :set_filter => 1, :c => %w(fixed_version)
906 assert_select 'table.issues td.fixed_version' do
906 assert_select 'table.issues td.fixed_version' do
907 assert_select 'a[href=?]', '/versions/2', :text => 'eCookbook - 1.0'
907 assert_select 'a[href=?]', '/versions/2', :text => 'eCookbook - 1.0'
908 end
908 end
909 end
909 end
910
910
911 def test_index_with_relations_column
911 def test_index_with_relations_column
912 IssueRelation.delete_all
912 IssueRelation.delete_all
913 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
913 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
914 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
914 IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
915 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
915 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
916 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
916 IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
917
917
918 get :index, :set_filter => 1, :c => %w(subject relations)
918 get :index, :set_filter => 1, :c => %w(subject relations)
919 assert_response :success
919 assert_response :success
920 assert_select "tr#issue-1 td.relations" do
920 assert_select "tr#issue-1 td.relations" do
921 assert_select "span", 3
921 assert_select "span", 3
922 assert_select "span", :text => "Related to #7"
922 assert_select "span", :text => "Related to #7"
923 assert_select "span", :text => "Related to #8"
923 assert_select "span", :text => "Related to #8"
924 assert_select "span", :text => "Blocks #11"
924 assert_select "span", :text => "Blocks #11"
925 end
925 end
926 assert_select "tr#issue-2 td.relations" do
926 assert_select "tr#issue-2 td.relations" do
927 assert_select "span", 1
927 assert_select "span", 1
928 assert_select "span", :text => "Blocked by #12"
928 assert_select "span", :text => "Blocked by #12"
929 end
929 end
930 assert_select "tr#issue-3 td.relations" do
930 assert_select "tr#issue-3 td.relations" do
931 assert_select "span", 0
931 assert_select "span", 0
932 end
932 end
933
933
934 get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
934 get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
935 assert_response :success
935 assert_response :success
936 assert_equal 'text/csv; header=present', response.content_type
936 assert_equal 'text/csv; header=present', response.content_type
937 lines = response.body.chomp.split("\n")
937 lines = response.body.chomp.split("\n")
938 assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
938 assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
939 assert_include '2,Blocked by #12', lines
939 assert_include '2,Blocked by #12', lines
940 assert_include '3,""', lines
940 assert_include '3,""', lines
941
941
942 get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
942 get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
943 assert_response :success
943 assert_response :success
944 assert_equal 'application/pdf', response.content_type
944 assert_equal 'application/pdf', response.content_type
945 end
945 end
946
946
947 def test_index_with_description_column
947 def test_index_with_description_column
948 get :index, :set_filter => 1, :c => %w(subject description)
948 get :index, :set_filter => 1, :c => %w(subject description)
949
949
950 assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
950 assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
951 assert_select 'td.description[colspan="3"]', :text => 'Unable to print recipes'
951 assert_select 'td.description[colspan="3"]', :text => 'Unable to print recipes'
952
952
953 get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
953 get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
954 assert_response :success
954 assert_response :success
955 assert_equal 'application/pdf', response.content_type
955 assert_equal 'application/pdf', response.content_type
956 end
956 end
957
957
958 def test_index_with_parent_column
958 def test_index_with_parent_column
959 Issue.delete_all
959 Issue.delete_all
960 parent = Issue.generate!
960 parent = Issue.generate!
961 child = Issue.generate!(:parent_issue_id => parent.id)
961 child = Issue.generate!(:parent_issue_id => parent.id)
962
962
963 get :index, :c => %w(parent)
963 get :index, :c => %w(parent)
964
964
965 assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
965 assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
966 assert_select 'td.parent a[title=?]', parent.subject
966 assert_select 'td.parent a[title=?]', parent.subject
967 end
967 end
968
968
969 def test_index_with_estimated_hours_total
969 def test_index_with_estimated_hours_total
970 Issue.delete_all
970 Issue.delete_all
971 Issue.generate!(:estimated_hours => 5.5)
971 Issue.generate!(:estimated_hours => 5.5)
972 Issue.generate!(:estimated_hours => 1.1)
972 Issue.generate!(:estimated_hours => 1.1)
973
973
974 get :index, :t => %w(estimated_hours)
974 get :index, :t => %w(estimated_hours)
975 assert_response :success
975 assert_response :success
976 assert_select '.query-totals'
976 assert_select '.query-totals'
977 assert_select '.total-for-estimated-hours span.value', :text => '6.60'
977 assert_select '.total-for-estimated-hours span.value', :text => '6.60'
978 assert_select 'input[type=checkbox][name=?][value=estimated_hours][checked=checked]', 't[]'
978 assert_select 'input[type=checkbox][name=?][value=estimated_hours][checked=checked]', 't[]'
979 end
979 end
980
980
981 def test_index_with_grouped_query_and_estimated_hours_total
981 def test_index_with_grouped_query_and_estimated_hours_total
982 Issue.delete_all
982 Issue.delete_all
983 Issue.generate!(:estimated_hours => 5.5, :category_id => 1)
983 Issue.generate!(:estimated_hours => 5.5, :category_id => 1)
984 Issue.generate!(:estimated_hours => 2.3, :category_id => 1)
984 Issue.generate!(:estimated_hours => 2.3, :category_id => 1)
985 Issue.generate!(:estimated_hours => 1.1, :category_id => 2)
985 Issue.generate!(:estimated_hours => 1.1, :category_id => 2)
986 Issue.generate!(:estimated_hours => 4.6)
986 Issue.generate!(:estimated_hours => 4.6)
987
987
988 get :index, :t => %w(estimated_hours), :group_by => 'category'
988 get :index, :t => %w(estimated_hours), :group_by => 'category'
989 assert_response :success
989 assert_response :success
990 assert_select '.query-totals'
990 assert_select '.query-totals'
991 assert_select '.query-totals .total-for-estimated-hours span.value', :text => '13.50'
991 assert_select '.query-totals .total-for-estimated-hours span.value', :text => '13.50'
992 assert_select 'tr.group', :text => /Printing/ do
992 assert_select 'tr.group', :text => /Printing/ do
993 assert_select '.total-for-estimated-hours span.value', :text => '7.80'
993 assert_select '.total-for-estimated-hours span.value', :text => '7.80'
994 end
994 end
995 assert_select 'tr.group', :text => /Recipes/ do
995 assert_select 'tr.group', :text => /Recipes/ do
996 assert_select '.total-for-estimated-hours span.value', :text => '1.10'
996 assert_select '.total-for-estimated-hours span.value', :text => '1.10'
997 end
997 end
998 assert_select 'tr.group', :text => /blank/ do
998 assert_select 'tr.group', :text => /blank/ do
999 assert_select '.total-for-estimated-hours span.value', :text => '4.60'
999 assert_select '.total-for-estimated-hours span.value', :text => '4.60'
1000 end
1000 end
1001 end
1001 end
1002
1002
1003 def test_index_with_int_custom_field_total
1003 def test_index_with_int_custom_field_total
1004 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1004 field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
1005 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1005 CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
1006 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1006 CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
1007
1007
1008 get :index, :t => ["cf_#{field.id}"]
1008 get :index, :t => ["cf_#{field.id}"]
1009 assert_response :success
1009 assert_response :success
1010 assert_select '.query-totals'
1010 assert_select '.query-totals'
1011 assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
1011 assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
1012 end
1012 end
1013
1013
1014 def test_index_totals_should_default_to_settings
1014 def test_index_totals_should_default_to_settings
1015 with_settings :issue_list_default_totals => ['estimated_hours'] do
1015 with_settings :issue_list_default_totals => ['estimated_hours'] do
1016 get :index
1016 get :index
1017 assert_response :success
1017 assert_response :success
1018 assert_select '.total-for-estimated-hours span.value'
1018 assert_select '.total-for-estimated-hours span.value'
1019 assert_select '.query-totals>span', 1
1019 assert_select '.query-totals>span', 1
1020 end
1020 end
1021 end
1021 end
1022
1022
1023 def test_index_send_html_if_query_is_invalid
1023 def test_index_send_html_if_query_is_invalid
1024 get :index, :f => ['start_date'], :op => {:start_date => '='}
1024 get :index, :f => ['start_date'], :op => {:start_date => '='}
1025 assert_equal 'text/html', @response.content_type
1025 assert_equal 'text/html', @response.content_type
1026 assert_select_error /Start date cannot be blank/i
1026 assert_select_error /Start date cannot be blank/i
1027 end
1027 end
1028
1028
1029 def test_index_send_nothing_if_query_is_invalid
1029 def test_index_send_nothing_if_query_is_invalid
1030 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
1030 get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
1031 assert_equal 'text/csv', @response.content_type
1031 assert_equal 'text/csv', @response.content_type
1032 assert @response.body.blank?
1032 assert @response.body.blank?
1033 end
1033 end
1034
1034
1035 def test_index_should_include_new_issue_link
1035 def test_index_should_include_new_issue_link
1036 @request.session[:user_id] = 2
1036 @request.session[:user_id] = 2
1037 get :index, :project_id => 1
1037 get :index, :project_id => 1
1038 assert_select '#content a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1038 assert_select '#content a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1039 end
1039 end
1040
1040
1041 def test_index_should_not_include_new_issue_link_for_project_without_trackers
1041 def test_index_should_not_include_new_issue_link_for_project_without_trackers
1042 Project.find(1).trackers.clear
1042 Project.find(1).trackers.clear
1043
1043
1044 @request.session[:user_id] = 2
1044 @request.session[:user_id] = 2
1045 get :index, :project_id => 1
1045 get :index, :project_id => 1
1046 assert_select '#content a.new-issue', 0
1046 assert_select '#content a.new-issue', 0
1047 end
1047 end
1048
1048
1049 def test_index_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
1049 def test_index_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
1050 role = Role.find(1)
1050 role = Role.find(1)
1051 role.remove_permission! :add_issues
1051 role.remove_permission! :add_issues
1052 role.add_permission! :copy_issues
1052 role.add_permission! :copy_issues
1053
1053
1054 @request.session[:user_id] = 2
1054 @request.session[:user_id] = 2
1055 get :index, :project_id => 1
1055 get :index, :project_id => 1
1056 assert_select '#content a.new-issue', 0
1056 assert_select '#content a.new-issue', 0
1057 end
1057 end
1058
1058
1059 def test_index_without_project_should_include_new_issue_link
1059 def test_index_without_project_should_include_new_issue_link
1060 @request.session[:user_id] = 2
1060 @request.session[:user_id] = 2
1061 get :index
1061 get :index
1062 assert_select '#content a.new-issue[href="/issues/new"]', :text => 'New issue'
1062 assert_select '#content a.new-issue[href="/issues/new"]', :text => 'New issue'
1063 end
1063 end
1064
1064
1065 def test_index_should_not_include_new_issue_tab_when_disabled
1065 def test_index_should_not_include_new_issue_tab_when_disabled
1066 with_settings :new_item_menu_tab => '0' do
1066 with_settings :new_item_menu_tab => '0' do
1067 @request.session[:user_id] = 2
1067 @request.session[:user_id] = 2
1068 get :index, :project_id => 1
1068 get :index, :project_id => 1
1069 assert_select '#main-menu a.new-issue', 0
1069 assert_select '#main-menu a.new-issue', 0
1070 end
1070 end
1071 end
1071 end
1072
1072
1073 def test_index_should_include_new_issue_tab_when_enabled
1073 def test_index_should_include_new_issue_tab_when_enabled
1074 with_settings :new_item_menu_tab => '1' do
1074 with_settings :new_item_menu_tab => '1' do
1075 @request.session[:user_id] = 2
1075 @request.session[:user_id] = 2
1076 get :index, :project_id => 1
1076 get :index, :project_id => 1
1077 assert_select '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1077 assert_select '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]', :text => 'New issue'
1078 end
1078 end
1079 end
1079 end
1080
1080
1081 def test_new_should_have_new_issue_tab_as_current_menu_item
1081 def test_new_should_have_new_issue_tab_as_current_menu_item
1082 with_settings :new_item_menu_tab => '1' do
1082 with_settings :new_item_menu_tab => '1' do
1083 @request.session[:user_id] = 2
1083 @request.session[:user_id] = 2
1084 get :new, :project_id => 1
1084 get :new, :project_id => 1
1085 assert_select '#main-menu a.new-issue.selected'
1085 assert_select '#main-menu a.new-issue.selected'
1086 end
1086 end
1087 end
1087 end
1088
1088
1089 def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1089 def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1090 with_settings :new_item_menu_tab => '1' do
1090 with_settings :new_item_menu_tab => '1' do
1091 Project.find(1).trackers.clear
1091 Project.find(1).trackers.clear
1092
1092
1093 @request.session[:user_id] = 2
1093 @request.session[:user_id] = 2
1094 get :index, :project_id => 1
1094 get :index, :project_id => 1
1095 assert_select '#main-menu a.new-issue', 0
1095 assert_select '#main-menu a.new-issue', 0
1096 end
1096 end
1097 end
1097 end
1098
1098
1099 def test_index_should_not_include_new_issue_tab_for_users_with_copy_issues_permission_only
1099 def test_index_should_not_include_new_issue_tab_for_users_with_copy_issues_permission_only
1100 with_settings :new_item_menu_tab => '1' do
1100 with_settings :new_item_menu_tab => '1' do
1101 role = Role.find(1)
1101 role = Role.find(1)
1102 role.remove_permission! :add_issues
1102 role.remove_permission! :add_issues
1103 role.add_permission! :copy_issues
1103 role.add_permission! :copy_issues
1104
1104
1105 @request.session[:user_id] = 2
1105 @request.session[:user_id] = 2
1106 get :index, :project_id => 1
1106 get :index, :project_id => 1
1107 assert_select '#main-menu a.new-issue', 0
1107 assert_select '#main-menu a.new-issue', 0
1108 end
1108 end
1109 end
1109 end
1110
1110
1111 def test_show_by_anonymous
1111 def test_show_by_anonymous
1112 get :show, :id => 1
1112 get :show, :id => 1
1113 assert_response :success
1113 assert_response :success
1114
1114
1115 assert_select 'div.issue div.description', :text => /Unable to print recipes/
1115 assert_select 'div.issue div.description', :text => /Unable to print recipes/
1116 # anonymous role is allowed to add a note
1116 # anonymous role is allowed to add a note
1117 assert_select 'form#issue-form' do
1117 assert_select 'form#issue-form' do
1118 assert_select 'fieldset' do
1118 assert_select 'fieldset' do
1119 assert_select 'legend', :text => 'Notes'
1119 assert_select 'legend', :text => 'Notes'
1120 assert_select 'textarea[name=?]', 'issue[notes]'
1120 assert_select 'textarea[name=?]', 'issue[notes]'
1121 end
1121 end
1122 end
1122 end
1123 assert_select 'title', :text => "Bug #1: Cannot print recipes - eCookbook - Redmine"
1123 assert_select 'title', :text => "Bug #1: Cannot print recipes - eCookbook - Redmine"
1124 end
1124 end
1125
1125
1126 def test_show_by_manager
1126 def test_show_by_manager
1127 @request.session[:user_id] = 2
1127 @request.session[:user_id] = 2
1128 get :show, :id => 1
1128 get :show, :id => 1
1129
1129
1130 assert_select 'a', :text => /Quote/
1130 assert_select 'a', :text => /Quote/
1131 assert_select 'form#issue-form' do
1131 assert_select 'form#issue-form' do
1132 assert_select 'fieldset' do
1132 assert_select 'fieldset' do
1133 assert_select 'legend', :text => 'Change properties'
1133 assert_select 'legend', :text => 'Change properties'
1134 assert_select 'input[name=?]', 'issue[subject]'
1134 assert_select 'input[name=?]', 'issue[subject]'
1135 end
1135 end
1136 assert_select 'fieldset' do
1136 assert_select 'fieldset' do
1137 assert_select 'legend', :text => 'Log time'
1137 assert_select 'legend', :text => 'Log time'
1138 assert_select 'input[name=?]', 'time_entry[hours]'
1138 assert_select 'input[name=?]', 'time_entry[hours]'
1139 end
1139 end
1140 assert_select 'fieldset' do
1140 assert_select 'fieldset' do
1141 assert_select 'legend', :text => 'Notes'
1141 assert_select 'legend', :text => 'Notes'
1142 assert_select 'textarea[name=?]', 'issue[notes]'
1142 assert_select 'textarea[name=?]', 'issue[notes]'
1143 end
1143 end
1144 end
1144 end
1145 end
1145 end
1146
1146
1147 def test_show_should_display_update_form
1147 def test_show_should_display_update_form
1148 @request.session[:user_id] = 2
1148 @request.session[:user_id] = 2
1149 get :show, :id => 1
1149 get :show, :id => 1
1150 assert_response :success
1150 assert_response :success
1151
1151
1152 assert_select 'form#issue-form' do
1152 assert_select 'form#issue-form' do
1153 assert_select 'input[name=?]', 'issue[is_private]'
1153 assert_select 'input[name=?]', 'issue[is_private]'
1154 assert_select 'select[name=?]', 'issue[project_id]'
1154 assert_select 'select[name=?]', 'issue[project_id]'
1155 assert_select 'select[name=?]', 'issue[tracker_id]'
1155 assert_select 'select[name=?]', 'issue[tracker_id]'
1156 assert_select 'input[name=?]', 'issue[subject]'
1156 assert_select 'input[name=?]', 'issue[subject]'
1157 assert_select 'textarea[name=?]', 'issue[description]'
1157 assert_select 'textarea[name=?]', 'issue[description]'
1158 assert_select 'select[name=?]', 'issue[status_id]'
1158 assert_select 'select[name=?]', 'issue[status_id]'
1159 assert_select 'select[name=?]', 'issue[priority_id]'
1159 assert_select 'select[name=?]', 'issue[priority_id]'
1160 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1160 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1161 assert_select 'select[name=?]', 'issue[category_id]'
1161 assert_select 'select[name=?]', 'issue[category_id]'
1162 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1162 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1163 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1163 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1164 assert_select 'input[name=?]', 'issue[start_date]'
1164 assert_select 'input[name=?]', 'issue[start_date]'
1165 assert_select 'input[name=?]', 'issue[due_date]'
1165 assert_select 'input[name=?]', 'issue[due_date]'
1166 assert_select 'select[name=?]', 'issue[done_ratio]'
1166 assert_select 'select[name=?]', 'issue[done_ratio]'
1167 assert_select 'input[name=?]', 'issue[custom_field_values][2]'
1167 assert_select 'input[name=?]', 'issue[custom_field_values][2]'
1168 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1168 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1169 assert_select 'textarea[name=?]', 'issue[notes]'
1169 assert_select 'textarea[name=?]', 'issue[notes]'
1170 end
1170 end
1171 end
1171 end
1172
1172
1173 def test_show_should_display_update_form_with_minimal_permissions
1173 def test_show_should_display_update_form_with_minimal_permissions
1174 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
1174 Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
1175 WorkflowTransition.where(:role_id => 1).delete_all
1175 WorkflowTransition.where(:role_id => 1).delete_all
1176
1176
1177 @request.session[:user_id] = 2
1177 @request.session[:user_id] = 2
1178 get :show, :id => 1
1178 get :show, :id => 1
1179 assert_response :success
1179 assert_response :success
1180
1180
1181 assert_select 'form#issue-form' do
1181 assert_select 'form#issue-form' do
1182 assert_select 'input[name=?]', 'issue[is_private]', 0
1182 assert_select 'input[name=?]', 'issue[is_private]', 0
1183 assert_select 'select[name=?]', 'issue[project_id]', 0
1183 assert_select 'select[name=?]', 'issue[project_id]', 0
1184 assert_select 'select[name=?]', 'issue[tracker_id]', 0
1184 assert_select 'select[name=?]', 'issue[tracker_id]', 0
1185 assert_select 'input[name=?]', 'issue[subject]', 0
1185 assert_select 'input[name=?]', 'issue[subject]', 0
1186 assert_select 'textarea[name=?]', 'issue[description]', 0
1186 assert_select 'textarea[name=?]', 'issue[description]', 0
1187 assert_select 'select[name=?]', 'issue[status_id]', 0
1187 assert_select 'select[name=?]', 'issue[status_id]', 0
1188 assert_select 'select[name=?]', 'issue[priority_id]', 0
1188 assert_select 'select[name=?]', 'issue[priority_id]', 0
1189 assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
1189 assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
1190 assert_select 'select[name=?]', 'issue[category_id]', 0
1190 assert_select 'select[name=?]', 'issue[category_id]', 0
1191 assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
1191 assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
1192 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1192 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1193 assert_select 'input[name=?]', 'issue[start_date]', 0
1193 assert_select 'input[name=?]', 'issue[start_date]', 0
1194 assert_select 'input[name=?]', 'issue[due_date]', 0
1194 assert_select 'input[name=?]', 'issue[due_date]', 0
1195 assert_select 'select[name=?]', 'issue[done_ratio]', 0
1195 assert_select 'select[name=?]', 'issue[done_ratio]', 0
1196 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
1196 assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
1197 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1197 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1198 assert_select 'textarea[name=?]', 'issue[notes]'
1198 assert_select 'textarea[name=?]', 'issue[notes]'
1199 end
1199 end
1200 end
1200 end
1201
1201
1202 def test_show_should_not_display_update_form_without_permissions
1202 def test_show_should_not_display_update_form_without_permissions
1203 Role.find(1).update_attribute :permissions, [:view_issues]
1203 Role.find(1).update_attribute :permissions, [:view_issues]
1204
1204
1205 @request.session[:user_id] = 2
1205 @request.session[:user_id] = 2
1206 get :show, :id => 1
1206 get :show, :id => 1
1207 assert_response :success
1207 assert_response :success
1208
1208
1209 assert_select 'form#issue-form', 0
1209 assert_select 'form#issue-form', 0
1210 end
1210 end
1211
1211
1212 def test_update_form_should_not_display_inactive_enumerations
1212 def test_update_form_should_not_display_inactive_enumerations
1213 assert !IssuePriority.find(15).active?
1213 assert !IssuePriority.find(15).active?
1214
1214
1215 @request.session[:user_id] = 2
1215 @request.session[:user_id] = 2
1216 get :show, :id => 1
1216 get :show, :id => 1
1217 assert_response :success
1217 assert_response :success
1218
1218
1219 assert_select 'form#issue-form' do
1219 assert_select 'form#issue-form' do
1220 assert_select 'select[name=?]', 'issue[priority_id]' do
1220 assert_select 'select[name=?]', 'issue[priority_id]' do
1221 assert_select 'option[value="4"]'
1221 assert_select 'option[value="4"]'
1222 assert_select 'option[value="15"]', 0
1222 assert_select 'option[value="15"]', 0
1223 end
1223 end
1224 end
1224 end
1225 end
1225 end
1226
1226
1227 def test_update_form_should_allow_attachment_upload
1227 def test_update_form_should_allow_attachment_upload
1228 @request.session[:user_id] = 2
1228 @request.session[:user_id] = 2
1229 get :show, :id => 1
1229 get :show, :id => 1
1230
1230
1231 assert_select 'form#issue-form[method=post][enctype="multipart/form-data"]' do
1231 assert_select 'form#issue-form[method=post][enctype="multipart/form-data"]' do
1232 assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
1232 assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
1233 end
1233 end
1234 end
1234 end
1235
1235
1236 def test_show_should_deny_anonymous_access_without_permission
1236 def test_show_should_deny_anonymous_access_without_permission
1237 Role.anonymous.remove_permission!(:view_issues)
1237 Role.anonymous.remove_permission!(:view_issues)
1238 get :show, :id => 1
1238 get :show, :id => 1
1239 assert_response :redirect
1239 assert_response :redirect
1240 end
1240 end
1241
1241
1242 def test_show_should_deny_anonymous_access_to_private_issue
1242 def test_show_should_deny_anonymous_access_to_private_issue
1243 Issue.where(:id => 1).update_all(["is_private = ?", true])
1243 Issue.where(:id => 1).update_all(["is_private = ?", true])
1244 get :show, :id => 1
1244 get :show, :id => 1
1245 assert_response :redirect
1245 assert_response :redirect
1246 end
1246 end
1247
1247
1248 def test_show_should_deny_non_member_access_without_permission
1248 def test_show_should_deny_non_member_access_without_permission
1249 Role.non_member.remove_permission!(:view_issues)
1249 Role.non_member.remove_permission!(:view_issues)
1250 @request.session[:user_id] = 9
1250 @request.session[:user_id] = 9
1251 get :show, :id => 1
1251 get :show, :id => 1
1252 assert_response 403
1252 assert_response 403
1253 end
1253 end
1254
1254
1255 def test_show_should_deny_non_member_access_to_private_issue
1255 def test_show_should_deny_non_member_access_to_private_issue
1256 Issue.where(:id => 1).update_all(["is_private = ?", true])
1256 Issue.where(:id => 1).update_all(["is_private = ?", true])
1257 @request.session[:user_id] = 9
1257 @request.session[:user_id] = 9
1258 get :show, :id => 1
1258 get :show, :id => 1
1259 assert_response 403
1259 assert_response 403
1260 end
1260 end
1261
1261
1262 def test_show_should_deny_member_access_without_permission
1262 def test_show_should_deny_member_access_without_permission
1263 Role.find(1).remove_permission!(:view_issues)
1263 Role.find(1).remove_permission!(:view_issues)
1264 @request.session[:user_id] = 2
1264 @request.session[:user_id] = 2
1265 get :show, :id => 1
1265 get :show, :id => 1
1266 assert_response 403
1266 assert_response 403
1267 end
1267 end
1268
1268
1269 def test_show_should_deny_member_access_to_private_issue_without_permission
1269 def test_show_should_deny_member_access_to_private_issue_without_permission
1270 Issue.where(:id => 1).update_all(["is_private = ?", true])
1270 Issue.where(:id => 1).update_all(["is_private = ?", true])
1271 @request.session[:user_id] = 3
1271 @request.session[:user_id] = 3
1272 get :show, :id => 1
1272 get :show, :id => 1
1273 assert_response 403
1273 assert_response 403
1274 end
1274 end
1275
1275
1276 def test_show_should_allow_author_access_to_private_issue
1276 def test_show_should_allow_author_access_to_private_issue
1277 Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
1277 Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
1278 @request.session[:user_id] = 3
1278 @request.session[:user_id] = 3
1279 get :show, :id => 1
1279 get :show, :id => 1
1280 assert_response :success
1280 assert_response :success
1281 end
1281 end
1282
1282
1283 def test_show_should_allow_assignee_access_to_private_issue
1283 def test_show_should_allow_assignee_access_to_private_issue
1284 Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
1284 Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
1285 @request.session[:user_id] = 3
1285 @request.session[:user_id] = 3
1286 get :show, :id => 1
1286 get :show, :id => 1
1287 assert_response :success
1287 assert_response :success
1288 end
1288 end
1289
1289
1290 def test_show_should_allow_member_access_to_private_issue_with_permission
1290 def test_show_should_allow_member_access_to_private_issue_with_permission
1291 Issue.where(:id => 1).update_all(["is_private = ?", true])
1291 Issue.where(:id => 1).update_all(["is_private = ?", true])
1292 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
1292 User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
1293 @request.session[:user_id] = 3
1293 @request.session[:user_id] = 3
1294 get :show, :id => 1
1294 get :show, :id => 1
1295 assert_response :success
1295 assert_response :success
1296 end
1296 end
1297
1297
1298 def test_show_should_not_disclose_relations_to_invisible_issues
1298 def test_show_should_not_disclose_relations_to_invisible_issues
1299 Setting.cross_project_issue_relations = '1'
1299 Setting.cross_project_issue_relations = '1'
1300 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
1300 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
1301 # Relation to a private project issue
1301 # Relation to a private project issue
1302 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
1302 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
1303
1303
1304 get :show, :id => 1
1304 get :show, :id => 1
1305 assert_response :success
1305 assert_response :success
1306
1306
1307 assert_select 'div#relations' do
1307 assert_select 'div#relations' do
1308 assert_select 'a', :text => /#2$/
1308 assert_select 'a', :text => /#2$/
1309 assert_select 'a', :text => /#4$/, :count => 0
1309 assert_select 'a', :text => /#4$/, :count => 0
1310 end
1310 end
1311 end
1311 end
1312
1312
1313 def test_show_should_list_subtasks
1313 def test_show_should_list_subtasks
1314 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1314 Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1315
1315
1316 get :show, :id => 1
1316 get :show, :id => 1
1317 assert_response :success
1317 assert_response :success
1318
1318
1319 assert_select 'div#issue_tree' do
1319 assert_select 'div#issue_tree' do
1320 assert_select 'td.subject', :text => /Child Issue/
1320 assert_select 'td.subject', :text => /Child Issue/
1321 end
1321 end
1322 end
1322 end
1323
1323
1324 def test_show_should_list_parents
1324 def test_show_should_list_parents
1325 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1325 issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
1326
1326
1327 get :show, :id => issue.id
1327 get :show, :id => issue.id
1328 assert_response :success
1328 assert_response :success
1329
1329
1330 assert_select 'div.subject' do
1330 assert_select 'div.subject' do
1331 assert_select 'h3', 'Child Issue'
1331 assert_select 'h3', 'Child Issue'
1332 assert_select 'a[href="/issues/1"]'
1332 assert_select 'a[href="/issues/1"]'
1333 end
1333 end
1334 end
1334 end
1335
1335
1336 def test_show_should_not_display_prev_next_links_without_query_in_session
1336 def test_show_should_not_display_prev_next_links_without_query_in_session
1337 get :show, :id => 1
1337 get :show, :id => 1
1338 assert_response :success
1338 assert_response :success
1339
1339
1340 assert_select 'div.next-prev-links', 0
1340 assert_select 'div.next-prev-links', 0
1341 end
1341 end
1342
1342
1343 def test_show_should_display_prev_next_links_with_query_in_session
1343 def test_show_should_display_prev_next_links_with_query_in_session
1344 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1344 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1345 @request.session['issues_index_sort'] = 'id'
1345 @request.session['issues_index_sort'] = 'id'
1346
1346
1347 with_settings :display_subprojects_issues => '0' do
1347 with_settings :display_subprojects_issues => '0' do
1348 get :show, :id => 3
1348 get :show, :id => 3
1349 end
1349 end
1350 assert_response :success
1350 assert_response :success
1351
1351
1352 count = Issue.open.visible.count
1352 count = Issue.open.visible.count
1353
1353
1354 # Previous and next issues for all projects
1354 # Previous and next issues for all projects
1355 assert_select 'div.next-prev-links' do
1355 assert_select 'div.next-prev-links' do
1356 assert_select 'a[href="/issues/2"]', :text => /Previous/
1356 assert_select 'a[href="/issues/2"]', :text => /Previous/
1357 assert_select 'a[href="/issues/5"]', :text => /Next/
1357 assert_select 'a[href="/issues/5"]', :text => /Next/
1358 assert_select 'span.position', :text => "3 of #{count}"
1358 assert_select 'span.position', :text => "3 of #{count}"
1359 end
1359 end
1360 end
1360 end
1361
1361
1362 def test_show_should_display_prev_next_links_with_saved_query_in_session
1362 def test_show_should_display_prev_next_links_with_saved_query_in_session
1363 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1,
1363 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1,
1364 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1364 :filters => {'status_id' => {:values => ['5'], :operator => '='}},
1365 :sort_criteria => [['id', 'asc']])
1365 :sort_criteria => [['id', 'asc']])
1366 @request.session[:query] = {:id => query.id, :project_id => nil}
1366 @request.session[:query] = {:id => query.id, :project_id => nil}
1367
1367
1368 get :show, :id => 11
1368 get :show, :id => 11
1369 assert_response :success
1369 assert_response :success
1370
1370
1371 # Previous and next issues for all projects
1371 # Previous and next issues for all projects
1372 assert_select 'div.next-prev-links' do
1372 assert_select 'div.next-prev-links' do
1373 assert_select 'a[href="/issues/8"]', :text => /Previous/
1373 assert_select 'a[href="/issues/8"]', :text => /Previous/
1374 assert_select 'a[href="/issues/12"]', :text => /Next/
1374 assert_select 'a[href="/issues/12"]', :text => /Next/
1375 end
1375 end
1376 end
1376 end
1377
1377
1378 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1378 def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1379 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1379 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1380
1380
1381 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1381 %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1382 @request.session['issues_index_sort'] = assoc_sort
1382 @request.session['issues_index_sort'] = assoc_sort
1383
1383
1384 get :show, :id => 3
1384 get :show, :id => 3
1385 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1385 assert_response :success, "Wrong response status for #{assoc_sort} sort"
1386
1386
1387 assert_select 'div.next-prev-links' do
1387 assert_select 'div.next-prev-links' do
1388 assert_select 'a', :text => /(Previous|Next)/
1388 assert_select 'a', :text => /(Previous|Next)/
1389 end
1389 end
1390 end
1390 end
1391 end
1391 end
1392
1392
1393 def test_show_should_display_prev_next_links_with_project_query_in_session
1393 def test_show_should_display_prev_next_links_with_project_query_in_session
1394 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1394 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1395 @request.session['issues_index_sort'] = 'id'
1395 @request.session['issues_index_sort'] = 'id'
1396
1396
1397 with_settings :display_subprojects_issues => '0' do
1397 with_settings :display_subprojects_issues => '0' do
1398 get :show, :id => 3
1398 get :show, :id => 3
1399 end
1399 end
1400 assert_response :success
1400 assert_response :success
1401
1401
1402 # Previous and next issues inside project
1402 # Previous and next issues inside project
1403 assert_select 'div.next-prev-links' do
1403 assert_select 'div.next-prev-links' do
1404 assert_select 'a[href="/issues/2"]', :text => /Previous/
1404 assert_select 'a[href="/issues/2"]', :text => /Previous/
1405 assert_select 'a[href="/issues/7"]', :text => /Next/
1405 assert_select 'a[href="/issues/7"]', :text => /Next/
1406 end
1406 end
1407 end
1407 end
1408
1408
1409 def test_show_should_not_display_prev_link_for_first_issue
1409 def test_show_should_not_display_prev_link_for_first_issue
1410 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1410 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
1411 @request.session['issues_index_sort'] = 'id'
1411 @request.session['issues_index_sort'] = 'id'
1412
1412
1413 with_settings :display_subprojects_issues => '0' do
1413 with_settings :display_subprojects_issues => '0' do
1414 get :show, :id => 1
1414 get :show, :id => 1
1415 end
1415 end
1416 assert_response :success
1416 assert_response :success
1417
1417
1418 assert_select 'div.next-prev-links' do
1418 assert_select 'div.next-prev-links' do
1419 assert_select 'a', :text => /Previous/, :count => 0
1419 assert_select 'a', :text => /Previous/, :count => 0
1420 assert_select 'a[href="/issues/2"]', :text => /Next/
1420 assert_select 'a[href="/issues/2"]', :text => /Next/
1421 end
1421 end
1422 end
1422 end
1423
1423
1424 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1424 def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
1425 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1425 @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
1426 @request.session['issues_index_sort'] = 'id'
1426 @request.session['issues_index_sort'] = 'id'
1427
1427
1428 get :show, :id => 1
1428 get :show, :id => 1
1429 assert_response :success
1429 assert_response :success
1430
1430
1431 assert_select 'a', :text => /Previous/, :count => 0
1431 assert_select 'a', :text => /Previous/, :count => 0
1432 assert_select 'a', :text => /Next/, :count => 0
1432 assert_select 'a', :text => /Next/, :count => 0
1433 end
1433 end
1434
1434
1435 def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
1435 def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
1436 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
1436 cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
1437 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
1437 CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
1438 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
1438 CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
1439 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
1439 CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
1440 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
1440 CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
1441
1441
1442 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1, :filters => {},
1442 query = IssueQuery.create!(:name => 'test', :visibility => IssueQuery::VISIBILITY_PUBLIC, :user_id => 1, :filters => {},
1443 :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
1443 :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
1444 @request.session[:query] = {:id => query.id, :project_id => nil}
1444 @request.session[:query] = {:id => query.id, :project_id => nil}
1445
1445
1446 get :show, :id => 3
1446 get :show, :id => 3
1447 assert_response :success
1447 assert_response :success
1448
1448
1449 assert_select 'div.next-prev-links' do
1449 assert_select 'div.next-prev-links' do
1450 assert_select 'a[href="/issues/2"]', :text => /Previous/
1450 assert_select 'a[href="/issues/2"]', :text => /Previous/
1451 assert_select 'a[href="/issues/1"]', :text => /Next/
1451 assert_select 'a[href="/issues/1"]', :text => /Next/
1452 end
1452 end
1453 end
1453 end
1454
1454
1455 def test_show_should_display_prev_next_links_when_request_has_previous_and_next_issue_ids_params
1455 def test_show_should_display_prev_next_links_when_request_has_previous_and_next_issue_ids_params
1456 get :show, :id => 1, :prev_issue_id => 1, :next_issue_id => 3, :issue_position => 2, :issue_count => 4
1456 get :show, :id => 1, :prev_issue_id => 1, :next_issue_id => 3, :issue_position => 2, :issue_count => 4
1457 assert_response :success
1457 assert_response :success
1458
1458
1459 assert_select 'div.next-prev-links' do
1459 assert_select 'div.next-prev-links' do
1460 assert_select 'a[href="/issues/1"]', :text => /Previous/
1460 assert_select 'a[href="/issues/1"]', :text => /Previous/
1461 assert_select 'a[href="/issues/3"]', :text => /Next/
1461 assert_select 'a[href="/issues/3"]', :text => /Next/
1462 assert_select 'span.position', :text => "2 of 4"
1462 assert_select 'span.position', :text => "2 of 4"
1463 end
1463 end
1464 end
1464 end
1465
1465
1466 def test_show_should_display_category_field_if_categories_are_defined
1466 def test_show_should_display_category_field_if_categories_are_defined
1467 Issue.update_all :category_id => nil
1467 Issue.update_all :category_id => nil
1468
1468
1469 get :show, :id => 1
1469 get :show, :id => 1
1470 assert_response :success
1470 assert_response :success
1471 assert_select '.attributes .category'
1471 assert_select '.attributes .category'
1472 end
1472 end
1473
1473
1474 def test_show_should_not_display_category_field_if_no_categories_are_defined
1474 def test_show_should_not_display_category_field_if_no_categories_are_defined
1475 Project.find(1).issue_categories.delete_all
1475 Project.find(1).issue_categories.delete_all
1476
1476
1477 get :show, :id => 1
1477 get :show, :id => 1
1478 assert_response :success
1478 assert_response :success
1479 assert_select 'table.attributes .category', 0
1479 assert_select 'table.attributes .category', 0
1480 end
1480 end
1481
1481
1482 def test_show_should_display_link_to_the_assignee
1482 def test_show_should_display_link_to_the_assignee
1483 get :show, :id => 2
1483 get :show, :id => 2
1484 assert_response :success
1484 assert_response :success
1485 assert_select '.assigned-to' do
1485 assert_select '.assigned-to' do
1486 assert_select 'a[href="/users/3"]'
1486 assert_select 'a[href="/users/3"]'
1487 end
1487 end
1488 end
1488 end
1489
1489
1490 def test_show_should_display_visible_changesets_from_other_projects
1490 def test_show_should_display_visible_changesets_from_other_projects
1491 project = Project.find(2)
1491 project = Project.find(2)
1492 issue = project.issues.first
1492 issue = project.issues.first
1493 issue.changeset_ids = [102]
1493 issue.changeset_ids = [102]
1494 issue.save!
1494 issue.save!
1495 # changesets from other projects should be displayed even if repository
1495 # changesets from other projects should be displayed even if repository
1496 # is disabled on issue's project
1496 # is disabled on issue's project
1497 project.disable_module! :repository
1497 project.disable_module! :repository
1498
1498
1499 @request.session[:user_id] = 2
1499 @request.session[:user_id] = 2
1500 get :show, :id => issue.id
1500 get :show, :id => issue.id
1501
1501
1502 assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
1502 assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
1503 end
1503 end
1504
1504
1505 def test_show_should_display_watchers
1505 def test_show_should_display_watchers
1506 @request.session[:user_id] = 2
1506 @request.session[:user_id] = 2
1507 Issue.find(1).add_watcher User.find(2)
1507 Issue.find(1).add_watcher User.find(2)
1508
1508
1509 get :show, :id => 1
1509 get :show, :id => 1
1510 assert_select 'div#watchers ul' do
1510 assert_select 'div#watchers ul' do
1511 assert_select 'li' do
1511 assert_select 'li' do
1512 assert_select 'a[href="/users/2"]'
1512 assert_select 'a[href="/users/2"]'
1513 assert_select 'a[class*=delete]'
1513 assert_select 'a[class*=delete]'
1514 end
1514 end
1515 end
1515 end
1516 end
1516 end
1517
1517
1518 def test_show_should_display_watchers_with_gravatars
1518 def test_show_should_display_watchers_with_gravatars
1519 @request.session[:user_id] = 2
1519 @request.session[:user_id] = 2
1520 Issue.find(1).add_watcher User.find(2)
1520 Issue.find(1).add_watcher User.find(2)
1521
1521
1522 with_settings :gravatar_enabled => '1' do
1522 with_settings :gravatar_enabled => '1' do
1523 get :show, :id => 1
1523 get :show, :id => 1
1524 end
1524 end
1525
1525
1526 assert_select 'div#watchers ul' do
1526 assert_select 'div#watchers ul' do
1527 assert_select 'li' do
1527 assert_select 'li' do
1528 assert_select 'img.gravatar'
1528 assert_select 'img.gravatar'
1529 assert_select 'a[href="/users/2"]'
1529 assert_select 'a[href="/users/2"]'
1530 assert_select 'a[class*=delete]'
1530 assert_select 'a[class*=delete]'
1531 end
1531 end
1532 end
1532 end
1533 end
1533 end
1534
1534
1535 def test_show_with_thumbnails_enabled_should_display_thumbnails
1535 def test_show_with_thumbnails_enabled_should_display_thumbnails
1536 @request.session[:user_id] = 2
1536 @request.session[:user_id] = 2
1537
1537
1538 with_settings :thumbnails_enabled => '1' do
1538 with_settings :thumbnails_enabled => '1' do
1539 get :show, :id => 14
1539 get :show, :id => 14
1540 assert_response :success
1540 assert_response :success
1541 end
1541 end
1542
1542
1543 assert_select 'div.thumbnails' do
1543 assert_select 'div.thumbnails' do
1544 assert_select 'a[href="/attachments/16/testfile.png"]' do
1544 assert_select 'a[href="/attachments/16/testfile.png"]' do
1545 assert_select 'img[src="/attachments/thumbnail/16"]'
1545 assert_select 'img[src="/attachments/thumbnail/16"]'
1546 end
1546 end
1547 end
1547 end
1548 end
1548 end
1549
1549
1550 def test_show_with_thumbnails_disabled_should_not_display_thumbnails
1550 def test_show_with_thumbnails_disabled_should_not_display_thumbnails
1551 @request.session[:user_id] = 2
1551 @request.session[:user_id] = 2
1552
1552
1553 with_settings :thumbnails_enabled => '0' do
1553 with_settings :thumbnails_enabled => '0' do
1554 get :show, :id => 14
1554 get :show, :id => 14
1555 assert_response :success
1555 assert_response :success
1556 end
1556 end
1557
1557
1558 assert_select 'div.thumbnails', 0
1558 assert_select 'div.thumbnails', 0
1559 end
1559 end
1560
1560
1561 def test_show_with_multi_custom_field
1561 def test_show_with_multi_custom_field
1562 field = CustomField.find(1)
1562 field = CustomField.find(1)
1563 field.update_attribute :multiple, true
1563 field.update_attribute :multiple, true
1564 issue = Issue.find(1)
1564 issue = Issue.find(1)
1565 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1565 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
1566 issue.save!
1566 issue.save!
1567
1567
1568 get :show, :id => 1
1568 get :show, :id => 1
1569 assert_response :success
1569 assert_response :success
1570
1570
1571 assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
1571 assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
1572 end
1572 end
1573
1573
1574 def test_show_with_multi_user_custom_field
1574 def test_show_with_multi_user_custom_field
1575 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1575 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1576 :tracker_ids => [1], :is_for_all => true)
1576 :tracker_ids => [1], :is_for_all => true)
1577 issue = Issue.find(1)
1577 issue = Issue.find(1)
1578 issue.custom_field_values = {field.id => ['2', '3']}
1578 issue.custom_field_values = {field.id => ['2', '3']}
1579 issue.save!
1579 issue.save!
1580
1580
1581 get :show, :id => 1
1581 get :show, :id => 1
1582 assert_response :success
1582 assert_response :success
1583
1583
1584 assert_select ".cf_#{field.id} .value", :text => 'Dave Lopper, John Smith' do
1584 assert_select ".cf_#{field.id} .value", :text => 'Dave Lopper, John Smith' do
1585 assert_select 'a', :text => 'Dave Lopper'
1585 assert_select 'a', :text => 'Dave Lopper'
1586 assert_select 'a', :text => 'John Smith'
1586 assert_select 'a', :text => 'John Smith'
1587 end
1587 end
1588 end
1588 end
1589
1589
1590 def test_show_should_display_private_notes_with_permission_only
1590 def test_show_should_display_private_notes_with_permission_only
1591 journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
1591 journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
1592 @request.session[:user_id] = 2
1592 @request.session[:user_id] = 2
1593
1593
1594 get :show, :id => 2
1594 get :show, :id => 2
1595 assert_response :success
1595 assert_response :success
1596 assert_select "#change-#{journal.id}", 1
1596 assert_select "#change-#{journal.id}", 1
1597
1597
1598 Role.find(1).remove_permission! :view_private_notes
1598 Role.find(1).remove_permission! :view_private_notes
1599 get :show, :id => 2
1599 get :show, :id => 2
1600 assert_response :success
1600 assert_response :success
1601 assert_select "#change-#{journal.id}", 0
1601 assert_select "#change-#{journal.id}", 0
1602 end
1602 end
1603
1603
1604 def test_show_atom
1604 def test_show_atom
1605 get :show, :id => 2, :format => 'atom'
1605 get :show, :id => 2, :format => 'atom'
1606 assert_response :success
1606 assert_response :success
1607 assert_equal 'application/atom+xml', response.content_type
1607 assert_equal 'application/atom+xml', response.content_type
1608 # Inline image
1608 # Inline image
1609 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1609 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
1610 end
1610 end
1611
1611
1612 def test_show_export_to_pdf
1612 def test_show_export_to_pdf
1613 issue = Issue.find(3)
1613 issue = Issue.find(3)
1614 assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1614 assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1615 get :show, :id => 3, :format => 'pdf'
1615 get :show, :id => 3, :format => 'pdf'
1616 assert_response :success
1616 assert_response :success
1617 assert_equal 'application/pdf', @response.content_type
1617 assert_equal 'application/pdf', @response.content_type
1618 assert @response.body.starts_with?('%PDF')
1618 assert @response.body.starts_with?('%PDF')
1619 end
1619 end
1620
1620
1621 def test_export_to_pdf_with_utf8_u_fffd
1621 def test_export_to_pdf_with_utf8_u_fffd
1622 # U+FFFD
1622 # U+FFFD
1623 s = "\xef\xbf\xbd"
1623 s = "\xef\xbf\xbd"
1624 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
1624 s.force_encoding('UTF-8') if s.respond_to?(:force_encoding)
1625 issue = Issue.generate!(:subject => s)
1625 issue = Issue.generate!(:subject => s)
1626 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
1626 ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
1627 with_settings :default_language => lang do
1627 with_settings :default_language => lang do
1628 get :show, :id => issue.id, :format => 'pdf'
1628 get :show, :id => issue.id, :format => 'pdf'
1629 assert_response :success
1629 assert_response :success
1630 assert_equal 'application/pdf', @response.content_type
1630 assert_equal 'application/pdf', @response.content_type
1631 assert @response.body.starts_with?('%PDF')
1631 assert @response.body.starts_with?('%PDF')
1632 end
1632 end
1633 end
1633 end
1634 end
1634 end
1635
1635
1636 def test_show_export_to_pdf_with_ancestors
1636 def test_show_export_to_pdf_with_ancestors
1637 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1637 issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1638
1638
1639 get :show, :id => issue.id, :format => 'pdf'
1639 get :show, :id => issue.id, :format => 'pdf'
1640 assert_response :success
1640 assert_response :success
1641 assert_equal 'application/pdf', @response.content_type
1641 assert_equal 'application/pdf', @response.content_type
1642 assert @response.body.starts_with?('%PDF')
1642 assert @response.body.starts_with?('%PDF')
1643 end
1643 end
1644
1644
1645 def test_show_export_to_pdf_with_descendants
1645 def test_show_export_to_pdf_with_descendants
1646 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1646 c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1647 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1647 c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
1648 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1648 c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
1649
1649
1650 get :show, :id => 1, :format => 'pdf'
1650 get :show, :id => 1, :format => 'pdf'
1651 assert_response :success
1651 assert_response :success
1652 assert_equal 'application/pdf', @response.content_type
1652 assert_equal 'application/pdf', @response.content_type
1653 assert @response.body.starts_with?('%PDF')
1653 assert @response.body.starts_with?('%PDF')
1654 end
1654 end
1655
1655
1656 def test_show_export_to_pdf_with_journals
1656 def test_show_export_to_pdf_with_journals
1657 get :show, :id => 1, :format => 'pdf'
1657 get :show, :id => 1, :format => 'pdf'
1658 assert_response :success
1658 assert_response :success
1659 assert_equal 'application/pdf', @response.content_type
1659 assert_equal 'application/pdf', @response.content_type
1660 assert @response.body.starts_with?('%PDF')
1660 assert @response.body.starts_with?('%PDF')
1661 end
1661 end
1662
1662
1663 def test_show_export_to_pdf_with_changesets
1663 def test_show_export_to_pdf_with_changesets
1664 [[100], [100, 101], [100, 101, 102]].each do |cs|
1664 [[100], [100, 101], [100, 101, 102]].each do |cs|
1665 issue1 = Issue.find(3)
1665 issue1 = Issue.find(3)
1666 issue1.changesets = Changeset.find(cs)
1666 issue1.changesets = Changeset.find(cs)
1667 issue1.save!
1667 issue1.save!
1668 issue = Issue.find(3)
1668 issue = Issue.find(3)
1669 assert_equal issue.changesets.count, cs.size
1669 assert_equal issue.changesets.count, cs.size
1670 get :show, :id => 3, :format => 'pdf'
1670 get :show, :id => 3, :format => 'pdf'
1671 assert_response :success
1671 assert_response :success
1672 assert_equal 'application/pdf', @response.content_type
1672 assert_equal 'application/pdf', @response.content_type
1673 assert @response.body.starts_with?('%PDF')
1673 assert @response.body.starts_with?('%PDF')
1674 end
1674 end
1675 end
1675 end
1676
1676
1677 def test_show_invalid_should_respond_with_404
1677 def test_show_invalid_should_respond_with_404
1678 get :show, :id => 999
1678 get :show, :id => 999
1679 assert_response 404
1679 assert_response 404
1680 end
1680 end
1681
1681
1682 def test_get_new
1682 def test_get_new
1683 @request.session[:user_id] = 2
1683 @request.session[:user_id] = 2
1684 get :new, :project_id => 1, :tracker_id => 1
1684 get :new, :project_id => 1, :tracker_id => 1
1685 assert_response :success
1685 assert_response :success
1686
1686
1687 assert_select 'form#issue-form[action=?]', '/projects/ecookbook/issues'
1687 assert_select 'form#issue-form[action=?]', '/projects/ecookbook/issues'
1688 assert_select 'form#issue-form' do
1688 assert_select 'form#issue-form' do
1689 assert_select 'input[name=?]', 'issue[is_private]'
1689 assert_select 'input[name=?]', 'issue[is_private]'
1690 assert_select 'select[name=?]', 'issue[project_id]', 0
1690 assert_select 'select[name=?]', 'issue[project_id]', 0
1691 assert_select 'select[name=?]', 'issue[tracker_id]'
1691 assert_select 'select[name=?]', 'issue[tracker_id]'
1692 assert_select 'input[name=?]', 'issue[subject]'
1692 assert_select 'input[name=?]', 'issue[subject]'
1693 assert_select 'textarea[name=?]', 'issue[description]'
1693 assert_select 'textarea[name=?]', 'issue[description]'
1694 assert_select 'select[name=?]', 'issue[status_id]'
1694 assert_select 'select[name=?]', 'issue[status_id]'
1695 assert_select 'select[name=?]', 'issue[priority_id]'
1695 assert_select 'select[name=?]', 'issue[priority_id]'
1696 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1696 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1697 assert_select 'select[name=?]', 'issue[category_id]'
1697 assert_select 'select[name=?]', 'issue[category_id]'
1698 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1698 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1699 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1699 assert_select 'input[name=?]', 'issue[parent_issue_id]'
1700 assert_select 'input[name=?]', 'issue[start_date]'
1700 assert_select 'input[name=?]', 'issue[start_date]'
1701 assert_select 'input[name=?]', 'issue[due_date]'
1701 assert_select 'input[name=?]', 'issue[due_date]'
1702 assert_select 'select[name=?]', 'issue[done_ratio]'
1702 assert_select 'select[name=?]', 'issue[done_ratio]'
1703 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1703 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1704 assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
1704 assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
1705 end
1705 end
1706
1706
1707 # Be sure we don't display inactive IssuePriorities
1707 # Be sure we don't display inactive IssuePriorities
1708 assert ! IssuePriority.find(15).active?
1708 assert ! IssuePriority.find(15).active?
1709 assert_select 'select[name=?]', 'issue[priority_id]' do
1709 assert_select 'select[name=?]', 'issue[priority_id]' do
1710 assert_select 'option[value="15"]', 0
1710 assert_select 'option[value="15"]', 0
1711 end
1711 end
1712 end
1712 end
1713
1713
1714 def test_get_new_with_minimal_permissions
1714 def test_get_new_with_minimal_permissions
1715 Role.find(1).update_attribute :permissions, [:add_issues]
1715 Role.find(1).update_attribute :permissions, [:add_issues]
1716 WorkflowTransition.where(:role_id => 1).delete_all
1716 WorkflowTransition.where(:role_id => 1).delete_all
1717
1717
1718 @request.session[:user_id] = 2
1718 @request.session[:user_id] = 2
1719 get :new, :project_id => 1, :tracker_id => 1
1719 get :new, :project_id => 1, :tracker_id => 1
1720 assert_response :success
1720 assert_response :success
1721
1721
1722 assert_select 'form#issue-form' do
1722 assert_select 'form#issue-form' do
1723 assert_select 'input[name=?]', 'issue[is_private]', 0
1723 assert_select 'input[name=?]', 'issue[is_private]', 0
1724 assert_select 'select[name=?]', 'issue[project_id]', 0
1724 assert_select 'select[name=?]', 'issue[project_id]', 0
1725 assert_select 'select[name=?]', 'issue[tracker_id]'
1725 assert_select 'select[name=?]', 'issue[tracker_id]'
1726 assert_select 'input[name=?]', 'issue[subject]'
1726 assert_select 'input[name=?]', 'issue[subject]'
1727 assert_select 'textarea[name=?]', 'issue[description]'
1727 assert_select 'textarea[name=?]', 'issue[description]'
1728 assert_select 'select[name=?]', 'issue[status_id]'
1728 assert_select 'select[name=?]', 'issue[status_id]'
1729 assert_select 'select[name=?]', 'issue[priority_id]'
1729 assert_select 'select[name=?]', 'issue[priority_id]'
1730 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1730 assert_select 'select[name=?]', 'issue[assigned_to_id]'
1731 assert_select 'select[name=?]', 'issue[category_id]'
1731 assert_select 'select[name=?]', 'issue[category_id]'
1732 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1732 assert_select 'select[name=?]', 'issue[fixed_version_id]'
1733 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1733 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
1734 assert_select 'input[name=?]', 'issue[start_date]'
1734 assert_select 'input[name=?]', 'issue[start_date]'
1735 assert_select 'input[name=?]', 'issue[due_date]'
1735 assert_select 'input[name=?]', 'issue[due_date]'
1736 assert_select 'select[name=?]', 'issue[done_ratio]'
1736 assert_select 'select[name=?]', 'issue[done_ratio]'
1737 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1737 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
1738 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1738 assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
1739 end
1739 end
1740 end
1740 end
1741
1741
1742 def test_new_without_project_id
1742 def test_new_without_project_id
1743 @request.session[:user_id] = 2
1743 @request.session[:user_id] = 2
1744 get :new
1744 get :new
1745 assert_response :success
1745 assert_response :success
1746
1746
1747 assert_select 'form#issue-form[action=?]', '/issues'
1747 assert_select 'form#issue-form[action=?]', '/issues'
1748 assert_select 'form#issue-form' do
1748 assert_select 'form#issue-form' do
1749 assert_select 'select[name=?]', 'issue[project_id]'
1749 assert_select 'select[name=?]', 'issue[project_id]'
1750 end
1750 end
1751 end
1751 end
1752
1752
1753 def test_new_should_select_default_status
1753 def test_new_should_select_default_status
1754 @request.session[:user_id] = 2
1754 @request.session[:user_id] = 2
1755
1755
1756 get :new, :project_id => 1
1756 get :new, :project_id => 1
1757 assert_response :success
1757 assert_response :success
1758 assert_select 'select[name=?]', 'issue[status_id]' do
1758 assert_select 'select[name=?]', 'issue[status_id]' do
1759 assert_select 'option[value="1"][selected=selected]'
1759 assert_select 'option[value="1"][selected=selected]'
1760 end
1760 end
1761 assert_select 'input[name=was_default_status][value="1"]'
1761 assert_select 'input[name=was_default_status][value="1"]'
1762 end
1762 end
1763
1763
1764 def test_new_should_propose_allowed_statuses
1764 def test_new_should_propose_allowed_statuses
1765 WorkflowTransition.delete_all
1765 WorkflowTransition.delete_all
1766 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 1)
1766 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 1)
1767 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 3)
1767 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 3)
1768 @request.session[:user_id] = 2
1768 @request.session[:user_id] = 2
1769
1769
1770 get :new, :project_id => 1
1770 get :new, :project_id => 1
1771 assert_response :success
1771 assert_response :success
1772 assert_select 'select[name=?]', 'issue[status_id]' do
1772 assert_select 'select[name=?]', 'issue[status_id]' do
1773 assert_select 'option[value="1"]'
1773 assert_select 'option[value="1"]'
1774 assert_select 'option[value="3"]'
1774 assert_select 'option[value="3"]'
1775 assert_select 'option', 2
1775 assert_select 'option', 2
1776 assert_select 'option[value="1"][selected=selected]'
1776 assert_select 'option[value="1"][selected=selected]'
1777 end
1777 end
1778 end
1778 end
1779
1779
1780 def test_new_should_propose_allowed_statuses_without_default_status_allowed
1780 def test_new_should_propose_allowed_statuses_without_default_status_allowed
1781 WorkflowTransition.delete_all
1781 WorkflowTransition.delete_all
1782 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 2)
1782 WorkflowTransition.create!(:tracker_id => 1, :role_id => 1, :old_status_id => 0, :new_status_id => 2)
1783 assert_equal 1, Tracker.find(1).default_status_id
1783 assert_equal 1, Tracker.find(1).default_status_id
1784 @request.session[:user_id] = 2
1784 @request.session[:user_id] = 2
1785
1785
1786 get :new, :project_id => 1
1786 get :new, :project_id => 1
1787 assert_response :success
1787 assert_response :success
1788 assert_select 'select[name=?]', 'issue[status_id]' do
1788 assert_select 'select[name=?]', 'issue[status_id]' do
1789 assert_select 'option[value="2"]'
1789 assert_select 'option[value="2"]'
1790 assert_select 'option', 1
1790 assert_select 'option', 1
1791 assert_select 'option[value="2"][selected=selected]'
1791 assert_select 'option[value="2"][selected=selected]'
1792 end
1792 end
1793 end
1793 end
1794
1794
1795 def test_new_should_propose_allowed_trackers
1795 def test_new_should_propose_allowed_trackers
1796 role = Role.find(1)
1796 role = Role.find(1)
1797 role.set_permission_trackers 'add_issues', [1, 3]
1797 role.set_permission_trackers 'add_issues', [1, 3]
1798 role.save!
1798 role.save!
1799 @request.session[:user_id] = 2
1799 @request.session[:user_id] = 2
1800
1800
1801 get :new, :project_id => 1
1801 get :new, :project_id => 1
1802 assert_response :success
1802 assert_response :success
1803 assert_select 'select[name=?]', 'issue[tracker_id]' do
1803 assert_select 'select[name=?]', 'issue[tracker_id]' do
1804 assert_select 'option', 2
1804 assert_select 'option', 2
1805 assert_select 'option[value="1"]'
1805 assert_select 'option[value="1"]'
1806 assert_select 'option[value="3"]'
1806 assert_select 'option[value="3"]'
1807 end
1807 end
1808 end
1808 end
1809
1809
1810 def test_new_without_allowed_trackers_should_respond_with_403
1810 def test_new_without_allowed_trackers_should_respond_with_403
1811 role = Role.find(1)
1811 role = Role.find(1)
1812 role.set_permission_trackers 'add_issues', []
1812 role.set_permission_trackers 'add_issues', []
1813 role.save!
1813 role.save!
1814 @request.session[:user_id] = 2
1814 @request.session[:user_id] = 2
1815
1815
1816 get :new, :project_id => 1
1816 get :new, :project_id => 1
1817 assert_response 403
1817 assert_response 403
1818 end
1818 end
1819
1819
1820 def test_new_without_projects_should_respond_with_403
1820 def test_new_without_projects_should_respond_with_403
1821 Project.delete_all
1821 Project.delete_all
1822 @request.session[:user_id] = 2
1822 @request.session[:user_id] = 2
1823
1823
1824 get :new
1824 get :new
1825 assert_response 403
1825 assert_response 403
1826 assert_select_error /no projects/
1826 assert_select_error /no projects/
1827 end
1827 end
1828
1828
1829 def test_new_without_enabled_trackers_on_projects_should_respond_with_403
1829 def test_new_without_enabled_trackers_on_projects_should_respond_with_403
1830 Project.all.each {|p| p.trackers.clear }
1830 Project.all.each {|p| p.trackers.clear }
1831 @request.session[:user_id] = 2
1831 @request.session[:user_id] = 2
1832
1832
1833 get :new
1833 get :new
1834 assert_response 403
1834 assert_response 403
1835 assert_select_error /no projects/
1835 assert_select_error /no projects/
1836 end
1836 end
1837
1837
1838 def test_new_should_preselect_default_version
1838 def test_new_should_preselect_default_version
1839 version = Version.generate!(:project_id => 1)
1839 version = Version.generate!(:project_id => 1)
1840 Project.find(1).update_attribute :default_version_id, version.id
1840 Project.find(1).update_attribute :default_version_id, version.id
1841 @request.session[:user_id] = 2
1841 @request.session[:user_id] = 2
1842
1842
1843 get :new, :project_id => 1
1843 get :new, :project_id => 1
1844 assert_response :success
1844 assert_response :success
1845 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
1845 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
1846 assert_select 'option[value=?][selected=selected]', version.id.to_s
1846 assert_select 'option[value=?][selected=selected]', version.id.to_s
1847 end
1847 end
1848 end
1848 end
1849
1849
1850 def test_get_new_with_list_custom_field
1850 def test_get_new_with_list_custom_field
1851 @request.session[:user_id] = 2
1851 @request.session[:user_id] = 2
1852 get :new, :project_id => 1, :tracker_id => 1
1852 get :new, :project_id => 1, :tracker_id => 1
1853 assert_response :success
1853 assert_response :success
1854
1854
1855 assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
1855 assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
1856 assert_select 'option', 4
1856 assert_select 'option', 4
1857 assert_select 'option[value=MySQL]', :text => 'MySQL'
1857 assert_select 'option[value=MySQL]', :text => 'MySQL'
1858 end
1858 end
1859 end
1859 end
1860
1860
1861 def test_get_new_with_multi_custom_field
1861 def test_get_new_with_multi_custom_field
1862 field = IssueCustomField.find(1)
1862 field = IssueCustomField.find(1)
1863 field.update_attribute :multiple, true
1863 field.update_attribute :multiple, true
1864
1864
1865 @request.session[:user_id] = 2
1865 @request.session[:user_id] = 2
1866 get :new, :project_id => 1, :tracker_id => 1
1866 get :new, :project_id => 1, :tracker_id => 1
1867 assert_response :success
1867 assert_response :success
1868
1868
1869 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
1869 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
1870 assert_select 'option', 3
1870 assert_select 'option', 3
1871 assert_select 'option[value=MySQL]', :text => 'MySQL'
1871 assert_select 'option[value=MySQL]', :text => 'MySQL'
1872 end
1872 end
1873 assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
1873 assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
1874 end
1874 end
1875
1875
1876 def test_get_new_with_multi_user_custom_field
1876 def test_get_new_with_multi_user_custom_field
1877 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1877 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1878 :tracker_ids => [1], :is_for_all => true)
1878 :tracker_ids => [1], :is_for_all => true)
1879
1879
1880 @request.session[:user_id] = 2
1880 @request.session[:user_id] = 2
1881 get :new, :project_id => 1, :tracker_id => 1
1881 get :new, :project_id => 1, :tracker_id => 1
1882 assert_response :success
1882 assert_response :success
1883
1883
1884 assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
1884 assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
1885 assert_select 'option', Project.find(1).users.count
1885 assert_select 'option', Project.find(1).users.count
1886 assert_select 'option[value="2"]', :text => 'John Smith'
1886 assert_select 'option[value="2"]', :text => 'John Smith'
1887 end
1887 end
1888 assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
1888 assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
1889 end
1889 end
1890
1890
1891 def test_get_new_with_date_custom_field
1891 def test_get_new_with_date_custom_field
1892 field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
1892 field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
1893
1893
1894 @request.session[:user_id] = 2
1894 @request.session[:user_id] = 2
1895 get :new, :project_id => 1, :tracker_id => 1
1895 get :new, :project_id => 1, :tracker_id => 1
1896 assert_response :success
1896 assert_response :success
1897
1897
1898 assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
1898 assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
1899 end
1899 end
1900
1900
1901 def test_get_new_with_text_custom_field
1901 def test_get_new_with_text_custom_field
1902 field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
1902 field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
1903
1903
1904 @request.session[:user_id] = 2
1904 @request.session[:user_id] = 2
1905 get :new, :project_id => 1, :tracker_id => 1
1905 get :new, :project_id => 1, :tracker_id => 1
1906 assert_response :success
1906 assert_response :success
1907
1907
1908 assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
1908 assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
1909 end
1909 end
1910
1910
1911 def test_get_new_without_default_start_date_is_creation_date
1911 def test_get_new_without_default_start_date_is_creation_date
1912 with_settings :default_issue_start_date_to_creation_date => 0 do
1912 with_settings :default_issue_start_date_to_creation_date => 0 do
1913 @request.session[:user_id] = 2
1913 @request.session[:user_id] = 2
1914 get :new, :project_id => 1, :tracker_id => 1
1914 get :new, :project_id => 1, :tracker_id => 1
1915 assert_response :success
1915 assert_response :success
1916 assert_select 'input[name=?]', 'issue[start_date]'
1916 assert_select 'input[name=?]', 'issue[start_date]'
1917 assert_select 'input[name=?][value]', 'issue[start_date]', 0
1917 assert_select 'input[name=?][value]', 'issue[start_date]', 0
1918 end
1918 end
1919 end
1919 end
1920
1920
1921 def test_get_new_with_default_start_date_is_creation_date
1921 def test_get_new_with_default_start_date_is_creation_date
1922 with_settings :default_issue_start_date_to_creation_date => 1 do
1922 with_settings :default_issue_start_date_to_creation_date => 1 do
1923 @request.session[:user_id] = 2
1923 @request.session[:user_id] = 2
1924 get :new, :project_id => 1, :tracker_id => 1
1924 get :new, :project_id => 1, :tracker_id => 1
1925 assert_response :success
1925 assert_response :success
1926 assert_select 'input[name=?][value=?]', 'issue[start_date]',
1926 assert_select 'input[name=?][value=?]', 'issue[start_date]',
1927 Date.today.to_s
1927 Date.today.to_s
1928 end
1928 end
1929 end
1929 end
1930
1930
1931 def test_get_new_form_should_allow_attachment_upload
1931 def test_get_new_form_should_allow_attachment_upload
1932 @request.session[:user_id] = 2
1932 @request.session[:user_id] = 2
1933 get :new, :project_id => 1, :tracker_id => 1
1933 get :new, :project_id => 1, :tracker_id => 1
1934 assert_response :success
1934 assert_response :success
1935
1935
1936 assert_select 'form[id=issue-form][method=post][enctype="multipart/form-data"]' do
1936 assert_select 'form[id=issue-form][method=post][enctype="multipart/form-data"]' do
1937 assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
1937 assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
1938 end
1938 end
1939 end
1939 end
1940
1940
1941 def test_get_new_should_prefill_the_form_from_params
1941 def test_get_new_should_prefill_the_form_from_params
1942 @request.session[:user_id] = 2
1942 @request.session[:user_id] = 2
1943 get :new, :project_id => 1,
1943 get :new, :project_id => 1,
1944 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
1944 :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
1945
1945
1946 assert_select 'select[name=?]', 'issue[tracker_id]' do
1946 assert_select 'select[name=?]', 'issue[tracker_id]' do
1947 assert_select 'option[value="3"][selected=selected]'
1947 assert_select 'option[value="3"][selected=selected]'
1948 end
1948 end
1949 assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
1949 assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
1950 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
1950 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
1951 end
1951 end
1952
1952
1953 def test_get_new_should_mark_required_fields
1953 def test_get_new_should_mark_required_fields
1954 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1954 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1955 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1955 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1956 WorkflowPermission.delete_all
1956 WorkflowPermission.delete_all
1957 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1957 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
1958 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1958 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
1959 @request.session[:user_id] = 2
1959 @request.session[:user_id] = 2
1960
1960
1961 get :new, :project_id => 1
1961 get :new, :project_id => 1
1962 assert_response :success
1962 assert_response :success
1963
1963
1964 assert_select 'label[for=issue_start_date]' do
1964 assert_select 'label[for=issue_start_date]' do
1965 assert_select 'span[class=required]', 0
1965 assert_select 'span[class=required]', 0
1966 end
1966 end
1967 assert_select 'label[for=issue_due_date]' do
1967 assert_select 'label[for=issue_due_date]' do
1968 assert_select 'span[class=required]'
1968 assert_select 'span[class=required]'
1969 end
1969 end
1970 assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
1970 assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
1971 assert_select 'span[class=required]', 0
1971 assert_select 'span[class=required]', 0
1972 end
1972 end
1973 assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
1973 assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
1974 assert_select 'span[class=required]'
1974 assert_select 'span[class=required]'
1975 end
1975 end
1976 end
1976 end
1977
1977
1978 def test_get_new_should_not_display_readonly_fields
1978 def test_get_new_should_not_display_readonly_fields
1979 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1979 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1980 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1980 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
1981 WorkflowPermission.delete_all
1981 WorkflowPermission.delete_all
1982 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1982 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
1983 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1983 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
1984 @request.session[:user_id] = 2
1984 @request.session[:user_id] = 2
1985
1985
1986 get :new, :project_id => 1
1986 get :new, :project_id => 1
1987 assert_response :success
1987 assert_response :success
1988
1988
1989 assert_select 'input[name=?]', 'issue[start_date]'
1989 assert_select 'input[name=?]', 'issue[start_date]'
1990 assert_select 'input[name=?]', 'issue[due_date]', 0
1990 assert_select 'input[name=?]', 'issue[due_date]', 0
1991 assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
1991 assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
1992 assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
1992 assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
1993 end
1993 end
1994
1994
1995 def test_new_with_tracker_set_as_readonly_should_accept_status
1995 def test_new_with_tracker_set_as_readonly_should_accept_status
1996 WorkflowPermission.delete_all
1996 WorkflowPermission.delete_all
1997 [1, 2].each do |status_id|
1997 [1, 2].each do |status_id|
1998 WorkflowPermission.create!(:tracker_id => 1, :old_status_id => status_id, :role_id => 1, :field_name => 'tracker_id', :rule => 'readonly')
1998 WorkflowPermission.create!(:tracker_id => 1, :old_status_id => status_id, :role_id => 1, :field_name => 'tracker_id', :rule => 'readonly')
1999 end
1999 end
2000 @request.session[:user_id] = 2
2000 @request.session[:user_id] = 2
2001
2001
2002 get :new, :project_id => 1, :issue => {:status_id => 2}
2002 get :new, :project_id => 1, :issue => {:status_id => 2}
2003 assert_select 'select[name=?]', 'issue[tracker_id]', 0
2003 assert_select 'select[name=?]', 'issue[tracker_id]', 0
2004 assert_select 'select[name=?]', 'issue[status_id]' do
2004 assert_select 'select[name=?]', 'issue[status_id]' do
2005 assert_select 'option[value=?][selected=selected]', '2'
2005 assert_select 'option[value=?][selected=selected]', '2'
2006 end
2006 end
2007 end
2007 end
2008
2008
2009 def test_get_new_without_tracker_id
2009 def test_get_new_without_tracker_id
2010 @request.session[:user_id] = 2
2010 @request.session[:user_id] = 2
2011 get :new, :project_id => 1
2011 get :new, :project_id => 1
2012 assert_response :success
2012 assert_response :success
2013
2013
2014 assert_select 'select[name=?]', 'issue[tracker_id]' do
2014 assert_select 'select[name=?]', 'issue[tracker_id]' do
2015 assert_select 'option[value=?][selected=selected]', Project.find(1).trackers.first.id.to_s
2015 assert_select 'option[value=?][selected=selected]', Project.find(1).trackers.first.id.to_s
2016 end
2016 end
2017 end
2017 end
2018
2018
2019 def test_get_new_with_no_default_status_should_display_an_error
2019 def test_get_new_with_no_default_status_should_display_an_error
2020 @request.session[:user_id] = 2
2020 @request.session[:user_id] = 2
2021 IssueStatus.delete_all
2021 IssueStatus.delete_all
2022
2022
2023 get :new, :project_id => 1
2023 get :new, :project_id => 1
2024 assert_response 500
2024 assert_response 500
2025 assert_select_error /No default issue/
2025 assert_select_error /No default issue/
2026 end
2026 end
2027
2027
2028 def test_get_new_with_no_tracker_should_display_an_error
2028 def test_get_new_with_no_tracker_should_display_an_error
2029 @request.session[:user_id] = 2
2029 @request.session[:user_id] = 2
2030 Tracker.delete_all
2030 Tracker.delete_all
2031
2031
2032 get :new, :project_id => 1
2032 get :new, :project_id => 1
2033 assert_response 500
2033 assert_response 500
2034 assert_select_error /No tracker/
2034 assert_select_error /No tracker/
2035 end
2035 end
2036
2036
2037 def test_new_with_invalid_project_id
2037 def test_new_with_invalid_project_id
2038 @request.session[:user_id] = 1
2038 @request.session[:user_id] = 1
2039 get :new, :project_id => 'invalid'
2039 get :new, :project_id => 'invalid'
2040 assert_response 404
2040 assert_response 404
2041 end
2041 end
2042
2042
2043 def test_new_with_parent_id_should_only_propose_valid_trackers
2043 def test_new_with_parent_id_should_only_propose_valid_trackers
2044 @request.session[:user_id] = 2
2044 @request.session[:user_id] = 2
2045 t = Tracker.find(3)
2045 t = Tracker.find(3)
2046 assert !t.disabled_core_fields.include?('parent_issue_id')
2046 assert !t.disabled_core_fields.include?('parent_issue_id')
2047
2047
2048 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2048 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2049 assert_response :success
2049 assert_response :success
2050 assert_select 'option', text: /#{t.name}/, count: 1
2050 assert_select 'option', text: /#{t.name}/, count: 1
2051
2051
2052 t.core_fields = Tracker::CORE_FIELDS - ['parent_issue_id']
2052 t.core_fields = Tracker::CORE_FIELDS - ['parent_issue_id']
2053 t.save!
2053 t.save!
2054 assert t.disabled_core_fields.include?('parent_issue_id')
2054 assert t.disabled_core_fields.include?('parent_issue_id')
2055 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2055 get :new, :project_id => 1, issue: { parent_issue_id: 1 }
2056 assert_response :success
2056 assert_response :success
2057 assert_select 'option', text: /#{t.name}/, count: 0
2057 assert_select 'option', text: /#{t.name}/, count: 0
2058 end
2058 end
2059
2059
2060 def test_update_form_for_new_issue
2060 def test_update_form_for_new_issue
2061 @request.session[:user_id] = 2
2061 @request.session[:user_id] = 2
2062 xhr :post, :new, :project_id => 1,
2062 xhr :post, :new, :project_id => 1,
2063 :issue => {:tracker_id => 2,
2063 :issue => {:tracker_id => 2,
2064 :subject => 'This is the test_new issue',
2064 :subject => 'This is the test_new issue',
2065 :description => 'This is the description',
2065 :description => 'This is the description',
2066 :priority_id => 5}
2066 :priority_id => 5}
2067 assert_response :success
2067 assert_response :success
2068 assert_equal 'text/javascript', response.content_type
2068 assert_equal 'text/javascript', response.content_type
2069 assert_include 'This is the test_new issue', response.body
2069 assert_include 'This is the test_new issue', response.body
2070 end
2070 end
2071
2071
2072 def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
2072 def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
2073 @request.session[:user_id] = 2
2073 @request.session[:user_id] = 2
2074 WorkflowTransition.delete_all
2074 WorkflowTransition.delete_all
2075 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2)
2075 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 2)
2076 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 5)
2076 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 0, :new_status_id => 5)
2077 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
2077 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
2078
2078
2079 post :new, :project_id => 1,
2079 post :new, :project_id => 1,
2080 :issue => {:tracker_id => 1,
2080 :issue => {:tracker_id => 1,
2081 :status_id => 5,
2081 :status_id => 5,
2082 :subject => 'This is an issue'}
2082 :subject => 'This is an issue'}
2083
2083
2084 assert_select 'select[name=?]', 'issue[status_id]' do
2084 assert_select 'select[name=?]', 'issue[status_id]' do
2085 assert_select 'option[value=?][selected=selected]', '5'
2085 assert_select 'option[value=?][selected=selected]', '5'
2086 assert_select 'option[value=?]', '2'
2086 assert_select 'option[value=?]', '2'
2087 assert_select 'option', :count => 2
2087 assert_select 'option', :count => 2
2088 end
2088 end
2089 end
2089 end
2090
2090
2091 def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
2091 def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
2092 @request.session[:user_id] = 2
2092 @request.session[:user_id] = 2
2093 tracker = Tracker.find(2)
2093 tracker = Tracker.find(2)
2094 tracker.update! :default_status_id => 2
2094 tracker.update! :default_status_id => 2
2095 tracker.generate_transitions! 2 => 1, :clear => true
2095 tracker.generate_transitions! 2 => 1, :clear => true
2096
2096
2097 post :new, :project_id => 1,
2097 post :new, :project_id => 1,
2098 :issue => {:tracker_id => 2,
2098 :issue => {:tracker_id => 2,
2099 :status_id => 1},
2099 :status_id => 1},
2100 :was_default_status => 1
2100 :was_default_status => 1
2101 assert_response :success
2101 assert_response :success
2102
2102
2103 assert_select 'select[name=?]', 'issue[status_id]' do
2103 assert_select 'select[name=?]', 'issue[status_id]' do
2104 assert_select 'option[value=?][selected=selected]', '2'
2104 assert_select 'option[value=?][selected=selected]', '2'
2105 end
2105 end
2106 end
2106 end
2107
2107
2108 def test_update_form_for_new_issue_should_ignore_version_when_changing_project
2108 def test_update_form_for_new_issue_should_ignore_version_when_changing_project
2109 version = Version.generate!(:project_id => 1)
2109 version = Version.generate!(:project_id => 1)
2110 Project.find(1).update_attribute :default_version_id, version.id
2110 Project.find(1).update_attribute :default_version_id, version.id
2111 @request.session[:user_id] = 2
2111 @request.session[:user_id] = 2
2112
2112
2113 post :new, :issue => {:project_id => 1,
2113 post :new, :issue => {:project_id => 1,
2114 :fixed_version_id => ''},
2114 :fixed_version_id => ''},
2115 :form_update_triggered_by => 'issue_project_id'
2115 :form_update_triggered_by => 'issue_project_id'
2116 assert_response :success
2116 assert_response :success
2117
2117
2118 assert_select 'select[name=?]', 'issue[project_id]' do
2118 assert_select 'select[name=?]', 'issue[project_id]' do
2119 assert_select 'option[value=?][selected=selected]', '1'
2119 assert_select 'option[value=?][selected=selected]', '1'
2120 end
2120 end
2121 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
2121 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
2122 assert_select 'option[value=?][selected=selected]', version.id.to_s
2122 assert_select 'option[value=?][selected=selected]', version.id.to_s
2123 end
2123 end
2124 end
2124 end
2125
2125
2126 def test_post_create
2126 def test_post_create
2127 @request.session[:user_id] = 2
2127 @request.session[:user_id] = 2
2128 assert_difference 'Issue.count' do
2128 assert_difference 'Issue.count' do
2129 assert_no_difference 'Journal.count' do
2129 assert_no_difference 'Journal.count' do
2130 post :create, :project_id => 1,
2130 post :create, :project_id => 1,
2131 :issue => {:tracker_id => 3,
2131 :issue => {:tracker_id => 3,
2132 :status_id => 2,
2132 :status_id => 2,
2133 :subject => 'This is the test_new issue',
2133 :subject => 'This is the test_new issue',
2134 :description => 'This is the description',
2134 :description => 'This is the description',
2135 :priority_id => 5,
2135 :priority_id => 5,
2136 :start_date => '2010-11-07',
2136 :start_date => '2010-11-07',
2137 :estimated_hours => '',
2137 :estimated_hours => '',
2138 :custom_field_values => {'2' => 'Value for field 2'}}
2138 :custom_field_values => {'2' => 'Value for field 2'}}
2139 end
2139 end
2140 end
2140 end
2141 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2141 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2142
2142
2143 issue = Issue.find_by_subject('This is the test_new issue')
2143 issue = Issue.find_by_subject('This is the test_new issue')
2144 assert_not_nil issue
2144 assert_not_nil issue
2145 assert_equal 2, issue.author_id
2145 assert_equal 2, issue.author_id
2146 assert_equal 3, issue.tracker_id
2146 assert_equal 3, issue.tracker_id
2147 assert_equal 2, issue.status_id
2147 assert_equal 2, issue.status_id
2148 assert_equal Date.parse('2010-11-07'), issue.start_date
2148 assert_equal Date.parse('2010-11-07'), issue.start_date
2149 assert_nil issue.estimated_hours
2149 assert_nil issue.estimated_hours
2150 v = issue.custom_values.where(:custom_field_id => 2).first
2150 v = issue.custom_values.where(:custom_field_id => 2).first
2151 assert_not_nil v
2151 assert_not_nil v
2152 assert_equal 'Value for field 2', v.value
2152 assert_equal 'Value for field 2', v.value
2153 end
2153 end
2154
2154
2155 def test_post_new_with_group_assignment
2155 def test_post_new_with_group_assignment
2156 group = Group.find(11)
2156 group = Group.find(11)
2157 project = Project.find(1)
2157 project = Project.find(1)
2158 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
2158 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
2159
2159
2160 with_settings :issue_group_assignment => '1' do
2160 with_settings :issue_group_assignment => '1' do
2161 @request.session[:user_id] = 2
2161 @request.session[:user_id] = 2
2162 assert_difference 'Issue.count' do
2162 assert_difference 'Issue.count' do
2163 post :create, :project_id => project.id,
2163 post :create, :project_id => project.id,
2164 :issue => {:tracker_id => 3,
2164 :issue => {:tracker_id => 3,
2165 :status_id => 1,
2165 :status_id => 1,
2166 :subject => 'This is the test_new_with_group_assignment issue',
2166 :subject => 'This is the test_new_with_group_assignment issue',
2167 :assigned_to_id => group.id}
2167 :assigned_to_id => group.id}
2168 end
2168 end
2169 end
2169 end
2170 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2170 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2171
2171
2172 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
2172 issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
2173 assert_not_nil issue
2173 assert_not_nil issue
2174 assert_equal group, issue.assigned_to
2174 assert_equal group, issue.assigned_to
2175 end
2175 end
2176
2176
2177 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
2177 def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
2178 with_settings :default_issue_start_date_to_creation_date => 0 do
2178 with_settings :default_issue_start_date_to_creation_date => 0 do
2179 @request.session[:user_id] = 2
2179 @request.session[:user_id] = 2
2180 assert_difference 'Issue.count' do
2180 assert_difference 'Issue.count' do
2181 post :create, :project_id => 1,
2181 post :create, :project_id => 1,
2182 :issue => {:tracker_id => 3,
2182 :issue => {:tracker_id => 3,
2183 :status_id => 2,
2183 :status_id => 2,
2184 :subject => 'This is the test_new issue',
2184 :subject => 'This is the test_new issue',
2185 :description => 'This is the description',
2185 :description => 'This is the description',
2186 :priority_id => 5,
2186 :priority_id => 5,
2187 :estimated_hours => '',
2187 :estimated_hours => '',
2188 :custom_field_values => {'2' => 'Value for field 2'}}
2188 :custom_field_values => {'2' => 'Value for field 2'}}
2189 end
2189 end
2190 assert_redirected_to :controller => 'issues', :action => 'show',
2190 assert_redirected_to :controller => 'issues', :action => 'show',
2191 :id => Issue.last.id
2191 :id => Issue.last.id
2192 issue = Issue.find_by_subject('This is the test_new issue')
2192 issue = Issue.find_by_subject('This is the test_new issue')
2193 assert_not_nil issue
2193 assert_not_nil issue
2194 assert_nil issue.start_date
2194 assert_nil issue.start_date
2195 end
2195 end
2196 end
2196 end
2197
2197
2198 def test_post_create_without_start_date_and_default_start_date_is_creation_date
2198 def test_post_create_without_start_date_and_default_start_date_is_creation_date
2199 with_settings :default_issue_start_date_to_creation_date => 1 do
2199 with_settings :default_issue_start_date_to_creation_date => 1 do
2200 @request.session[:user_id] = 2
2200 @request.session[:user_id] = 2
2201 assert_difference 'Issue.count' do
2201 assert_difference 'Issue.count' do
2202 post :create, :project_id => 1,
2202 post :create, :project_id => 1,
2203 :issue => {:tracker_id => 3,
2203 :issue => {:tracker_id => 3,
2204 :status_id => 2,
2204 :status_id => 2,
2205 :subject => 'This is the test_new issue',
2205 :subject => 'This is the test_new issue',
2206 :description => 'This is the description',
2206 :description => 'This is the description',
2207 :priority_id => 5,
2207 :priority_id => 5,
2208 :estimated_hours => '',
2208 :estimated_hours => '',
2209 :custom_field_values => {'2' => 'Value for field 2'}}
2209 :custom_field_values => {'2' => 'Value for field 2'}}
2210 end
2210 end
2211 assert_redirected_to :controller => 'issues', :action => 'show',
2211 assert_redirected_to :controller => 'issues', :action => 'show',
2212 :id => Issue.last.id
2212 :id => Issue.last.id
2213 issue = Issue.find_by_subject('This is the test_new issue')
2213 issue = Issue.find_by_subject('This is the test_new issue')
2214 assert_not_nil issue
2214 assert_not_nil issue
2215 assert_equal Date.today, issue.start_date
2215 assert_equal Date.today, issue.start_date
2216 end
2216 end
2217 end
2217 end
2218
2218
2219 def test_post_create_and_continue
2219 def test_post_create_and_continue
2220 @request.session[:user_id] = 2
2220 @request.session[:user_id] = 2
2221 assert_difference 'Issue.count' do
2221 assert_difference 'Issue.count' do
2222 post :create, :project_id => 1,
2222 post :create, :project_id => 1,
2223 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
2223 :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
2224 :continue => ''
2224 :continue => ''
2225 end
2225 end
2226
2226
2227 issue = Issue.order('id DESC').first
2227 issue = Issue.order('id DESC').first
2228 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
2228 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
2229 assert_not_nil flash[:notice], "flash was not set"
2229 assert_not_nil flash[:notice], "flash was not set"
2230 assert_select_in flash[:notice],
2230 assert_select_in flash[:notice],
2231 'a[href=?][title=?]', "/issues/#{issue.id}", "This is first issue", :text => "##{issue.id}"
2231 'a[href=?][title=?]', "/issues/#{issue.id}", "This is first issue", :text => "##{issue.id}"
2232 end
2232 end
2233
2233
2234 def test_post_create_without_custom_fields_param
2234 def test_post_create_without_custom_fields_param
2235 @request.session[:user_id] = 2
2235 @request.session[:user_id] = 2
2236 assert_difference 'Issue.count' do
2236 assert_difference 'Issue.count' do
2237 post :create, :project_id => 1,
2237 post :create, :project_id => 1,
2238 :issue => {:tracker_id => 1,
2238 :issue => {:tracker_id => 1,
2239 :subject => 'This is the test_new issue',
2239 :subject => 'This is the test_new issue',
2240 :description => 'This is the description',
2240 :description => 'This is the description',
2241 :priority_id => 5}
2241 :priority_id => 5}
2242 end
2242 end
2243 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2243 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2244 end
2244 end
2245
2245
2246 def test_post_create_with_multi_custom_field
2246 def test_post_create_with_multi_custom_field
2247 field = IssueCustomField.find_by_name('Database')
2247 field = IssueCustomField.find_by_name('Database')
2248 field.update_attribute(:multiple, true)
2248 field.update_attribute(:multiple, true)
2249
2249
2250 @request.session[:user_id] = 2
2250 @request.session[:user_id] = 2
2251 assert_difference 'Issue.count' do
2251 assert_difference 'Issue.count' do
2252 post :create, :project_id => 1,
2252 post :create, :project_id => 1,
2253 :issue => {:tracker_id => 1,
2253 :issue => {:tracker_id => 1,
2254 :subject => 'This is the test_new issue',
2254 :subject => 'This is the test_new issue',
2255 :description => 'This is the description',
2255 :description => 'This is the description',
2256 :priority_id => 5,
2256 :priority_id => 5,
2257 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
2257 :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
2258 end
2258 end
2259 assert_response 302
2259 assert_response 302
2260 issue = Issue.order('id DESC').first
2260 issue = Issue.order('id DESC').first
2261 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
2261 assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
2262 end
2262 end
2263
2263
2264 def test_post_create_with_empty_multi_custom_field
2264 def test_post_create_with_empty_multi_custom_field
2265 field = IssueCustomField.find_by_name('Database')
2265 field = IssueCustomField.find_by_name('Database')
2266 field.update_attribute(:multiple, true)
2266 field.update_attribute(:multiple, true)
2267
2267
2268 @request.session[:user_id] = 2
2268 @request.session[:user_id] = 2
2269 assert_difference 'Issue.count' do
2269 assert_difference 'Issue.count' do
2270 post :create, :project_id => 1,
2270 post :create, :project_id => 1,
2271 :issue => {:tracker_id => 1,
2271 :issue => {:tracker_id => 1,
2272 :subject => 'This is the test_new issue',
2272 :subject => 'This is the test_new issue',
2273 :description => 'This is the description',
2273 :description => 'This is the description',
2274 :priority_id => 5,
2274 :priority_id => 5,
2275 :custom_field_values => {'1' => ['']}}
2275 :custom_field_values => {'1' => ['']}}
2276 end
2276 end
2277 assert_response 302
2277 assert_response 302
2278 issue = Issue.order('id DESC').first
2278 issue = Issue.order('id DESC').first
2279 assert_equal [''], issue.custom_field_value(1).sort
2279 assert_equal [''], issue.custom_field_value(1).sort
2280 end
2280 end
2281
2281
2282 def test_post_create_with_multi_user_custom_field
2282 def test_post_create_with_multi_user_custom_field
2283 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
2283 field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
2284 :tracker_ids => [1], :is_for_all => true)
2284 :tracker_ids => [1], :is_for_all => true)
2285
2285
2286 @request.session[:user_id] = 2
2286 @request.session[:user_id] = 2
2287 assert_difference 'Issue.count' do
2287 assert_difference 'Issue.count' do
2288 post :create, :project_id => 1,
2288 post :create, :project_id => 1,
2289 :issue => {:tracker_id => 1,
2289 :issue => {:tracker_id => 1,
2290 :subject => 'This is the test_new issue',
2290 :subject => 'This is the test_new issue',
2291 :description => 'This is the description',
2291 :description => 'This is the description',
2292 :priority_id => 5,
2292 :priority_id => 5,
2293 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
2293 :custom_field_values => {field.id.to_s => ['', '2', '3']}}
2294 end
2294 end
2295 assert_response 302
2295 assert_response 302
2296 issue = Issue.order('id DESC').first
2296 issue = Issue.order('id DESC').first
2297 assert_equal ['2', '3'], issue.custom_field_value(field).sort
2297 assert_equal ['2', '3'], issue.custom_field_value(field).sort
2298 end
2298 end
2299
2299
2300 def test_post_create_with_required_custom_field_and_without_custom_fields_param
2300 def test_post_create_with_required_custom_field_and_without_custom_fields_param
2301 field = IssueCustomField.find_by_name('Database')
2301 field = IssueCustomField.find_by_name('Database')
2302 field.update_attribute(:is_required, true)
2302 field.update_attribute(:is_required, true)
2303
2303
2304 @request.session[:user_id] = 2
2304 @request.session[:user_id] = 2
2305 assert_no_difference 'Issue.count' do
2305 assert_no_difference 'Issue.count' do
2306 post :create, :project_id => 1,
2306 post :create, :project_id => 1,
2307 :issue => {:tracker_id => 1,
2307 :issue => {:tracker_id => 1,
2308 :subject => 'This is the test_new issue',
2308 :subject => 'This is the test_new issue',
2309 :description => 'This is the description',
2309 :description => 'This is the description',
2310 :priority_id => 5}
2310 :priority_id => 5}
2311 end
2311 end
2312 assert_response :success
2312 assert_response :success
2313 assert_select_error /Database cannot be blank/
2313 assert_select_error /Database cannot be blank/
2314 end
2314 end
2315
2315
2316 def test_create_should_validate_required_fields
2316 def test_create_should_validate_required_fields
2317 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2317 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2318 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2318 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2319 WorkflowPermission.delete_all
2319 WorkflowPermission.delete_all
2320 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
2320 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
2321 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2321 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2322 @request.session[:user_id] = 2
2322 @request.session[:user_id] = 2
2323
2323
2324 assert_no_difference 'Issue.count' do
2324 assert_no_difference 'Issue.count' do
2325 post :create, :project_id => 1, :issue => {
2325 post :create, :project_id => 1, :issue => {
2326 :tracker_id => 2,
2326 :tracker_id => 2,
2327 :status_id => 1,
2327 :status_id => 1,
2328 :subject => 'Test',
2328 :subject => 'Test',
2329 :start_date => '',
2329 :start_date => '',
2330 :due_date => '',
2330 :due_date => '',
2331 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
2331 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
2332 }
2332 }
2333 assert_response :success
2333 assert_response :success
2334 end
2334 end
2335
2335
2336 assert_select_error /Due date cannot be blank/i
2336 assert_select_error /Due date cannot be blank/i
2337 assert_select_error /Bar cannot be blank/i
2337 assert_select_error /Bar cannot be blank/i
2338 end
2338 end
2339
2339
2340 def test_create_should_validate_required_list_fields
2340 def test_create_should_validate_required_list_fields
2341 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => false, :possible_values => ['a', 'b'])
2341 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => false, :possible_values => ['a', 'b'])
2342 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => true, :possible_values => ['a', 'b'])
2342 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => true, :possible_values => ['a', 'b'])
2343 WorkflowPermission.delete_all
2343 WorkflowPermission.delete_all
2344 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf1.id.to_s, :rule => 'required')
2344 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf1.id.to_s, :rule => 'required')
2345 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2345 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
2346 @request.session[:user_id] = 2
2346 @request.session[:user_id] = 2
2347
2347
2348 assert_no_difference 'Issue.count' do
2348 assert_no_difference 'Issue.count' do
2349 post :create, :project_id => 1, :issue => {
2349 post :create, :project_id => 1, :issue => {
2350 :tracker_id => 2,
2350 :tracker_id => 2,
2351 :status_id => 1,
2351 :status_id => 1,
2352 :subject => 'Test',
2352 :subject => 'Test',
2353 :start_date => '',
2353 :start_date => '',
2354 :due_date => '',
2354 :due_date => '',
2355 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ['']}
2355 :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ['']}
2356 }
2356 }
2357 assert_response :success
2357 assert_response :success
2358 end
2358 end
2359
2359
2360 assert_select_error /Foo cannot be blank/i
2360 assert_select_error /Foo cannot be blank/i
2361 assert_select_error /Bar cannot be blank/i
2361 assert_select_error /Bar cannot be blank/i
2362 end
2362 end
2363
2363
2364 def test_create_should_ignore_readonly_fields
2364 def test_create_should_ignore_readonly_fields
2365 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2365 cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2366 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2366 cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
2367 WorkflowPermission.delete_all
2367 WorkflowPermission.delete_all
2368 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
2368 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
2369 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
2369 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
2370 @request.session[:user_id] = 2
2370 @request.session[:user_id] = 2
2371
2371
2372 assert_difference 'Issue.count' do
2372 assert_difference 'Issue.count' do
2373 post :create, :project_id => 1, :issue => {
2373 post :create, :project_id => 1, :issue => {
2374 :tracker_id => 2,
2374 :tracker_id => 2,
2375 :status_id => 1,
2375 :status_id => 1,
2376 :subject => 'Test',
2376 :subject => 'Test',
2377 :start_date => '2012-07-14',
2377 :start_date => '2012-07-14',
2378 :due_date => '2012-07-16',
2378 :due_date => '2012-07-16',
2379 :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
2379 :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
2380 }
2380 }
2381 assert_response 302
2381 assert_response 302
2382 end
2382 end
2383
2383
2384 issue = Issue.order('id DESC').first
2384 issue = Issue.order('id DESC').first
2385 assert_equal Date.parse('2012-07-14'), issue.start_date
2385 assert_equal Date.parse('2012-07-14'), issue.start_date
2386 assert_nil issue.due_date
2386 assert_nil issue.due_date
2387 assert_equal 'value1', issue.custom_field_value(cf1)
2387 assert_equal 'value1', issue.custom_field_value(cf1)
2388 assert_nil issue.custom_field_value(cf2)
2388 assert_nil issue.custom_field_value(cf2)
2389 end
2389 end
2390
2390
2391 def test_create_should_ignore_unallowed_trackers
2391 def test_create_should_ignore_unallowed_trackers
2392 role = Role.find(1)
2392 role = Role.find(1)
2393 role.set_permission_trackers :add_issues, [3]
2393 role.set_permission_trackers :add_issues, [3]
2394 role.save!
2394 role.save!
2395 @request.session[:user_id] = 2
2395 @request.session[:user_id] = 2
2396
2396
2397 issue = new_record(Issue) do
2397 issue = new_record(Issue) do
2398 post :create, :project_id => 1, :issue => {
2398 post :create, :project_id => 1, :issue => {
2399 :tracker_id => 1,
2399 :tracker_id => 1,
2400 :status_id => 1,
2400 :status_id => 1,
2401 :subject => 'Test'
2401 :subject => 'Test'
2402 }
2402 }
2403 assert_response 302
2403 assert_response 302
2404 end
2404 end
2405 assert_equal 3, issue.tracker_id
2405 assert_equal 3, issue.tracker_id
2406 end
2406 end
2407
2407
2408 def test_post_create_with_watchers
2408 def test_post_create_with_watchers
2409 @request.session[:user_id] = 2
2409 @request.session[:user_id] = 2
2410 ActionMailer::Base.deliveries.clear
2410 ActionMailer::Base.deliveries.clear
2411
2411
2412 with_settings :notified_events => %w(issue_added) do
2412 with_settings :notified_events => %w(issue_added) do
2413 assert_difference 'Watcher.count', 2 do
2413 assert_difference 'Watcher.count', 2 do
2414 post :create, :project_id => 1,
2414 post :create, :project_id => 1,
2415 :issue => {:tracker_id => 1,
2415 :issue => {:tracker_id => 1,
2416 :subject => 'This is a new issue with watchers',
2416 :subject => 'This is a new issue with watchers',
2417 :description => 'This is the description',
2417 :description => 'This is the description',
2418 :priority_id => 5,
2418 :priority_id => 5,
2419 :watcher_user_ids => ['2', '3']}
2419 :watcher_user_ids => ['2', '3']}
2420 end
2420 end
2421 end
2421 end
2422 issue = Issue.find_by_subject('This is a new issue with watchers')
2422 issue = Issue.find_by_subject('This is a new issue with watchers')
2423 assert_not_nil issue
2423 assert_not_nil issue
2424 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2424 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
2425
2425
2426 # Watchers added
2426 # Watchers added
2427 assert_equal [2, 3], issue.watcher_user_ids.sort
2427 assert_equal [2, 3], issue.watcher_user_ids.sort
2428 assert issue.watched_by?(User.find(3))
2428 assert issue.watched_by?(User.find(3))
2429 # Watchers notified
2429 # Watchers notified
2430 mail = ActionMailer::Base.deliveries.last
2430 mail = ActionMailer::Base.deliveries.last
2431 assert_not_nil mail
2431 assert_not_nil mail
2432 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
2432 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
2433 end
2433 end
2434
2434
2435 def test_post_create_subissue
2435 def test_post_create_subissue
2436 @request.session[:user_id] = 2
2436 @request.session[:user_id] = 2
2437
2437
2438 assert_difference 'Issue.count' do
2438 assert_difference 'Issue.count' do
2439 post :create, :project_id => 1,
2439 post :create, :project_id => 1,
2440 :issue => {:tracker_id => 1,
2440 :issue => {:tracker_id => 1,
2441 :subject => 'This is a child issue',
2441 :subject => 'This is a child issue',
2442 :parent_issue_id => '2'}
2442 :parent_issue_id => '2'}
2443 assert_response 302
2443 assert_response 302
2444 end
2444 end
2445 issue = Issue.order('id DESC').first
2445 issue = Issue.order('id DESC').first
2446 assert_equal Issue.find(2), issue.parent
2446 assert_equal Issue.find(2), issue.parent
2447 end
2447 end
2448
2448
2449 def test_post_create_subissue_with_sharp_parent_id
2449 def test_post_create_subissue_with_sharp_parent_id
2450 @request.session[:user_id] = 2
2450 @request.session[:user_id] = 2
2451
2451
2452 assert_difference 'Issue.count' do
2452 assert_difference 'Issue.count' do
2453 post :create, :project_id => 1,
2453 post :create, :project_id => 1,
2454 :issue => {:tracker_id => 1,
2454 :issue => {:tracker_id => 1,
2455 :subject => 'This is a child issue',
2455 :subject => 'This is a child issue',
2456 :parent_issue_id => '#2'}
2456 :parent_issue_id => '#2'}
2457 assert_response 302
2457 assert_response 302
2458 end
2458 end
2459 issue = Issue.order('id DESC').first
2459 issue = Issue.order('id DESC').first
2460 assert_equal Issue.find(2), issue.parent
2460 assert_equal Issue.find(2), issue.parent
2461 end
2461 end
2462
2462
2463 def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
2463 def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
2464 @request.session[:user_id] = 2
2464 @request.session[:user_id] = 2
2465
2465
2466 assert_no_difference 'Issue.count' do
2466 assert_no_difference 'Issue.count' do
2467 post :create, :project_id => 1,
2467 post :create, :project_id => 1,
2468 :issue => {:tracker_id => 1,
2468 :issue => {:tracker_id => 1,
2469 :subject => 'This is a child issue',
2469 :subject => 'This is a child issue',
2470 :parent_issue_id => '4'}
2470 :parent_issue_id => '4'}
2471
2471
2472 assert_response :success
2472 assert_response :success
2473 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
2473 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
2474 assert_select_error /Parent task is invalid/i
2474 assert_select_error /Parent task is invalid/i
2475 end
2475 end
2476 end
2476 end
2477
2477
2478 def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
2478 def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
2479 @request.session[:user_id] = 2
2479 @request.session[:user_id] = 2
2480
2480
2481 assert_no_difference 'Issue.count' do
2481 assert_no_difference 'Issue.count' do
2482 post :create, :project_id => 1,
2482 post :create, :project_id => 1,
2483 :issue => {:tracker_id => 1,
2483 :issue => {:tracker_id => 1,
2484 :subject => 'This is a child issue',
2484 :subject => 'This is a child issue',
2485 :parent_issue_id => '01ABC'}
2485 :parent_issue_id => '01ABC'}
2486
2486
2487 assert_response :success
2487 assert_response :success
2488 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
2488 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
2489 assert_select_error /Parent task is invalid/i
2489 assert_select_error /Parent task is invalid/i
2490 end
2490 end
2491 end
2491 end
2492
2492
2493 def test_post_create_private
2493 def test_post_create_private
2494 @request.session[:user_id] = 2
2494 @request.session[:user_id] = 2
2495
2495
2496 assert_difference 'Issue.count' do
2496 assert_difference 'Issue.count' do
2497 post :create, :project_id => 1,
2497 post :create, :project_id => 1,
2498 :issue => {:tracker_id => 1,
2498 :issue => {:tracker_id => 1,
2499 :subject => 'This is a private issue',
2499 :subject => 'This is a private issue',
2500 :is_private => '1'}
2500 :is_private => '1'}
2501 end
2501 end
2502 issue = Issue.order('id DESC').first
2502 issue = Issue.order('id DESC').first
2503 assert issue.is_private?
2503 assert issue.is_private?
2504 end
2504 end
2505
2505
2506 def test_post_create_private_with_set_own_issues_private_permission
2506 def test_post_create_private_with_set_own_issues_private_permission
2507 role = Role.find(1)
2507 role = Role.find(1)
2508 role.remove_permission! :set_issues_private
2508 role.remove_permission! :set_issues_private
2509 role.add_permission! :set_own_issues_private
2509 role.add_permission! :set_own_issues_private
2510
2510
2511 @request.session[:user_id] = 2
2511 @request.session[:user_id] = 2
2512
2512
2513 assert_difference 'Issue.count' do
2513 assert_difference 'Issue.count' do
2514 post :create, :project_id => 1,
2514 post :create, :project_id => 1,
2515 :issue => {:tracker_id => 1,
2515 :issue => {:tracker_id => 1,
2516 :subject => 'This is a private issue',
2516 :subject => 'This is a private issue',
2517 :is_private => '1'}
2517 :is_private => '1'}
2518 end
2518 end
2519 issue = Issue.order('id DESC').first
2519 issue = Issue.order('id DESC').first
2520 assert issue.is_private?
2520 assert issue.is_private?
2521 end
2521 end
2522
2522
2523 def test_create_without_project_id
2523 def test_create_without_project_id
2524 @request.session[:user_id] = 2
2524 @request.session[:user_id] = 2
2525
2525
2526 assert_difference 'Issue.count' do
2526 assert_difference 'Issue.count' do
2527 post :create,
2527 post :create,
2528 :issue => {:project_id => 3,
2528 :issue => {:project_id => 3,
2529 :tracker_id => 2,
2529 :tracker_id => 2,
2530 :subject => 'Foo'}
2530 :subject => 'Foo'}
2531 assert_response 302
2531 assert_response 302
2532 end
2532 end
2533 issue = Issue.order('id DESC').first
2533 issue = Issue.order('id DESC').first
2534 assert_equal 3, issue.project_id
2534 assert_equal 3, issue.project_id
2535 assert_equal 2, issue.tracker_id
2535 assert_equal 2, issue.tracker_id
2536 end
2536 end
2537
2537
2538 def test_create_without_project_id_and_continue_should_redirect_without_project_id
2538 def test_create_without_project_id_and_continue_should_redirect_without_project_id
2539 @request.session[:user_id] = 2
2539 @request.session[:user_id] = 2
2540
2540
2541 assert_difference 'Issue.count' do
2541 assert_difference 'Issue.count' do
2542 post :create,
2542 post :create,
2543 :issue => {:project_id => 3,
2543 :issue => {:project_id => 3,
2544 :tracker_id => 2,
2544 :tracker_id => 2,
2545 :subject => 'Foo'},
2545 :subject => 'Foo'},
2546 :continue => '1'
2546 :continue => '1'
2547 assert_redirected_to '/issues/new?issue%5Bproject_id%5D=3&issue%5Btracker_id%5D=2'
2547 assert_redirected_to '/issues/new?issue%5Bproject_id%5D=3&issue%5Btracker_id%5D=2'
2548 end
2548 end
2549 end
2549 end
2550
2550
2551 def test_create_without_project_id_should_be_denied_without_permission
2551 def test_create_without_project_id_should_be_denied_without_permission
2552 Role.non_member.remove_permission! :add_issues
2552 Role.non_member.remove_permission! :add_issues
2553 Role.anonymous.remove_permission! :add_issues
2553 Role.anonymous.remove_permission! :add_issues
2554 @request.session[:user_id] = 2
2554 @request.session[:user_id] = 2
2555
2555
2556 assert_no_difference 'Issue.count' do
2556 assert_no_difference 'Issue.count' do
2557 post :create,
2557 post :create,
2558 :issue => {:project_id => 3,
2558 :issue => {:project_id => 3,
2559 :tracker_id => 2,
2559 :tracker_id => 2,
2560 :subject => 'Foo'}
2560 :subject => 'Foo'}
2561 assert_response 422
2561 assert_response 422
2562 end
2562 end
2563 end
2563 end
2564
2564
2565 def test_create_without_project_id_with_failure_should_not_set_project
2565 def test_create_without_project_id_with_failure_should_not_set_project
2566 @request.session[:user_id] = 2
2566 @request.session[:user_id] = 2
2567
2567
2568 post :create,
2568 post :create,
2569 :issue => {:project_id => 3,
2569 :issue => {:project_id => 3,
2570 :tracker_id => 2,
2570 :tracker_id => 2,
2571 :subject => ''}
2571 :subject => ''}
2572 assert_response :success
2572 assert_response :success
2573 # no project menu
2573 # no project menu
2574 assert_select '#main-menu', 0
2574 assert_select '#main-menu', 0
2575 end
2575 end
2576
2576
2577 def test_post_create_should_send_a_notification
2577 def test_post_create_should_send_a_notification
2578 ActionMailer::Base.deliveries.clear
2578 ActionMailer::Base.deliveries.clear
2579 @request.session[:user_id] = 2
2579 @request.session[:user_id] = 2
2580 with_settings :notified_events => %w(issue_added) do
2580 with_settings :notified_events => %w(issue_added) do
2581 assert_difference 'Issue.count' do
2581 assert_difference 'Issue.count' do
2582 post :create, :project_id => 1,
2582 post :create, :project_id => 1,
2583 :issue => {:tracker_id => 3,
2583 :issue => {:tracker_id => 3,
2584 :subject => 'This is the test_new issue',
2584 :subject => 'This is the test_new issue',
2585 :description => 'This is the description',
2585 :description => 'This is the description',
2586 :priority_id => 5,
2586 :priority_id => 5,
2587 :estimated_hours => '',
2587 :estimated_hours => '',
2588 :custom_field_values => {'2' => 'Value for field 2'}}
2588 :custom_field_values => {'2' => 'Value for field 2'}}
2589 end
2589 end
2590 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2590 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2591
2591
2592 assert_equal 1, ActionMailer::Base.deliveries.size
2592 assert_equal 1, ActionMailer::Base.deliveries.size
2593 end
2593 end
2594 end
2594 end
2595
2595
2596 def test_post_create_should_preserve_fields_values_on_validation_failure
2596 def test_post_create_should_preserve_fields_values_on_validation_failure
2597 @request.session[:user_id] = 2
2597 @request.session[:user_id] = 2
2598 post :create, :project_id => 1,
2598 post :create, :project_id => 1,
2599 :issue => {:tracker_id => 1,
2599 :issue => {:tracker_id => 1,
2600 # empty subject
2600 # empty subject
2601 :subject => '',
2601 :subject => '',
2602 :description => 'This is a description',
2602 :description => 'This is a description',
2603 :priority_id => 6,
2603 :priority_id => 6,
2604 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
2604 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
2605 assert_response :success
2605 assert_response :success
2606
2606
2607 assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
2607 assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
2608 assert_select 'select[name=?]', 'issue[priority_id]' do
2608 assert_select 'select[name=?]', 'issue[priority_id]' do
2609 assert_select 'option[value="6"][selected=selected]', :text => 'High'
2609 assert_select 'option[value="6"][selected=selected]', :text => 'High'
2610 end
2610 end
2611 # Custom fields
2611 # Custom fields
2612 assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
2612 assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
2613 assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
2613 assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
2614 end
2614 end
2615 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
2615 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
2616 end
2616 end
2617
2617
2618 def test_post_create_with_failure_should_preserve_watchers
2618 def test_post_create_with_failure_should_preserve_watchers
2619 assert !User.find(8).member_of?(Project.find(1))
2619 assert !User.find(8).member_of?(Project.find(1))
2620
2620
2621 @request.session[:user_id] = 2
2621 @request.session[:user_id] = 2
2622 post :create, :project_id => 1,
2622 post :create, :project_id => 1,
2623 :issue => {:tracker_id => 1,
2623 :issue => {:tracker_id => 1,
2624 :watcher_user_ids => ['3', '8']}
2624 :watcher_user_ids => ['3', '8']}
2625 assert_response :success
2625 assert_response :success
2626
2626
2627 assert_select 'input[name=?][value="2"]:not(checked)', 'issue[watcher_user_ids][]'
2627 assert_select 'input[name=?][value="2"]:not(checked)', 'issue[watcher_user_ids][]'
2628 assert_select 'input[name=?][value="3"][checked=checked]', 'issue[watcher_user_ids][]'
2628 assert_select 'input[name=?][value="3"][checked=checked]', 'issue[watcher_user_ids][]'
2629 assert_select 'input[name=?][value="8"][checked=checked]', 'issue[watcher_user_ids][]'
2629 assert_select 'input[name=?][value="8"][checked=checked]', 'issue[watcher_user_ids][]'
2630 end
2630 end
2631
2631
2632 def test_post_create_should_ignore_non_safe_attributes
2632 def test_post_create_should_ignore_non_safe_attributes
2633 @request.session[:user_id] = 2
2633 @request.session[:user_id] = 2
2634 assert_nothing_raised do
2634 assert_nothing_raised do
2635 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
2635 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
2636 end
2636 end
2637 end
2637 end
2638
2638
2639 def test_post_create_with_attachment
2639 def test_post_create_with_attachment
2640 set_tmp_attachments_directory
2640 set_tmp_attachments_directory
2641 @request.session[:user_id] = 2
2641 @request.session[:user_id] = 2
2642
2642
2643 assert_difference 'Issue.count' do
2643 assert_difference 'Issue.count' do
2644 assert_difference 'Attachment.count' do
2644 assert_difference 'Attachment.count' do
2645 assert_no_difference 'Journal.count' do
2645 assert_no_difference 'Journal.count' do
2646 post :create, :project_id => 1,
2646 post :create, :project_id => 1,
2647 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2647 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2648 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2648 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2649 end
2649 end
2650 end
2650 end
2651 end
2651 end
2652
2652
2653 issue = Issue.order('id DESC').first
2653 issue = Issue.order('id DESC').first
2654 attachment = Attachment.order('id DESC').first
2654 attachment = Attachment.order('id DESC').first
2655
2655
2656 assert_equal issue, attachment.container
2656 assert_equal issue, attachment.container
2657 assert_equal 2, attachment.author_id
2657 assert_equal 2, attachment.author_id
2658 assert_equal 'testfile.txt', attachment.filename
2658 assert_equal 'testfile.txt', attachment.filename
2659 assert_equal 'text/plain', attachment.content_type
2659 assert_equal 'text/plain', attachment.content_type
2660 assert_equal 'test file', attachment.description
2660 assert_equal 'test file', attachment.description
2661 assert_equal 59, attachment.filesize
2661 assert_equal 59, attachment.filesize
2662 assert File.exists?(attachment.diskfile)
2662 assert File.exists?(attachment.diskfile)
2663 assert_equal 59, File.size(attachment.diskfile)
2663 assert_equal 59, File.size(attachment.diskfile)
2664 end
2664 end
2665
2665
2666 def test_post_create_with_attachment_should_notify_with_attachments
2666 def test_post_create_with_attachment_should_notify_with_attachments
2667 ActionMailer::Base.deliveries.clear
2667 ActionMailer::Base.deliveries.clear
2668 set_tmp_attachments_directory
2668 set_tmp_attachments_directory
2669 @request.session[:user_id] = 2
2669 @request.session[:user_id] = 2
2670
2670
2671 with_settings :notified_events => %w(issue_added) do
2671 with_settings :notified_events => %w(issue_added) do
2672 assert_difference 'Issue.count' do
2672 assert_difference 'Issue.count' do
2673 post :create, :project_id => 1,
2673 post :create, :project_id => 1,
2674 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2674 :issue => { :tracker_id => '1', :subject => 'With attachment' },
2675 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2675 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2676 end
2676 end
2677 end
2677 end
2678
2678
2679 assert_not_nil ActionMailer::Base.deliveries.last
2679 assert_not_nil ActionMailer::Base.deliveries.last
2680 assert_select_email do
2680 assert_select_email do
2681 assert_select 'a[href^=?]', 'http://localhost:3000/attachments/download', 'testfile.txt'
2681 assert_select 'a[href^=?]', 'http://localhost:3000/attachments/download', 'testfile.txt'
2682 end
2682 end
2683 end
2683 end
2684
2684
2685 def test_post_create_with_failure_should_save_attachments
2685 def test_post_create_with_failure_should_save_attachments
2686 set_tmp_attachments_directory
2686 set_tmp_attachments_directory
2687 @request.session[:user_id] = 2
2687 @request.session[:user_id] = 2
2688
2688
2689 assert_no_difference 'Issue.count' do
2689 assert_no_difference 'Issue.count' do
2690 assert_difference 'Attachment.count' do
2690 assert_difference 'Attachment.count' do
2691 post :create, :project_id => 1,
2691 post :create, :project_id => 1,
2692 :issue => { :tracker_id => '1', :subject => '' },
2692 :issue => { :tracker_id => '1', :subject => '' },
2693 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2693 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
2694 assert_response :success
2694 assert_response :success
2695 end
2695 end
2696 end
2696 end
2697
2697
2698 attachment = Attachment.order('id DESC').first
2698 attachment = Attachment.order('id DESC').first
2699 assert_equal 'testfile.txt', attachment.filename
2699 assert_equal 'testfile.txt', attachment.filename
2700 assert File.exists?(attachment.diskfile)
2700 assert File.exists?(attachment.diskfile)
2701 assert_nil attachment.container
2701 assert_nil attachment.container
2702
2702
2703 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2703 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2704 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2704 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2705 end
2705 end
2706
2706
2707 def test_post_create_with_failure_should_keep_saved_attachments
2707 def test_post_create_with_failure_should_keep_saved_attachments
2708 set_tmp_attachments_directory
2708 set_tmp_attachments_directory
2709 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2709 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2710 @request.session[:user_id] = 2
2710 @request.session[:user_id] = 2
2711
2711
2712 assert_no_difference 'Issue.count' do
2712 assert_no_difference 'Issue.count' do
2713 assert_no_difference 'Attachment.count' do
2713 assert_no_difference 'Attachment.count' do
2714 post :create, :project_id => 1,
2714 post :create, :project_id => 1,
2715 :issue => { :tracker_id => '1', :subject => '' },
2715 :issue => { :tracker_id => '1', :subject => '' },
2716 :attachments => {'p0' => {'token' => attachment.token}}
2716 :attachments => {'p0' => {'token' => attachment.token}}
2717 assert_response :success
2717 assert_response :success
2718 end
2718 end
2719 end
2719 end
2720
2720
2721 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2721 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
2722 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2722 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
2723 end
2723 end
2724
2724
2725 def test_post_create_should_attach_saved_attachments
2725 def test_post_create_should_attach_saved_attachments
2726 set_tmp_attachments_directory
2726 set_tmp_attachments_directory
2727 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2727 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
2728 @request.session[:user_id] = 2
2728 @request.session[:user_id] = 2
2729
2729
2730 assert_difference 'Issue.count' do
2730 assert_difference 'Issue.count' do
2731 assert_no_difference 'Attachment.count' do
2731 assert_no_difference 'Attachment.count' do
2732 post :create, :project_id => 1,
2732 post :create, :project_id => 1,
2733 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
2733 :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
2734 :attachments => {'p0' => {'token' => attachment.token}}
2734 :attachments => {'p0' => {'token' => attachment.token}}
2735 assert_response 302
2735 assert_response 302
2736 end
2736 end
2737 end
2737 end
2738
2738
2739 issue = Issue.order('id DESC').first
2739 issue = Issue.order('id DESC').first
2740 assert_equal 1, issue.attachments.count
2740 assert_equal 1, issue.attachments.count
2741
2741
2742 attachment.reload
2742 attachment.reload
2743 assert_equal issue, attachment.container
2743 assert_equal issue, attachment.container
2744 end
2744 end
2745
2745
2746 def setup_without_workflow_privilege
2746 def setup_without_workflow_privilege
2747 WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
2747 WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
2748 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2748 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2749 end
2749 end
2750 private :setup_without_workflow_privilege
2750 private :setup_without_workflow_privilege
2751
2751
2752 test "without workflow privilege #new should propose default status only" do
2752 test "without workflow privilege #new should propose default status only" do
2753 setup_without_workflow_privilege
2753 setup_without_workflow_privilege
2754 get :new, :project_id => 1
2754 get :new, :project_id => 1
2755 assert_response :success
2755 assert_response :success
2756
2756
2757 assert_select 'select[name=?]', 'issue[status_id]' do
2757 assert_select 'select[name=?]', 'issue[status_id]' do
2758 assert_select 'option', 1
2758 assert_select 'option', 1
2759 assert_select 'option[value=?][selected=selected]', '1'
2759 assert_select 'option[value=?][selected=selected]', '1'
2760 end
2760 end
2761 end
2761 end
2762
2762
2763 test "without workflow privilege #create should accept default status" do
2763 test "without workflow privilege #create should accept default status" do
2764 setup_without_workflow_privilege
2764 setup_without_workflow_privilege
2765 assert_difference 'Issue.count' do
2765 assert_difference 'Issue.count' do
2766 post :create, :project_id => 1,
2766 post :create, :project_id => 1,
2767 :issue => {:tracker_id => 1,
2767 :issue => {:tracker_id => 1,
2768 :subject => 'This is an issue',
2768 :subject => 'This is an issue',
2769 :status_id => 1}
2769 :status_id => 1}
2770 end
2770 end
2771 issue = Issue.order('id').last
2771 issue = Issue.order('id').last
2772 assert_not_nil issue.default_status
2772 assert_not_nil issue.default_status
2773 assert_equal issue.default_status, issue.status
2773 assert_equal issue.default_status, issue.status
2774 end
2774 end
2775
2775
2776 test "without workflow privilege #create should ignore unauthorized status" do
2776 test "without workflow privilege #create should ignore unauthorized status" do
2777 setup_without_workflow_privilege
2777 setup_without_workflow_privilege
2778 assert_difference 'Issue.count' do
2778 assert_difference 'Issue.count' do
2779 post :create, :project_id => 1,
2779 post :create, :project_id => 1,
2780 :issue => {:tracker_id => 1,
2780 :issue => {:tracker_id => 1,
2781 :subject => 'This is an issue',
2781 :subject => 'This is an issue',
2782 :status_id => 3}
2782 :status_id => 3}
2783 end
2783 end
2784 issue = Issue.order('id').last
2784 issue = Issue.order('id').last
2785 assert_not_nil issue.default_status
2785 assert_not_nil issue.default_status
2786 assert_equal issue.default_status, issue.status
2786 assert_equal issue.default_status, issue.status
2787 end
2787 end
2788
2788
2789 test "without workflow privilege #update should ignore status change" do
2789 test "without workflow privilege #update should ignore status change" do
2790 setup_without_workflow_privilege
2790 setup_without_workflow_privilege
2791 assert_difference 'Journal.count' do
2791 assert_difference 'Journal.count' do
2792 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2792 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2793 end
2793 end
2794 assert_equal 1, Issue.find(1).status_id
2794 assert_equal 1, Issue.find(1).status_id
2795 end
2795 end
2796
2796
2797 test "without workflow privilege #update ignore attributes changes" do
2797 test "without workflow privilege #update ignore attributes changes" do
2798 setup_without_workflow_privilege
2798 setup_without_workflow_privilege
2799 assert_difference 'Journal.count' do
2799 assert_difference 'Journal.count' do
2800 put :update, :id => 1,
2800 put :update, :id => 1,
2801 :issue => {:subject => 'changed', :assigned_to_id => 2,
2801 :issue => {:subject => 'changed', :assigned_to_id => 2,
2802 :notes => 'just trying'}
2802 :notes => 'just trying'}
2803 end
2803 end
2804 issue = Issue.find(1)
2804 issue = Issue.find(1)
2805 assert_equal "Cannot print recipes", issue.subject
2805 assert_equal "Cannot print recipes", issue.subject
2806 assert_nil issue.assigned_to
2806 assert_nil issue.assigned_to
2807 end
2807 end
2808
2808
2809 def setup_with_workflow_privilege
2809 def setup_with_workflow_privilege
2810 WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
2810 WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
2811 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2811 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2812 :old_status_id => 1, :new_status_id => 3)
2812 :old_status_id => 1, :new_status_id => 3)
2813 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2813 WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
2814 :old_status_id => 1, :new_status_id => 4)
2814 :old_status_id => 1, :new_status_id => 4)
2815 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2815 Role.anonymous.add_permission! :add_issues, :add_issue_notes
2816 end
2816 end
2817 private :setup_with_workflow_privilege
2817 private :setup_with_workflow_privilege
2818
2818
2819 def setup_with_workflow_privilege_and_edit_issues_permission
2819 def setup_with_workflow_privilege_and_edit_issues_permission
2820 setup_with_workflow_privilege
2820 setup_with_workflow_privilege
2821 Role.anonymous.add_permission! :add_issues, :edit_issues
2821 Role.anonymous.add_permission! :add_issues, :edit_issues
2822 end
2822 end
2823 private :setup_with_workflow_privilege_and_edit_issues_permission
2823 private :setup_with_workflow_privilege_and_edit_issues_permission
2824
2824
2825 test "with workflow privilege and :edit_issues permission should accept authorized status" do
2825 test "with workflow privilege and :edit_issues permission should accept authorized status" do
2826 setup_with_workflow_privilege_and_edit_issues_permission
2826 setup_with_workflow_privilege_and_edit_issues_permission
2827 assert_difference 'Journal.count' do
2827 assert_difference 'Journal.count' do
2828 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2828 put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
2829 end
2829 end
2830 assert_equal 3, Issue.find(1).status_id
2830 assert_equal 3, Issue.find(1).status_id
2831 end
2831 end
2832
2832
2833 test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
2833 test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
2834 setup_with_workflow_privilege_and_edit_issues_permission
2834 setup_with_workflow_privilege_and_edit_issues_permission
2835 assert_difference 'Journal.count' do
2835 assert_difference 'Journal.count' do
2836 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2836 put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
2837 end
2837 end
2838 assert_equal 1, Issue.find(1).status_id
2838 assert_equal 1, Issue.find(1).status_id
2839 end
2839 end
2840
2840
2841 test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
2841 test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
2842 setup_with_workflow_privilege_and_edit_issues_permission
2842 setup_with_workflow_privilege_and_edit_issues_permission
2843 assert_difference 'Journal.count' do
2843 assert_difference 'Journal.count' do
2844 put :update, :id => 1,
2844 put :update, :id => 1,
2845 :issue => {:subject => 'changed', :assigned_to_id => 2,
2845 :issue => {:subject => 'changed', :assigned_to_id => 2,
2846 :notes => 'just trying'}
2846 :notes => 'just trying'}
2847 end
2847 end
2848 issue = Issue.find(1)
2848 issue = Issue.find(1)
2849 assert_equal "changed", issue.subject
2849 assert_equal "changed", issue.subject
2850 assert_equal 2, issue.assigned_to_id
2850 assert_equal 2, issue.assigned_to_id
2851 end
2851 end
2852
2852
2853 def test_new_as_copy
2853 def test_new_as_copy
2854 orig = Issue.find(1)
2854 orig = Issue.find(1)
2855 @request.session[:user_id] = 2
2855 @request.session[:user_id] = 2
2856
2856
2857 get :new, :project_id => 1, :copy_from => orig.id
2857 get :new, :project_id => 1, :copy_from => orig.id
2858 assert_response :success
2858 assert_response :success
2859
2859
2860 assert_select 'form[id=issue-form][action="/projects/ecookbook/issues"]' do
2860 assert_select 'form[id=issue-form][action="/projects/ecookbook/issues"]' do
2861 assert_select 'select[name=?]', 'issue[project_id]' do
2861 assert_select 'select[name=?]', 'issue[project_id]' do
2862 assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2862 assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2863 assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2863 assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2864 end
2864 end
2865 assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
2865 assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
2866 assert_select 'input[name=copy_from][value="1"]'
2866 assert_select 'input[name=copy_from][value="1"]'
2867 end
2867 end
2868 end
2868 end
2869
2869
2870 def test_new_as_copy_without_add_issues_permission_should_not_propose_current_project_as_target
2870 def test_new_as_copy_without_add_issues_permission_should_not_propose_current_project_as_target
2871 user = setup_user_with_copy_but_not_add_permission
2871 user = setup_user_with_copy_but_not_add_permission
2872
2872
2873 @request.session[:user_id] = user.id
2873 @request.session[:user_id] = user.id
2874 get :new, :project_id => 1, :copy_from => 1
2874 get :new, :project_id => 1, :copy_from => 1
2875 assert_response :success
2875 assert_response :success
2876
2876
2877 assert_select 'select[name=?]', 'issue[project_id]' do
2877 assert_select 'select[name=?]', 'issue[project_id]' do
2878 assert_select 'option[value="1"]', 0
2878 assert_select 'option[value="1"]', 0
2879 assert_select 'option[value="2"]', :text => 'OnlineStore'
2879 assert_select 'option[value="2"]', :text => 'OnlineStore'
2880 end
2880 end
2881 end
2881 end
2882
2882
2883 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2883 def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
2884 @request.session[:user_id] = 2
2884 @request.session[:user_id] = 2
2885 issue = Issue.find(3)
2885 issue = Issue.find(3)
2886 assert issue.attachments.count > 0
2886 assert issue.attachments.count > 0
2887 get :new, :project_id => 1, :copy_from => 3
2887 get :new, :project_id => 1, :copy_from => 3
2888
2888
2889 assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value="1"]'
2889 assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value="1"]'
2890 end
2890 end
2891
2891
2892 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2892 def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
2893 @request.session[:user_id] = 2
2893 @request.session[:user_id] = 2
2894 issue = Issue.find(3)
2894 issue = Issue.find(3)
2895 issue.attachments.delete_all
2895 issue.attachments.delete_all
2896 get :new, :project_id => 1, :copy_from => 3
2896 get :new, :project_id => 1, :copy_from => 3
2897
2897
2898 assert_select 'input[name=copy_attachments]', 0
2898 assert_select 'input[name=copy_attachments]', 0
2899 end
2899 end
2900
2900
2901 def test_new_as_copy_should_preserve_parent_id
2901 def test_new_as_copy_should_preserve_parent_id
2902 @request.session[:user_id] = 2
2902 @request.session[:user_id] = 2
2903 issue = Issue.generate!(:parent_issue_id => 2)
2903 issue = Issue.generate!(:parent_issue_id => 2)
2904 get :new, :project_id => 1, :copy_from => issue.id
2904 get :new, :project_id => 1, :copy_from => issue.id
2905
2905
2906 assert_select 'input[name=?][value="2"]', 'issue[parent_issue_id]'
2906 assert_select 'input[name=?][value="2"]', 'issue[parent_issue_id]'
2907 end
2907 end
2908
2908
2909 def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
2909 def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
2910 @request.session[:user_id] = 2
2910 @request.session[:user_id] = 2
2911 issue = Issue.generate_with_descendants!
2911 issue = Issue.generate_with_descendants!
2912 get :new, :project_id => 1, :copy_from => issue.id
2912 get :new, :project_id => 1, :copy_from => issue.id
2913
2913
2914 assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value="1"]'
2914 assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value="1"]'
2915 end
2915 end
2916
2916
2917 def test_new_as_copy_with_invalid_issue_should_respond_with_404
2917 def test_new_as_copy_with_invalid_issue_should_respond_with_404
2918 @request.session[:user_id] = 2
2918 @request.session[:user_id] = 2
2919 get :new, :project_id => 1, :copy_from => 99999
2919 get :new, :project_id => 1, :copy_from => 99999
2920 assert_response 404
2920 assert_response 404
2921 end
2921 end
2922
2922
2923 def test_create_as_copy_on_different_project
2923 def test_create_as_copy_on_different_project
2924 @request.session[:user_id] = 2
2924 @request.session[:user_id] = 2
2925 assert_difference 'Issue.count' do
2925 assert_difference 'Issue.count' do
2926 post :create, :project_id => 1, :copy_from => 1,
2926 post :create, :project_id => 1, :copy_from => 1,
2927 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2927 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
2928 end
2928 end
2929 issue = Issue.order('id DESC').first
2929 issue = Issue.order('id DESC').first
2930 assert_redirected_to "/issues/#{issue.id}"
2930 assert_redirected_to "/issues/#{issue.id}"
2931
2931
2932 assert_equal 2, issue.project_id
2932 assert_equal 2, issue.project_id
2933 assert_equal 3, issue.tracker_id
2933 assert_equal 3, issue.tracker_id
2934 assert_equal 'Copy', issue.subject
2934 assert_equal 'Copy', issue.subject
2935 end
2935 end
2936
2936
2937 def test_create_as_copy_should_allow_status_to_be_set_to_default
2937 def test_create_as_copy_should_allow_status_to_be_set_to_default
2938 copied = Issue.generate! :status_id => 2
2938 copied = Issue.generate! :status_id => 2
2939 assert_equal 2, copied.reload.status_id
2939 assert_equal 2, copied.reload.status_id
2940
2940
2941 @request.session[:user_id] = 2
2941 @request.session[:user_id] = 2
2942 assert_difference 'Issue.count' do
2942 assert_difference 'Issue.count' do
2943 post :create, :project_id => 1, :copy_from => copied.id,
2943 post :create, :project_id => 1, :copy_from => copied.id,
2944 :issue => {:project_id => '1', :tracker_id => '1', :status_id => '1'},
2944 :issue => {:project_id => '1', :tracker_id => '1', :status_id => '1'},
2945 :was_default_status => '1'
2945 :was_default_status => '1'
2946 end
2946 end
2947 issue = Issue.order('id DESC').first
2947 issue = Issue.order('id DESC').first
2948 assert_equal 1, issue.status_id
2948 assert_equal 1, issue.status_id
2949 end
2949 end
2950
2950
2951 def test_create_as_copy_should_copy_attachments
2951 def test_create_as_copy_should_copy_attachments
2952 @request.session[:user_id] = 2
2952 @request.session[:user_id] = 2
2953 issue = Issue.find(3)
2953 issue = Issue.find(3)
2954 count = issue.attachments.count
2954 count = issue.attachments.count
2955 assert count > 0
2955 assert count > 0
2956 assert_difference 'Issue.count' do
2956 assert_difference 'Issue.count' do
2957 assert_difference 'Attachment.count', count do
2957 assert_difference 'Attachment.count', count do
2958 post :create, :project_id => 1, :copy_from => 3,
2958 post :create, :project_id => 1, :copy_from => 3,
2959 :issue => {:project_id => '1', :tracker_id => '3',
2959 :issue => {:project_id => '1', :tracker_id => '3',
2960 :status_id => '1', :subject => 'Copy with attachments'},
2960 :status_id => '1', :subject => 'Copy with attachments'},
2961 :copy_attachments => '1'
2961 :copy_attachments => '1'
2962 end
2962 end
2963 end
2963 end
2964 copy = Issue.order('id DESC').first
2964 copy = Issue.order('id DESC').first
2965 assert_equal count, copy.attachments.count
2965 assert_equal count, copy.attachments.count
2966 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
2966 assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
2967 end
2967 end
2968
2968
2969 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
2969 def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
2970 @request.session[:user_id] = 2
2970 @request.session[:user_id] = 2
2971 issue = Issue.find(3)
2971 issue = Issue.find(3)
2972 count = issue.attachments.count
2972 count = issue.attachments.count
2973 assert count > 0
2973 assert count > 0
2974 assert_difference 'Issue.count' do
2974 assert_difference 'Issue.count' do
2975 assert_no_difference 'Attachment.count' do
2975 assert_no_difference 'Attachment.count' do
2976 post :create, :project_id => 1, :copy_from => 3,
2976 post :create, :project_id => 1, :copy_from => 3,
2977 :issue => {:project_id => '1', :tracker_id => '3',
2977 :issue => {:project_id => '1', :tracker_id => '3',
2978 :status_id => '1', :subject => 'Copy with attachments'}
2978 :status_id => '1', :subject => 'Copy with attachments'}
2979 end
2979 end
2980 end
2980 end
2981 copy = Issue.order('id DESC').first
2981 copy = Issue.order('id DESC').first
2982 assert_equal 0, copy.attachments.count
2982 assert_equal 0, copy.attachments.count
2983 end
2983 end
2984
2984
2985 def test_create_as_copy_with_attachments_should_also_add_new_files
2985 def test_create_as_copy_with_attachments_should_also_add_new_files
2986 @request.session[:user_id] = 2
2986 @request.session[:user_id] = 2
2987 issue = Issue.find(3)
2987 issue = Issue.find(3)
2988 count = issue.attachments.count
2988 count = issue.attachments.count
2989 assert count > 0
2989 assert count > 0
2990 assert_difference 'Issue.count' do
2990 assert_difference 'Issue.count' do
2991 assert_difference 'Attachment.count', count + 1 do
2991 assert_difference 'Attachment.count', count + 1 do
2992 post :create, :project_id => 1, :copy_from => 3,
2992 post :create, :project_id => 1, :copy_from => 3,
2993 :issue => {:project_id => '1', :tracker_id => '3',
2993 :issue => {:project_id => '1', :tracker_id => '3',
2994 :status_id => '1', :subject => 'Copy with attachments'},
2994 :status_id => '1', :subject => 'Copy with attachments'},
2995 :copy_attachments => '1',
2995 :copy_attachments => '1',
2996 :attachments => {'1' =>
2996 :attachments => {'1' =>
2997 {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
2997 {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
2998 'description' => 'test file'}}
2998 'description' => 'test file'}}
2999 end
2999 end
3000 end
3000 end
3001 copy = Issue.order('id DESC').first
3001 copy = Issue.order('id DESC').first
3002 assert_equal count + 1, copy.attachments.count
3002 assert_equal count + 1, copy.attachments.count
3003 end
3003 end
3004
3004
3005 def test_create_as_copy_should_add_relation_with_copied_issue
3005 def test_create_as_copy_should_add_relation_with_copied_issue
3006 @request.session[:user_id] = 2
3006 @request.session[:user_id] = 2
3007 assert_difference 'Issue.count' do
3007 assert_difference 'Issue.count' do
3008 assert_difference 'IssueRelation.count' do
3008 assert_difference 'IssueRelation.count' do
3009 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3009 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3010 :issue => {:project_id => '1', :tracker_id => '3',
3010 :issue => {:project_id => '1', :tracker_id => '3',
3011 :status_id => '1', :subject => 'Copy'}
3011 :status_id => '1', :subject => 'Copy'}
3012 end
3012 end
3013 end
3013 end
3014 copy = Issue.order('id DESC').first
3014 copy = Issue.order('id DESC').first
3015 assert_equal 1, copy.relations.size
3015 assert_equal 1, copy.relations.size
3016 end
3016 end
3017
3017
3018 def test_create_as_copy_should_allow_not_to_add_relation_with_copied_issue
3018 def test_create_as_copy_should_allow_not_to_add_relation_with_copied_issue
3019 @request.session[:user_id] = 2
3019 @request.session[:user_id] = 2
3020 assert_difference 'Issue.count' do
3020 assert_difference 'Issue.count' do
3021 assert_no_difference 'IssueRelation.count' do
3021 assert_no_difference 'IssueRelation.count' do
3022 post :create, :project_id => 1, :copy_from => 1,
3022 post :create, :project_id => 1, :copy_from => 1,
3023 :issue => {:subject => 'Copy'}
3023 :issue => {:subject => 'Copy'}
3024 end
3024 end
3025 end
3025 end
3026 end
3026 end
3027
3027
3028 def test_create_as_copy_should_always_add_relation_with_copied_issue_by_setting
3028 def test_create_as_copy_should_always_add_relation_with_copied_issue_by_setting
3029 with_settings :link_copied_issue => 'yes' do
3029 with_settings :link_copied_issue => 'yes' do
3030 @request.session[:user_id] = 2
3030 @request.session[:user_id] = 2
3031 assert_difference 'Issue.count' do
3031 assert_difference 'Issue.count' do
3032 assert_difference 'IssueRelation.count' do
3032 assert_difference 'IssueRelation.count' do
3033 post :create, :project_id => 1, :copy_from => 1,
3033 post :create, :project_id => 1, :copy_from => 1,
3034 :issue => {:subject => 'Copy'}
3034 :issue => {:subject => 'Copy'}
3035 end
3035 end
3036 end
3036 end
3037 end
3037 end
3038 end
3038 end
3039
3039
3040 def test_create_as_copy_should_never_add_relation_with_copied_issue_by_setting
3040 def test_create_as_copy_should_never_add_relation_with_copied_issue_by_setting
3041 with_settings :link_copied_issue => 'no' do
3041 with_settings :link_copied_issue => 'no' do
3042 @request.session[:user_id] = 2
3042 @request.session[:user_id] = 2
3043 assert_difference 'Issue.count' do
3043 assert_difference 'Issue.count' do
3044 assert_no_difference 'IssueRelation.count' do
3044 assert_no_difference 'IssueRelation.count' do
3045 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3045 post :create, :project_id => 1, :copy_from => 1, :link_copy => '1',
3046 :issue => {:subject => 'Copy'}
3046 :issue => {:subject => 'Copy'}
3047 end
3047 end
3048 end
3048 end
3049 end
3049 end
3050 end
3050 end
3051
3051
3052 def test_create_as_copy_should_copy_subtasks
3052 def test_create_as_copy_should_copy_subtasks
3053 @request.session[:user_id] = 2
3053 @request.session[:user_id] = 2
3054 issue = Issue.generate_with_descendants!
3054 issue = Issue.generate_with_descendants!
3055 count = issue.descendants.count
3055 count = issue.descendants.count
3056 assert_difference 'Issue.count', count + 1 do
3056 assert_difference 'Issue.count', count + 1 do
3057 post :create, :project_id => 1, :copy_from => issue.id,
3057 post :create, :project_id => 1, :copy_from => issue.id,
3058 :issue => {:project_id => '1', :tracker_id => '3',
3058 :issue => {:project_id => '1', :tracker_id => '3',
3059 :status_id => '1', :subject => 'Copy with subtasks'},
3059 :status_id => '1', :subject => 'Copy with subtasks'},
3060 :copy_subtasks => '1'
3060 :copy_subtasks => '1'
3061 end
3061 end
3062 copy = Issue.where(:parent_id => nil).order('id DESC').first
3062 copy = Issue.where(:parent_id => nil).order('id DESC').first
3063 assert_equal count, copy.descendants.count
3063 assert_equal count, copy.descendants.count
3064 assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
3064 assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
3065 end
3065 end
3066
3066
3067 def test_create_as_copy_to_a_different_project_should_copy_subtask_custom_fields
3067 def test_create_as_copy_to_a_different_project_should_copy_subtask_custom_fields
3068 issue = Issue.generate! {|i| i.custom_field_values = {'2' => 'Foo'}}
3068 issue = Issue.generate! {|i| i.custom_field_values = {'2' => 'Foo'}}
3069 child = Issue.generate!(:parent_issue_id => issue.id) {|i| i.custom_field_values = {'2' => 'Bar'}}
3069 child = Issue.generate!(:parent_issue_id => issue.id) {|i| i.custom_field_values = {'2' => 'Bar'}}
3070 @request.session[:user_id] = 1
3070 @request.session[:user_id] = 1
3071
3071
3072 assert_difference 'Issue.count', 2 do
3072 assert_difference 'Issue.count', 2 do
3073 post :create, :project_id => 'ecookbook', :copy_from => issue.id,
3073 post :create, :project_id => 'ecookbook', :copy_from => issue.id,
3074 :issue => {:project_id => '2', :tracker_id => 1, :status_id => '1',
3074 :issue => {:project_id => '2', :tracker_id => 1, :status_id => '1',
3075 :subject => 'Copy with subtasks', :custom_field_values => {'2' => 'Foo'}},
3075 :subject => 'Copy with subtasks', :custom_field_values => {'2' => 'Foo'}},
3076 :copy_subtasks => '1'
3076 :copy_subtasks => '1'
3077 end
3077 end
3078
3078
3079 child_copy, issue_copy = Issue.order(:id => :desc).limit(2).to_a
3079 child_copy, issue_copy = Issue.order(:id => :desc).limit(2).to_a
3080 assert_equal 2, issue_copy.project_id
3080 assert_equal 2, issue_copy.project_id
3081 assert_equal 'Foo', issue_copy.custom_field_value(2)
3081 assert_equal 'Foo', issue_copy.custom_field_value(2)
3082 assert_equal 'Bar', child_copy.custom_field_value(2)
3082 assert_equal 'Bar', child_copy.custom_field_value(2)
3083 end
3083 end
3084
3084
3085 def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
3085 def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
3086 @request.session[:user_id] = 2
3086 @request.session[:user_id] = 2
3087 issue = Issue.generate_with_descendants!
3087 issue = Issue.generate_with_descendants!
3088 assert_difference 'Issue.count', 1 do
3088 assert_difference 'Issue.count', 1 do
3089 post :create, :project_id => 1, :copy_from => 3,
3089 post :create, :project_id => 1, :copy_from => 3,
3090 :issue => {:project_id => '1', :tracker_id => '3',
3090 :issue => {:project_id => '1', :tracker_id => '3',
3091 :status_id => '1', :subject => 'Copy with subtasks'}
3091 :status_id => '1', :subject => 'Copy with subtasks'}
3092 end
3092 end
3093 copy = Issue.where(:parent_id => nil).order('id DESC').first
3093 copy = Issue.where(:parent_id => nil).order('id DESC').first
3094 assert_equal 0, copy.descendants.count
3094 assert_equal 0, copy.descendants.count
3095 end
3095 end
3096
3096
3097 def test_create_as_copy_with_failure
3097 def test_create_as_copy_with_failure
3098 @request.session[:user_id] = 2
3098 @request.session[:user_id] = 2
3099 post :create, :project_id => 1, :copy_from => 1,
3099 post :create, :project_id => 1, :copy_from => 1,
3100 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
3100 :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
3101
3101
3102 assert_response :success
3102 assert_response :success
3103
3103
3104 assert_select 'form#issue-form[action="/projects/ecookbook/issues"]' do
3104 assert_select 'form#issue-form[action="/projects/ecookbook/issues"]' do
3105 assert_select 'select[name=?]', 'issue[project_id]' do
3105 assert_select 'select[name=?]', 'issue[project_id]' do
3106 assert_select 'option[value="1"]:not([selected])', :text => 'eCookbook'
3106 assert_select 'option[value="1"]:not([selected])', :text => 'eCookbook'
3107 assert_select 'option[value="2"][selected=selected]', :text => 'OnlineStore'
3107 assert_select 'option[value="2"][selected=selected]', :text => 'OnlineStore'
3108 end
3108 end
3109 assert_select 'input[name=copy_from][value="1"]'
3109 assert_select 'input[name=copy_from][value="1"]'
3110 end
3110 end
3111 end
3111 end
3112
3112
3113 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
3113 def test_create_as_copy_on_project_without_permission_should_ignore_target_project
3114 @request.session[:user_id] = 2
3114 @request.session[:user_id] = 2
3115 assert !User.find(2).member_of?(Project.find(4))
3115 assert !User.find(2).member_of?(Project.find(4))
3116
3116
3117 assert_difference 'Issue.count' do
3117 assert_difference 'Issue.count' do
3118 post :create, :project_id => 1, :copy_from => 1,
3118 post :create, :project_id => 1, :copy_from => 1,
3119 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
3119 :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
3120 end
3120 end
3121 issue = Issue.order('id DESC').first
3121 issue = Issue.order('id DESC').first
3122 assert_equal 1, issue.project_id
3122 assert_equal 1, issue.project_id
3123 end
3123 end
3124
3124
3125 def test_get_edit
3125 def test_get_edit
3126 @request.session[:user_id] = 2
3126 @request.session[:user_id] = 2
3127 get :edit, :id => 1
3127 get :edit, :id => 1
3128 assert_response :success
3128 assert_response :success
3129
3129
3130 # Be sure we don't display inactive IssuePriorities
3130 # Be sure we don't display inactive IssuePriorities
3131 assert ! IssuePriority.find(15).active?
3131 assert ! IssuePriority.find(15).active?
3132 assert_select 'select[name=?]', 'issue[priority_id]' do
3132 assert_select 'select[name=?]', 'issue[priority_id]' do
3133 assert_select 'option[value="15"]', 0
3133 assert_select 'option[value="15"]', 0
3134 end
3134 end
3135 end
3135 end
3136
3136
3137 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3137 def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3138 @request.session[:user_id] = 2
3138 @request.session[:user_id] = 2
3139 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3139 Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3140
3140
3141 get :edit, :id => 1
3141 get :edit, :id => 1
3142 assert_select 'input[name=?]', 'time_entry[hours]'
3142 assert_select 'input[name=?]', 'time_entry[hours]'
3143 end
3143 end
3144
3144
3145 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3145 def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3146 @request.session[:user_id] = 2
3146 @request.session[:user_id] = 2
3147 Role.find_by_name('Manager').remove_permission! :log_time
3147 Role.find_by_name('Manager').remove_permission! :log_time
3148
3148
3149 get :edit, :id => 1
3149 get :edit, :id => 1
3150 assert_select 'input[name=?]', 'time_entry[hours]', 0
3150 assert_select 'input[name=?]', 'time_entry[hours]', 0
3151 end
3151 end
3152
3152
3153 def test_get_edit_with_params
3153 def test_get_edit_with_params
3154 @request.session[:user_id] = 2
3154 @request.session[:user_id] = 2
3155 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
3155 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
3156 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
3156 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
3157 assert_response :success
3157 assert_response :success
3158
3158
3159 assert_select 'select[name=?]', 'issue[status_id]' do
3159 assert_select 'select[name=?]', 'issue[status_id]' do
3160 assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
3160 assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
3161 end
3161 end
3162
3162
3163 assert_select 'select[name=?]', 'issue[priority_id]' do
3163 assert_select 'select[name=?]', 'issue[priority_id]' do
3164 assert_select 'option[value="7"][selected=selected]', :text => 'Urgent'
3164 assert_select 'option[value="7"][selected=selected]', :text => 'Urgent'
3165 end
3165 end
3166
3166
3167 assert_select 'input[name=?][value="2.5"]', 'time_entry[hours]'
3167 assert_select 'input[name=?][value="2.5"]', 'time_entry[hours]'
3168 assert_select 'select[name=?]', 'time_entry[activity_id]' do
3168 assert_select 'select[name=?]', 'time_entry[activity_id]' do
3169 assert_select 'option[value="10"][selected=selected]', :text => 'Development'
3169 assert_select 'option[value="10"][selected=selected]', :text => 'Development'
3170 end
3170 end
3171 assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
3171 assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
3172 end
3172 end
3173
3173
3174 def test_get_edit_with_multi_custom_field
3174 def test_get_edit_with_multi_custom_field
3175 field = CustomField.find(1)
3175 field = CustomField.find(1)
3176 field.update_attribute :multiple, true
3176 field.update_attribute :multiple, true
3177 issue = Issue.find(1)
3177 issue = Issue.find(1)
3178 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3178 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3179 issue.save!
3179 issue.save!
3180
3180
3181 @request.session[:user_id] = 2
3181 @request.session[:user_id] = 2
3182 get :edit, :id => 1
3182 get :edit, :id => 1
3183 assert_response :success
3183 assert_response :success
3184
3184
3185 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
3185 assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
3186 assert_select 'option', 3
3186 assert_select 'option', 3
3187 assert_select 'option[value=MySQL][selected=selected]'
3187 assert_select 'option[value=MySQL][selected=selected]'
3188 assert_select 'option[value=Oracle][selected=selected]'
3188 assert_select 'option[value=Oracle][selected=selected]'
3189 assert_select 'option[value=PostgreSQL]:not([selected])'
3189 assert_select 'option[value=PostgreSQL]:not([selected])'
3190 end
3190 end
3191 end
3191 end
3192
3192
3193 def test_update_form_for_existing_issue
3193 def test_update_form_for_existing_issue
3194 @request.session[:user_id] = 2
3194 @request.session[:user_id] = 2
3195 xhr :patch, :edit, :id => 1,
3195 xhr :patch, :edit, :id => 1,
3196 :issue => {:tracker_id => 2,
3196 :issue => {:tracker_id => 2,
3197 :subject => 'This is the test_new issue',
3197 :subject => 'This is the test_new issue',
3198 :description => 'This is the description',
3198 :description => 'This is the description',
3199 :priority_id => 5}
3199 :priority_id => 5}
3200 assert_response :success
3200 assert_response :success
3201 assert_equal 'text/javascript', response.content_type
3201 assert_equal 'text/javascript', response.content_type
3202
3202
3203 assert_include 'This is the test_new issue', response.body
3203 assert_include 'This is the test_new issue', response.body
3204 end
3204 end
3205
3205
3206 def test_update_form_for_existing_issue_should_keep_issue_author
3206 def test_update_form_for_existing_issue_should_keep_issue_author
3207 @request.session[:user_id] = 3
3207 @request.session[:user_id] = 3
3208 patch :edit, :id => 1, :issue => {:subject => 'Changed'}
3208 patch :edit, :id => 1, :issue => {:subject => 'Changed'}
3209 assert_response :success
3209 assert_response :success
3210
3210
3211 assert_equal User.find(2), Issue.find(1).author
3211 assert_equal User.find(2), Issue.find(1).author
3212 end
3212 end
3213
3213
3214 def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
3214 def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
3215 @request.session[:user_id] = 2
3215 @request.session[:user_id] = 2
3216 WorkflowTransition.delete_all
3216 WorkflowTransition.delete_all
3217 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
3217 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
3218 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
3218 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
3219 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
3219 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
3220
3220
3221 patch :edit, :id => 2,
3221 patch :edit, :id => 2,
3222 :issue => {:tracker_id => 2,
3222 :issue => {:tracker_id => 2,
3223 :status_id => 5,
3223 :status_id => 5,
3224 :subject => 'This is an issue'}
3224 :subject => 'This is an issue'}
3225
3225
3226 assert_select 'select[name=?]', 'issue[status_id]' do
3226 assert_select 'select[name=?]', 'issue[status_id]' do
3227 assert_select 'option[value="1"]'
3227 assert_select 'option[value="1"]'
3228 assert_select 'option[value="2"]'
3228 assert_select 'option[value="2"]'
3229 assert_select 'option[value="5"][selected=selected]'
3229 assert_select 'option[value="5"][selected=selected]'
3230 assert_select 'option', 3
3230 assert_select 'option', 3
3231 end
3231 end
3232 end
3232 end
3233
3233
3234 def test_update_form_for_existing_issue_with_project_change
3234 def test_update_form_for_existing_issue_with_project_change
3235 @request.session[:user_id] = 2
3235 @request.session[:user_id] = 2
3236 patch :edit, :id => 1,
3236 patch :edit, :id => 1,
3237 :issue => {:project_id => 2,
3237 :issue => {:project_id => 2,
3238 :tracker_id => 2,
3238 :tracker_id => 2,
3239 :subject => 'This is the test_new issue',
3239 :subject => 'This is the test_new issue',
3240 :description => 'This is the description',
3240 :description => 'This is the description',
3241 :priority_id => 5}
3241 :priority_id => 5}
3242 assert_response :success
3242 assert_response :success
3243 assert_select 'select[name=?]', 'issue[project_id]' do
3243 assert_select 'select[name=?]', 'issue[project_id]' do
3244 assert_select 'option[value="2"][selected=selected]'
3244 assert_select 'option[value="2"][selected=selected]'
3245 end
3245 end
3246 assert_select 'select[name=?]', 'issue[tracker_id]' do
3246 assert_select 'select[name=?]', 'issue[tracker_id]' do
3247 assert_select 'option[value="2"][selected=selected]'
3247 assert_select 'option[value="2"][selected=selected]'
3248 end
3248 end
3249 assert_select 'input[name=?][value=?]', 'issue[subject]', 'This is the test_new issue'
3249 assert_select 'input[name=?][value=?]', 'issue[subject]', 'This is the test_new issue'
3250 end
3250 end
3251
3251
3252 def test_update_form_should_keep_category_with_same_when_changing_project
3252 def test_update_form_should_keep_category_with_same_when_changing_project
3253 source = Project.generate!
3253 source = Project.generate!
3254 target = Project.generate!
3254 target = Project.generate!
3255 source_category = IssueCategory.create!(:name => 'Foo', :project => source)
3255 source_category = IssueCategory.create!(:name => 'Foo', :project => source)
3256 target_category = IssueCategory.create!(:name => 'Foo', :project => target)
3256 target_category = IssueCategory.create!(:name => 'Foo', :project => target)
3257 issue = Issue.generate!(:project => source, :category => source_category)
3257 issue = Issue.generate!(:project => source, :category => source_category)
3258
3258
3259 @request.session[:user_id] = 1
3259 @request.session[:user_id] = 1
3260 patch :edit, :id => issue.id,
3260 patch :edit, :id => issue.id,
3261 :issue => {:project_id => target.id, :category_id => source_category.id}
3261 :issue => {:project_id => target.id, :category_id => source_category.id}
3262 assert_response :success
3262 assert_response :success
3263
3263
3264 assert_select 'select[name=?]', 'issue[category_id]' do
3264 assert_select 'select[name=?]', 'issue[category_id]' do
3265 assert_select 'option[value=?][selected=selected]', target_category.id.to_s
3265 assert_select 'option[value=?][selected=selected]', target_category.id.to_s
3266 end
3266 end
3267 end
3267 end
3268
3268
3269 def test_update_form_should_propose_default_status_for_existing_issue
3269 def test_update_form_should_propose_default_status_for_existing_issue
3270 @request.session[:user_id] = 2
3270 @request.session[:user_id] = 2
3271 WorkflowTransition.delete_all
3271 WorkflowTransition.delete_all
3272 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
3272 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
3273
3273
3274 patch :edit, :id => 2
3274 patch :edit, :id => 2
3275 assert_response :success
3275 assert_response :success
3276 assert_select 'select[name=?]', 'issue[status_id]' do
3276 assert_select 'select[name=?]', 'issue[status_id]' do
3277 assert_select 'option[value="2"]'
3277 assert_select 'option[value="2"]'
3278 assert_select 'option[value="3"]'
3278 assert_select 'option[value="3"]'
3279 assert_select 'option', 2
3279 assert_select 'option', 2
3280 end
3280 end
3281 end
3281 end
3282
3282
3283 def test_put_update_without_custom_fields_param
3283 def test_put_update_without_custom_fields_param
3284 @request.session[:user_id] = 2
3284 @request.session[:user_id] = 2
3285
3285
3286 issue = Issue.find(1)
3286 issue = Issue.find(1)
3287 assert_equal '125', issue.custom_value_for(2).value
3287 assert_equal '125', issue.custom_value_for(2).value
3288
3288
3289 assert_difference('Journal.count') do
3289 assert_difference('Journal.count') do
3290 assert_difference('JournalDetail.count') do
3290 assert_difference('JournalDetail.count') do
3291 put :update, :id => 1, :issue => {:subject => 'New subject'}
3291 put :update, :id => 1, :issue => {:subject => 'New subject'}
3292 end
3292 end
3293 end
3293 end
3294 assert_redirected_to :action => 'show', :id => '1'
3294 assert_redirected_to :action => 'show', :id => '1'
3295 issue.reload
3295 issue.reload
3296 assert_equal 'New subject', issue.subject
3296 assert_equal 'New subject', issue.subject
3297 # Make sure custom fields were not cleared
3297 # Make sure custom fields were not cleared
3298 assert_equal '125', issue.custom_value_for(2).value
3298 assert_equal '125', issue.custom_value_for(2).value
3299 end
3299 end
3300
3300
3301 def test_put_update_with_project_change
3301 def test_put_update_with_project_change
3302 @request.session[:user_id] = 2
3302 @request.session[:user_id] = 2
3303 ActionMailer::Base.deliveries.clear
3303 ActionMailer::Base.deliveries.clear
3304
3304
3305 with_settings :notified_events => %w(issue_updated) do
3305 with_settings :notified_events => %w(issue_updated) do
3306 assert_difference('Journal.count') do
3306 assert_difference('Journal.count') do
3307 assert_difference('JournalDetail.count', 3) do
3307 assert_difference('JournalDetail.count', 3) do
3308 put :update, :id => 1, :issue => {:project_id => '2',
3308 put :update, :id => 1, :issue => {:project_id => '2',
3309 :tracker_id => '1', # no change
3309 :tracker_id => '1', # no change
3310 :priority_id => '6',
3310 :priority_id => '6',
3311 :category_id => '3'
3311 :category_id => '3'
3312 }
3312 }
3313 end
3313 end
3314 end
3314 end
3315 end
3315 end
3316 assert_redirected_to :action => 'show', :id => '1'
3316 assert_redirected_to :action => 'show', :id => '1'
3317 issue = Issue.find(1)
3317 issue = Issue.find(1)
3318 assert_equal 2, issue.project_id
3318 assert_equal 2, issue.project_id
3319 assert_equal 1, issue.tracker_id
3319 assert_equal 1, issue.tracker_id
3320 assert_equal 6, issue.priority_id
3320 assert_equal 6, issue.priority_id
3321 assert_equal 3, issue.category_id
3321 assert_equal 3, issue.category_id
3322
3322
3323 mail = ActionMailer::Base.deliveries.last
3323 mail = ActionMailer::Base.deliveries.last
3324 assert_not_nil mail
3324 assert_not_nil mail
3325 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3325 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3326 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
3326 assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
3327 end
3327 end
3328
3328
3329 def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_error
3329 def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_error
3330 target = Project.generate!(:tracker_ids => [])
3330 target = Project.generate!(:tracker_ids => [])
3331 assert target.trackers.empty?
3331 assert target.trackers.empty?
3332 issue = Issue.generate!
3332 issue = Issue.generate!
3333 @request.session[:user_id] = 1
3333 @request.session[:user_id] = 1
3334
3334
3335 put :update, :id => issue.id, :issue => {:project_id => target.id}
3335 put :update, :id => issue.id, :issue => {:project_id => target.id}
3336 assert_response 302
3336 assert_response 302
3337 end
3337 end
3338
3338
3339 def test_put_update_with_tracker_change
3339 def test_put_update_with_tracker_change
3340 @request.session[:user_id] = 2
3340 @request.session[:user_id] = 2
3341 ActionMailer::Base.deliveries.clear
3341 ActionMailer::Base.deliveries.clear
3342
3342
3343 with_settings :notified_events => %w(issue_updated) do
3343 with_settings :notified_events => %w(issue_updated) do
3344 assert_difference('Journal.count') do
3344 assert_difference('Journal.count') do
3345 assert_difference('JournalDetail.count', 3) do
3345 assert_difference('JournalDetail.count', 3) do
3346 put :update, :id => 1, :issue => {:project_id => '1',
3346 put :update, :id => 1, :issue => {:project_id => '1',
3347 :tracker_id => '2',
3347 :tracker_id => '2',
3348 :priority_id => '6'
3348 :priority_id => '6'
3349 }
3349 }
3350 end
3350 end
3351 end
3351 end
3352 end
3352 end
3353 assert_redirected_to :action => 'show', :id => '1'
3353 assert_redirected_to :action => 'show', :id => '1'
3354 issue = Issue.find(1)
3354 issue = Issue.find(1)
3355 assert_equal 1, issue.project_id
3355 assert_equal 1, issue.project_id
3356 assert_equal 2, issue.tracker_id
3356 assert_equal 2, issue.tracker_id
3357 assert_equal 6, issue.priority_id
3357 assert_equal 6, issue.priority_id
3358 assert_equal 1, issue.category_id
3358 assert_equal 1, issue.category_id
3359
3359
3360 mail = ActionMailer::Base.deliveries.last
3360 mail = ActionMailer::Base.deliveries.last
3361 assert_not_nil mail
3361 assert_not_nil mail
3362 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3362 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
3363 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
3363 assert_mail_body_match "Tracker changed from Bug to Feature request", mail
3364 end
3364 end
3365
3365
3366 def test_put_update_with_custom_field_change
3366 def test_put_update_with_custom_field_change
3367 @request.session[:user_id] = 2
3367 @request.session[:user_id] = 2
3368 issue = Issue.find(1)
3368 issue = Issue.find(1)
3369 assert_equal '125', issue.custom_value_for(2).value
3369 assert_equal '125', issue.custom_value_for(2).value
3370
3370
3371 with_settings :notified_events => %w(issue_updated) do
3371 with_settings :notified_events => %w(issue_updated) do
3372 assert_difference('Journal.count') do
3372 assert_difference('Journal.count') do
3373 assert_difference('JournalDetail.count', 3) do
3373 assert_difference('JournalDetail.count', 3) do
3374 put :update, :id => 1, :issue => {:subject => 'Custom field change',
3374 put :update, :id => 1, :issue => {:subject => 'Custom field change',
3375 :priority_id => '6',
3375 :priority_id => '6',
3376 :category_id => '1', # no change
3376 :category_id => '1', # no change
3377 :custom_field_values => { '2' => 'New custom value' }
3377 :custom_field_values => { '2' => 'New custom value' }
3378 }
3378 }
3379 end
3379 end
3380 end
3380 end
3381 end
3381 end
3382 assert_redirected_to :action => 'show', :id => '1'
3382 assert_redirected_to :action => 'show', :id => '1'
3383 issue.reload
3383 issue.reload
3384 assert_equal 'New custom value', issue.custom_value_for(2).value
3384 assert_equal 'New custom value', issue.custom_value_for(2).value
3385
3385
3386 mail = ActionMailer::Base.deliveries.last
3386 mail = ActionMailer::Base.deliveries.last
3387 assert_not_nil mail
3387 assert_not_nil mail
3388 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
3388 assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
3389 end
3389 end
3390
3390
3391 def test_put_update_with_multi_custom_field_change
3391 def test_put_update_with_multi_custom_field_change
3392 field = CustomField.find(1)
3392 field = CustomField.find(1)
3393 field.update_attribute :multiple, true
3393 field.update_attribute :multiple, true
3394 issue = Issue.find(1)
3394 issue = Issue.find(1)
3395 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3395 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
3396 issue.save!
3396 issue.save!
3397
3397
3398 @request.session[:user_id] = 2
3398 @request.session[:user_id] = 2
3399 assert_difference('Journal.count') do
3399 assert_difference('Journal.count') do
3400 assert_difference('JournalDetail.count', 3) do
3400 assert_difference('JournalDetail.count', 3) do
3401 put :update, :id => 1,
3401 put :update, :id => 1,
3402 :issue => {
3402 :issue => {
3403 :subject => 'Custom field change',
3403 :subject => 'Custom field change',
3404 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
3404 :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
3405 }
3405 }
3406 end
3406 end
3407 end
3407 end
3408 assert_redirected_to :action => 'show', :id => '1'
3408 assert_redirected_to :action => 'show', :id => '1'
3409 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
3409 assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
3410 end
3410 end
3411
3411
3412 def test_put_update_with_status_and_assignee_change
3412 def test_put_update_with_status_and_assignee_change
3413 issue = Issue.find(1)
3413 issue = Issue.find(1)
3414 assert_equal 1, issue.status_id
3414 assert_equal 1, issue.status_id
3415 @request.session[:user_id] = 2
3415 @request.session[:user_id] = 2
3416
3416
3417 with_settings :notified_events => %w(issue_updated) do
3417 with_settings :notified_events => %w(issue_updated) do
3418 assert_difference('TimeEntry.count', 0) do
3418 assert_difference('TimeEntry.count', 0) do
3419 put :update,
3419 put :update,
3420 :id => 1,
3420 :id => 1,
3421 :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
3421 :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
3422 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
3422 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
3423 end
3423 end
3424 end
3424 end
3425 assert_redirected_to :action => 'show', :id => '1'
3425 assert_redirected_to :action => 'show', :id => '1'
3426 issue.reload
3426 issue.reload
3427 assert_equal 2, issue.status_id
3427 assert_equal 2, issue.status_id
3428 j = Journal.order('id DESC').first
3428 j = Journal.order('id DESC').first
3429 assert_equal 'Assigned to dlopper', j.notes
3429 assert_equal 'Assigned to dlopper', j.notes
3430 assert_equal 2, j.details.size
3430 assert_equal 2, j.details.size
3431
3431
3432 mail = ActionMailer::Base.deliveries.last
3432 mail = ActionMailer::Base.deliveries.last
3433 assert_mail_body_match "Status changed from New to Assigned", mail
3433 assert_mail_body_match "Status changed from New to Assigned", mail
3434 # subject should contain the new status
3434 # subject should contain the new status
3435 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
3435 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
3436 end
3436 end
3437
3437
3438 def test_put_update_with_note_only
3438 def test_put_update_with_note_only
3439 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
3439 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
3440
3440
3441 with_settings :notified_events => %w(issue_updated) do
3441 with_settings :notified_events => %w(issue_updated) do
3442 # anonymous user
3442 # anonymous user
3443 put :update,
3443 put :update,
3444 :id => 1,
3444 :id => 1,
3445 :issue => { :notes => notes }
3445 :issue => { :notes => notes }
3446 end
3446 end
3447 assert_redirected_to :action => 'show', :id => '1'
3447 assert_redirected_to :action => 'show', :id => '1'
3448 j = Journal.order('id DESC').first
3448 j = Journal.order('id DESC').first
3449 assert_equal notes, j.notes
3449 assert_equal notes, j.notes
3450 assert_equal 0, j.details.size
3450 assert_equal 0, j.details.size
3451 assert_equal User.anonymous, j.user
3451 assert_equal User.anonymous, j.user
3452
3452
3453 mail = ActionMailer::Base.deliveries.last
3453 mail = ActionMailer::Base.deliveries.last
3454 assert_mail_body_match notes, mail
3454 assert_mail_body_match notes, mail
3455 end
3455 end
3456
3456
3457 def test_put_update_with_private_note_only
3457 def test_put_update_with_private_note_only
3458 notes = 'Private note'
3458 notes = 'Private note'
3459 @request.session[:user_id] = 2
3459 @request.session[:user_id] = 2
3460
3460
3461 assert_difference 'Journal.count' do
3461 assert_difference 'Journal.count' do
3462 put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
3462 put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
3463 assert_redirected_to :action => 'show', :id => '1'
3463 assert_redirected_to :action => 'show', :id => '1'
3464 end
3464 end
3465
3465
3466 j = Journal.order('id DESC').first
3466 j = Journal.order('id DESC').first
3467 assert_equal notes, j.notes
3467 assert_equal notes, j.notes
3468 assert_equal true, j.private_notes
3468 assert_equal true, j.private_notes
3469 end
3469 end
3470
3470
3471 def test_put_update_with_private_note_and_changes
3471 def test_put_update_with_private_note_and_changes
3472 notes = 'Private note'
3472 notes = 'Private note'
3473 @request.session[:user_id] = 2
3473 @request.session[:user_id] = 2
3474
3474
3475 assert_difference 'Journal.count', 2 do
3475 assert_difference 'Journal.count', 2 do
3476 put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
3476 put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
3477 assert_redirected_to :action => 'show', :id => '1'
3477 assert_redirected_to :action => 'show', :id => '1'
3478 end
3478 end
3479
3479
3480 j = Journal.order('id DESC').first
3480 j = Journal.order('id DESC').first
3481 assert_equal notes, j.notes
3481 assert_equal notes, j.notes
3482 assert_equal true, j.private_notes
3482 assert_equal true, j.private_notes
3483 assert_equal 0, j.details.count
3483 assert_equal 0, j.details.count
3484
3484
3485 j = Journal.order('id DESC').offset(1).first
3485 j = Journal.order('id DESC').offset(1).first
3486 assert_nil j.notes
3486 assert_nil j.notes
3487 assert_equal false, j.private_notes
3487 assert_equal false, j.private_notes
3488 assert_equal 1, j.details.count
3488 assert_equal 1, j.details.count
3489 end
3489 end
3490
3490
3491 def test_put_update_with_note_and_spent_time
3491 def test_put_update_with_note_and_spent_time
3492 @request.session[:user_id] = 2
3492 @request.session[:user_id] = 2
3493 spent_hours_before = Issue.find(1).spent_hours
3493 spent_hours_before = Issue.find(1).spent_hours
3494 assert_difference('TimeEntry.count') do
3494 assert_difference('TimeEntry.count') do
3495 put :update,
3495 put :update,
3496 :id => 1,
3496 :id => 1,
3497 :issue => { :notes => '2.5 hours added' },
3497 :issue => { :notes => '2.5 hours added' },
3498 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
3498 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
3499 end
3499 end
3500 assert_redirected_to :action => 'show', :id => '1'
3500 assert_redirected_to :action => 'show', :id => '1'
3501
3501
3502 issue = Issue.find(1)
3502 issue = Issue.find(1)
3503
3503
3504 j = Journal.order('id DESC').first
3504 j = Journal.order('id DESC').first
3505 assert_equal '2.5 hours added', j.notes
3505 assert_equal '2.5 hours added', j.notes
3506 assert_equal 0, j.details.size
3506 assert_equal 0, j.details.size
3507
3507
3508 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
3508 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
3509 assert_not_nil t
3509 assert_not_nil t
3510 assert_equal 2.5, t.hours
3510 assert_equal 2.5, t.hours
3511 assert_equal spent_hours_before + 2.5, issue.spent_hours
3511 assert_equal spent_hours_before + 2.5, issue.spent_hours
3512 end
3512 end
3513
3513
3514 def test_put_update_should_preserve_parent_issue_even_if_not_visible
3514 def test_put_update_should_preserve_parent_issue_even_if_not_visible
3515 parent = Issue.generate!(:project_id => 1, :is_private => true)
3515 parent = Issue.generate!(:project_id => 1, :is_private => true)
3516 issue = Issue.generate!(:parent_issue_id => parent.id)
3516 issue = Issue.generate!(:parent_issue_id => parent.id)
3517 assert !parent.visible?(User.find(3))
3517 assert !parent.visible?(User.find(3))
3518 @request.session[:user_id] = 3
3518 @request.session[:user_id] = 3
3519
3519
3520 get :edit, :id => issue.id
3520 get :edit, :id => issue.id
3521 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
3521 assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
3522
3522
3523 put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
3523 put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
3524 assert_response 302
3524 assert_response 302
3525 assert_equal parent, issue.parent
3525 assert_equal parent, issue.parent
3526 end
3526 end
3527
3527
3528 def test_put_update_with_attachment_only
3528 def test_put_update_with_attachment_only
3529 set_tmp_attachments_directory
3529 set_tmp_attachments_directory
3530
3530
3531 # Delete all fixtured journals, a race condition can occur causing the wrong
3531 # Delete all fixtured journals, a race condition can occur causing the wrong
3532 # journal to get fetched in the next find.
3532 # journal to get fetched in the next find.
3533 Journal.delete_all
3533 Journal.delete_all
3534
3534
3535 with_settings :notified_events => %w(issue_updated) do
3535 with_settings :notified_events => %w(issue_updated) do
3536 # anonymous user
3536 # anonymous user
3537 assert_difference 'Attachment.count' do
3537 assert_difference 'Attachment.count' do
3538 put :update, :id => 1,
3538 put :update, :id => 1,
3539 :issue => {:notes => ''},
3539 :issue => {:notes => ''},
3540 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3540 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3541 end
3541 end
3542 end
3542 end
3543
3543
3544 assert_redirected_to :action => 'show', :id => '1'
3544 assert_redirected_to :action => 'show', :id => '1'
3545 j = Issue.find(1).journals.reorder('id DESC').first
3545 j = Issue.find(1).journals.reorder('id DESC').first
3546 assert j.notes.blank?
3546 assert j.notes.blank?
3547 assert_equal 1, j.details.size
3547 assert_equal 1, j.details.size
3548 assert_equal 'testfile.txt', j.details.first.value
3548 assert_equal 'testfile.txt', j.details.first.value
3549 assert_equal User.anonymous, j.user
3549 assert_equal User.anonymous, j.user
3550
3550
3551 attachment = Attachment.order('id DESC').first
3551 attachment = Attachment.order('id DESC').first
3552 assert_equal Issue.find(1), attachment.container
3552 assert_equal Issue.find(1), attachment.container
3553 assert_equal User.anonymous, attachment.author
3553 assert_equal User.anonymous, attachment.author
3554 assert_equal 'testfile.txt', attachment.filename
3554 assert_equal 'testfile.txt', attachment.filename
3555 assert_equal 'text/plain', attachment.content_type
3555 assert_equal 'text/plain', attachment.content_type
3556 assert_equal 'test file', attachment.description
3556 assert_equal 'test file', attachment.description
3557 assert_equal 59, attachment.filesize
3557 assert_equal 59, attachment.filesize
3558 assert File.exists?(attachment.diskfile)
3558 assert File.exists?(attachment.diskfile)
3559 assert_equal 59, File.size(attachment.diskfile)
3559 assert_equal 59, File.size(attachment.diskfile)
3560
3560
3561 mail = ActionMailer::Base.deliveries.last
3561 mail = ActionMailer::Base.deliveries.last
3562 assert_mail_body_match 'testfile.txt', mail
3562 assert_mail_body_match 'testfile.txt', mail
3563 end
3563 end
3564
3564
3565 def test_put_update_with_failure_should_save_attachments
3565 def test_put_update_with_failure_should_save_attachments
3566 set_tmp_attachments_directory
3566 set_tmp_attachments_directory
3567 @request.session[:user_id] = 2
3567 @request.session[:user_id] = 2
3568
3568
3569 assert_no_difference 'Journal.count' do
3569 assert_no_difference 'Journal.count' do
3570 assert_difference 'Attachment.count' do
3570 assert_difference 'Attachment.count' do
3571 put :update, :id => 1,
3571 put :update, :id => 1,
3572 :issue => { :subject => '' },
3572 :issue => { :subject => '' },
3573 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3573 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
3574 assert_response :success
3574 assert_response :success
3575 end
3575 end
3576 end
3576 end
3577
3577
3578 attachment = Attachment.order('id DESC').first
3578 attachment = Attachment.order('id DESC').first
3579 assert_equal 'testfile.txt', attachment.filename
3579 assert_equal 'testfile.txt', attachment.filename
3580 assert File.exists?(attachment.diskfile)
3580 assert File.exists?(attachment.diskfile)
3581 assert_nil attachment.container
3581 assert_nil attachment.container
3582
3582
3583 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3583 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3584 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3584 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3585 end
3585 end
3586
3586
3587 def test_put_update_with_failure_should_keep_saved_attachments
3587 def test_put_update_with_failure_should_keep_saved_attachments
3588 set_tmp_attachments_directory
3588 set_tmp_attachments_directory
3589 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3589 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3590 @request.session[:user_id] = 2
3590 @request.session[:user_id] = 2
3591
3591
3592 assert_no_difference 'Journal.count' do
3592 assert_no_difference 'Journal.count' do
3593 assert_no_difference 'Attachment.count' do
3593 assert_no_difference 'Attachment.count' do
3594 put :update, :id => 1,
3594 put :update, :id => 1,
3595 :issue => { :subject => '' },
3595 :issue => { :subject => '' },
3596 :attachments => {'p0' => {'token' => attachment.token}}
3596 :attachments => {'p0' => {'token' => attachment.token}}
3597 assert_response :success
3597 assert_response :success
3598 end
3598 end
3599 end
3599 end
3600
3600
3601 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3601 assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
3602 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3602 assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
3603 end
3603 end
3604
3604
3605 def test_put_update_should_attach_saved_attachments
3605 def test_put_update_should_attach_saved_attachments
3606 set_tmp_attachments_directory
3606 set_tmp_attachments_directory
3607 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3607 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
3608 @request.session[:user_id] = 2
3608 @request.session[:user_id] = 2
3609
3609
3610 assert_difference 'Journal.count' do
3610 assert_difference 'Journal.count' do
3611 assert_difference 'JournalDetail.count' do
3611 assert_difference 'JournalDetail.count' do
3612 assert_no_difference 'Attachment.count' do
3612 assert_no_difference 'Attachment.count' do
3613 put :update, :id => 1,
3613 put :update, :id => 1,
3614 :issue => {:notes => 'Attachment added'},
3614 :issue => {:notes => 'Attachment added'},
3615 :attachments => {'p0' => {'token' => attachment.token}}
3615 :attachments => {'p0' => {'token' => attachment.token}}
3616 assert_redirected_to '/issues/1'
3616 assert_redirected_to '/issues/1'
3617 end
3617 end
3618 end
3618 end
3619 end
3619 end
3620
3620
3621 attachment.reload
3621 attachment.reload
3622 assert_equal Issue.find(1), attachment.container
3622 assert_equal Issue.find(1), attachment.container
3623
3623
3624 journal = Journal.order('id DESC').first
3624 journal = Journal.order('id DESC').first
3625 assert_equal 1, journal.details.size
3625 assert_equal 1, journal.details.size
3626 assert_equal 'testfile.txt', journal.details.first.value
3626 assert_equal 'testfile.txt', journal.details.first.value
3627 end
3627 end
3628
3628
3629 def test_put_update_with_attachment_that_fails_to_save
3629 def test_put_update_with_attachment_that_fails_to_save
3630 set_tmp_attachments_directory
3630 set_tmp_attachments_directory
3631
3631
3632 # anonymous user
3632 # anonymous user
3633 with_settings :attachment_max_size => 0 do
3633 with_settings :attachment_max_size => 0 do
3634 put :update,
3634 put :update,
3635 :id => 1,
3635 :id => 1,
3636 :issue => {:notes => ''},
3636 :issue => {:notes => ''},
3637 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
3637 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
3638 assert_redirected_to :action => 'show', :id => '1'
3638 assert_redirected_to :action => 'show', :id => '1'
3639 assert_equal '1 file(s) could not be saved.', flash[:warning]
3639 assert_equal '1 file(s) could not be saved.', flash[:warning]
3640 end
3640 end
3641 end
3641 end
3642
3642
3643 def test_put_update_with_attachment_deletion_should_create_a_single_journal
3643 def test_put_update_with_attachment_deletion_should_create_a_single_journal
3644 set_tmp_attachments_directory
3644 set_tmp_attachments_directory
3645 @request.session[:user_id] = 2
3645 @request.session[:user_id] = 2
3646
3646
3647 journal = new_record(Journal) do
3647 journal = new_record(Journal) do
3648 assert_difference 'Attachment.count', -2 do
3648 assert_difference 'Attachment.count', -2 do
3649 put :update,
3649 put :update,
3650 :id => 3,
3650 :id => 3,
3651 :issue => {
3651 :issue => {
3652 :notes => 'Removing attachments',
3652 :notes => 'Removing attachments',
3653 :deleted_attachment_ids => ['1', '5']
3653 :deleted_attachment_ids => ['1', '5']
3654 }
3654 }
3655 end
3655 end
3656 end
3656 end
3657 assert_equal 'Removing attachments', journal.notes
3657 assert_equal 'Removing attachments', journal.notes
3658 assert_equal 2, journal.details.count
3658 assert_equal 2, journal.details.count
3659 end
3659 end
3660
3660
3661 def test_put_update_with_attachment_deletion_and_failure_should_preserve_selected_attachments
3661 def test_put_update_with_attachment_deletion_and_failure_should_preserve_selected_attachments
3662 set_tmp_attachments_directory
3662 set_tmp_attachments_directory
3663 @request.session[:user_id] = 2
3663 @request.session[:user_id] = 2
3664
3664
3665 assert_no_difference 'Journal.count' do
3665 assert_no_difference 'Journal.count' do
3666 assert_no_difference 'Attachment.count' do
3666 assert_no_difference 'Attachment.count' do
3667 put :update,
3667 put :update,
3668 :id => 3,
3668 :id => 3,
3669 :issue => {
3669 :issue => {
3670 :subject => '',
3670 :subject => '',
3671 :notes => 'Removing attachments',
3671 :notes => 'Removing attachments',
3672 :deleted_attachment_ids => ['1', '5']
3672 :deleted_attachment_ids => ['1', '5']
3673 }
3673 }
3674 end
3674 end
3675 end
3675 end
3676 assert_select 'input[name=?][value="1"][checked=checked]', 'issue[deleted_attachment_ids][]'
3676 assert_select 'input[name=?][value="1"][checked=checked]', 'issue[deleted_attachment_ids][]'
3677 assert_select 'input[name=?][value="5"][checked=checked]', 'issue[deleted_attachment_ids][]'
3677 assert_select 'input[name=?][value="5"][checked=checked]', 'issue[deleted_attachment_ids][]'
3678 assert_select 'input[name=?][value="6"]:not([checked])', 'issue[deleted_attachment_ids][]'
3678 assert_select 'input[name=?][value="6"]:not([checked])', 'issue[deleted_attachment_ids][]'
3679 end
3679 end
3680
3680
3681 def test_put_update_with_no_change
3681 def test_put_update_with_no_change
3682 issue = Issue.find(1)
3682 issue = Issue.find(1)
3683 issue.journals.clear
3683 issue.journals.clear
3684 ActionMailer::Base.deliveries.clear
3684 ActionMailer::Base.deliveries.clear
3685
3685
3686 put :update,
3686 put :update,
3687 :id => 1,
3687 :id => 1,
3688 :issue => {:notes => ''}
3688 :issue => {:notes => ''}
3689 assert_redirected_to :action => 'show', :id => '1'
3689 assert_redirected_to :action => 'show', :id => '1'
3690
3690
3691 issue.reload
3691 issue.reload
3692 assert issue.journals.empty?
3692 assert issue.journals.empty?
3693 # No email should be sent
3693 # No email should be sent
3694 assert ActionMailer::Base.deliveries.empty?
3694 assert ActionMailer::Base.deliveries.empty?
3695 end
3695 end
3696
3696
3697 def test_put_update_should_send_a_notification
3697 def test_put_update_should_send_a_notification
3698 @request.session[:user_id] = 2
3698 @request.session[:user_id] = 2
3699 ActionMailer::Base.deliveries.clear
3699 ActionMailer::Base.deliveries.clear
3700 issue = Issue.find(1)
3700 issue = Issue.find(1)
3701 old_subject = issue.subject
3701 old_subject = issue.subject
3702 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
3702 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
3703
3703
3704 with_settings :notified_events => %w(issue_updated) do
3704 with_settings :notified_events => %w(issue_updated) do
3705 put :update, :id => 1, :issue => {:subject => new_subject,
3705 put :update, :id => 1, :issue => {:subject => new_subject,
3706 :priority_id => '6',
3706 :priority_id => '6',
3707 :category_id => '1' # no change
3707 :category_id => '1' # no change
3708 }
3708 }
3709 assert_equal 1, ActionMailer::Base.deliveries.size
3709 assert_equal 1, ActionMailer::Base.deliveries.size
3710 end
3710 end
3711 end
3711 end
3712
3712
3713 def test_put_update_with_invalid_spent_time_hours_only
3713 def test_put_update_with_invalid_spent_time_hours_only
3714 @request.session[:user_id] = 2
3714 @request.session[:user_id] = 2
3715 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3715 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3716
3716
3717 assert_no_difference('Journal.count') do
3717 assert_no_difference('Journal.count') do
3718 put :update,
3718 put :update,
3719 :id => 1,
3719 :id => 1,
3720 :issue => {:notes => notes},
3720 :issue => {:notes => notes},
3721 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
3721 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
3722 end
3722 end
3723 assert_response :success
3723 assert_response :success
3724
3724
3725 assert_select_error /Activity cannot be blank/
3725 assert_select_error /Activity cannot be blank/
3726 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3726 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3727 assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
3727 assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
3728 end
3728 end
3729
3729
3730 def test_put_update_with_invalid_spent_time_comments_only
3730 def test_put_update_with_invalid_spent_time_comments_only
3731 @request.session[:user_id] = 2
3731 @request.session[:user_id] = 2
3732 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3732 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
3733
3733
3734 assert_no_difference('Journal.count') do
3734 assert_no_difference('Journal.count') do
3735 put :update,
3735 put :update,
3736 :id => 1,
3736 :id => 1,
3737 :issue => {:notes => notes},
3737 :issue => {:notes => notes},
3738 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
3738 :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
3739 end
3739 end
3740 assert_response :success
3740 assert_response :success
3741
3741
3742 assert_select_error /Activity cannot be blank/
3742 assert_select_error /Activity cannot be blank/
3743 assert_select_error /Hours cannot be blank/
3743 assert_select_error /Hours cannot be blank/
3744 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3744 assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
3745 assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
3745 assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
3746 end
3746 end
3747
3747
3748 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
3748 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
3749 issue = Issue.find(2)
3749 issue = Issue.find(2)
3750 @request.session[:user_id] = 2
3750 @request.session[:user_id] = 2
3751
3751
3752 put :update,
3752 put :update,
3753 :id => issue.id,
3753 :id => issue.id,
3754 :issue => {
3754 :issue => {
3755 :fixed_version_id => 4
3755 :fixed_version_id => 4
3756 }
3756 }
3757
3757
3758 assert_response :redirect
3758 assert_response :redirect
3759 issue.reload
3759 issue.reload
3760 assert_equal 4, issue.fixed_version_id
3760 assert_equal 4, issue.fixed_version_id
3761 assert_not_equal issue.project_id, issue.fixed_version.project_id
3761 assert_not_equal issue.project_id, issue.fixed_version.project_id
3762 end
3762 end
3763
3763
3764 def test_put_update_should_redirect_back_using_the_back_url_parameter
3764 def test_put_update_should_redirect_back_using_the_back_url_parameter
3765 issue = Issue.find(2)
3765 issue = Issue.find(2)
3766 @request.session[:user_id] = 2
3766 @request.session[:user_id] = 2
3767
3767
3768 put :update,
3768 put :update,
3769 :id => issue.id,
3769 :id => issue.id,
3770 :issue => {
3770 :issue => {
3771 :fixed_version_id => 4
3771 :fixed_version_id => 4
3772 },
3772 },
3773 :back_url => '/issues'
3773 :back_url => '/issues'
3774
3774
3775 assert_response :redirect
3775 assert_response :redirect
3776 assert_redirected_to '/issues'
3776 assert_redirected_to '/issues'
3777 end
3777 end
3778
3778
3779 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3779 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
3780 issue = Issue.find(2)
3780 issue = Issue.find(2)
3781 @request.session[:user_id] = 2
3781 @request.session[:user_id] = 2
3782
3782
3783 put :update,
3783 put :update,
3784 :id => issue.id,
3784 :id => issue.id,
3785 :issue => {
3785 :issue => {
3786 :fixed_version_id => 4
3786 :fixed_version_id => 4
3787 },
3787 },
3788 :back_url => 'http://google.com'
3788 :back_url => 'http://google.com'
3789
3789
3790 assert_response :redirect
3790 assert_response :redirect
3791 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3791 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3792 end
3792 end
3793
3793
3794 def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3794 def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3795 @request.session[:user_id] = 2
3795 @request.session[:user_id] = 2
3796
3796
3797 put :update, :id => 11,
3797 put :update, :id => 11,
3798 :issue => {:status_id => 6, :notes => 'Notes'},
3798 :issue => {:status_id => 6, :notes => 'Notes'},
3799 :prev_issue_id => 8,
3799 :prev_issue_id => 8,
3800 :next_issue_id => 12,
3800 :next_issue_id => 12,
3801 :issue_position => 2,
3801 :issue_position => 2,
3802 :issue_count => 3
3802 :issue_count => 3
3803
3803
3804 assert_redirected_to '/issues/11?issue_count=3&issue_position=2&next_issue_id=12&prev_issue_id=8'
3804 assert_redirected_to '/issues/11?issue_count=3&issue_position=2&next_issue_id=12&prev_issue_id=8'
3805 end
3805 end
3806
3806
3807 def test_update_with_permission_on_tracker_should_be_allowed
3807 def test_update_with_permission_on_tracker_should_be_allowed
3808 role = Role.find(1)
3808 role = Role.find(1)
3809 role.set_permission_trackers :edit_issues, [1]
3809 role.set_permission_trackers :edit_issues, [1]
3810 role.save!
3810 role.save!
3811 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Original subject')
3811 issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Original subject')
3812
3812
3813 @request.session[:user_id] = 2
3813 @request.session[:user_id] = 2
3814 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3814 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3815 assert_response 302
3815 assert_response 302
3816 assert_equal 'Changed subject', issue.reload.subject
3816 assert_equal 'Changed subject', issue.reload.subject
3817 end
3817 end
3818
3818
3819 def test_update_without_permission_on_tracker_should_be_denied
3819 def test_update_without_permission_on_tracker_should_be_denied
3820 role = Role.find(1)
3820 role = Role.find(1)
3821 role.set_permission_trackers :edit_issues, [1]
3821 role.set_permission_trackers :edit_issues, [1]
3822 role.save!
3822 role.save!
3823 issue = Issue.generate!(:project_id => 1, :tracker_id => 2, :subject => 'Original subject')
3823 issue = Issue.generate!(:project_id => 1, :tracker_id => 2, :subject => 'Original subject')
3824
3824
3825 @request.session[:user_id] = 2
3825 @request.session[:user_id] = 2
3826 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3826 put :update, :id => issue.id, :issue => {:subject => 'Changed subject'}
3827 assert_response 302
3827 assert_response 302
3828 assert_equal 'Original subject', issue.reload.subject
3828 assert_equal 'Original subject', issue.reload.subject
3829 end
3829 end
3830
3830
3831 def test_get_bulk_edit
3831 def test_get_bulk_edit
3832 @request.session[:user_id] = 2
3832 @request.session[:user_id] = 2
3833 get :bulk_edit, :ids => [1, 3]
3833 get :bulk_edit, :ids => [1, 3]
3834 assert_response :success
3834 assert_response :success
3835
3835
3836 assert_select 'ul#bulk-selection' do
3836 assert_select 'ul#bulk-selection' do
3837 assert_select 'li', 2
3837 assert_select 'li', 2
3838 assert_select 'li a', :text => 'Bug #1'
3838 assert_select 'li a', :text => 'Bug #1'
3839 end
3839 end
3840
3840
3841 assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
3841 assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
3842 assert_select 'input[name=?]', 'ids[]', 2
3842 assert_select 'input[name=?]', 'ids[]', 2
3843 assert_select 'input[name=?][value="1"][type=hidden]', 'ids[]'
3843 assert_select 'input[name=?][value="1"][type=hidden]', 'ids[]'
3844
3844
3845 assert_select 'select[name=?]', 'issue[project_id]'
3845 assert_select 'select[name=?]', 'issue[project_id]'
3846 assert_select 'input[name=?]', 'issue[parent_issue_id]'
3846 assert_select 'input[name=?]', 'issue[parent_issue_id]'
3847
3847
3848 # Project specific custom field, date type
3848 # Project specific custom field, date type
3849 field = CustomField.find(9)
3849 field = CustomField.find(9)
3850 assert !field.is_for_all?
3850 assert !field.is_for_all?
3851 assert_equal 'date', field.field_format
3851 assert_equal 'date', field.field_format
3852 assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3852 assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3853
3853
3854 # System wide custom field
3854 # System wide custom field
3855 assert CustomField.find(1).is_for_all?
3855 assert CustomField.find(1).is_for_all?
3856 assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3856 assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3857
3857
3858 # Be sure we don't display inactive IssuePriorities
3858 # Be sure we don't display inactive IssuePriorities
3859 assert ! IssuePriority.find(15).active?
3859 assert ! IssuePriority.find(15).active?
3860 assert_select 'select[name=?]', 'issue[priority_id]' do
3860 assert_select 'select[name=?]', 'issue[priority_id]' do
3861 assert_select 'option[value="15"]', 0
3861 assert_select 'option[value="15"]', 0
3862 end
3862 end
3863 end
3863 end
3864 end
3864 end
3865
3865
3866 def test_get_bulk_edit_on_different_projects
3866 def test_get_bulk_edit_on_different_projects
3867 @request.session[:user_id] = 2
3867 @request.session[:user_id] = 2
3868 get :bulk_edit, :ids => [1, 2, 6]
3868 get :bulk_edit, :ids => [1, 2, 6]
3869 assert_response :success
3869 assert_response :success
3870
3870
3871 # Can not set issues from different projects as children of an issue
3871 # Can not set issues from different projects as children of an issue
3872 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
3872 assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
3873
3873
3874 # Project specific custom field, date type
3874 # Project specific custom field, date type
3875 field = CustomField.find(9)
3875 field = CustomField.find(9)
3876 assert !field.is_for_all?
3876 assert !field.is_for_all?
3877 assert !field.project_ids.include?(Issue.find(6).project_id)
3877 assert !field.project_ids.include?(Issue.find(6).project_id)
3878 assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
3878 assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
3879 end
3879 end
3880
3880
3881 def test_get_bulk_edit_with_user_custom_field
3881 def test_get_bulk_edit_with_user_custom_field
3882 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :tracker_ids => [1,2,3])
3882 field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true, :tracker_ids => [1,2,3])
3883
3883
3884 @request.session[:user_id] = 2
3884 @request.session[:user_id] = 2
3885 get :bulk_edit, :ids => [1, 2]
3885 get :bulk_edit, :ids => [1, 2]
3886 assert_response :success
3886 assert_response :success
3887
3887
3888 assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3888 assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3889 assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
3889 assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
3890 end
3890 end
3891 end
3891 end
3892
3892
3893 def test_get_bulk_edit_with_version_custom_field
3893 def test_get_bulk_edit_with_version_custom_field
3894 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
3894 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
3895
3895
3896 @request.session[:user_id] = 2
3896 @request.session[:user_id] = 2
3897 get :bulk_edit, :ids => [1, 2]
3897 get :bulk_edit, :ids => [1, 2]
3898 assert_response :success
3898 assert_response :success
3899
3899
3900 assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3900 assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
3901 assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
3901 assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
3902 end
3902 end
3903 end
3903 end
3904
3904
3905 def test_get_bulk_edit_with_multi_custom_field
3905 def test_get_bulk_edit_with_multi_custom_field
3906 field = CustomField.find(1)
3906 field = CustomField.find(1)
3907 field.update_attribute :multiple, true
3907 field.update_attribute :multiple, true
3908
3908
3909 @request.session[:user_id] = 2
3909 @request.session[:user_id] = 2
3910 get :bulk_edit, :ids => [1, 3]
3910 get :bulk_edit, :ids => [1, 3]
3911 assert_response :success
3911 assert_response :success
3912
3912
3913 assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
3913 assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
3914 assert_select 'option', field.possible_values.size + 1 # "none" options
3914 assert_select 'option', field.possible_values.size + 1 # "none" options
3915 end
3915 end
3916 end
3916 end
3917
3917
3918 def test_bulk_edit_should_propose_to_clear_text_custom_fields
3918 def test_bulk_edit_should_propose_to_clear_text_custom_fields
3919 @request.session[:user_id] = 2
3919 @request.session[:user_id] = 2
3920 get :bulk_edit, :ids => [1, 3]
3920 get :bulk_edit, :ids => [1, 3]
3921 assert_response :success
3921 assert_response :success
3922
3922
3923 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
3923 assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
3924 end
3924 end
3925
3925
3926 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
3926 def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
3927 WorkflowTransition.delete_all
3927 WorkflowTransition.delete_all
3928 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3928 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3929 :old_status_id => 1, :new_status_id => 1)
3929 :old_status_id => 1, :new_status_id => 1)
3930 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3930 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3931 :old_status_id => 1, :new_status_id => 3)
3931 :old_status_id => 1, :new_status_id => 3)
3932 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3932 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
3933 :old_status_id => 1, :new_status_id => 4)
3933 :old_status_id => 1, :new_status_id => 4)
3934 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3934 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3935 :old_status_id => 2, :new_status_id => 1)
3935 :old_status_id => 2, :new_status_id => 1)
3936 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3936 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3937 :old_status_id => 2, :new_status_id => 3)
3937 :old_status_id => 2, :new_status_id => 3)
3938 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3938 WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
3939 :old_status_id => 2, :new_status_id => 5)
3939 :old_status_id => 2, :new_status_id => 5)
3940 @request.session[:user_id] = 2
3940 @request.session[:user_id] = 2
3941 get :bulk_edit, :ids => [1, 2]
3941 get :bulk_edit, :ids => [1, 2]
3942
3942
3943 assert_select 'select[name=?]', 'issue[status_id]' do
3943 assert_select 'select[name=?]', 'issue[status_id]' do
3944 assert_select 'option[value=""]'
3944 assert_select 'option[value=""]'
3945 assert_select 'option[value="1"]'
3945 assert_select 'option[value="1"]'
3946 assert_select 'option[value="3"]'
3946 assert_select 'option[value="3"]'
3947 assert_select 'option', 3 # 2 statuses + "no change" option
3947 assert_select 'option', 3 # 2 statuses + "no change" option
3948 end
3948 end
3949 end
3949 end
3950
3950
3951 def test_bulk_edit_should_propose_target_project_open_shared_versions
3951 def test_bulk_edit_should_propose_target_project_open_shared_versions
3952 @request.session[:user_id] = 2
3952 @request.session[:user_id] = 2
3953 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3953 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3954 assert_response :success
3954 assert_response :success
3955
3955
3956 expected_versions = Project.find(1).shared_versions.open.to_a.sort
3956 expected_versions = Project.find(1).shared_versions.open.to_a.sort
3957
3957
3958 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
3958 assert_select 'select[name=?]', 'issue[fixed_version_id]' do
3959 expected_versions.each do |version|
3959 expected_versions.each do |version|
3960 assert_select 'option[value=?]', version.id.to_s
3960 assert_select 'option[value=?]', version.id.to_s
3961 end
3961 end
3962 assert_select 'option[value=""]'
3962 assert_select 'option[value=""]'
3963 assert_select 'option[value="none"]'
3963 assert_select 'option[value="none"]'
3964 assert_select 'option', expected_versions.size + 2
3964 assert_select 'option', expected_versions.size + 2
3965 end
3965 end
3966 end
3966 end
3967
3967
3968 def test_bulk_edit_should_propose_target_project_categories
3968 def test_bulk_edit_should_propose_target_project_categories
3969 @request.session[:user_id] = 2
3969 @request.session[:user_id] = 2
3970 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3970 post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
3971 assert_response :success
3971 assert_response :success
3972
3972
3973 expected_categories = Project.find(1).issue_categories.sort
3973 expected_categories = Project.find(1).issue_categories.sort
3974
3974
3975 assert_select 'select[name=?]', 'issue[category_id]' do
3975 assert_select 'select[name=?]', 'issue[category_id]' do
3976 expected_categories.each do |category|
3976 expected_categories.each do |category|
3977 assert_select 'option[value=?]', category.id.to_s
3977 assert_select 'option[value=?]', category.id.to_s
3978 end
3978 end
3979 assert_select 'option[value=""]'
3979 assert_select 'option[value=""]'
3980 assert_select 'option[value="none"]'
3980 assert_select 'option[value="none"]'
3981 assert_select 'option', expected_categories.size + 2
3981 assert_select 'option', expected_categories.size + 2
3982 end
3982 end
3983 end
3983 end
3984
3984
3985 def test_bulk_edit_should_only_propose_issues_trackers_custom_fields
3985 def test_bulk_edit_should_only_propose_issues_trackers_custom_fields
3986 IssueCustomField.delete_all
3986 IssueCustomField.delete_all
3987 field1 = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
3987 field1 = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
3988 field2 = IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
3988 field2 = IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
3989 @request.session[:user_id] = 2
3989 @request.session[:user_id] = 2
3990
3990
3991 issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
3991 issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
3992 get :bulk_edit, :ids => issue_ids
3992 get :bulk_edit, :ids => issue_ids
3993 assert_response :success
3993 assert_response :success
3994
3994
3995 assert_select 'input[name=?]', "issue[custom_field_values][#{field1.id}]"
3995 assert_select 'input[name=?]', "issue[custom_field_values][#{field1.id}]"
3996 assert_select 'input[name=?]', "issue[custom_field_values][#{field2.id}]", 0
3996 assert_select 'input[name=?]', "issue[custom_field_values][#{field2.id}]", 0
3997 end
3997 end
3998
3998
3999 def test_bulk_edit_should_propose_target_tracker_custom_fields
4000 IssueCustomField.delete_all
4001 field1 = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
4002 field2 = IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
4003 @request.session[:user_id] = 2
4004
4005 issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
4006 get :bulk_edit, :ids => issue_ids, :issue => {:tracker_id => 2}
4007 assert_response :success
4008
4009 assert_select 'input[name=?]', "issue[custom_field_values][#{field1.id}]", 0
4010 assert_select 'input[name=?]', "issue[custom_field_values][#{field2.id}]"
4011 end
4012
3999 def test_bulk_update
4013 def test_bulk_update
4000 @request.session[:user_id] = 2
4014 @request.session[:user_id] = 2
4001 # update issues priority
4015 # update issues priority
4002 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4016 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4003 :issue => {:priority_id => 7,
4017 :issue => {:priority_id => 7,
4004 :assigned_to_id => '',
4018 :assigned_to_id => '',
4005 :custom_field_values => {'2' => ''}}
4019 :custom_field_values => {'2' => ''}}
4006
4020
4007 assert_response 302
4021 assert_response 302
4008 # check that the issues were updated
4022 # check that the issues were updated
4009 assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
4023 assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
4010
4024
4011 issue = Issue.find(1)
4025 issue = Issue.find(1)
4012 journal = issue.journals.reorder('created_on DESC').first
4026 journal = issue.journals.reorder('created_on DESC').first
4013 assert_equal '125', issue.custom_value_for(2).value
4027 assert_equal '125', issue.custom_value_for(2).value
4014 assert_equal 'Bulk editing', journal.notes
4028 assert_equal 'Bulk editing', journal.notes
4015 assert_equal 1, journal.details.size
4029 assert_equal 1, journal.details.size
4016 end
4030 end
4017
4031
4018 def test_bulk_update_with_group_assignee
4032 def test_bulk_update_with_group_assignee
4019 group = Group.find(11)
4033 group = Group.find(11)
4020 project = Project.find(1)
4034 project = Project.find(1)
4021 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
4035 project.members << Member.new(:principal => group, :roles => [Role.givable.first])
4022
4036
4023 @request.session[:user_id] = 2
4037 @request.session[:user_id] = 2
4024 # update issues assignee
4038 # update issues assignee
4025 with_settings :issue_group_assignment => '1' do
4039 with_settings :issue_group_assignment => '1' do
4026 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4040 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
4027 :issue => {:priority_id => '',
4041 :issue => {:priority_id => '',
4028 :assigned_to_id => group.id,
4042 :assigned_to_id => group.id,
4029 :custom_field_values => {'2' => ''}}
4043 :custom_field_values => {'2' => ''}}
4030
4044
4031 assert_response 302
4045 assert_response 302
4032 assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4046 assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4033 end
4047 end
4034 end
4048 end
4035
4049
4036 def test_bulk_update_on_different_projects
4050 def test_bulk_update_on_different_projects
4037 @request.session[:user_id] = 2
4051 @request.session[:user_id] = 2
4038 # update issues priority
4052 # update issues priority
4039 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
4053 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
4040 :issue => {:priority_id => 7,
4054 :issue => {:priority_id => 7,
4041 :assigned_to_id => '',
4055 :assigned_to_id => '',
4042 :custom_field_values => {'2' => ''}}
4056 :custom_field_values => {'2' => ''}}
4043
4057
4044 assert_response 302
4058 assert_response 302
4045 # check that the issues were updated
4059 # check that the issues were updated
4046 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
4060 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
4047
4061
4048 issue = Issue.find(1)
4062 issue = Issue.find(1)
4049 journal = issue.journals.reorder('created_on DESC').first
4063 journal = issue.journals.reorder('created_on DESC').first
4050 assert_equal '125', issue.custom_value_for(2).value
4064 assert_equal '125', issue.custom_value_for(2).value
4051 assert_equal 'Bulk editing', journal.notes
4065 assert_equal 'Bulk editing', journal.notes
4052 assert_equal 1, journal.details.size
4066 assert_equal 1, journal.details.size
4053 end
4067 end
4054
4068
4055 def test_bulk_update_on_different_projects_without_rights
4069 def test_bulk_update_on_different_projects_without_rights
4056 @request.session[:user_id] = 3
4070 @request.session[:user_id] = 3
4057 user = User.find(3)
4071 user = User.find(3)
4058 action = { :controller => "issues", :action => "bulk_update" }
4072 action = { :controller => "issues", :action => "bulk_update" }
4059 assert user.allowed_to?(action, Issue.find(1).project)
4073 assert user.allowed_to?(action, Issue.find(1).project)
4060 assert ! user.allowed_to?(action, Issue.find(6).project)
4074 assert ! user.allowed_to?(action, Issue.find(6).project)
4061 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
4075 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
4062 :issue => {:priority_id => 7,
4076 :issue => {:priority_id => 7,
4063 :assigned_to_id => '',
4077 :assigned_to_id => '',
4064 :custom_field_values => {'2' => ''}}
4078 :custom_field_values => {'2' => ''}}
4065 assert_response 403
4079 assert_response 403
4066 assert_not_equal "Bulk should fail", Journal.last.notes
4080 assert_not_equal "Bulk should fail", Journal.last.notes
4067 end
4081 end
4068
4082
4069 def test_bullk_update_should_send_a_notification
4083 def test_bullk_update_should_send_a_notification
4070 @request.session[:user_id] = 2
4084 @request.session[:user_id] = 2
4071 ActionMailer::Base.deliveries.clear
4085 ActionMailer::Base.deliveries.clear
4072 with_settings :notified_events => %w(issue_updated) do
4086 with_settings :notified_events => %w(issue_updated) do
4073 post(:bulk_update,
4087 post(:bulk_update,
4074 {
4088 {
4075 :ids => [1, 2],
4089 :ids => [1, 2],
4076 :notes => 'Bulk editing',
4090 :notes => 'Bulk editing',
4077 :issue => {
4091 :issue => {
4078 :priority_id => 7,
4092 :priority_id => 7,
4079 :assigned_to_id => '',
4093 :assigned_to_id => '',
4080 :custom_field_values => {'2' => ''}
4094 :custom_field_values => {'2' => ''}
4081 }
4095 }
4082 })
4096 })
4083 assert_response 302
4097 assert_response 302
4084 assert_equal 2, ActionMailer::Base.deliveries.size
4098 assert_equal 2, ActionMailer::Base.deliveries.size
4085 end
4099 end
4086 end
4100 end
4087
4101
4088 def test_bulk_update_project
4102 def test_bulk_update_project
4089 @request.session[:user_id] = 2
4103 @request.session[:user_id] = 2
4090 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
4104 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
4091 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4105 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4092 # Issues moved to project 2
4106 # Issues moved to project 2
4093 assert_equal 2, Issue.find(1).project_id
4107 assert_equal 2, Issue.find(1).project_id
4094 assert_equal 2, Issue.find(2).project_id
4108 assert_equal 2, Issue.find(2).project_id
4095 # No tracker change
4109 # No tracker change
4096 assert_equal 1, Issue.find(1).tracker_id
4110 assert_equal 1, Issue.find(1).tracker_id
4097 assert_equal 2, Issue.find(2).tracker_id
4111 assert_equal 2, Issue.find(2).tracker_id
4098 end
4112 end
4099
4113
4100 def test_bulk_update_project_on_single_issue_should_follow_when_needed
4114 def test_bulk_update_project_on_single_issue_should_follow_when_needed
4101 @request.session[:user_id] = 2
4115 @request.session[:user_id] = 2
4102 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
4116 post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
4103 assert_redirected_to '/issues/1'
4117 assert_redirected_to '/issues/1'
4104 end
4118 end
4105
4119
4106 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
4120 def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
4107 @request.session[:user_id] = 2
4121 @request.session[:user_id] = 2
4108 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
4122 post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
4109 assert_redirected_to '/projects/onlinestore/issues'
4123 assert_redirected_to '/projects/onlinestore/issues'
4110 end
4124 end
4111
4125
4112 def test_bulk_update_tracker
4126 def test_bulk_update_tracker
4113 @request.session[:user_id] = 2
4127 @request.session[:user_id] = 2
4114 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
4128 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
4115 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4129 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4116 assert_equal 2, Issue.find(1).tracker_id
4130 assert_equal 2, Issue.find(1).tracker_id
4117 assert_equal 2, Issue.find(2).tracker_id
4131 assert_equal 2, Issue.find(2).tracker_id
4118 end
4132 end
4119
4133
4120 def test_bulk_update_status
4134 def test_bulk_update_status
4121 @request.session[:user_id] = 2
4135 @request.session[:user_id] = 2
4122 # update issues priority
4136 # update issues priority
4123 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
4137 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
4124 :issue => {:priority_id => '',
4138 :issue => {:priority_id => '',
4125 :assigned_to_id => '',
4139 :assigned_to_id => '',
4126 :status_id => '5'}
4140 :status_id => '5'}
4127
4141
4128 assert_response 302
4142 assert_response 302
4129 issue = Issue.find(1)
4143 issue = Issue.find(1)
4130 assert issue.closed?
4144 assert issue.closed?
4131 end
4145 end
4132
4146
4133 def test_bulk_update_priority
4147 def test_bulk_update_priority
4134 @request.session[:user_id] = 2
4148 @request.session[:user_id] = 2
4135 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
4149 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
4136
4150
4137 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4151 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4138 assert_equal 6, Issue.find(1).priority_id
4152 assert_equal 6, Issue.find(1).priority_id
4139 assert_equal 6, Issue.find(2).priority_id
4153 assert_equal 6, Issue.find(2).priority_id
4140 end
4154 end
4141
4155
4142 def test_bulk_update_with_notes
4156 def test_bulk_update_with_notes
4143 @request.session[:user_id] = 2
4157 @request.session[:user_id] = 2
4144 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
4158 post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
4145
4159
4146 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4160 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4147 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
4161 assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
4148 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
4162 assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
4149 end
4163 end
4150
4164
4151 def test_bulk_update_parent_id
4165 def test_bulk_update_parent_id
4152 IssueRelation.delete_all
4166 IssueRelation.delete_all
4153 @request.session[:user_id] = 2
4167 @request.session[:user_id] = 2
4154 post :bulk_update, :ids => [1, 3],
4168 post :bulk_update, :ids => [1, 3],
4155 :notes => 'Bulk editing parent',
4169 :notes => 'Bulk editing parent',
4156 :issue => {:priority_id => '', :assigned_to_id => '',
4170 :issue => {:priority_id => '', :assigned_to_id => '',
4157 :status_id => '', :parent_issue_id => '2'}
4171 :status_id => '', :parent_issue_id => '2'}
4158 assert_response 302
4172 assert_response 302
4159 parent = Issue.find(2)
4173 parent = Issue.find(2)
4160 assert_equal parent.id, Issue.find(1).parent_id
4174 assert_equal parent.id, Issue.find(1).parent_id
4161 assert_equal parent.id, Issue.find(3).parent_id
4175 assert_equal parent.id, Issue.find(3).parent_id
4162 assert_equal [1, 3], parent.children.collect(&:id).sort
4176 assert_equal [1, 3], parent.children.collect(&:id).sort
4163 end
4177 end
4164
4178
4165 def test_bulk_update_estimated_hours
4179 def test_bulk_update_estimated_hours
4166 @request.session[:user_id] = 2
4180 @request.session[:user_id] = 2
4167 post :bulk_update, :ids => [1, 2], :issue => {:estimated_hours => 4.25}
4181 post :bulk_update, :ids => [1, 2], :issue => {:estimated_hours => 4.25}
4168
4182
4169 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4183 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
4170 assert_equal 4.25, Issue.find(1).estimated_hours
4184 assert_equal 4.25, Issue.find(1).estimated_hours
4171 assert_equal 4.25, Issue.find(2).estimated_hours
4185 assert_equal 4.25, Issue.find(2).estimated_hours
4172 end
4186 end
4173
4187
4174 def test_bulk_update_custom_field
4188 def test_bulk_update_custom_field
4175 @request.session[:user_id] = 2
4189 @request.session[:user_id] = 2
4176 # update issues priority
4190 # update issues priority
4177 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
4191 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
4178 :issue => {:priority_id => '',
4192 :issue => {:priority_id => '',
4179 :assigned_to_id => '',
4193 :assigned_to_id => '',
4180 :custom_field_values => {'2' => '777'}}
4194 :custom_field_values => {'2' => '777'}}
4181
4195
4182 assert_response 302
4196 assert_response 302
4183
4197
4184 issue = Issue.find(1)
4198 issue = Issue.find(1)
4185 journal = issue.journals.reorder('created_on DESC').first
4199 journal = issue.journals.reorder('created_on DESC').first
4186 assert_equal '777', issue.custom_value_for(2).value
4200 assert_equal '777', issue.custom_value_for(2).value
4187 assert_equal 1, journal.details.size
4201 assert_equal 1, journal.details.size
4188 assert_equal '125', journal.details.first.old_value
4202 assert_equal '125', journal.details.first.old_value
4189 assert_equal '777', journal.details.first.value
4203 assert_equal '777', journal.details.first.value
4190 end
4204 end
4191
4205
4192 def test_bulk_update_custom_field_to_blank
4206 def test_bulk_update_custom_field_to_blank
4193 @request.session[:user_id] = 2
4207 @request.session[:user_id] = 2
4194 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
4208 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
4195 :issue => {:priority_id => '',
4209 :issue => {:priority_id => '',
4196 :assigned_to_id => '',
4210 :assigned_to_id => '',
4197 :custom_field_values => {'1' => '__none__'}}
4211 :custom_field_values => {'1' => '__none__'}}
4198 assert_response 302
4212 assert_response 302
4199 assert_equal '', Issue.find(1).custom_field_value(1)
4213 assert_equal '', Issue.find(1).custom_field_value(1)
4200 assert_equal '', Issue.find(3).custom_field_value(1)
4214 assert_equal '', Issue.find(3).custom_field_value(1)
4201 end
4215 end
4202
4216
4203 def test_bulk_update_multi_custom_field
4217 def test_bulk_update_multi_custom_field
4204 field = CustomField.find(1)
4218 field = CustomField.find(1)
4205 field.update_attribute :multiple, true
4219 field.update_attribute :multiple, true
4206
4220
4207 @request.session[:user_id] = 2
4221 @request.session[:user_id] = 2
4208 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
4222 post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
4209 :issue => {:priority_id => '',
4223 :issue => {:priority_id => '',
4210 :assigned_to_id => '',
4224 :assigned_to_id => '',
4211 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
4225 :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
4212
4226
4213 assert_response 302
4227 assert_response 302
4214
4228
4215 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
4229 assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
4216 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
4230 assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
4217 # the custom field is not associated with the issue tracker
4231 # the custom field is not associated with the issue tracker
4218 assert_nil Issue.find(2).custom_field_value(1)
4232 assert_nil Issue.find(2).custom_field_value(1)
4219 end
4233 end
4220
4234
4221 def test_bulk_update_multi_custom_field_to_blank
4235 def test_bulk_update_multi_custom_field_to_blank
4222 field = CustomField.find(1)
4236 field = CustomField.find(1)
4223 field.update_attribute :multiple, true
4237 field.update_attribute :multiple, true
4224
4238
4225 @request.session[:user_id] = 2
4239 @request.session[:user_id] = 2
4226 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
4240 post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
4227 :issue => {:priority_id => '',
4241 :issue => {:priority_id => '',
4228 :assigned_to_id => '',
4242 :assigned_to_id => '',
4229 :custom_field_values => {'1' => ['__none__']}}
4243 :custom_field_values => {'1' => ['__none__']}}
4230 assert_response 302
4244 assert_response 302
4231 assert_equal [''], Issue.find(1).custom_field_value(1)
4245 assert_equal [''], Issue.find(1).custom_field_value(1)
4232 assert_equal [''], Issue.find(3).custom_field_value(1)
4246 assert_equal [''], Issue.find(3).custom_field_value(1)
4233 end
4247 end
4234
4248
4235 def test_bulk_update_unassign
4249 def test_bulk_update_unassign
4236 assert_not_nil Issue.find(2).assigned_to
4250 assert_not_nil Issue.find(2).assigned_to
4237 @request.session[:user_id] = 2
4251 @request.session[:user_id] = 2
4238 # unassign issues
4252 # unassign issues
4239 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
4253 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
4240 assert_response 302
4254 assert_response 302
4241 # check that the issues were updated
4255 # check that the issues were updated
4242 assert_nil Issue.find(2).assigned_to
4256 assert_nil Issue.find(2).assigned_to
4243 end
4257 end
4244
4258
4245 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
4259 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
4246 @request.session[:user_id] = 2
4260 @request.session[:user_id] = 2
4247
4261
4248 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
4262 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
4249
4263
4250 assert_response :redirect
4264 assert_response :redirect
4251 issues = Issue.find([1,2])
4265 issues = Issue.find([1,2])
4252 issues.each do |issue|
4266 issues.each do |issue|
4253 assert_equal 4, issue.fixed_version_id
4267 assert_equal 4, issue.fixed_version_id
4254 assert_not_equal issue.project_id, issue.fixed_version.project_id
4268 assert_not_equal issue.project_id, issue.fixed_version.project_id
4255 end
4269 end
4256 end
4270 end
4257
4271
4258 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
4272 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
4259 @request.session[:user_id] = 2
4273 @request.session[:user_id] = 2
4260 post :bulk_update, :ids => [1,2], :back_url => '/issues'
4274 post :bulk_update, :ids => [1,2], :back_url => '/issues'
4261
4275
4262 assert_response :redirect
4276 assert_response :redirect
4263 assert_redirected_to '/issues'
4277 assert_redirected_to '/issues'
4264 end
4278 end
4265
4279
4266 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
4280 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
4267 @request.session[:user_id] = 2
4281 @request.session[:user_id] = 2
4268 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
4282 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
4269
4283
4270 assert_response :redirect
4284 assert_response :redirect
4271 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
4285 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
4272 end
4286 end
4273
4287
4274 def test_bulk_update_with_all_failures_should_show_errors
4288 def test_bulk_update_with_all_failures_should_show_errors
4275 @request.session[:user_id] = 2
4289 @request.session[:user_id] = 2
4276 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
4290 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
4277 assert_response :success
4291 assert_response :success
4278
4292
4279 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
4293 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
4280 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
4294 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
4281 end
4295 end
4282
4296
4283 def test_bulk_update_with_some_failures_should_show_errors
4297 def test_bulk_update_with_some_failures_should_show_errors
4284 issue1 = Issue.generate!(:start_date => '2013-05-12')
4298 issue1 = Issue.generate!(:start_date => '2013-05-12')
4285 issue2 = Issue.generate!(:start_date => '2013-05-15')
4299 issue2 = Issue.generate!(:start_date => '2013-05-15')
4286 issue3 = Issue.generate!
4300 issue3 = Issue.generate!
4287 @request.session[:user_id] = 2
4301 @request.session[:user_id] = 2
4288 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
4302 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id],
4289 :issue => {:due_date => '2013-05-01'}
4303 :issue => {:due_date => '2013-05-01'}
4290 assert_response :success
4304 assert_response :success
4291
4305
4292 assert_select '#errorExplanation span',
4306 assert_select '#errorExplanation span',
4293 :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
4307 :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
4294 assert_select '#errorExplanation ul li',
4308 assert_select '#errorExplanation ul li',
4295 :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
4309 :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
4296
4310
4297 assert_select '#bulk-selection li', 2
4311 assert_select '#bulk-selection li', 2
4298 end
4312 end
4299
4313
4300 def test_bulk_update_with_failure_should_preserved_form_values
4314 def test_bulk_update_with_failure_should_preserved_form_values
4301 @request.session[:user_id] = 2
4315 @request.session[:user_id] = 2
4302 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
4316 post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2', :start_date => 'foo'}
4303 assert_response :success
4317 assert_response :success
4304
4318
4305 assert_select 'select[name=?]', 'issue[tracker_id]' do
4319 assert_select 'select[name=?]', 'issue[tracker_id]' do
4306 assert_select 'option[value="2"][selected=selected]'
4320 assert_select 'option[value="2"][selected=selected]'
4307 end
4321 end
4308 assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
4322 assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
4309 end
4323 end
4310
4324
4311 def test_get_bulk_copy
4325 def test_get_bulk_copy
4312 @request.session[:user_id] = 2
4326 @request.session[:user_id] = 2
4313 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4327 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4314 assert_response :success
4328 assert_response :success
4315
4329
4316 assert_select '#bulk-selection li', 3
4330 assert_select '#bulk-selection li', 3
4317
4331
4318 assert_select 'select[name=?]', 'issue[project_id]' do
4332 assert_select 'select[name=?]', 'issue[project_id]' do
4319 assert_select 'option[value=""]'
4333 assert_select 'option[value=""]'
4320 end
4334 end
4321 assert_select 'input[name=copy_attachments]'
4335 assert_select 'input[name=copy_attachments]'
4322 end
4336 end
4323
4337
4324 def test_get_bulk_copy_without_add_issues_permission_should_not_propose_current_project_as_target
4338 def test_get_bulk_copy_without_add_issues_permission_should_not_propose_current_project_as_target
4325 user = setup_user_with_copy_but_not_add_permission
4339 user = setup_user_with_copy_but_not_add_permission
4326 @request.session[:user_id] = user.id
4340 @request.session[:user_id] = user.id
4327
4341
4328 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4342 get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
4329 assert_response :success
4343 assert_response :success
4330
4344
4331 assert_select 'select[name=?]', 'issue[project_id]' do
4345 assert_select 'select[name=?]', 'issue[project_id]' do
4332 assert_select 'option[value=""]', 0
4346 assert_select 'option[value=""]', 0
4333 assert_select 'option[value="2"]'
4347 assert_select 'option[value="2"]'
4334 end
4348 end
4335 end
4349 end
4336
4350
4337 def test_bulk_copy_to_another_project
4351 def test_bulk_copy_to_another_project
4338 @request.session[:user_id] = 2
4352 @request.session[:user_id] = 2
4339 assert_difference 'Issue.count', 2 do
4353 assert_difference 'Issue.count', 2 do
4340 assert_no_difference 'Project.find(1).issues.count' do
4354 assert_no_difference 'Project.find(1).issues.count' do
4341 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
4355 post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
4342 end
4356 end
4343 end
4357 end
4344 assert_redirected_to '/projects/ecookbook/issues'
4358 assert_redirected_to '/projects/ecookbook/issues'
4345
4359
4346 copies = Issue.order('id DESC').limit(issues.size)
4360 copies = Issue.order('id DESC').limit(issues.size)
4347 copies.each do |copy|
4361 copies.each do |copy|
4348 assert_equal 2, copy.project_id
4362 assert_equal 2, copy.project_id
4349 end
4363 end
4350 end
4364 end
4351
4365
4352 def test_bulk_copy_without_add_issues_permission_should_be_allowed_on_project_with_permission
4366 def test_bulk_copy_without_add_issues_permission_should_be_allowed_on_project_with_permission
4353 user = setup_user_with_copy_but_not_add_permission
4367 user = setup_user_with_copy_but_not_add_permission
4354 @request.session[:user_id] = user.id
4368 @request.session[:user_id] = user.id
4355
4369
4356 assert_difference 'Issue.count', 3 do
4370 assert_difference 'Issue.count', 3 do
4357 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '2'}, :copy => '1'
4371 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '2'}, :copy => '1'
4358 assert_response 302
4372 assert_response 302
4359 end
4373 end
4360 end
4374 end
4361
4375
4362 def test_bulk_copy_on_same_project_without_add_issues_permission_should_be_denied
4376 def test_bulk_copy_on_same_project_without_add_issues_permission_should_be_denied
4363 user = setup_user_with_copy_but_not_add_permission
4377 user = setup_user_with_copy_but_not_add_permission
4364 @request.session[:user_id] = user.id
4378 @request.session[:user_id] = user.id
4365
4379
4366 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => ''}, :copy => '1'
4380 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => ''}, :copy => '1'
4367 assert_response 403
4381 assert_response 403
4368 end
4382 end
4369
4383
4370 def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_denied
4384 def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_denied
4371 user = setup_user_with_copy_but_not_add_permission
4385 user = setup_user_with_copy_but_not_add_permission
4372 @request.session[:user_id] = user.id
4386 @request.session[:user_id] = user.id
4373
4387
4374 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '1'}, :copy => '1'
4388 post :bulk_update, :ids => [1, 2, 3], :issue => {:project_id => '1'}, :copy => '1'
4375 assert_response 403
4389 assert_response 403
4376 end
4390 end
4377
4391
4378 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
4392 def test_bulk_copy_should_allow_not_changing_the_issue_attributes
4379 @request.session[:user_id] = 2
4393 @request.session[:user_id] = 2
4380 issues = [
4394 issues = [
4381 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
4395 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
4382 :priority_id => 2, :subject => 'issue 1', :author_id => 1,
4396 :priority_id => 2, :subject => 'issue 1', :author_id => 1,
4383 :assigned_to_id => nil),
4397 :assigned_to_id => nil),
4384 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
4398 Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
4385 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
4399 :priority_id => 1, :subject => 'issue 2', :author_id => 2,
4386 :assigned_to_id => 3)
4400 :assigned_to_id => 3)
4387 ]
4401 ]
4388 assert_difference 'Issue.count', issues.size do
4402 assert_difference 'Issue.count', issues.size do
4389 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4403 post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4390 :issue => {
4404 :issue => {
4391 :project_id => '', :tracker_id => '', :assigned_to_id => '',
4405 :project_id => '', :tracker_id => '', :assigned_to_id => '',
4392 :status_id => '', :start_date => '', :due_date => ''
4406 :status_id => '', :start_date => '', :due_date => ''
4393 }
4407 }
4394 end
4408 end
4395
4409
4396 copies = Issue.order('id DESC').limit(issues.size)
4410 copies = Issue.order('id DESC').limit(issues.size)
4397 issues.each do |orig|
4411 issues.each do |orig|
4398 copy = copies.detect {|c| c.subject == orig.subject}
4412 copy = copies.detect {|c| c.subject == orig.subject}
4399 assert_not_nil copy
4413 assert_not_nil copy
4400 assert_equal orig.project_id, copy.project_id
4414 assert_equal orig.project_id, copy.project_id
4401 assert_equal orig.tracker_id, copy.tracker_id
4415 assert_equal orig.tracker_id, copy.tracker_id
4402 assert_equal orig.status_id, copy.status_id
4416 assert_equal orig.status_id, copy.status_id
4403 assert_equal orig.assigned_to_id, copy.assigned_to_id
4417 assert_equal orig.assigned_to_id, copy.assigned_to_id
4404 assert_equal orig.priority_id, copy.priority_id
4418 assert_equal orig.priority_id, copy.priority_id
4405 end
4419 end
4406 end
4420 end
4407
4421
4408 def test_bulk_copy_should_allow_changing_the_issue_attributes
4422 def test_bulk_copy_should_allow_changing_the_issue_attributes
4409 # Fixes random test failure with Mysql
4423 # Fixes random test failure with Mysql
4410 # where Issue.where(:project_id => 2).limit(2).order('id desc')
4424 # where Issue.where(:project_id => 2).limit(2).order('id desc')
4411 # doesn't return the expected results
4425 # doesn't return the expected results
4412 Issue.where("project_id=2").delete_all
4426 Issue.where("project_id=2").delete_all
4413
4427
4414 @request.session[:user_id] = 2
4428 @request.session[:user_id] = 2
4415 assert_difference 'Issue.count', 2 do
4429 assert_difference 'Issue.count', 2 do
4416 assert_no_difference 'Project.find(1).issues.count' do
4430 assert_no_difference 'Project.find(1).issues.count' do
4417 post :bulk_update, :ids => [1, 2], :copy => '1',
4431 post :bulk_update, :ids => [1, 2], :copy => '1',
4418 :issue => {
4432 :issue => {
4419 :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4433 :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4420 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
4434 :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
4421 }
4435 }
4422 end
4436 end
4423 end
4437 end
4424
4438
4425 copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
4439 copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
4426 assert_equal 2, copied_issues.size
4440 assert_equal 2, copied_issues.size
4427 copied_issues.each do |issue|
4441 copied_issues.each do |issue|
4428 assert_equal 2, issue.project_id, "Project is incorrect"
4442 assert_equal 2, issue.project_id, "Project is incorrect"
4429 assert_equal 2, issue.assigned_to_id, "Assigned to is incorrect"
4443 assert_equal 2, issue.assigned_to_id, "Assigned to is incorrect"
4430 assert_equal 1, issue.status_id, "Status is incorrect"
4444 assert_equal 1, issue.status_id, "Status is incorrect"
4431 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
4445 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
4432 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
4446 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
4433 end
4447 end
4434 end
4448 end
4435
4449
4436 def test_bulk_copy_should_allow_adding_a_note
4450 def test_bulk_copy_should_allow_adding_a_note
4437 @request.session[:user_id] = 2
4451 @request.session[:user_id] = 2
4438 assert_difference 'Issue.count', 1 do
4452 assert_difference 'Issue.count', 1 do
4439 post :bulk_update, :ids => [1], :copy => '1',
4453 post :bulk_update, :ids => [1], :copy => '1',
4440 :notes => 'Copying one issue',
4454 :notes => 'Copying one issue',
4441 :issue => {
4455 :issue => {
4442 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
4456 :project_id => '', :tracker_id => '', :assigned_to_id => '4',
4443 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
4457 :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
4444 }
4458 }
4445 end
4459 end
4446 issue = Issue.order('id DESC').first
4460 issue = Issue.order('id DESC').first
4447 assert_equal 1, issue.journals.size
4461 assert_equal 1, issue.journals.size
4448 journal = issue.journals.first
4462 journal = issue.journals.first
4449 assert_equal 'Copying one issue', journal.notes
4463 assert_equal 'Copying one issue', journal.notes
4450 end
4464 end
4451
4465
4452 def test_bulk_copy_should_allow_not_copying_the_attachments
4466 def test_bulk_copy_should_allow_not_copying_the_attachments
4453 attachment_count = Issue.find(3).attachments.size
4467 attachment_count = Issue.find(3).attachments.size
4454 assert attachment_count > 0
4468 assert attachment_count > 0
4455 @request.session[:user_id] = 2
4469 @request.session[:user_id] = 2
4456
4470
4457 assert_difference 'Issue.count', 1 do
4471 assert_difference 'Issue.count', 1 do
4458 assert_no_difference 'Attachment.count' do
4472 assert_no_difference 'Attachment.count' do
4459 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '0',
4473 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '0',
4460 :issue => {
4474 :issue => {
4461 :project_id => ''
4475 :project_id => ''
4462 }
4476 }
4463 end
4477 end
4464 end
4478 end
4465 end
4479 end
4466
4480
4467 def test_bulk_copy_should_allow_copying_the_attachments
4481 def test_bulk_copy_should_allow_copying_the_attachments
4468 attachment_count = Issue.find(3).attachments.size
4482 attachment_count = Issue.find(3).attachments.size
4469 assert attachment_count > 0
4483 assert attachment_count > 0
4470 @request.session[:user_id] = 2
4484 @request.session[:user_id] = 2
4471
4485
4472 assert_difference 'Issue.count', 1 do
4486 assert_difference 'Issue.count', 1 do
4473 assert_difference 'Attachment.count', attachment_count do
4487 assert_difference 'Attachment.count', attachment_count do
4474 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
4488 post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
4475 :issue => {
4489 :issue => {
4476 :project_id => ''
4490 :project_id => ''
4477 }
4491 }
4478 end
4492 end
4479 end
4493 end
4480 end
4494 end
4481
4495
4482 def test_bulk_copy_should_add_relations_with_copied_issues
4496 def test_bulk_copy_should_add_relations_with_copied_issues
4483 @request.session[:user_id] = 2
4497 @request.session[:user_id] = 2
4484
4498
4485 assert_difference 'Issue.count', 2 do
4499 assert_difference 'Issue.count', 2 do
4486 assert_difference 'IssueRelation.count', 2 do
4500 assert_difference 'IssueRelation.count', 2 do
4487 post :bulk_update, :ids => [1, 3], :copy => '1', :link_copy => '1',
4501 post :bulk_update, :ids => [1, 3], :copy => '1', :link_copy => '1',
4488 :issue => {
4502 :issue => {
4489 :project_id => '1'
4503 :project_id => '1'
4490 }
4504 }
4491 end
4505 end
4492 end
4506 end
4493 end
4507 end
4494
4508
4495 def test_bulk_copy_should_allow_not_copying_the_subtasks
4509 def test_bulk_copy_should_allow_not_copying_the_subtasks
4496 issue = Issue.generate_with_descendants!
4510 issue = Issue.generate_with_descendants!
4497 @request.session[:user_id] = 2
4511 @request.session[:user_id] = 2
4498
4512
4499 assert_difference 'Issue.count', 1 do
4513 assert_difference 'Issue.count', 1 do
4500 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '0',
4514 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '0',
4501 :issue => {
4515 :issue => {
4502 :project_id => ''
4516 :project_id => ''
4503 }
4517 }
4504 end
4518 end
4505 end
4519 end
4506
4520
4507 def test_bulk_copy_should_allow_copying_the_subtasks
4521 def test_bulk_copy_should_allow_copying_the_subtasks
4508 issue = Issue.generate_with_descendants!
4522 issue = Issue.generate_with_descendants!
4509 count = issue.descendants.count
4523 count = issue.descendants.count
4510 @request.session[:user_id] = 2
4524 @request.session[:user_id] = 2
4511
4525
4512 assert_difference 'Issue.count', count+1 do
4526 assert_difference 'Issue.count', count+1 do
4513 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
4527 post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
4514 :issue => {
4528 :issue => {
4515 :project_id => ''
4529 :project_id => ''
4516 }
4530 }
4517 end
4531 end
4518 copy = Issue.where(:parent_id => nil).order("id DESC").first
4532 copy = Issue.where(:parent_id => nil).order("id DESC").first
4519 assert_equal count, copy.descendants.count
4533 assert_equal count, copy.descendants.count
4520 end
4534 end
4521
4535
4522 def test_bulk_copy_should_not_copy_selected_subtasks_twice
4536 def test_bulk_copy_should_not_copy_selected_subtasks_twice
4523 issue = Issue.generate_with_descendants!
4537 issue = Issue.generate_with_descendants!
4524 count = issue.descendants.count
4538 count = issue.descendants.count
4525 @request.session[:user_id] = 2
4539 @request.session[:user_id] = 2
4526
4540
4527 assert_difference 'Issue.count', count+1 do
4541 assert_difference 'Issue.count', count+1 do
4528 post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
4542 post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
4529 :issue => {
4543 :issue => {
4530 :project_id => ''
4544 :project_id => ''
4531 }
4545 }
4532 end
4546 end
4533 copy = Issue.where(:parent_id => nil).order("id DESC").first
4547 copy = Issue.where(:parent_id => nil).order("id DESC").first
4534 assert_equal count, copy.descendants.count
4548 assert_equal count, copy.descendants.count
4535 end
4549 end
4536
4550
4537 def test_bulk_copy_to_another_project_should_follow_when_needed
4551 def test_bulk_copy_to_another_project_should_follow_when_needed
4538 @request.session[:user_id] = 2
4552 @request.session[:user_id] = 2
4539 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
4553 post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
4540 issue = Issue.order('id DESC').first
4554 issue = Issue.order('id DESC').first
4541 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
4555 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
4542 end
4556 end
4543
4557
4544 def test_bulk_copy_with_all_failures_should_display_errors
4558 def test_bulk_copy_with_all_failures_should_display_errors
4545 @request.session[:user_id] = 2
4559 @request.session[:user_id] = 2
4546 post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
4560 post :bulk_update, :ids => [1, 2], :copy => '1', :issue => {:start_date => 'foo'}
4547
4561
4548 assert_response :success
4562 assert_response :success
4549 end
4563 end
4550
4564
4551 def test_destroy_issue_with_no_time_entries
4565 def test_destroy_issue_with_no_time_entries
4552 assert_nil TimeEntry.find_by_issue_id(2)
4566 assert_nil TimeEntry.find_by_issue_id(2)
4553 @request.session[:user_id] = 2
4567 @request.session[:user_id] = 2
4554
4568
4555 assert_difference 'Issue.count', -1 do
4569 assert_difference 'Issue.count', -1 do
4556 delete :destroy, :id => 2
4570 delete :destroy, :id => 2
4557 end
4571 end
4558 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4572 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4559 assert_nil Issue.find_by_id(2)
4573 assert_nil Issue.find_by_id(2)
4560 end
4574 end
4561
4575
4562 def test_destroy_issues_with_time_entries
4576 def test_destroy_issues_with_time_entries
4563 @request.session[:user_id] = 2
4577 @request.session[:user_id] = 2
4564
4578
4565 assert_no_difference 'Issue.count' do
4579 assert_no_difference 'Issue.count' do
4566 delete :destroy, :ids => [1, 3]
4580 delete :destroy, :ids => [1, 3]
4567 end
4581 end
4568 assert_response :success
4582 assert_response :success
4569
4583
4570 assert_select 'form' do
4584 assert_select 'form' do
4571 assert_select 'input[name=_method][value=delete]'
4585 assert_select 'input[name=_method][value=delete]'
4572 end
4586 end
4573 end
4587 end
4574
4588
4575 def test_destroy_issues_and_destroy_time_entries
4589 def test_destroy_issues_and_destroy_time_entries
4576 @request.session[:user_id] = 2
4590 @request.session[:user_id] = 2
4577
4591
4578 assert_difference 'Issue.count', -2 do
4592 assert_difference 'Issue.count', -2 do
4579 assert_difference 'TimeEntry.count', -3 do
4593 assert_difference 'TimeEntry.count', -3 do
4580 delete :destroy, :ids => [1, 3], :todo => 'destroy'
4594 delete :destroy, :ids => [1, 3], :todo => 'destroy'
4581 end
4595 end
4582 end
4596 end
4583 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4597 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4584 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4598 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4585 assert_nil TimeEntry.find_by_id([1, 2])
4599 assert_nil TimeEntry.find_by_id([1, 2])
4586 end
4600 end
4587
4601
4588 def test_destroy_issues_and_assign_time_entries_to_project
4602 def test_destroy_issues_and_assign_time_entries_to_project
4589 @request.session[:user_id] = 2
4603 @request.session[:user_id] = 2
4590
4604
4591 assert_difference 'Issue.count', -2 do
4605 assert_difference 'Issue.count', -2 do
4592 assert_no_difference 'TimeEntry.count' do
4606 assert_no_difference 'TimeEntry.count' do
4593 delete :destroy, :ids => [1, 3], :todo => 'nullify'
4607 delete :destroy, :ids => [1, 3], :todo => 'nullify'
4594 end
4608 end
4595 end
4609 end
4596 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4610 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4597 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4611 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4598 assert_nil TimeEntry.find(1).issue_id
4612 assert_nil TimeEntry.find(1).issue_id
4599 assert_nil TimeEntry.find(2).issue_id
4613 assert_nil TimeEntry.find(2).issue_id
4600 end
4614 end
4601
4615
4602 def test_destroy_issues_and_reassign_time_entries_to_another_issue
4616 def test_destroy_issues_and_reassign_time_entries_to_another_issue
4603 @request.session[:user_id] = 2
4617 @request.session[:user_id] = 2
4604
4618
4605 assert_difference 'Issue.count', -2 do
4619 assert_difference 'Issue.count', -2 do
4606 assert_no_difference 'TimeEntry.count' do
4620 assert_no_difference 'TimeEntry.count' do
4607 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
4621 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
4608 end
4622 end
4609 end
4623 end
4610 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4624 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
4611 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4625 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
4612 assert_equal 2, TimeEntry.find(1).issue_id
4626 assert_equal 2, TimeEntry.find(1).issue_id
4613 assert_equal 2, TimeEntry.find(2).issue_id
4627 assert_equal 2, TimeEntry.find(2).issue_id
4614 end
4628 end
4615
4629
4616 def test_destroy_issues_and_reassign_time_entries_to_an_invalid_issue_should_fail
4630 def test_destroy_issues_and_reassign_time_entries_to_an_invalid_issue_should_fail
4617 @request.session[:user_id] = 2
4631 @request.session[:user_id] = 2
4618
4632
4619 assert_no_difference 'Issue.count' do
4633 assert_no_difference 'Issue.count' do
4620 assert_no_difference 'TimeEntry.count' do
4634 assert_no_difference 'TimeEntry.count' do
4621 # try to reassign time to an issue of another project
4635 # try to reassign time to an issue of another project
4622 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 4
4636 delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 4
4623 end
4637 end
4624 end
4638 end
4625 assert_response :success
4639 assert_response :success
4626 end
4640 end
4627
4641
4628 def test_destroy_issues_from_different_projects
4642 def test_destroy_issues_from_different_projects
4629 @request.session[:user_id] = 2
4643 @request.session[:user_id] = 2
4630
4644
4631 assert_difference 'Issue.count', -3 do
4645 assert_difference 'Issue.count', -3 do
4632 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
4646 delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
4633 end
4647 end
4634 assert_redirected_to :controller => 'issues', :action => 'index'
4648 assert_redirected_to :controller => 'issues', :action => 'index'
4635 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
4649 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
4636 end
4650 end
4637
4651
4638 def test_destroy_parent_and_child_issues
4652 def test_destroy_parent_and_child_issues
4639 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
4653 parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
4640 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
4654 child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
4641 assert child.is_descendant_of?(parent.reload)
4655 assert child.is_descendant_of?(parent.reload)
4642
4656
4643 @request.session[:user_id] = 2
4657 @request.session[:user_id] = 2
4644 assert_difference 'Issue.count', -2 do
4658 assert_difference 'Issue.count', -2 do
4645 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
4659 delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
4646 end
4660 end
4647 assert_response 302
4661 assert_response 302
4648 end
4662 end
4649
4663
4650 def test_destroy_invalid_should_respond_with_404
4664 def test_destroy_invalid_should_respond_with_404
4651 @request.session[:user_id] = 2
4665 @request.session[:user_id] = 2
4652 assert_no_difference 'Issue.count' do
4666 assert_no_difference 'Issue.count' do
4653 delete :destroy, :id => 999
4667 delete :destroy, :id => 999
4654 end
4668 end
4655 assert_response 404
4669 assert_response 404
4656 end
4670 end
4657
4671
4658 def test_destroy_with_permission_on_tracker_should_be_allowed
4672 def test_destroy_with_permission_on_tracker_should_be_allowed
4659 role = Role.find(1)
4673 role = Role.find(1)
4660 role.set_permission_trackers :delete_issues, [1]
4674 role.set_permission_trackers :delete_issues, [1]
4661 role.save!
4675 role.save!
4662 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4676 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4663
4677
4664 @request.session[:user_id] = 2
4678 @request.session[:user_id] = 2
4665 assert_difference 'Issue.count', -1 do
4679 assert_difference 'Issue.count', -1 do
4666 delete :destroy, :id => issue.id
4680 delete :destroy, :id => issue.id
4667 end
4681 end
4668 assert_response 302
4682 assert_response 302
4669 end
4683 end
4670
4684
4671 def test_destroy_without_permission_on_tracker_should_be_denied
4685 def test_destroy_without_permission_on_tracker_should_be_denied
4672 role = Role.find(1)
4686 role = Role.find(1)
4673 role.set_permission_trackers :delete_issues, [2]
4687 role.set_permission_trackers :delete_issues, [2]
4674 role.save!
4688 role.save!
4675 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4689 issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
4676
4690
4677 @request.session[:user_id] = 2
4691 @request.session[:user_id] = 2
4678 assert_no_difference 'Issue.count' do
4692 assert_no_difference 'Issue.count' do
4679 delete :destroy, :id => issue.id
4693 delete :destroy, :id => issue.id
4680 end
4694 end
4681 assert_response 403
4695 assert_response 403
4682 end
4696 end
4683
4697
4684 def test_default_search_scope
4698 def test_default_search_scope
4685 get :index
4699 get :index
4686
4700
4687 assert_select 'div#quick-search form' do
4701 assert_select 'div#quick-search form' do
4688 assert_select 'input[name=issues][value="1"][type=hidden]'
4702 assert_select 'input[name=issues][value="1"][type=hidden]'
4689 end
4703 end
4690 end
4704 end
4691
4705
4692 def setup_user_with_copy_but_not_add_permission
4706 def setup_user_with_copy_but_not_add_permission
4693 Role.all.each {|r| r.remove_permission! :add_issues}
4707 Role.all.each {|r| r.remove_permission! :add_issues}
4694 Role.find_by_name('Manager').add_permission! :add_issues
4708 Role.find_by_name('Manager').add_permission! :add_issues
4695 user = User.generate!
4709 user = User.generate!
4696 User.add_to_project(user, Project.find(1), Role.find_by_name('Developer'))
4710 User.add_to_project(user, Project.find(1), Role.find_by_name('Developer'))
4697 User.add_to_project(user, Project.find(2), Role.find_by_name('Manager'))
4711 User.add_to_project(user, Project.find(2), Role.find_by_name('Manager'))
4698 user
4712 user
4699 end
4713 end
4700 end
4714 end
General Comments 0
You need to be logged in to leave comments. Login now