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