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