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