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