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