##// END OF EJS Templates
Initialize TimeEntry attributes with params when editing an issue (#5441)....
Jean-Philippe Lang -
r4297:8bb75da1acf9
parent child
Show More
@@ -1,321 +1,322
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 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, :move, :perform_move, :destroy]
23 before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy]
24 before_filter :check_project_uniqueness, :only => [:move, :perform_move]
24 before_filter :check_project_uniqueness, :only => [:move, :perform_move]
25 before_filter :find_project, :only => [:new, :create]
25 before_filter :find_project, :only => [:new, :create]
26 before_filter :authorize, :except => [:index]
26 before_filter :authorize, :except => [:index]
27 before_filter :find_optional_project, :only => [:index]
27 before_filter :find_optional_project, :only => [:index]
28 before_filter :check_for_default_issue_status, :only => [:new, :create]
28 before_filter :check_for_default_issue_status, :only => [:new, :create]
29 before_filter :build_new_issue_from_params, :only => [:new, :create]
29 before_filter :build_new_issue_from_params, :only => [:new, :create]
30 accept_key_auth :index, :show, :create, :update, :destroy
30 accept_key_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 :sort
47 helper :sort
48 include SortHelper
48 include SortHelper
49 include IssuesHelper
49 include IssuesHelper
50 helper :timelog
50 helper :timelog
51 helper :gantt
51 helper :gantt
52 include Redmine::Export::PDF
52 include Redmine::Export::PDF
53
53
54 verify :method => [:post, :delete],
54 verify :method => [:post, :delete],
55 :only => :destroy,
55 :only => :destroy,
56 :render => { :nothing => true, :status => :method_not_allowed }
56 :render => { :nothing => true, :status => :method_not_allowed }
57
57
58 verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
58 verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
59 verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
59 verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
60 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
60 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
61
61
62 def index
62 def index
63 retrieve_query
63 retrieve_query
64 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
64 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
65 sort_update(@query.sortable_columns)
65 sort_update(@query.sortable_columns)
66
66
67 if @query.valid?
67 if @query.valid?
68 limit = case params[:format]
68 limit = case params[:format]
69 when 'csv', 'pdf'
69 when 'csv', 'pdf'
70 Setting.issues_export_limit.to_i
70 Setting.issues_export_limit.to_i
71 when 'atom'
71 when 'atom'
72 Setting.feeds_limit.to_i
72 Setting.feeds_limit.to_i
73 else
73 else
74 per_page_option
74 per_page_option
75 end
75 end
76
76
77 @issue_count = @query.issue_count
77 @issue_count = @query.issue_count
78 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
78 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
79 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
79 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
80 :order => sort_clause,
80 :order => sort_clause,
81 :offset => @issue_pages.current.offset,
81 :offset => @issue_pages.current.offset,
82 :limit => limit)
82 :limit => limit)
83 @issue_count_by_group = @query.issue_count_by_group
83 @issue_count_by_group = @query.issue_count_by_group
84
84
85 respond_to do |format|
85 respond_to do |format|
86 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
86 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
87 format.xml { render :layout => false }
87 format.xml { render :layout => false }
88 format.json { render :text => @issues.to_json, :layout => false }
88 format.json { render :text => @issues.to_json, :layout => false }
89 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
89 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
90 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
90 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
91 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
91 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
92 end
92 end
93 else
93 else
94 # Send html if the query is not valid
94 # Send html if the query is not valid
95 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
95 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
96 end
96 end
97 rescue ActiveRecord::RecordNotFound
97 rescue ActiveRecord::RecordNotFound
98 render_404
98 render_404
99 end
99 end
100
100
101 def show
101 def show
102 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
102 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
103 @journals.each_with_index {|j,i| j.indice = i+1}
103 @journals.each_with_index {|j,i| j.indice = i+1}
104 @journals.reverse! if User.current.wants_comments_in_reverse_order?
104 @journals.reverse! if User.current.wants_comments_in_reverse_order?
105 @changesets = @issue.changesets.visible.all
105 @changesets = @issue.changesets.visible.all
106 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
106 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
107 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
107 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
108 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
108 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
109 @priorities = IssuePriority.all
109 @priorities = IssuePriority.all
110 @time_entry = TimeEntry.new
110 @time_entry = TimeEntry.new
111 respond_to do |format|
111 respond_to do |format|
112 format.html { render :template => 'issues/show.rhtml' }
112 format.html { render :template => 'issues/show.rhtml' }
113 format.xml { render :layout => false }
113 format.xml { render :layout => false }
114 format.json { render :text => @issue.to_json, :layout => false }
114 format.json { render :text => @issue.to_json, :layout => false }
115 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
115 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
116 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
116 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
117 end
117 end
118 end
118 end
119
119
120 # Add a new issue
120 # Add a new issue
121 # The new issue will be created from an existing one if copy_from parameter is given
121 # The new issue will be created from an existing one if copy_from parameter is given
122 def new
122 def new
123 respond_to do |format|
123 respond_to do |format|
124 format.html { render :action => 'new', :layout => !request.xhr? }
124 format.html { render :action => 'new', :layout => !request.xhr? }
125 format.js { render :partial => 'attributes' }
125 format.js { render :partial => 'attributes' }
126 end
126 end
127 end
127 end
128
128
129 def create
129 def create
130 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
130 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
131 if @issue.save
131 if @issue.save
132 attachments = Attachment.attach_files(@issue, params[:attachments])
132 attachments = Attachment.attach_files(@issue, params[:attachments])
133 render_attachment_warning_if_needed(@issue)
133 render_attachment_warning_if_needed(@issue)
134 flash[:notice] = l(:notice_successful_create)
134 flash[:notice] = l(:notice_successful_create)
135 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
135 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
136 respond_to do |format|
136 respond_to do |format|
137 format.html {
137 format.html {
138 redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
138 redirect_to(params[:continue] ? { :action => 'new', :project_id => @project, :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
139 { :action => 'show', :id => @issue })
139 { :action => 'show', :id => @issue })
140 }
140 }
141 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
141 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
142 format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
142 format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
143 end
143 end
144 return
144 return
145 else
145 else
146 respond_to do |format|
146 respond_to do |format|
147 format.html { render :action => 'new' }
147 format.html { render :action => 'new' }
148 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
148 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
149 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
149 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
150 end
150 end
151 end
151 end
152 end
152 end
153
153
154 def edit
154 def edit
155 update_issue_from_params
155 update_issue_from_params
156
156
157 @journal = @issue.current_journal
157 @journal = @issue.current_journal
158
158
159 respond_to do |format|
159 respond_to do |format|
160 format.html { }
160 format.html { }
161 format.xml { }
161 format.xml { }
162 end
162 end
163 end
163 end
164
164
165 def update
165 def update
166 update_issue_from_params
166 update_issue_from_params
167
167
168 if @issue.save_issue_with_child_records(params, @time_entry)
168 if @issue.save_issue_with_child_records(params, @time_entry)
169 render_attachment_warning_if_needed(@issue)
169 render_attachment_warning_if_needed(@issue)
170 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
170 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
171
171
172 respond_to do |format|
172 respond_to do |format|
173 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
173 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
174 format.xml { head :ok }
174 format.xml { head :ok }
175 format.json { head :ok }
175 format.json { head :ok }
176 end
176 end
177 else
177 else
178 render_attachment_warning_if_needed(@issue)
178 render_attachment_warning_if_needed(@issue)
179 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
179 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
180 @journal = @issue.current_journal
180 @journal = @issue.current_journal
181
181
182 respond_to do |format|
182 respond_to do |format|
183 format.html { render :action => 'edit' }
183 format.html { render :action => 'edit' }
184 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
184 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
185 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
185 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
186 end
186 end
187 end
187 end
188 end
188 end
189
189
190 # Bulk edit a set of issues
190 # Bulk edit a set of issues
191 def bulk_edit
191 def bulk_edit
192 @issues.sort!
192 @issues.sort!
193 @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w}
193 @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w}
194 @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c}
194 @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c}
195 @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a}
195 @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a}
196 @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t}
196 @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t}
197 end
197 end
198
198
199 def bulk_update
199 def bulk_update
200 @issues.sort!
200 @issues.sort!
201 attributes = parse_params_for_bulk_issue_attributes(params)
201 attributes = parse_params_for_bulk_issue_attributes(params)
202
202
203 unsaved_issue_ids = []
203 unsaved_issue_ids = []
204 @issues.each do |issue|
204 @issues.each do |issue|
205 issue.reload
205 issue.reload
206 journal = issue.init_journal(User.current, params[:notes])
206 journal = issue.init_journal(User.current, params[:notes])
207 issue.safe_attributes = attributes
207 issue.safe_attributes = attributes
208 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
208 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
209 unless issue.save
209 unless issue.save
210 # Keep unsaved issue ids to display them in flash error
210 # Keep unsaved issue ids to display them in flash error
211 unsaved_issue_ids << issue.id
211 unsaved_issue_ids << issue.id
212 end
212 end
213 end
213 end
214 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
214 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
215 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
215 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
216 end
216 end
217
217
218 def destroy
218 def destroy
219 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
219 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
220 if @hours > 0
220 if @hours > 0
221 case params[:todo]
221 case params[:todo]
222 when 'destroy'
222 when 'destroy'
223 # nothing to do
223 # nothing to do
224 when 'nullify'
224 when 'nullify'
225 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
225 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
226 when 'reassign'
226 when 'reassign'
227 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
227 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
228 if reassign_to.nil?
228 if reassign_to.nil?
229 flash.now[:error] = l(:error_issue_not_found_in_project)
229 flash.now[:error] = l(:error_issue_not_found_in_project)
230 return
230 return
231 else
231 else
232 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
232 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
233 end
233 end
234 else
234 else
235 unless params[:format] == 'xml' || params[:format] == 'json'
235 unless params[:format] == 'xml' || params[:format] == 'json'
236 # display the destroy form if it's a user request
236 # display the destroy form if it's a user request
237 return
237 return
238 end
238 end
239 end
239 end
240 end
240 end
241 @issues.each(&:destroy)
241 @issues.each(&:destroy)
242 respond_to do |format|
242 respond_to do |format|
243 format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
243 format.html { redirect_back_or_default(:action => 'index', :project_id => @project) }
244 format.xml { head :ok }
244 format.xml { head :ok }
245 format.json { head :ok }
245 format.json { head :ok }
246 end
246 end
247 end
247 end
248
248
249 private
249 private
250 def find_issue
250 def find_issue
251 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
251 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
252 @project = @issue.project
252 @project = @issue.project
253 rescue ActiveRecord::RecordNotFound
253 rescue ActiveRecord::RecordNotFound
254 render_404
254 render_404
255 end
255 end
256
256
257 def find_project
257 def find_project
258 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
258 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
259 @project = Project.find(project_id)
259 @project = Project.find(project_id)
260 rescue ActiveRecord::RecordNotFound
260 rescue ActiveRecord::RecordNotFound
261 render_404
261 render_404
262 end
262 end
263
263
264 # Used by #edit and #update to set some common instance variables
264 # Used by #edit and #update to set some common instance variables
265 # from the params
265 # from the params
266 # TODO: Refactor, not everything in here is needed by #edit
266 # TODO: Refactor, not everything in here is needed by #edit
267 def update_issue_from_params
267 def update_issue_from_params
268 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
268 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
269 @priorities = IssuePriority.all
269 @priorities = IssuePriority.all
270 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
270 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
271 @time_entry = TimeEntry.new
271 @time_entry = TimeEntry.new
272 @time_entry.attributes = params[:time_entry]
272
273
273 @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
274 @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil)
274 @issue.init_journal(User.current, @notes)
275 @issue.init_journal(User.current, @notes)
275 @issue.safe_attributes = params[:issue]
276 @issue.safe_attributes = params[:issue]
276 end
277 end
277
278
278 # TODO: Refactor, lots of extra code in here
279 # TODO: Refactor, lots of extra code in here
279 # TODO: Changing tracker on an existing issue should not trigger this
280 # TODO: Changing tracker on an existing issue should not trigger this
280 def build_new_issue_from_params
281 def build_new_issue_from_params
281 if params[:id].blank?
282 if params[:id].blank?
282 @issue = Issue.new
283 @issue = Issue.new
283 @issue.copy_from(params[:copy_from]) if params[:copy_from]
284 @issue.copy_from(params[:copy_from]) if params[:copy_from]
284 @issue.project = @project
285 @issue.project = @project
285 else
286 else
286 @issue = @project.issues.visible.find(params[:id])
287 @issue = @project.issues.visible.find(params[:id])
287 end
288 end
288
289
289 @issue.project = @project
290 @issue.project = @project
290 # Tracker must be set before custom field values
291 # Tracker must be set before custom field values
291 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
292 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
292 if @issue.tracker.nil?
293 if @issue.tracker.nil?
293 render_error l(:error_no_tracker_in_project)
294 render_error l(:error_no_tracker_in_project)
294 return false
295 return false
295 end
296 end
296 @issue.start_date ||= Date.today
297 @issue.start_date ||= Date.today
297 if params[:issue].is_a?(Hash)
298 if params[:issue].is_a?(Hash)
298 @issue.safe_attributes = params[:issue]
299 @issue.safe_attributes = params[:issue]
299 if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record?
300 if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record?
300 @issue.watcher_user_ids = params[:issue]['watcher_user_ids']
301 @issue.watcher_user_ids = params[:issue]['watcher_user_ids']
301 end
302 end
302 end
303 end
303 @issue.author = User.current
304 @issue.author = User.current
304 @priorities = IssuePriority.all
305 @priorities = IssuePriority.all
305 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
306 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
306 end
307 end
307
308
308 def check_for_default_issue_status
309 def check_for_default_issue_status
309 if IssueStatus.default.nil?
310 if IssueStatus.default.nil?
310 render_error l(:error_no_default_issue_status)
311 render_error l(:error_no_default_issue_status)
311 return false
312 return false
312 end
313 end
313 end
314 end
314
315
315 def parse_params_for_bulk_issue_attributes(params)
316 def parse_params_for_bulk_issue_attributes(params)
316 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
317 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
317 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
318 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
318 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
319 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
319 attributes
320 attributes
320 end
321 end
321 end
322 end
@@ -1,1271 +1,1278
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 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.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'issues_controller'
19 require 'issues_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class IssuesController; def rescue_action(e) raise e end; end
22 class IssuesController; def rescue_action(e) raise e end; end
23
23
24 class IssuesControllerTest < ActionController::TestCase
24 class IssuesControllerTest < ActionController::TestCase
25 fixtures :projects,
25 fixtures :projects,
26 :users,
26 :users,
27 :roles,
27 :roles,
28 :members,
28 :members,
29 :member_roles,
29 :member_roles,
30 :issues,
30 :issues,
31 :issue_statuses,
31 :issue_statuses,
32 :versions,
32 :versions,
33 :trackers,
33 :trackers,
34 :projects_trackers,
34 :projects_trackers,
35 :issue_categories,
35 :issue_categories,
36 :enabled_modules,
36 :enabled_modules,
37 :enumerations,
37 :enumerations,
38 :attachments,
38 :attachments,
39 :workflows,
39 :workflows,
40 :custom_fields,
40 :custom_fields,
41 :custom_values,
41 :custom_values,
42 :custom_fields_projects,
42 :custom_fields_projects,
43 :custom_fields_trackers,
43 :custom_fields_trackers,
44 :time_entries,
44 :time_entries,
45 :journals,
45 :journals,
46 :journal_details,
46 :journal_details,
47 :queries
47 :queries
48
48
49 def setup
49 def setup
50 @controller = IssuesController.new
50 @controller = IssuesController.new
51 @request = ActionController::TestRequest.new
51 @request = ActionController::TestRequest.new
52 @response = ActionController::TestResponse.new
52 @response = ActionController::TestResponse.new
53 User.current = nil
53 User.current = nil
54 end
54 end
55
55
56 def test_index
56 def test_index
57 Setting.default_language = 'en'
57 Setting.default_language = 'en'
58
58
59 get :index
59 get :index
60 assert_response :success
60 assert_response :success
61 assert_template 'index.rhtml'
61 assert_template 'index.rhtml'
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
72
73 def test_index_should_not_list_issues_when_module_disabled
73 def test_index_should_not_list_issues_when_module_disabled
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
75 get :index
75 get :index
76 assert_response :success
76 assert_response :success
77 assert_template 'index.rhtml'
77 assert_template 'index.rhtml'
78 assert_not_nil assigns(:issues)
78 assert_not_nil assigns(:issues)
79 assert_nil assigns(:project)
79 assert_nil assigns(:project)
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
81 assert_tag :tag => 'a', :content => /Subproject issue/
81 assert_tag :tag => 'a', :content => /Subproject issue/
82 end
82 end
83
83
84 def test_index_should_not_list_issues_when_module_disabled
84 def test_index_should_not_list_issues_when_module_disabled
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
86 get :index
86 get :index
87 assert_response :success
87 assert_response :success
88 assert_template 'index.rhtml'
88 assert_template 'index.rhtml'
89 assert_not_nil assigns(:issues)
89 assert_not_nil assigns(:issues)
90 assert_nil assigns(:project)
90 assert_nil assigns(:project)
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
92 assert_tag :tag => 'a', :content => /Subproject issue/
92 assert_tag :tag => 'a', :content => /Subproject issue/
93 end
93 end
94
94
95 def test_index_with_project
95 def test_index_with_project
96 Setting.display_subprojects_issues = 0
96 Setting.display_subprojects_issues = 0
97 get :index, :project_id => 1
97 get :index, :project_id => 1
98 assert_response :success
98 assert_response :success
99 assert_template 'index.rhtml'
99 assert_template 'index.rhtml'
100 assert_not_nil assigns(:issues)
100 assert_not_nil assigns(:issues)
101 assert_tag :tag => 'a', :content => /Can't print recipes/
101 assert_tag :tag => 'a', :content => /Can't print recipes/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
103 end
103 end
104
104
105 def test_index_with_project_and_subprojects
105 def test_index_with_project_and_subprojects
106 Setting.display_subprojects_issues = 1
106 Setting.display_subprojects_issues = 1
107 get :index, :project_id => 1
107 get :index, :project_id => 1
108 assert_response :success
108 assert_response :success
109 assert_template 'index.rhtml'
109 assert_template 'index.rhtml'
110 assert_not_nil assigns(:issues)
110 assert_not_nil assigns(:issues)
111 assert_tag :tag => 'a', :content => /Can't print recipes/
111 assert_tag :tag => 'a', :content => /Can't print recipes/
112 assert_tag :tag => 'a', :content => /Subproject issue/
112 assert_tag :tag => 'a', :content => /Subproject issue/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
114 end
114 end
115
115
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
117 @request.session[:user_id] = 2
117 @request.session[:user_id] = 2
118 Setting.display_subprojects_issues = 1
118 Setting.display_subprojects_issues = 1
119 get :index, :project_id => 1
119 get :index, :project_id => 1
120 assert_response :success
120 assert_response :success
121 assert_template 'index.rhtml'
121 assert_template 'index.rhtml'
122 assert_not_nil assigns(:issues)
122 assert_not_nil assigns(:issues)
123 assert_tag :tag => 'a', :content => /Can't print recipes/
123 assert_tag :tag => 'a', :content => /Can't print recipes/
124 assert_tag :tag => 'a', :content => /Subproject issue/
124 assert_tag :tag => 'a', :content => /Subproject issue/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
126 end
126 end
127
127
128 def test_index_with_project_and_default_filter
128 def test_index_with_project_and_default_filter
129 get :index, :project_id => 1, :set_filter => 1
129 get :index, :project_id => 1, :set_filter => 1
130 assert_response :success
130 assert_response :success
131 assert_template 'index.rhtml'
131 assert_template 'index.rhtml'
132 assert_not_nil assigns(:issues)
132 assert_not_nil assigns(:issues)
133
133
134 query = assigns(:query)
134 query = assigns(:query)
135 assert_not_nil query
135 assert_not_nil query
136 # default filter
136 # default filter
137 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
137 assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
138 end
138 end
139
139
140 def test_index_with_project_and_filter
140 def test_index_with_project_and_filter
141 get :index, :project_id => 1, :set_filter => 1,
141 get :index, :project_id => 1, :set_filter => 1,
142 :fields => ['tracker_id'],
142 :fields => ['tracker_id'],
143 :operators => {'tracker_id' => '='},
143 :operators => {'tracker_id' => '='},
144 :values => {'tracker_id' => ['1']}
144 :values => {'tracker_id' => ['1']}
145 assert_response :success
145 assert_response :success
146 assert_template 'index.rhtml'
146 assert_template 'index.rhtml'
147 assert_not_nil assigns(:issues)
147 assert_not_nil assigns(:issues)
148
148
149 query = assigns(:query)
149 query = assigns(:query)
150 assert_not_nil query
150 assert_not_nil query
151 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
151 assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
152 end
152 end
153
153
154 def test_index_with_project_and_empty_filters
154 def test_index_with_project_and_empty_filters
155 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
155 get :index, :project_id => 1, :set_filter => 1, :fields => ['']
156 assert_response :success
156 assert_response :success
157 assert_template 'index.rhtml'
157 assert_template 'index.rhtml'
158 assert_not_nil assigns(:issues)
158 assert_not_nil assigns(:issues)
159
159
160 query = assigns(:query)
160 query = assigns(:query)
161 assert_not_nil query
161 assert_not_nil query
162 # no filter
162 # no filter
163 assert_equal({}, query.filters)
163 assert_equal({}, query.filters)
164 end
164 end
165
165
166 def test_index_with_query
166 def test_index_with_query
167 get :index, :project_id => 1, :query_id => 5
167 get :index, :project_id => 1, :query_id => 5
168 assert_response :success
168 assert_response :success
169 assert_template 'index.rhtml'
169 assert_template 'index.rhtml'
170 assert_not_nil assigns(:issues)
170 assert_not_nil assigns(:issues)
171 assert_nil assigns(:issue_count_by_group)
171 assert_nil assigns(:issue_count_by_group)
172 end
172 end
173
173
174 def test_index_with_query_grouped_by_tracker
174 def test_index_with_query_grouped_by_tracker
175 get :index, :project_id => 1, :query_id => 6
175 get :index, :project_id => 1, :query_id => 6
176 assert_response :success
176 assert_response :success
177 assert_template 'index.rhtml'
177 assert_template 'index.rhtml'
178 assert_not_nil assigns(:issues)
178 assert_not_nil assigns(:issues)
179 assert_not_nil assigns(:issue_count_by_group)
179 assert_not_nil assigns(:issue_count_by_group)
180 end
180 end
181
181
182 def test_index_with_query_grouped_by_list_custom_field
182 def test_index_with_query_grouped_by_list_custom_field
183 get :index, :project_id => 1, :query_id => 9
183 get :index, :project_id => 1, :query_id => 9
184 assert_response :success
184 assert_response :success
185 assert_template 'index.rhtml'
185 assert_template 'index.rhtml'
186 assert_not_nil assigns(:issues)
186 assert_not_nil assigns(:issues)
187 assert_not_nil assigns(:issue_count_by_group)
187 assert_not_nil assigns(:issue_count_by_group)
188 end
188 end
189
189
190 def test_index_sort_by_field_not_included_in_columns
190 def test_index_sort_by_field_not_included_in_columns
191 Setting.issue_list_default_columns = %w(subject author)
191 Setting.issue_list_default_columns = %w(subject author)
192 get :index, :sort => 'tracker'
192 get :index, :sort => 'tracker'
193 end
193 end
194
194
195 def test_index_csv_with_project
195 def test_index_csv_with_project
196 Setting.default_language = 'en'
196 Setting.default_language = 'en'
197
197
198 get :index, :format => 'csv'
198 get :index, :format => 'csv'
199 assert_response :success
199 assert_response :success
200 assert_not_nil assigns(:issues)
200 assert_not_nil assigns(:issues)
201 assert_equal 'text/csv', @response.content_type
201 assert_equal 'text/csv', @response.content_type
202 assert @response.body.starts_with?("#,")
202 assert @response.body.starts_with?("#,")
203
203
204 get :index, :project_id => 1, :format => 'csv'
204 get :index, :project_id => 1, :format => 'csv'
205 assert_response :success
205 assert_response :success
206 assert_not_nil assigns(:issues)
206 assert_not_nil assigns(:issues)
207 assert_equal 'text/csv', @response.content_type
207 assert_equal 'text/csv', @response.content_type
208 end
208 end
209
209
210 def test_index_pdf
210 def test_index_pdf
211 get :index, :format => 'pdf'
211 get :index, :format => 'pdf'
212 assert_response :success
212 assert_response :success
213 assert_not_nil assigns(:issues)
213 assert_not_nil assigns(:issues)
214 assert_equal 'application/pdf', @response.content_type
214 assert_equal 'application/pdf', @response.content_type
215
215
216 get :index, :project_id => 1, :format => 'pdf'
216 get :index, :project_id => 1, :format => 'pdf'
217 assert_response :success
217 assert_response :success
218 assert_not_nil assigns(:issues)
218 assert_not_nil assigns(:issues)
219 assert_equal 'application/pdf', @response.content_type
219 assert_equal 'application/pdf', @response.content_type
220
220
221 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
221 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
222 assert_response :success
222 assert_response :success
223 assert_not_nil assigns(:issues)
223 assert_not_nil assigns(:issues)
224 assert_equal 'application/pdf', @response.content_type
224 assert_equal 'application/pdf', @response.content_type
225 end
225 end
226
226
227 def test_index_pdf_with_query_grouped_by_list_custom_field
227 def test_index_pdf_with_query_grouped_by_list_custom_field
228 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
228 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
229 assert_response :success
229 assert_response :success
230 assert_not_nil assigns(:issues)
230 assert_not_nil assigns(:issues)
231 assert_not_nil assigns(:issue_count_by_group)
231 assert_not_nil assigns(:issue_count_by_group)
232 assert_equal 'application/pdf', @response.content_type
232 assert_equal 'application/pdf', @response.content_type
233 end
233 end
234
234
235 def test_index_sort
235 def test_index_sort
236 get :index, :sort => 'tracker,id:desc'
236 get :index, :sort => 'tracker,id:desc'
237 assert_response :success
237 assert_response :success
238
238
239 sort_params = @request.session['issues_index_sort']
239 sort_params = @request.session['issues_index_sort']
240 assert sort_params.is_a?(String)
240 assert sort_params.is_a?(String)
241 assert_equal 'tracker,id:desc', sort_params
241 assert_equal 'tracker,id:desc', sort_params
242
242
243 issues = assigns(:issues)
243 issues = assigns(:issues)
244 assert_not_nil issues
244 assert_not_nil issues
245 assert !issues.empty?
245 assert !issues.empty?
246 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
246 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
247 end
247 end
248
248
249 def test_index_with_columns
249 def test_index_with_columns
250 columns = ['tracker', 'subject', 'assigned_to']
250 columns = ['tracker', 'subject', 'assigned_to']
251 get :index, :set_filter => 1, :query => { 'column_names' => columns}
251 get :index, :set_filter => 1, :query => { 'column_names' => columns}
252 assert_response :success
252 assert_response :success
253
253
254 # query should use specified columns
254 # query should use specified columns
255 query = assigns(:query)
255 query = assigns(:query)
256 assert_kind_of Query, query
256 assert_kind_of Query, query
257 assert_equal columns, query.column_names.map(&:to_s)
257 assert_equal columns, query.column_names.map(&:to_s)
258
258
259 # columns should be stored in session
259 # columns should be stored in session
260 assert_kind_of Hash, session[:query]
260 assert_kind_of Hash, session[:query]
261 assert_kind_of Array, session[:query][:column_names]
261 assert_kind_of Array, session[:query][:column_names]
262 assert_equal columns, session[:query][:column_names].map(&:to_s)
262 assert_equal columns, session[:query][:column_names].map(&:to_s)
263 end
263 end
264
264
265 def test_show_by_anonymous
265 def test_show_by_anonymous
266 get :show, :id => 1
266 get :show, :id => 1
267 assert_response :success
267 assert_response :success
268 assert_template 'show.rhtml'
268 assert_template 'show.rhtml'
269 assert_not_nil assigns(:issue)
269 assert_not_nil assigns(:issue)
270 assert_equal Issue.find(1), assigns(:issue)
270 assert_equal Issue.find(1), assigns(:issue)
271
271
272 # anonymous role is allowed to add a note
272 # anonymous role is allowed to add a note
273 assert_tag :tag => 'form',
273 assert_tag :tag => 'form',
274 :descendant => { :tag => 'fieldset',
274 :descendant => { :tag => 'fieldset',
275 :child => { :tag => 'legend',
275 :child => { :tag => 'legend',
276 :content => /Notes/ } }
276 :content => /Notes/ } }
277 end
277 end
278
278
279 def test_show_by_manager
279 def test_show_by_manager
280 @request.session[:user_id] = 2
280 @request.session[:user_id] = 2
281 get :show, :id => 1
281 get :show, :id => 1
282 assert_response :success
282 assert_response :success
283
283
284 assert_tag :tag => 'form',
284 assert_tag :tag => 'form',
285 :descendant => { :tag => 'fieldset',
285 :descendant => { :tag => 'fieldset',
286 :child => { :tag => 'legend',
286 :child => { :tag => 'legend',
287 :content => /Change properties/ } },
287 :content => /Change properties/ } },
288 :descendant => { :tag => 'fieldset',
288 :descendant => { :tag => 'fieldset',
289 :child => { :tag => 'legend',
289 :child => { :tag => 'legend',
290 :content => /Log time/ } },
290 :content => /Log time/ } },
291 :descendant => { :tag => 'fieldset',
291 :descendant => { :tag => 'fieldset',
292 :child => { :tag => 'legend',
292 :child => { :tag => 'legend',
293 :content => /Notes/ } }
293 :content => /Notes/ } }
294 end
294 end
295
295
296 def test_show_should_deny_anonymous_access_without_permission
296 def test_show_should_deny_anonymous_access_without_permission
297 Role.anonymous.remove_permission!(:view_issues)
297 Role.anonymous.remove_permission!(:view_issues)
298 get :show, :id => 1
298 get :show, :id => 1
299 assert_response :redirect
299 assert_response :redirect
300 end
300 end
301
301
302 def test_show_should_deny_non_member_access_without_permission
302 def test_show_should_deny_non_member_access_without_permission
303 Role.non_member.remove_permission!(:view_issues)
303 Role.non_member.remove_permission!(:view_issues)
304 @request.session[:user_id] = 9
304 @request.session[:user_id] = 9
305 get :show, :id => 1
305 get :show, :id => 1
306 assert_response 403
306 assert_response 403
307 end
307 end
308
308
309 def test_show_should_deny_member_access_without_permission
309 def test_show_should_deny_member_access_without_permission
310 Role.find(1).remove_permission!(:view_issues)
310 Role.find(1).remove_permission!(:view_issues)
311 @request.session[:user_id] = 2
311 @request.session[:user_id] = 2
312 get :show, :id => 1
312 get :show, :id => 1
313 assert_response 403
313 assert_response 403
314 end
314 end
315
315
316 def test_show_should_not_disclose_relations_to_invisible_issues
316 def test_show_should_not_disclose_relations_to_invisible_issues
317 Setting.cross_project_issue_relations = '1'
317 Setting.cross_project_issue_relations = '1'
318 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
318 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
319 # Relation to a private project issue
319 # Relation to a private project issue
320 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
320 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
321
321
322 get :show, :id => 1
322 get :show, :id => 1
323 assert_response :success
323 assert_response :success
324
324
325 assert_tag :div, :attributes => { :id => 'relations' },
325 assert_tag :div, :attributes => { :id => 'relations' },
326 :descendant => { :tag => 'a', :content => /#2$/ }
326 :descendant => { :tag => 'a', :content => /#2$/ }
327 assert_no_tag :div, :attributes => { :id => 'relations' },
327 assert_no_tag :div, :attributes => { :id => 'relations' },
328 :descendant => { :tag => 'a', :content => /#4$/ }
328 :descendant => { :tag => 'a', :content => /#4$/ }
329 end
329 end
330
330
331 def test_show_atom
331 def test_show_atom
332 get :show, :id => 2, :format => 'atom'
332 get :show, :id => 2, :format => 'atom'
333 assert_response :success
333 assert_response :success
334 assert_template 'journals/index.rxml'
334 assert_template 'journals/index.rxml'
335 # Inline image
335 # Inline image
336 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
336 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
337 end
337 end
338
338
339 def test_show_export_to_pdf
339 def test_show_export_to_pdf
340 get :show, :id => 3, :format => 'pdf'
340 get :show, :id => 3, :format => 'pdf'
341 assert_response :success
341 assert_response :success
342 assert_equal 'application/pdf', @response.content_type
342 assert_equal 'application/pdf', @response.content_type
343 assert @response.body.starts_with?('%PDF')
343 assert @response.body.starts_with?('%PDF')
344 assert_not_nil assigns(:issue)
344 assert_not_nil assigns(:issue)
345 end
345 end
346
346
347 def test_get_new
347 def test_get_new
348 @request.session[:user_id] = 2
348 @request.session[:user_id] = 2
349 get :new, :project_id => 1, :tracker_id => 1
349 get :new, :project_id => 1, :tracker_id => 1
350 assert_response :success
350 assert_response :success
351 assert_template 'new'
351 assert_template 'new'
352
352
353 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
353 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
354 :value => 'Default string' }
354 :value => 'Default string' }
355 end
355 end
356
356
357 def test_get_new_without_tracker_id
357 def test_get_new_without_tracker_id
358 @request.session[:user_id] = 2
358 @request.session[:user_id] = 2
359 get :new, :project_id => 1
359 get :new, :project_id => 1
360 assert_response :success
360 assert_response :success
361 assert_template 'new'
361 assert_template 'new'
362
362
363 issue = assigns(:issue)
363 issue = assigns(:issue)
364 assert_not_nil issue
364 assert_not_nil issue
365 assert_equal Project.find(1).trackers.first, issue.tracker
365 assert_equal Project.find(1).trackers.first, issue.tracker
366 end
366 end
367
367
368 def test_get_new_with_no_default_status_should_display_an_error
368 def test_get_new_with_no_default_status_should_display_an_error
369 @request.session[:user_id] = 2
369 @request.session[:user_id] = 2
370 IssueStatus.delete_all
370 IssueStatus.delete_all
371
371
372 get :new, :project_id => 1
372 get :new, :project_id => 1
373 assert_response 500
373 assert_response 500
374 assert_error_tag :content => /No default issue/
374 assert_error_tag :content => /No default issue/
375 end
375 end
376
376
377 def test_get_new_with_no_tracker_should_display_an_error
377 def test_get_new_with_no_tracker_should_display_an_error
378 @request.session[:user_id] = 2
378 @request.session[:user_id] = 2
379 Tracker.delete_all
379 Tracker.delete_all
380
380
381 get :new, :project_id => 1
381 get :new, :project_id => 1
382 assert_response 500
382 assert_response 500
383 assert_error_tag :content => /No tracker/
383 assert_error_tag :content => /No tracker/
384 end
384 end
385
385
386 def test_update_new_form
386 def test_update_new_form
387 @request.session[:user_id] = 2
387 @request.session[:user_id] = 2
388 xhr :post, :new, :project_id => 1,
388 xhr :post, :new, :project_id => 1,
389 :issue => {:tracker_id => 2,
389 :issue => {:tracker_id => 2,
390 :subject => 'This is the test_new issue',
390 :subject => 'This is the test_new issue',
391 :description => 'This is the description',
391 :description => 'This is the description',
392 :priority_id => 5}
392 :priority_id => 5}
393 assert_response :success
393 assert_response :success
394 assert_template 'attributes'
394 assert_template 'attributes'
395
395
396 issue = assigns(:issue)
396 issue = assigns(:issue)
397 assert_kind_of Issue, issue
397 assert_kind_of Issue, issue
398 assert_equal 1, issue.project_id
398 assert_equal 1, issue.project_id
399 assert_equal 2, issue.tracker_id
399 assert_equal 2, issue.tracker_id
400 assert_equal 'This is the test_new issue', issue.subject
400 assert_equal 'This is the test_new issue', issue.subject
401 end
401 end
402
402
403 def test_post_create
403 def test_post_create
404 @request.session[:user_id] = 2
404 @request.session[:user_id] = 2
405 assert_difference 'Issue.count' do
405 assert_difference 'Issue.count' do
406 post :create, :project_id => 1,
406 post :create, :project_id => 1,
407 :issue => {:tracker_id => 3,
407 :issue => {:tracker_id => 3,
408 :status_id => 2,
408 :status_id => 2,
409 :subject => 'This is the test_new issue',
409 :subject => 'This is the test_new issue',
410 :description => 'This is the description',
410 :description => 'This is the description',
411 :priority_id => 5,
411 :priority_id => 5,
412 :start_date => '2010-11-07',
412 :start_date => '2010-11-07',
413 :estimated_hours => '',
413 :estimated_hours => '',
414 :custom_field_values => {'2' => 'Value for field 2'}}
414 :custom_field_values => {'2' => 'Value for field 2'}}
415 end
415 end
416 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
416 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
417
417
418 issue = Issue.find_by_subject('This is the test_new issue')
418 issue = Issue.find_by_subject('This is the test_new issue')
419 assert_not_nil issue
419 assert_not_nil issue
420 assert_equal 2, issue.author_id
420 assert_equal 2, issue.author_id
421 assert_equal 3, issue.tracker_id
421 assert_equal 3, issue.tracker_id
422 assert_equal 2, issue.status_id
422 assert_equal 2, issue.status_id
423 assert_equal Date.parse('2010-11-07'), issue.start_date
423 assert_equal Date.parse('2010-11-07'), issue.start_date
424 assert_nil issue.estimated_hours
424 assert_nil issue.estimated_hours
425 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
425 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
426 assert_not_nil v
426 assert_not_nil v
427 assert_equal 'Value for field 2', v.value
427 assert_equal 'Value for field 2', v.value
428 end
428 end
429
429
430 def test_post_create_without_start_date
430 def test_post_create_without_start_date
431 @request.session[:user_id] = 2
431 @request.session[:user_id] = 2
432 assert_difference 'Issue.count' do
432 assert_difference 'Issue.count' do
433 post :create, :project_id => 1,
433 post :create, :project_id => 1,
434 :issue => {:tracker_id => 3,
434 :issue => {:tracker_id => 3,
435 :status_id => 2,
435 :status_id => 2,
436 :subject => 'This is the test_new issue',
436 :subject => 'This is the test_new issue',
437 :description => 'This is the description',
437 :description => 'This is the description',
438 :priority_id => 5,
438 :priority_id => 5,
439 :start_date => '',
439 :start_date => '',
440 :estimated_hours => '',
440 :estimated_hours => '',
441 :custom_field_values => {'2' => 'Value for field 2'}}
441 :custom_field_values => {'2' => 'Value for field 2'}}
442 end
442 end
443 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
443 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
444
444
445 issue = Issue.find_by_subject('This is the test_new issue')
445 issue = Issue.find_by_subject('This is the test_new issue')
446 assert_not_nil issue
446 assert_not_nil issue
447 assert_nil issue.start_date
447 assert_nil issue.start_date
448 end
448 end
449
449
450 def test_post_create_and_continue
450 def test_post_create_and_continue
451 @request.session[:user_id] = 2
451 @request.session[:user_id] = 2
452 post :create, :project_id => 1,
452 post :create, :project_id => 1,
453 :issue => {:tracker_id => 3,
453 :issue => {:tracker_id => 3,
454 :subject => 'This is first issue',
454 :subject => 'This is first issue',
455 :priority_id => 5},
455 :priority_id => 5},
456 :continue => ''
456 :continue => ''
457 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook',
457 assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook',
458 :issue => {:tracker_id => 3}
458 :issue => {:tracker_id => 3}
459 end
459 end
460
460
461 def test_post_create_without_custom_fields_param
461 def test_post_create_without_custom_fields_param
462 @request.session[:user_id] = 2
462 @request.session[:user_id] = 2
463 assert_difference 'Issue.count' do
463 assert_difference 'Issue.count' do
464 post :create, :project_id => 1,
464 post :create, :project_id => 1,
465 :issue => {:tracker_id => 1,
465 :issue => {:tracker_id => 1,
466 :subject => 'This is the test_new issue',
466 :subject => 'This is the test_new issue',
467 :description => 'This is the description',
467 :description => 'This is the description',
468 :priority_id => 5}
468 :priority_id => 5}
469 end
469 end
470 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
470 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
471 end
471 end
472
472
473 def test_post_create_with_required_custom_field_and_without_custom_fields_param
473 def test_post_create_with_required_custom_field_and_without_custom_fields_param
474 field = IssueCustomField.find_by_name('Database')
474 field = IssueCustomField.find_by_name('Database')
475 field.update_attribute(:is_required, true)
475 field.update_attribute(:is_required, true)
476
476
477 @request.session[:user_id] = 2
477 @request.session[:user_id] = 2
478 post :create, :project_id => 1,
478 post :create, :project_id => 1,
479 :issue => {:tracker_id => 1,
479 :issue => {:tracker_id => 1,
480 :subject => 'This is the test_new issue',
480 :subject => 'This is the test_new issue',
481 :description => 'This is the description',
481 :description => 'This is the description',
482 :priority_id => 5}
482 :priority_id => 5}
483 assert_response :success
483 assert_response :success
484 assert_template 'new'
484 assert_template 'new'
485 issue = assigns(:issue)
485 issue = assigns(:issue)
486 assert_not_nil issue
486 assert_not_nil issue
487 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
487 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
488 end
488 end
489
489
490 def test_post_create_with_watchers
490 def test_post_create_with_watchers
491 @request.session[:user_id] = 2
491 @request.session[:user_id] = 2
492 ActionMailer::Base.deliveries.clear
492 ActionMailer::Base.deliveries.clear
493
493
494 assert_difference 'Watcher.count', 2 do
494 assert_difference 'Watcher.count', 2 do
495 post :create, :project_id => 1,
495 post :create, :project_id => 1,
496 :issue => {:tracker_id => 1,
496 :issue => {:tracker_id => 1,
497 :subject => 'This is a new issue with watchers',
497 :subject => 'This is a new issue with watchers',
498 :description => 'This is the description',
498 :description => 'This is the description',
499 :priority_id => 5,
499 :priority_id => 5,
500 :watcher_user_ids => ['2', '3']}
500 :watcher_user_ids => ['2', '3']}
501 end
501 end
502 issue = Issue.find_by_subject('This is a new issue with watchers')
502 issue = Issue.find_by_subject('This is a new issue with watchers')
503 assert_not_nil issue
503 assert_not_nil issue
504 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
504 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
505
505
506 # Watchers added
506 # Watchers added
507 assert_equal [2, 3], issue.watcher_user_ids.sort
507 assert_equal [2, 3], issue.watcher_user_ids.sort
508 assert issue.watched_by?(User.find(3))
508 assert issue.watched_by?(User.find(3))
509 # Watchers notified
509 # Watchers notified
510 mail = ActionMailer::Base.deliveries.last
510 mail = ActionMailer::Base.deliveries.last
511 assert_kind_of TMail::Mail, mail
511 assert_kind_of TMail::Mail, mail
512 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
512 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
513 end
513 end
514
514
515 def test_post_create_subissue
515 def test_post_create_subissue
516 @request.session[:user_id] = 2
516 @request.session[:user_id] = 2
517
517
518 assert_difference 'Issue.count' do
518 assert_difference 'Issue.count' do
519 post :create, :project_id => 1,
519 post :create, :project_id => 1,
520 :issue => {:tracker_id => 1,
520 :issue => {:tracker_id => 1,
521 :subject => 'This is a child issue',
521 :subject => 'This is a child issue',
522 :parent_issue_id => 2}
522 :parent_issue_id => 2}
523 end
523 end
524 issue = Issue.find_by_subject('This is a child issue')
524 issue = Issue.find_by_subject('This is a child issue')
525 assert_not_nil issue
525 assert_not_nil issue
526 assert_equal Issue.find(2), issue.parent
526 assert_equal Issue.find(2), issue.parent
527 end
527 end
528
528
529 def test_post_create_should_send_a_notification
529 def test_post_create_should_send_a_notification
530 ActionMailer::Base.deliveries.clear
530 ActionMailer::Base.deliveries.clear
531 @request.session[:user_id] = 2
531 @request.session[:user_id] = 2
532 assert_difference 'Issue.count' do
532 assert_difference 'Issue.count' do
533 post :create, :project_id => 1,
533 post :create, :project_id => 1,
534 :issue => {:tracker_id => 3,
534 :issue => {:tracker_id => 3,
535 :subject => 'This is the test_new issue',
535 :subject => 'This is the test_new issue',
536 :description => 'This is the description',
536 :description => 'This is the description',
537 :priority_id => 5,
537 :priority_id => 5,
538 :estimated_hours => '',
538 :estimated_hours => '',
539 :custom_field_values => {'2' => 'Value for field 2'}}
539 :custom_field_values => {'2' => 'Value for field 2'}}
540 end
540 end
541 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
541 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
542
542
543 assert_equal 1, ActionMailer::Base.deliveries.size
543 assert_equal 1, ActionMailer::Base.deliveries.size
544 end
544 end
545
545
546 def test_post_create_should_preserve_fields_values_on_validation_failure
546 def test_post_create_should_preserve_fields_values_on_validation_failure
547 @request.session[:user_id] = 2
547 @request.session[:user_id] = 2
548 post :create, :project_id => 1,
548 post :create, :project_id => 1,
549 :issue => {:tracker_id => 1,
549 :issue => {:tracker_id => 1,
550 # empty subject
550 # empty subject
551 :subject => '',
551 :subject => '',
552 :description => 'This is a description',
552 :description => 'This is a description',
553 :priority_id => 6,
553 :priority_id => 6,
554 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
554 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
555 assert_response :success
555 assert_response :success
556 assert_template 'new'
556 assert_template 'new'
557
557
558 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
558 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
559 :content => 'This is a description'
559 :content => 'This is a description'
560 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
560 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
561 :child => { :tag => 'option', :attributes => { :selected => 'selected',
561 :child => { :tag => 'option', :attributes => { :selected => 'selected',
562 :value => '6' },
562 :value => '6' },
563 :content => 'High' }
563 :content => 'High' }
564 # Custom fields
564 # Custom fields
565 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
565 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
566 :child => { :tag => 'option', :attributes => { :selected => 'selected',
566 :child => { :tag => 'option', :attributes => { :selected => 'selected',
567 :value => 'Oracle' },
567 :value => 'Oracle' },
568 :content => 'Oracle' }
568 :content => 'Oracle' }
569 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
569 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
570 :value => 'Value for field 2'}
570 :value => 'Value for field 2'}
571 end
571 end
572
572
573 def test_post_create_should_ignore_non_safe_attributes
573 def test_post_create_should_ignore_non_safe_attributes
574 @request.session[:user_id] = 2
574 @request.session[:user_id] = 2
575 assert_nothing_raised do
575 assert_nothing_raised do
576 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
576 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
577 end
577 end
578 end
578 end
579
579
580 context "without workflow privilege" do
580 context "without workflow privilege" do
581 setup do
581 setup do
582 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
582 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
583 Role.anonymous.add_permission! :add_issues, :add_issue_notes
583 Role.anonymous.add_permission! :add_issues, :add_issue_notes
584 end
584 end
585
585
586 context "#new" do
586 context "#new" do
587 should "propose default status only" do
587 should "propose default status only" do
588 get :new, :project_id => 1
588 get :new, :project_id => 1
589 assert_response :success
589 assert_response :success
590 assert_template 'new'
590 assert_template 'new'
591 assert_tag :tag => 'select',
591 assert_tag :tag => 'select',
592 :attributes => {:name => 'issue[status_id]'},
592 :attributes => {:name => 'issue[status_id]'},
593 :children => {:count => 1},
593 :children => {:count => 1},
594 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
594 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
595 end
595 end
596
596
597 should "accept default status" do
597 should "accept default status" do
598 assert_difference 'Issue.count' do
598 assert_difference 'Issue.count' do
599 post :create, :project_id => 1,
599 post :create, :project_id => 1,
600 :issue => {:tracker_id => 1,
600 :issue => {:tracker_id => 1,
601 :subject => 'This is an issue',
601 :subject => 'This is an issue',
602 :status_id => 1}
602 :status_id => 1}
603 end
603 end
604 issue = Issue.last(:order => 'id')
604 issue = Issue.last(:order => 'id')
605 assert_equal IssueStatus.default, issue.status
605 assert_equal IssueStatus.default, issue.status
606 end
606 end
607
607
608 should "accept default status" do
608 should "accept default status" do
609 assert_difference 'Issue.count' do
609 assert_difference 'Issue.count' do
610 post :create, :project_id => 1,
610 post :create, :project_id => 1,
611 :issue => {:tracker_id => 1,
611 :issue => {:tracker_id => 1,
612 :subject => 'This is an issue',
612 :subject => 'This is an issue',
613 :status_id => 1}
613 :status_id => 1}
614 end
614 end
615 issue = Issue.last(:order => 'id')
615 issue = Issue.last(:order => 'id')
616 assert_equal IssueStatus.default, issue.status
616 assert_equal IssueStatus.default, issue.status
617 end
617 end
618
618
619 should "ignore unauthorized status" do
619 should "ignore unauthorized status" do
620 assert_difference 'Issue.count' do
620 assert_difference 'Issue.count' do
621 post :create, :project_id => 1,
621 post :create, :project_id => 1,
622 :issue => {:tracker_id => 1,
622 :issue => {:tracker_id => 1,
623 :subject => 'This is an issue',
623 :subject => 'This is an issue',
624 :status_id => 3}
624 :status_id => 3}
625 end
625 end
626 issue = Issue.last(:order => 'id')
626 issue = Issue.last(:order => 'id')
627 assert_equal IssueStatus.default, issue.status
627 assert_equal IssueStatus.default, issue.status
628 end
628 end
629 end
629 end
630
630
631 context "#update" do
631 context "#update" do
632 should "ignore status change" do
632 should "ignore status change" do
633 assert_difference 'Journal.count' do
633 assert_difference 'Journal.count' do
634 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
634 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
635 end
635 end
636 assert_equal 1, Issue.find(1).status_id
636 assert_equal 1, Issue.find(1).status_id
637 end
637 end
638
638
639 should "ignore attributes changes" do
639 should "ignore attributes changes" do
640 assert_difference 'Journal.count' do
640 assert_difference 'Journal.count' do
641 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
641 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
642 end
642 end
643 issue = Issue.find(1)
643 issue = Issue.find(1)
644 assert_equal "Can't print recipes", issue.subject
644 assert_equal "Can't print recipes", issue.subject
645 assert_nil issue.assigned_to
645 assert_nil issue.assigned_to
646 end
646 end
647 end
647 end
648 end
648 end
649
649
650 context "with workflow privilege" do
650 context "with workflow privilege" do
651 setup do
651 setup do
652 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
652 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
653 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
653 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
654 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
654 Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
655 Role.anonymous.add_permission! :add_issues, :add_issue_notes
655 Role.anonymous.add_permission! :add_issues, :add_issue_notes
656 end
656 end
657
657
658 context "#update" do
658 context "#update" do
659 should "accept authorized status" do
659 should "accept authorized status" do
660 assert_difference 'Journal.count' do
660 assert_difference 'Journal.count' do
661 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
661 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
662 end
662 end
663 assert_equal 3, Issue.find(1).status_id
663 assert_equal 3, Issue.find(1).status_id
664 end
664 end
665
665
666 should "ignore unauthorized status" do
666 should "ignore unauthorized status" do
667 assert_difference 'Journal.count' do
667 assert_difference 'Journal.count' do
668 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
668 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
669 end
669 end
670 assert_equal 1, Issue.find(1).status_id
670 assert_equal 1, Issue.find(1).status_id
671 end
671 end
672
672
673 should "accept authorized attributes changes" do
673 should "accept authorized attributes changes" do
674 assert_difference 'Journal.count' do
674 assert_difference 'Journal.count' do
675 put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2}
675 put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2}
676 end
676 end
677 issue = Issue.find(1)
677 issue = Issue.find(1)
678 assert_equal 2, issue.assigned_to_id
678 assert_equal 2, issue.assigned_to_id
679 end
679 end
680
680
681 should "ignore unauthorized attributes changes" do
681 should "ignore unauthorized attributes changes" do
682 assert_difference 'Journal.count' do
682 assert_difference 'Journal.count' do
683 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'}
683 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'}
684 end
684 end
685 issue = Issue.find(1)
685 issue = Issue.find(1)
686 assert_equal "Can't print recipes", issue.subject
686 assert_equal "Can't print recipes", issue.subject
687 end
687 end
688 end
688 end
689
689
690 context "and :edit_issues permission" do
690 context "and :edit_issues permission" do
691 setup do
691 setup do
692 Role.anonymous.add_permission! :add_issues, :edit_issues
692 Role.anonymous.add_permission! :add_issues, :edit_issues
693 end
693 end
694
694
695 should "accept authorized status" do
695 should "accept authorized status" do
696 assert_difference 'Journal.count' do
696 assert_difference 'Journal.count' do
697 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
697 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
698 end
698 end
699 assert_equal 3, Issue.find(1).status_id
699 assert_equal 3, Issue.find(1).status_id
700 end
700 end
701
701
702 should "ignore unauthorized status" do
702 should "ignore unauthorized status" do
703 assert_difference 'Journal.count' do
703 assert_difference 'Journal.count' do
704 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
704 put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
705 end
705 end
706 assert_equal 1, Issue.find(1).status_id
706 assert_equal 1, Issue.find(1).status_id
707 end
707 end
708
708
709 should "accept authorized attributes changes" do
709 should "accept authorized attributes changes" do
710 assert_difference 'Journal.count' do
710 assert_difference 'Journal.count' do
711 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
711 put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
712 end
712 end
713 issue = Issue.find(1)
713 issue = Issue.find(1)
714 assert_equal "changed", issue.subject
714 assert_equal "changed", issue.subject
715 assert_equal 2, issue.assigned_to_id
715 assert_equal 2, issue.assigned_to_id
716 end
716 end
717 end
717 end
718 end
718 end
719
719
720 def test_copy_issue
720 def test_copy_issue
721 @request.session[:user_id] = 2
721 @request.session[:user_id] = 2
722 get :new, :project_id => 1, :copy_from => 1
722 get :new, :project_id => 1, :copy_from => 1
723 assert_template 'new'
723 assert_template 'new'
724 assert_not_nil assigns(:issue)
724 assert_not_nil assigns(:issue)
725 orig = Issue.find(1)
725 orig = Issue.find(1)
726 assert_equal orig.subject, assigns(:issue).subject
726 assert_equal orig.subject, assigns(:issue).subject
727 end
727 end
728
728
729 def test_get_edit
729 def test_get_edit
730 @request.session[:user_id] = 2
730 @request.session[:user_id] = 2
731 get :edit, :id => 1
731 get :edit, :id => 1
732 assert_response :success
732 assert_response :success
733 assert_template 'edit'
733 assert_template 'edit'
734 assert_not_nil assigns(:issue)
734 assert_not_nil assigns(:issue)
735 assert_equal Issue.find(1), assigns(:issue)
735 assert_equal Issue.find(1), assigns(:issue)
736 end
736 end
737
737
738 def test_get_edit_with_params
738 def test_get_edit_with_params
739 @request.session[:user_id] = 2
739 @request.session[:user_id] = 2
740 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
740 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
741 :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => TimeEntryActivity.first.id }
741 assert_response :success
742 assert_response :success
742 assert_template 'edit'
743 assert_template 'edit'
743
744
744 issue = assigns(:issue)
745 issue = assigns(:issue)
745 assert_not_nil issue
746 assert_not_nil issue
746
747
747 assert_equal 5, issue.status_id
748 assert_equal 5, issue.status_id
748 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
749 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
749 :child => { :tag => 'option',
750 :child => { :tag => 'option',
750 :content => 'Closed',
751 :content => 'Closed',
751 :attributes => { :selected => 'selected' } }
752 :attributes => { :selected => 'selected' } }
752
753
753 assert_equal 7, issue.priority_id
754 assert_equal 7, issue.priority_id
754 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
755 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
755 :child => { :tag => 'option',
756 :child => { :tag => 'option',
756 :content => 'Urgent',
757 :content => 'Urgent',
757 :attributes => { :selected => 'selected' } }
758 :attributes => { :selected => 'selected' } }
759
760 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => '2.5' }
761 assert_tag :select, :attributes => { :name => 'time_entry[activity_id]' },
762 :child => { :tag => 'option',
763 :attributes => { :selected => 'selected', :value => TimeEntryActivity.first.id } }
764 assert_tag :input, :attributes => { :name => 'time_entry[comments]', :value => 'test_get_edit_with_params' }
758 end
765 end
759
766
760 def test_update_edit_form
767 def test_update_edit_form
761 @request.session[:user_id] = 2
768 @request.session[:user_id] = 2
762 xhr :post, :new, :project_id => 1,
769 xhr :post, :new, :project_id => 1,
763 :id => 1,
770 :id => 1,
764 :issue => {:tracker_id => 2,
771 :issue => {:tracker_id => 2,
765 :subject => 'This is the test_new issue',
772 :subject => 'This is the test_new issue',
766 :description => 'This is the description',
773 :description => 'This is the description',
767 :priority_id => 5}
774 :priority_id => 5}
768 assert_response :success
775 assert_response :success
769 assert_template 'attributes'
776 assert_template 'attributes'
770
777
771 issue = assigns(:issue)
778 issue = assigns(:issue)
772 assert_kind_of Issue, issue
779 assert_kind_of Issue, issue
773 assert_equal 1, issue.id
780 assert_equal 1, issue.id
774 assert_equal 1, issue.project_id
781 assert_equal 1, issue.project_id
775 assert_equal 2, issue.tracker_id
782 assert_equal 2, issue.tracker_id
776 assert_equal 'This is the test_new issue', issue.subject
783 assert_equal 'This is the test_new issue', issue.subject
777 end
784 end
778
785
779 def test_update_using_invalid_http_verbs
786 def test_update_using_invalid_http_verbs
780 @request.session[:user_id] = 2
787 @request.session[:user_id] = 2
781 subject = 'Updated by an invalid http verb'
788 subject = 'Updated by an invalid http verb'
782
789
783 get :update, :id => 1, :issue => {:subject => subject}
790 get :update, :id => 1, :issue => {:subject => subject}
784 assert_not_equal subject, Issue.find(1).subject
791 assert_not_equal subject, Issue.find(1).subject
785
792
786 post :update, :id => 1, :issue => {:subject => subject}
793 post :update, :id => 1, :issue => {:subject => subject}
787 assert_not_equal subject, Issue.find(1).subject
794 assert_not_equal subject, Issue.find(1).subject
788
795
789 delete :update, :id => 1, :issue => {:subject => subject}
796 delete :update, :id => 1, :issue => {:subject => subject}
790 assert_not_equal subject, Issue.find(1).subject
797 assert_not_equal subject, Issue.find(1).subject
791 end
798 end
792
799
793 def test_put_update_without_custom_fields_param
800 def test_put_update_without_custom_fields_param
794 @request.session[:user_id] = 2
801 @request.session[:user_id] = 2
795 ActionMailer::Base.deliveries.clear
802 ActionMailer::Base.deliveries.clear
796
803
797 issue = Issue.find(1)
804 issue = Issue.find(1)
798 assert_equal '125', issue.custom_value_for(2).value
805 assert_equal '125', issue.custom_value_for(2).value
799 old_subject = issue.subject
806 old_subject = issue.subject
800 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
807 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
801
808
802 assert_difference('Journal.count') do
809 assert_difference('Journal.count') do
803 assert_difference('JournalDetail.count', 2) do
810 assert_difference('JournalDetail.count', 2) do
804 put :update, :id => 1, :issue => {:subject => new_subject,
811 put :update, :id => 1, :issue => {:subject => new_subject,
805 :priority_id => '6',
812 :priority_id => '6',
806 :category_id => '1' # no change
813 :category_id => '1' # no change
807 }
814 }
808 end
815 end
809 end
816 end
810 assert_redirected_to :action => 'show', :id => '1'
817 assert_redirected_to :action => 'show', :id => '1'
811 issue.reload
818 issue.reload
812 assert_equal new_subject, issue.subject
819 assert_equal new_subject, issue.subject
813 # Make sure custom fields were not cleared
820 # Make sure custom fields were not cleared
814 assert_equal '125', issue.custom_value_for(2).value
821 assert_equal '125', issue.custom_value_for(2).value
815
822
816 mail = ActionMailer::Base.deliveries.last
823 mail = ActionMailer::Base.deliveries.last
817 assert_kind_of TMail::Mail, mail
824 assert_kind_of TMail::Mail, mail
818 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
825 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
819 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
826 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
820 end
827 end
821
828
822 def test_put_update_with_custom_field_change
829 def test_put_update_with_custom_field_change
823 @request.session[:user_id] = 2
830 @request.session[:user_id] = 2
824 issue = Issue.find(1)
831 issue = Issue.find(1)
825 assert_equal '125', issue.custom_value_for(2).value
832 assert_equal '125', issue.custom_value_for(2).value
826
833
827 assert_difference('Journal.count') do
834 assert_difference('Journal.count') do
828 assert_difference('JournalDetail.count', 3) do
835 assert_difference('JournalDetail.count', 3) do
829 put :update, :id => 1, :issue => {:subject => 'Custom field change',
836 put :update, :id => 1, :issue => {:subject => 'Custom field change',
830 :priority_id => '6',
837 :priority_id => '6',
831 :category_id => '1', # no change
838 :category_id => '1', # no change
832 :custom_field_values => { '2' => 'New custom value' }
839 :custom_field_values => { '2' => 'New custom value' }
833 }
840 }
834 end
841 end
835 end
842 end
836 assert_redirected_to :action => 'show', :id => '1'
843 assert_redirected_to :action => 'show', :id => '1'
837 issue.reload
844 issue.reload
838 assert_equal 'New custom value', issue.custom_value_for(2).value
845 assert_equal 'New custom value', issue.custom_value_for(2).value
839
846
840 mail = ActionMailer::Base.deliveries.last
847 mail = ActionMailer::Base.deliveries.last
841 assert_kind_of TMail::Mail, mail
848 assert_kind_of TMail::Mail, mail
842 assert mail.body.include?("Searchable field changed from 125 to New custom value")
849 assert mail.body.include?("Searchable field changed from 125 to New custom value")
843 end
850 end
844
851
845 def test_put_update_with_status_and_assignee_change
852 def test_put_update_with_status_and_assignee_change
846 issue = Issue.find(1)
853 issue = Issue.find(1)
847 assert_equal 1, issue.status_id
854 assert_equal 1, issue.status_id
848 @request.session[:user_id] = 2
855 @request.session[:user_id] = 2
849 assert_difference('TimeEntry.count', 0) do
856 assert_difference('TimeEntry.count', 0) do
850 put :update,
857 put :update,
851 :id => 1,
858 :id => 1,
852 :issue => { :status_id => 2, :assigned_to_id => 3 },
859 :issue => { :status_id => 2, :assigned_to_id => 3 },
853 :notes => 'Assigned to dlopper',
860 :notes => 'Assigned to dlopper',
854 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
861 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
855 end
862 end
856 assert_redirected_to :action => 'show', :id => '1'
863 assert_redirected_to :action => 'show', :id => '1'
857 issue.reload
864 issue.reload
858 assert_equal 2, issue.status_id
865 assert_equal 2, issue.status_id
859 j = Journal.find(:first, :order => 'id DESC')
866 j = Journal.find(:first, :order => 'id DESC')
860 assert_equal 'Assigned to dlopper', j.notes
867 assert_equal 'Assigned to dlopper', j.notes
861 assert_equal 2, j.details.size
868 assert_equal 2, j.details.size
862
869
863 mail = ActionMailer::Base.deliveries.last
870 mail = ActionMailer::Base.deliveries.last
864 assert mail.body.include?("Status changed from New to Assigned")
871 assert mail.body.include?("Status changed from New to Assigned")
865 # subject should contain the new status
872 # subject should contain the new status
866 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
873 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
867 end
874 end
868
875
869 def test_put_update_with_note_only
876 def test_put_update_with_note_only
870 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
877 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
871 # anonymous user
878 # anonymous user
872 put :update,
879 put :update,
873 :id => 1,
880 :id => 1,
874 :notes => notes
881 :notes => notes
875 assert_redirected_to :action => 'show', :id => '1'
882 assert_redirected_to :action => 'show', :id => '1'
876 j = Journal.find(:first, :order => 'id DESC')
883 j = Journal.find(:first, :order => 'id DESC')
877 assert_equal notes, j.notes
884 assert_equal notes, j.notes
878 assert_equal 0, j.details.size
885 assert_equal 0, j.details.size
879 assert_equal User.anonymous, j.user
886 assert_equal User.anonymous, j.user
880
887
881 mail = ActionMailer::Base.deliveries.last
888 mail = ActionMailer::Base.deliveries.last
882 assert mail.body.include?(notes)
889 assert mail.body.include?(notes)
883 end
890 end
884
891
885 def test_put_update_with_note_and_spent_time
892 def test_put_update_with_note_and_spent_time
886 @request.session[:user_id] = 2
893 @request.session[:user_id] = 2
887 spent_hours_before = Issue.find(1).spent_hours
894 spent_hours_before = Issue.find(1).spent_hours
888 assert_difference('TimeEntry.count') do
895 assert_difference('TimeEntry.count') do
889 put :update,
896 put :update,
890 :id => 1,
897 :id => 1,
891 :notes => '2.5 hours added',
898 :notes => '2.5 hours added',
892 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
899 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
893 end
900 end
894 assert_redirected_to :action => 'show', :id => '1'
901 assert_redirected_to :action => 'show', :id => '1'
895
902
896 issue = Issue.find(1)
903 issue = Issue.find(1)
897
904
898 j = Journal.find(:first, :order => 'id DESC')
905 j = Journal.find(:first, :order => 'id DESC')
899 assert_equal '2.5 hours added', j.notes
906 assert_equal '2.5 hours added', j.notes
900 assert_equal 0, j.details.size
907 assert_equal 0, j.details.size
901
908
902 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
909 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
903 assert_not_nil t
910 assert_not_nil t
904 assert_equal 2.5, t.hours
911 assert_equal 2.5, t.hours
905 assert_equal spent_hours_before + 2.5, issue.spent_hours
912 assert_equal spent_hours_before + 2.5, issue.spent_hours
906 end
913 end
907
914
908 def test_put_update_with_attachment_only
915 def test_put_update_with_attachment_only
909 set_tmp_attachments_directory
916 set_tmp_attachments_directory
910
917
911 # Delete all fixtured journals, a race condition can occur causing the wrong
918 # Delete all fixtured journals, a race condition can occur causing the wrong
912 # journal to get fetched in the next find.
919 # journal to get fetched in the next find.
913 Journal.delete_all
920 Journal.delete_all
914
921
915 # anonymous user
922 # anonymous user
916 put :update,
923 put :update,
917 :id => 1,
924 :id => 1,
918 :notes => '',
925 :notes => '',
919 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
926 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
920 assert_redirected_to :action => 'show', :id => '1'
927 assert_redirected_to :action => 'show', :id => '1'
921 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
928 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
922 assert j.notes.blank?
929 assert j.notes.blank?
923 assert_equal 1, j.details.size
930 assert_equal 1, j.details.size
924 assert_equal 'testfile.txt', j.details.first.value
931 assert_equal 'testfile.txt', j.details.first.value
925 assert_equal User.anonymous, j.user
932 assert_equal User.anonymous, j.user
926
933
927 mail = ActionMailer::Base.deliveries.last
934 mail = ActionMailer::Base.deliveries.last
928 assert mail.body.include?('testfile.txt')
935 assert mail.body.include?('testfile.txt')
929 end
936 end
930
937
931 def test_put_update_with_attachment_that_fails_to_save
938 def test_put_update_with_attachment_that_fails_to_save
932 set_tmp_attachments_directory
939 set_tmp_attachments_directory
933
940
934 # Delete all fixtured journals, a race condition can occur causing the wrong
941 # Delete all fixtured journals, a race condition can occur causing the wrong
935 # journal to get fetched in the next find.
942 # journal to get fetched in the next find.
936 Journal.delete_all
943 Journal.delete_all
937
944
938 # Mock out the unsaved attachment
945 # Mock out the unsaved attachment
939 Attachment.any_instance.stubs(:create).returns(Attachment.new)
946 Attachment.any_instance.stubs(:create).returns(Attachment.new)
940
947
941 # anonymous user
948 # anonymous user
942 put :update,
949 put :update,
943 :id => 1,
950 :id => 1,
944 :notes => '',
951 :notes => '',
945 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
952 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
946 assert_redirected_to :action => 'show', :id => '1'
953 assert_redirected_to :action => 'show', :id => '1'
947 assert_equal '1 file(s) could not be saved.', flash[:warning]
954 assert_equal '1 file(s) could not be saved.', flash[:warning]
948
955
949 end if Object.const_defined?(:Mocha)
956 end if Object.const_defined?(:Mocha)
950
957
951 def test_put_update_with_no_change
958 def test_put_update_with_no_change
952 issue = Issue.find(1)
959 issue = Issue.find(1)
953 issue.journals.clear
960 issue.journals.clear
954 ActionMailer::Base.deliveries.clear
961 ActionMailer::Base.deliveries.clear
955
962
956 put :update,
963 put :update,
957 :id => 1,
964 :id => 1,
958 :notes => ''
965 :notes => ''
959 assert_redirected_to :action => 'show', :id => '1'
966 assert_redirected_to :action => 'show', :id => '1'
960
967
961 issue.reload
968 issue.reload
962 assert issue.journals.empty?
969 assert issue.journals.empty?
963 # No email should be sent
970 # No email should be sent
964 assert ActionMailer::Base.deliveries.empty?
971 assert ActionMailer::Base.deliveries.empty?
965 end
972 end
966
973
967 def test_put_update_should_send_a_notification
974 def test_put_update_should_send_a_notification
968 @request.session[:user_id] = 2
975 @request.session[:user_id] = 2
969 ActionMailer::Base.deliveries.clear
976 ActionMailer::Base.deliveries.clear
970 issue = Issue.find(1)
977 issue = Issue.find(1)
971 old_subject = issue.subject
978 old_subject = issue.subject
972 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
979 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
973
980
974 put :update, :id => 1, :issue => {:subject => new_subject,
981 put :update, :id => 1, :issue => {:subject => new_subject,
975 :priority_id => '6',
982 :priority_id => '6',
976 :category_id => '1' # no change
983 :category_id => '1' # no change
977 }
984 }
978 assert_equal 1, ActionMailer::Base.deliveries.size
985 assert_equal 1, ActionMailer::Base.deliveries.size
979 end
986 end
980
987
981 def test_put_update_with_invalid_spent_time
988 def test_put_update_with_invalid_spent_time
982 @request.session[:user_id] = 2
989 @request.session[:user_id] = 2
983 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
990 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
984
991
985 assert_no_difference('Journal.count') do
992 assert_no_difference('Journal.count') do
986 put :update,
993 put :update,
987 :id => 1,
994 :id => 1,
988 :notes => notes,
995 :notes => notes,
989 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
996 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
990 end
997 end
991 assert_response :success
998 assert_response :success
992 assert_template 'edit'
999 assert_template 'edit'
993
1000
994 assert_tag :textarea, :attributes => { :name => 'notes' },
1001 assert_tag :textarea, :attributes => { :name => 'notes' },
995 :content => notes
1002 :content => notes
996 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
1003 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
997 end
1004 end
998
1005
999 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
1006 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
1000 issue = Issue.find(2)
1007 issue = Issue.find(2)
1001 @request.session[:user_id] = 2
1008 @request.session[:user_id] = 2
1002
1009
1003 put :update,
1010 put :update,
1004 :id => issue.id,
1011 :id => issue.id,
1005 :issue => {
1012 :issue => {
1006 :fixed_version_id => 4
1013 :fixed_version_id => 4
1007 }
1014 }
1008
1015
1009 assert_response :redirect
1016 assert_response :redirect
1010 issue.reload
1017 issue.reload
1011 assert_equal 4, issue.fixed_version_id
1018 assert_equal 4, issue.fixed_version_id
1012 assert_not_equal issue.project_id, issue.fixed_version.project_id
1019 assert_not_equal issue.project_id, issue.fixed_version.project_id
1013 end
1020 end
1014
1021
1015 def test_put_update_should_redirect_back_using_the_back_url_parameter
1022 def test_put_update_should_redirect_back_using_the_back_url_parameter
1016 issue = Issue.find(2)
1023 issue = Issue.find(2)
1017 @request.session[:user_id] = 2
1024 @request.session[:user_id] = 2
1018
1025
1019 put :update,
1026 put :update,
1020 :id => issue.id,
1027 :id => issue.id,
1021 :issue => {
1028 :issue => {
1022 :fixed_version_id => 4
1029 :fixed_version_id => 4
1023 },
1030 },
1024 :back_url => '/issues'
1031 :back_url => '/issues'
1025
1032
1026 assert_response :redirect
1033 assert_response :redirect
1027 assert_redirected_to '/issues'
1034 assert_redirected_to '/issues'
1028 end
1035 end
1029
1036
1030 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1037 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1031 issue = Issue.find(2)
1038 issue = Issue.find(2)
1032 @request.session[:user_id] = 2
1039 @request.session[:user_id] = 2
1033
1040
1034 put :update,
1041 put :update,
1035 :id => issue.id,
1042 :id => issue.id,
1036 :issue => {
1043 :issue => {
1037 :fixed_version_id => 4
1044 :fixed_version_id => 4
1038 },
1045 },
1039 :back_url => 'http://google.com'
1046 :back_url => 'http://google.com'
1040
1047
1041 assert_response :redirect
1048 assert_response :redirect
1042 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
1049 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
1043 end
1050 end
1044
1051
1045 def test_get_bulk_edit
1052 def test_get_bulk_edit
1046 @request.session[:user_id] = 2
1053 @request.session[:user_id] = 2
1047 get :bulk_edit, :ids => [1, 2]
1054 get :bulk_edit, :ids => [1, 2]
1048 assert_response :success
1055 assert_response :success
1049 assert_template 'bulk_edit'
1056 assert_template 'bulk_edit'
1050
1057
1051 # Project specific custom field, date type
1058 # Project specific custom field, date type
1052 field = CustomField.find(9)
1059 field = CustomField.find(9)
1053 assert !field.is_for_all?
1060 assert !field.is_for_all?
1054 assert_equal 'date', field.field_format
1061 assert_equal 'date', field.field_format
1055 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
1062 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
1056
1063
1057 # System wide custom field
1064 # System wide custom field
1058 assert CustomField.find(1).is_for_all?
1065 assert CustomField.find(1).is_for_all?
1059 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
1066 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
1060 end
1067 end
1061
1068
1062 def test_get_bulk_edit_on_different_projects
1069 def test_get_bulk_edit_on_different_projects
1063 @request.session[:user_id] = 2
1070 @request.session[:user_id] = 2
1064 get :bulk_edit, :ids => [1, 2, 6]
1071 get :bulk_edit, :ids => [1, 2, 6]
1065 assert_response :success
1072 assert_response :success
1066 assert_template 'bulk_edit'
1073 assert_template 'bulk_edit'
1067
1074
1068 # Project specific custom field, date type
1075 # Project specific custom field, date type
1069 field = CustomField.find(9)
1076 field = CustomField.find(9)
1070 assert !field.is_for_all?
1077 assert !field.is_for_all?
1071 assert !field.project_ids.include?(Issue.find(6).project_id)
1078 assert !field.project_ids.include?(Issue.find(6).project_id)
1072 assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
1079 assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
1073 end
1080 end
1074
1081
1075 def test_bulk_update
1082 def test_bulk_update
1076 @request.session[:user_id] = 2
1083 @request.session[:user_id] = 2
1077 # update issues priority
1084 # update issues priority
1078 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
1085 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
1079 :issue => {:priority_id => 7,
1086 :issue => {:priority_id => 7,
1080 :assigned_to_id => '',
1087 :assigned_to_id => '',
1081 :custom_field_values => {'2' => ''}}
1088 :custom_field_values => {'2' => ''}}
1082
1089
1083 assert_response 302
1090 assert_response 302
1084 # check that the issues were updated
1091 # check that the issues were updated
1085 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
1092 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
1086
1093
1087 issue = Issue.find(1)
1094 issue = Issue.find(1)
1088 journal = issue.journals.find(:first, :order => 'created_on DESC')
1095 journal = issue.journals.find(:first, :order => 'created_on DESC')
1089 assert_equal '125', issue.custom_value_for(2).value
1096 assert_equal '125', issue.custom_value_for(2).value
1090 assert_equal 'Bulk editing', journal.notes
1097 assert_equal 'Bulk editing', journal.notes
1091 assert_equal 1, journal.details.size
1098 assert_equal 1, journal.details.size
1092 end
1099 end
1093
1100
1094 def test_bulk_update_on_different_projects
1101 def test_bulk_update_on_different_projects
1095 @request.session[:user_id] = 2
1102 @request.session[:user_id] = 2
1096 # update issues priority
1103 # update issues priority
1097 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
1104 post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
1098 :issue => {:priority_id => 7,
1105 :issue => {:priority_id => 7,
1099 :assigned_to_id => '',
1106 :assigned_to_id => '',
1100 :custom_field_values => {'2' => ''}}
1107 :custom_field_values => {'2' => ''}}
1101
1108
1102 assert_response 302
1109 assert_response 302
1103 # check that the issues were updated
1110 # check that the issues were updated
1104 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
1111 assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
1105
1112
1106 issue = Issue.find(1)
1113 issue = Issue.find(1)
1107 journal = issue.journals.find(:first, :order => 'created_on DESC')
1114 journal = issue.journals.find(:first, :order => 'created_on DESC')
1108 assert_equal '125', issue.custom_value_for(2).value
1115 assert_equal '125', issue.custom_value_for(2).value
1109 assert_equal 'Bulk editing', journal.notes
1116 assert_equal 'Bulk editing', journal.notes
1110 assert_equal 1, journal.details.size
1117 assert_equal 1, journal.details.size
1111 end
1118 end
1112
1119
1113 def test_bulk_update_on_different_projects_without_rights
1120 def test_bulk_update_on_different_projects_without_rights
1114 @request.session[:user_id] = 3
1121 @request.session[:user_id] = 3
1115 user = User.find(3)
1122 user = User.find(3)
1116 action = { :controller => "issues", :action => "bulk_update" }
1123 action = { :controller => "issues", :action => "bulk_update" }
1117 assert user.allowed_to?(action, Issue.find(1).project)
1124 assert user.allowed_to?(action, Issue.find(1).project)
1118 assert ! user.allowed_to?(action, Issue.find(6).project)
1125 assert ! user.allowed_to?(action, Issue.find(6).project)
1119 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
1126 post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
1120 :issue => {:priority_id => 7,
1127 :issue => {:priority_id => 7,
1121 :assigned_to_id => '',
1128 :assigned_to_id => '',
1122 :custom_field_values => {'2' => ''}}
1129 :custom_field_values => {'2' => ''}}
1123 assert_response 403
1130 assert_response 403
1124 assert_not_equal "Bulk should fail", Journal.last.notes
1131 assert_not_equal "Bulk should fail", Journal.last.notes
1125 end
1132 end
1126
1133
1127 def test_bullk_update_should_send_a_notification
1134 def test_bullk_update_should_send_a_notification
1128 @request.session[:user_id] = 2
1135 @request.session[:user_id] = 2
1129 ActionMailer::Base.deliveries.clear
1136 ActionMailer::Base.deliveries.clear
1130 post(:bulk_update,
1137 post(:bulk_update,
1131 {
1138 {
1132 :ids => [1, 2],
1139 :ids => [1, 2],
1133 :notes => 'Bulk editing',
1140 :notes => 'Bulk editing',
1134 :issue => {
1141 :issue => {
1135 :priority_id => 7,
1142 :priority_id => 7,
1136 :assigned_to_id => '',
1143 :assigned_to_id => '',
1137 :custom_field_values => {'2' => ''}
1144 :custom_field_values => {'2' => ''}
1138 }
1145 }
1139 })
1146 })
1140
1147
1141 assert_response 302
1148 assert_response 302
1142 assert_equal 2, ActionMailer::Base.deliveries.size
1149 assert_equal 2, ActionMailer::Base.deliveries.size
1143 end
1150 end
1144
1151
1145 def test_bulk_update_status
1152 def test_bulk_update_status
1146 @request.session[:user_id] = 2
1153 @request.session[:user_id] = 2
1147 # update issues priority
1154 # update issues priority
1148 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
1155 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
1149 :issue => {:priority_id => '',
1156 :issue => {:priority_id => '',
1150 :assigned_to_id => '',
1157 :assigned_to_id => '',
1151 :status_id => '5'}
1158 :status_id => '5'}
1152
1159
1153 assert_response 302
1160 assert_response 302
1154 issue = Issue.find(1)
1161 issue = Issue.find(1)
1155 assert issue.closed?
1162 assert issue.closed?
1156 end
1163 end
1157
1164
1158 def test_bulk_update_custom_field
1165 def test_bulk_update_custom_field
1159 @request.session[:user_id] = 2
1166 @request.session[:user_id] = 2
1160 # update issues priority
1167 # update issues priority
1161 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
1168 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
1162 :issue => {:priority_id => '',
1169 :issue => {:priority_id => '',
1163 :assigned_to_id => '',
1170 :assigned_to_id => '',
1164 :custom_field_values => {'2' => '777'}}
1171 :custom_field_values => {'2' => '777'}}
1165
1172
1166 assert_response 302
1173 assert_response 302
1167
1174
1168 issue = Issue.find(1)
1175 issue = Issue.find(1)
1169 journal = issue.journals.find(:first, :order => 'created_on DESC')
1176 journal = issue.journals.find(:first, :order => 'created_on DESC')
1170 assert_equal '777', issue.custom_value_for(2).value
1177 assert_equal '777', issue.custom_value_for(2).value
1171 assert_equal 1, journal.details.size
1178 assert_equal 1, journal.details.size
1172 assert_equal '125', journal.details.first.old_value
1179 assert_equal '125', journal.details.first.old_value
1173 assert_equal '777', journal.details.first.value
1180 assert_equal '777', journal.details.first.value
1174 end
1181 end
1175
1182
1176 def test_bulk_update_unassign
1183 def test_bulk_update_unassign
1177 assert_not_nil Issue.find(2).assigned_to
1184 assert_not_nil Issue.find(2).assigned_to
1178 @request.session[:user_id] = 2
1185 @request.session[:user_id] = 2
1179 # unassign issues
1186 # unassign issues
1180 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1187 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1181 assert_response 302
1188 assert_response 302
1182 # check that the issues were updated
1189 # check that the issues were updated
1183 assert_nil Issue.find(2).assigned_to
1190 assert_nil Issue.find(2).assigned_to
1184 end
1191 end
1185
1192
1186 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
1193 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
1187 @request.session[:user_id] = 2
1194 @request.session[:user_id] = 2
1188
1195
1189 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
1196 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
1190
1197
1191 assert_response :redirect
1198 assert_response :redirect
1192 issues = Issue.find([1,2])
1199 issues = Issue.find([1,2])
1193 issues.each do |issue|
1200 issues.each do |issue|
1194 assert_equal 4, issue.fixed_version_id
1201 assert_equal 4, issue.fixed_version_id
1195 assert_not_equal issue.project_id, issue.fixed_version.project_id
1202 assert_not_equal issue.project_id, issue.fixed_version.project_id
1196 end
1203 end
1197 end
1204 end
1198
1205
1199 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
1206 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
1200 @request.session[:user_id] = 2
1207 @request.session[:user_id] = 2
1201 post :bulk_update, :ids => [1,2], :back_url => '/issues'
1208 post :bulk_update, :ids => [1,2], :back_url => '/issues'
1202
1209
1203 assert_response :redirect
1210 assert_response :redirect
1204 assert_redirected_to '/issues'
1211 assert_redirected_to '/issues'
1205 end
1212 end
1206
1213
1207 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1214 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1208 @request.session[:user_id] = 2
1215 @request.session[:user_id] = 2
1209 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
1216 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
1210
1217
1211 assert_response :redirect
1218 assert_response :redirect
1212 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1219 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1213 end
1220 end
1214
1221
1215 def test_destroy_issue_with_no_time_entries
1222 def test_destroy_issue_with_no_time_entries
1216 assert_nil TimeEntry.find_by_issue_id(2)
1223 assert_nil TimeEntry.find_by_issue_id(2)
1217 @request.session[:user_id] = 2
1224 @request.session[:user_id] = 2
1218 post :destroy, :id => 2
1225 post :destroy, :id => 2
1219 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1226 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1220 assert_nil Issue.find_by_id(2)
1227 assert_nil Issue.find_by_id(2)
1221 end
1228 end
1222
1229
1223 def test_destroy_issues_with_time_entries
1230 def test_destroy_issues_with_time_entries
1224 @request.session[:user_id] = 2
1231 @request.session[:user_id] = 2
1225 post :destroy, :ids => [1, 3]
1232 post :destroy, :ids => [1, 3]
1226 assert_response :success
1233 assert_response :success
1227 assert_template 'destroy'
1234 assert_template 'destroy'
1228 assert_not_nil assigns(:hours)
1235 assert_not_nil assigns(:hours)
1229 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1236 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1230 end
1237 end
1231
1238
1232 def test_destroy_issues_and_destroy_time_entries
1239 def test_destroy_issues_and_destroy_time_entries
1233 @request.session[:user_id] = 2
1240 @request.session[:user_id] = 2
1234 post :destroy, :ids => [1, 3], :todo => 'destroy'
1241 post :destroy, :ids => [1, 3], :todo => 'destroy'
1235 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1242 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1236 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1243 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1237 assert_nil TimeEntry.find_by_id([1, 2])
1244 assert_nil TimeEntry.find_by_id([1, 2])
1238 end
1245 end
1239
1246
1240 def test_destroy_issues_and_assign_time_entries_to_project
1247 def test_destroy_issues_and_assign_time_entries_to_project
1241 @request.session[:user_id] = 2
1248 @request.session[:user_id] = 2
1242 post :destroy, :ids => [1, 3], :todo => 'nullify'
1249 post :destroy, :ids => [1, 3], :todo => 'nullify'
1243 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1250 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1244 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1251 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1245 assert_nil TimeEntry.find(1).issue_id
1252 assert_nil TimeEntry.find(1).issue_id
1246 assert_nil TimeEntry.find(2).issue_id
1253 assert_nil TimeEntry.find(2).issue_id
1247 end
1254 end
1248
1255
1249 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1256 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1250 @request.session[:user_id] = 2
1257 @request.session[:user_id] = 2
1251 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1258 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1252 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1259 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1253 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1260 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1254 assert_equal 2, TimeEntry.find(1).issue_id
1261 assert_equal 2, TimeEntry.find(1).issue_id
1255 assert_equal 2, TimeEntry.find(2).issue_id
1262 assert_equal 2, TimeEntry.find(2).issue_id
1256 end
1263 end
1257
1264
1258 def test_destroy_issues_from_different_projects
1265 def test_destroy_issues_from_different_projects
1259 @request.session[:user_id] = 2
1266 @request.session[:user_id] = 2
1260 post :destroy, :ids => [1, 2, 6], :todo => 'destroy'
1267 post :destroy, :ids => [1, 2, 6], :todo => 'destroy'
1261 assert_redirected_to :controller => 'issues', :action => 'index'
1268 assert_redirected_to :controller => 'issues', :action => 'index'
1262 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
1269 assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
1263 end
1270 end
1264
1271
1265 def test_default_search_scope
1272 def test_default_search_scope
1266 get :index
1273 get :index
1267 assert_tag :div, :attributes => {:id => 'quick-search'},
1274 assert_tag :div, :attributes => {:id => 'quick-search'},
1268 :child => {:tag => 'form',
1275 :child => {:tag => 'form',
1269 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1276 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1270 end
1277 end
1271 end
1278 end
General Comments 0
You need to be logged in to leave comments. Login now