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