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