##// END OF EJS Templates
Refactor: extract #bulk_update method from IssuesController#bulk_edit....
Eric Davis -
r3923:80256cf298e6
parent child
Show More
@@ -1,318 +1,321
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class IssuesController < ApplicationController
18 class IssuesController < ApplicationController
19 menu_item :new_issue, :only => [:new, :create]
19 menu_item :new_issue, :only => [:new, :create]
20 default_search_scope :issues
20 default_search_scope :issues
21
21
22 before_filter :find_issue, :only => [:show, :edit, :update]
22 before_filter :find_issue, :only => [:show, :edit, :update]
23 before_filter :find_issues, :only => [:bulk_edit, :move, :perform_move, :destroy]
23 before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy]
24 before_filter :find_project, :only => [:new, :create]
24 before_filter :find_project, :only => [:new, :create]
25 before_filter :authorize, :except => [:index]
25 before_filter :authorize, :except => [:index]
26 before_filter :find_optional_project, :only => [:index]
26 before_filter :find_optional_project, :only => [:index]
27 before_filter :check_for_default_issue_status, :only => [:new, :create]
27 before_filter :check_for_default_issue_status, :only => [:new, :create]
28 before_filter :build_new_issue_from_params, :only => [:new, :create]
28 before_filter :build_new_issue_from_params, :only => [:new, :create]
29 accept_key_auth :index, :show
29 accept_key_auth :index, :show
30
30
31 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
31 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
32
32
33 helper :journals
33 helper :journals
34 helper :projects
34 helper :projects
35 include ProjectsHelper
35 include ProjectsHelper
36 helper :custom_fields
36 helper :custom_fields
37 include CustomFieldsHelper
37 include CustomFieldsHelper
38 helper :issue_relations
38 helper :issue_relations
39 include IssueRelationsHelper
39 include IssueRelationsHelper
40 helper :watchers
40 helper :watchers
41 include WatchersHelper
41 include WatchersHelper
42 helper :attachments
42 helper :attachments
43 include AttachmentsHelper
43 include AttachmentsHelper
44 helper :queries
44 helper :queries
45 include QueriesHelper
45 include QueriesHelper
46 helper :sort
46 helper :sort
47 include SortHelper
47 include SortHelper
48 include IssuesHelper
48 include IssuesHelper
49 helper :timelog
49 helper :timelog
50 include Redmine::Export::PDF
50 include Redmine::Export::PDF
51
51
52 verify :method => [:post, :delete],
52 verify :method => [:post, :delete],
53 :only => :destroy,
53 :only => :destroy,
54 :render => { :nothing => true, :status => :method_not_allowed }
54 :render => { :nothing => true, :status => :method_not_allowed }
55
55
56 verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
56 verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
57 verify :method => :post, :only => :bulk_update, :render => {:nothing => true, :status => :method_not_allowed }
57 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
58 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
58
59
59 def index
60 def index
60 retrieve_query
61 retrieve_query
61 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
62 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
62 sort_update(@query.sortable_columns)
63 sort_update(@query.sortable_columns)
63
64
64 if @query.valid?
65 if @query.valid?
65 limit = case params[:format]
66 limit = case params[:format]
66 when 'csv', 'pdf'
67 when 'csv', 'pdf'
67 Setting.issues_export_limit.to_i
68 Setting.issues_export_limit.to_i
68 when 'atom'
69 when 'atom'
69 Setting.feeds_limit.to_i
70 Setting.feeds_limit.to_i
70 else
71 else
71 per_page_option
72 per_page_option
72 end
73 end
73
74
74 @issue_count = @query.issue_count
75 @issue_count = @query.issue_count
75 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
76 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
76 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
77 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
77 :order => sort_clause,
78 :order => sort_clause,
78 :offset => @issue_pages.current.offset,
79 :offset => @issue_pages.current.offset,
79 :limit => limit)
80 :limit => limit)
80 @issue_count_by_group = @query.issue_count_by_group
81 @issue_count_by_group = @query.issue_count_by_group
81
82
82 respond_to do |format|
83 respond_to do |format|
83 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
84 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
84 format.xml { render :layout => false }
85 format.xml { render :layout => false }
85 format.json { render :text => @issues.to_json, :layout => false }
86 format.json { render :text => @issues.to_json, :layout => false }
86 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
87 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
87 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
88 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
88 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
89 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
89 end
90 end
90 else
91 else
91 # Send html if the query is not valid
92 # Send html if the query is not valid
92 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
93 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
93 end
94 end
94 rescue ActiveRecord::RecordNotFound
95 rescue ActiveRecord::RecordNotFound
95 render_404
96 render_404
96 end
97 end
97
98
98 def show
99 def show
99 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
100 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
100 @journals.each_with_index {|j,i| j.indice = i+1}
101 @journals.each_with_index {|j,i| j.indice = i+1}
101 @journals.reverse! if User.current.wants_comments_in_reverse_order?
102 @journals.reverse! if User.current.wants_comments_in_reverse_order?
102 @changesets = @issue.changesets.visible.all
103 @changesets = @issue.changesets.visible.all
103 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
104 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
104 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
105 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
105 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
106 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
106 @priorities = IssuePriority.all
107 @priorities = IssuePriority.all
107 @time_entry = TimeEntry.new
108 @time_entry = TimeEntry.new
108 respond_to do |format|
109 respond_to do |format|
109 format.html { render :template => 'issues/show.rhtml' }
110 format.html { render :template => 'issues/show.rhtml' }
110 format.xml { render :layout => false }
111 format.xml { render :layout => false }
111 format.json { render :text => @issue.to_json, :layout => false }
112 format.json { render :text => @issue.to_json, :layout => false }
112 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
113 format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
113 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
114 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
114 end
115 end
115 end
116 end
116
117
117 # Add a new issue
118 # Add a new issue
118 # The new issue will be created from an existing one if copy_from parameter is given
119 # The new issue will be created from an existing one if copy_from parameter is given
119 def new
120 def new
120 respond_to do |format|
121 respond_to do |format|
121 format.html { render :action => 'new', :layout => !request.xhr? }
122 format.html { render :action => 'new', :layout => !request.xhr? }
122 format.js { render :partial => 'attributes' }
123 format.js { render :partial => 'attributes' }
123 end
124 end
124 end
125 end
125
126
126 def create
127 def create
127 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
128 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
128 if @issue.save
129 if @issue.save
129 attachments = Attachment.attach_files(@issue, params[:attachments])
130 attachments = Attachment.attach_files(@issue, params[:attachments])
130 render_attachment_warning_if_needed(@issue)
131 render_attachment_warning_if_needed(@issue)
131 flash[:notice] = l(:notice_successful_create)
132 flash[:notice] = l(:notice_successful_create)
132 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
133 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
133 respond_to do |format|
134 respond_to do |format|
134 format.html {
135 format.html {
135 redirect_to(params[:continue] ? { :action => 'new', :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
136 redirect_to(params[:continue] ? { :action => 'new', :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
136 { :action => 'show', :id => @issue })
137 { :action => 'show', :id => @issue })
137 }
138 }
138 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
139 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
139 format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
140 format.json { render :text => @issue.to_json, :status => :created, :location => url_for(:controller => 'issues', :action => 'show'), :layout => false }
140 end
141 end
141 return
142 return
142 else
143 else
143 respond_to do |format|
144 respond_to do |format|
144 format.html { render :action => 'new' }
145 format.html { render :action => 'new' }
145 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
146 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
146 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
147 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
147 end
148 end
148 end
149 end
149 end
150 end
150
151
151 # Attributes that can be updated on workflow transition (without :edit permission)
152 # Attributes that can be updated on workflow transition (without :edit permission)
152 # TODO: make it configurable (at least per role)
153 # TODO: make it configurable (at least per role)
153 UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
154 UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
154
155
155 def edit
156 def edit
156 update_issue_from_params
157 update_issue_from_params
157
158
158 @journal = @issue.current_journal
159 @journal = @issue.current_journal
159
160
160 respond_to do |format|
161 respond_to do |format|
161 format.html { }
162 format.html { }
162 format.xml { }
163 format.xml { }
163 end
164 end
164 end
165 end
165
166
166 def update
167 def update
167 update_issue_from_params
168 update_issue_from_params
168
169
169 if @issue.save_issue_with_child_records(params, @time_entry)
170 if @issue.save_issue_with_child_records(params, @time_entry)
170 render_attachment_warning_if_needed(@issue)
171 render_attachment_warning_if_needed(@issue)
171 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
172 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
172
173
173 respond_to do |format|
174 respond_to do |format|
174 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
175 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
175 format.xml { head :ok }
176 format.xml { head :ok }
176 format.json { head :ok }
177 format.json { head :ok }
177 end
178 end
178 else
179 else
179 render_attachment_warning_if_needed(@issue)
180 render_attachment_warning_if_needed(@issue)
180 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
181 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
181 @journal = @issue.current_journal
182 @journal = @issue.current_journal
182
183
183 respond_to do |format|
184 respond_to do |format|
184 format.html { render :action => 'edit' }
185 format.html { render :action => 'edit' }
185 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
186 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
186 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
187 format.json { render :text => object_errors_to_json(@issue), :status => :unprocessable_entity, :layout => false }
187 end
188 end
188 end
189 end
189 end
190 end
190
191
191 # Bulk edit a set of issues
192 # Bulk edit a set of issues
192 def bulk_edit
193 def bulk_edit
193 @issues.sort!
194 @issues.sort!
194 if request.post?
195 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
196 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
197 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
198
199 unsaved_issue_ids = []
200 @issues.each do |issue|
201 issue.reload
202 journal = issue.init_journal(User.current, params[:notes])
203 issue.safe_attributes = attributes
204 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
205 unless issue.save
206 # Keep unsaved issue ids to display them in flash error
207 unsaved_issue_ids << issue.id
208 end
209 end
210 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
211 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
212 return
213 end
214 @available_statuses = Workflow.available_statuses(@project)
195 @available_statuses = Workflow.available_statuses(@project)
215 @custom_fields = @project.all_issue_custom_fields
196 @custom_fields = @project.all_issue_custom_fields
216 end
197 end
198
199 def bulk_update
200 @issues.sort!
201
202 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
203 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
204 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
205
206 unsaved_issue_ids = []
207 @issues.each do |issue|
208 issue.reload
209 journal = issue.init_journal(User.current, params[:notes])
210 issue.safe_attributes = attributes
211 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
212 unless issue.save
213 # Keep unsaved issue ids to display them in flash error
214 unsaved_issue_ids << issue.id
215 end
216 end
217 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
218 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
219 end
217
220
218 def destroy
221 def destroy
219 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
222 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
220 if @hours > 0
223 if @hours > 0
221 case params[:todo]
224 case params[:todo]
222 when 'destroy'
225 when 'destroy'
223 # nothing to do
226 # nothing to do
224 when 'nullify'
227 when 'nullify'
225 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
228 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
226 when 'reassign'
229 when 'reassign'
227 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
230 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
228 if reassign_to.nil?
231 if reassign_to.nil?
229 flash.now[:error] = l(:error_issue_not_found_in_project)
232 flash.now[:error] = l(:error_issue_not_found_in_project)
230 return
233 return
231 else
234 else
232 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
235 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
233 end
236 end
234 else
237 else
235 unless params[:format] == 'xml' || params[:format] == 'json'
238 unless params[:format] == 'xml' || params[:format] == 'json'
236 # display the destroy form if it's a user request
239 # display the destroy form if it's a user request
237 return
240 return
238 end
241 end
239 end
242 end
240 end
243 end
241 @issues.each(&:destroy)
244 @issues.each(&:destroy)
242 respond_to do |format|
245 respond_to do |format|
243 format.html { redirect_to :action => 'index', :project_id => @project }
246 format.html { redirect_to :action => 'index', :project_id => @project }
244 format.xml { head :ok }
247 format.xml { head :ok }
245 format.json { head :ok }
248 format.json { head :ok }
246 end
249 end
247 end
250 end
248
251
249 private
252 private
250 def find_issue
253 def find_issue
251 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
254 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
252 @project = @issue.project
255 @project = @issue.project
253 rescue ActiveRecord::RecordNotFound
256 rescue ActiveRecord::RecordNotFound
254 render_404
257 render_404
255 end
258 end
256
259
257 def find_project
260 def find_project
258 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
261 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
259 @project = Project.find(project_id)
262 @project = Project.find(project_id)
260 rescue ActiveRecord::RecordNotFound
263 rescue ActiveRecord::RecordNotFound
261 render_404
264 render_404
262 end
265 end
263
266
264 # Used by #edit and #update to set some common instance variables
267 # Used by #edit and #update to set some common instance variables
265 # from the params
268 # from the params
266 # TODO: Refactor, not everything in here is needed by #edit
269 # TODO: Refactor, not everything in here is needed by #edit
267 def update_issue_from_params
270 def update_issue_from_params
268 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
271 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
269 @priorities = IssuePriority.all
272 @priorities = IssuePriority.all
270 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
273 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
271 @time_entry = TimeEntry.new
274 @time_entry = TimeEntry.new
272
275
273 @notes = params[:notes]
276 @notes = params[:notes]
274 @issue.init_journal(User.current, @notes)
277 @issue.init_journal(User.current, @notes)
275 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
278 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
276 if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue]
279 if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue]
277 attrs = params[:issue].dup
280 attrs = params[:issue].dup
278 attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed
281 attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed
279 attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s}
282 attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s}
280 @issue.safe_attributes = attrs
283 @issue.safe_attributes = attrs
281 end
284 end
282
285
283 end
286 end
284
287
285 # TODO: Refactor, lots of extra code in here
288 # TODO: Refactor, lots of extra code in here
286 def build_new_issue_from_params
289 def build_new_issue_from_params
287 if params[:id].blank?
290 if params[:id].blank?
288 @issue = Issue.new
291 @issue = Issue.new
289 @issue.copy_from(params[:copy_from]) if params[:copy_from]
292 @issue.copy_from(params[:copy_from]) if params[:copy_from]
290 @issue.project = @project
293 @issue.project = @project
291 else
294 else
292 @issue = @project.issues.visible.find(params[:id])
295 @issue = @project.issues.visible.find(params[:id])
293 end
296 end
294
297
295 @issue.project = @project
298 @issue.project = @project
296 # Tracker must be set before custom field values
299 # Tracker must be set before custom field values
297 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
300 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
298 if @issue.tracker.nil?
301 if @issue.tracker.nil?
299 render_error l(:error_no_tracker_in_project)
302 render_error l(:error_no_tracker_in_project)
300 return false
303 return false
301 end
304 end
302 if params[:issue].is_a?(Hash)
305 if params[:issue].is_a?(Hash)
303 @issue.safe_attributes = params[:issue]
306 @issue.safe_attributes = params[:issue]
304 @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
307 @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
305 end
308 end
306 @issue.author = User.current
309 @issue.author = User.current
307 @issue.start_date ||= Date.today
310 @issue.start_date ||= Date.today
308 @priorities = IssuePriority.all
311 @priorities = IssuePriority.all
309 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
312 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
310 end
313 end
311
314
312 def check_for_default_issue_status
315 def check_for_default_issue_status
313 if IssueStatus.default.nil?
316 if IssueStatus.default.nil?
314 render_error l(:error_no_default_issue_status)
317 render_error l(:error_no_default_issue_status)
315 return false
318 return false
316 end
319 end
317 end
320 end
318 end
321 end
@@ -1,78 +1,78
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() 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(@project.trackers, :id, :name)) %>
14 <%= select_tag('issue[tracker_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.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.all, :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(@project.assignable_users, :id, :name)) %>
30 options_from_collection_for_select(@project.assignable_users, :id, :name)) %>
31 </p>
31 </p>
32 <p>
32 <p>
33 <label><%= l(:field_category) %></label>
33 <label><%= l(:field_category) %></label>
34 <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') +
34 <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') +
35 content_tag('option', l(:label_none), :value => 'none') +
35 content_tag('option', l(:label_none), :value => 'none') +
36 options_from_collection_for_select(@project.issue_categories, :id, :name)) %>
36 options_from_collection_for_select(@project.issue_categories, :id, :name)) %>
37 </p>
37 </p>
38 <p>
38 <p>
39 <label><%= l(:field_fixed_version) %></label>
39 <label><%= l(:field_fixed_version) %></label>
40 <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
40 <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
41 content_tag('option', l(:label_none), :value => 'none') +
41 content_tag('option', l(:label_none), :value => 'none') +
42 version_options_for_select(@project.shared_versions.open)) %>
42 version_options_for_select(@project.shared_versions.open)) %>
43 </p>
43 </p>
44
44
45 <% @custom_fields.each do |custom_field| %>
45 <% @custom_fields.each do |custom_field| %>
46 <p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('issue', custom_field) %></p>
46 <p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('issue', custom_field) %></p>
47 <% end %>
47 <% end %>
48
48
49 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
49 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
50 </div>
50 </div>
51
51
52 <div class="splitcontentright">
52 <div class="splitcontentright">
53 <p>
53 <p>
54 <label><%= l(:field_start_date) %></label>
54 <label><%= l(:field_start_date) %></label>
55 <%= text_field_tag 'issue[start_date]', '', :size => 10 %><%= calendar_for('issue_start_date') %>
55 <%= text_field_tag 'issue[start_date]', '', :size => 10 %><%= calendar_for('issue_start_date') %>
56 </p>
56 </p>
57 <p>
57 <p>
58 <label><%= l(:field_due_date) %></label>
58 <label><%= l(:field_due_date) %></label>
59 <%= text_field_tag 'issue[due_date]', '', :size => 10 %><%= calendar_for('issue_due_date') %>
59 <%= text_field_tag 'issue[due_date]', '', :size => 10 %><%= calendar_for('issue_due_date') %>
60 </p>
60 </p>
61 <% if Issue.use_field_for_done_ratio? %>
61 <% if Issue.use_field_for_done_ratio? %>
62 <p>
62 <p>
63 <label><%= l(:field_done_ratio) %></label>
63 <label><%= l(:field_done_ratio) %></label>
64 <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
64 <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
65 </p>
65 </p>
66 <% end %>
66 <% end %>
67 </div>
67 </div>
68
68
69 </fieldset>
69 </fieldset>
70
70
71 <fieldset><legend><%= l(:field_notes) %></legend>
71 <fieldset><legend><%= l(:field_notes) %></legend>
72 <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
72 <%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
73 <%= wikitoolbar_for 'notes' %>
73 <%= wikitoolbar_for 'notes' %>
74 </fieldset>
74 </fieldset>
75 </div>
75 </div>
76
76
77 <p><%= submit_tag l(:button_submit) %></p>
77 <p><%= submit_tag l(:button_submit) %></p>
78 <% end %>
78 <% end %>
@@ -1,299 +1,300
1 ActionController::Routing::Routes.draw do |map|
1 ActionController::Routing::Routes.draw do |map|
2 # Add your own custom routes here.
2 # Add your own custom routes here.
3 # The priority is based upon order of creation: first created -> highest priority.
3 # The priority is based upon order of creation: first created -> highest priority.
4
4
5 # Here's a sample route:
5 # Here's a sample route:
6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
7 # Keep in mind you can assign values other than :controller and :action
7 # Keep in mind you can assign values other than :controller and :action
8
8
9 map.home '', :controller => 'welcome'
9 map.home '', :controller => 'welcome'
10
10
11 map.signin 'login', :controller => 'account', :action => 'login'
11 map.signin 'login', :controller => 'account', :action => 'login'
12 map.signout 'logout', :controller => 'account', :action => 'logout'
12 map.signout 'logout', :controller => 'account', :action => 'logout'
13
13
14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
15 map.connect 'help/:ctrl/:page', :controller => 'help'
15 map.connect 'help/:ctrl/:page', :controller => 'help'
16
16
17 map.connect 'time_entries/:id/edit', :action => 'edit', :controller => 'timelog'
17 map.connect 'time_entries/:id/edit', :action => 'edit', :controller => 'timelog'
18 map.connect 'projects/:project_id/time_entries/new', :action => 'edit', :controller => 'timelog'
18 map.connect 'projects/:project_id/time_entries/new', :action => 'edit', :controller => 'timelog'
19 map.connect 'projects/:project_id/issues/:issue_id/time_entries/new', :action => 'edit', :controller => 'timelog'
19 map.connect 'projects/:project_id/issues/:issue_id/time_entries/new', :action => 'edit', :controller => 'timelog'
20
20
21 map.with_options :controller => 'timelog' do |timelog|
21 map.with_options :controller => 'timelog' do |timelog|
22 timelog.connect 'projects/:project_id/time_entries', :action => 'details'
22 timelog.connect 'projects/:project_id/time_entries', :action => 'details'
23
23
24 timelog.with_options :action => 'details', :conditions => {:method => :get} do |time_details|
24 timelog.with_options :action => 'details', :conditions => {:method => :get} do |time_details|
25 time_details.connect 'time_entries'
25 time_details.connect 'time_entries'
26 time_details.connect 'time_entries.:format'
26 time_details.connect 'time_entries.:format'
27 time_details.connect 'issues/:issue_id/time_entries'
27 time_details.connect 'issues/:issue_id/time_entries'
28 time_details.connect 'issues/:issue_id/time_entries.:format'
28 time_details.connect 'issues/:issue_id/time_entries.:format'
29 time_details.connect 'projects/:project_id/time_entries.:format'
29 time_details.connect 'projects/:project_id/time_entries.:format'
30 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries'
30 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries'
31 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries.:format'
31 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries.:format'
32 end
32 end
33 timelog.connect 'projects/:project_id/time_entries/report', :action => 'report'
33 timelog.connect 'projects/:project_id/time_entries/report', :action => 'report'
34 timelog.with_options :action => 'report',:conditions => {:method => :get} do |time_report|
34 timelog.with_options :action => 'report',:conditions => {:method => :get} do |time_report|
35 time_report.connect 'time_entries/report'
35 time_report.connect 'time_entries/report'
36 time_report.connect 'time_entries/report.:format'
36 time_report.connect 'time_entries/report.:format'
37 time_report.connect 'projects/:project_id/time_entries/report.:format'
37 time_report.connect 'projects/:project_id/time_entries/report.:format'
38 end
38 end
39
39
40 timelog.with_options :action => 'edit', :conditions => {:method => :get} do |time_edit|
40 timelog.with_options :action => 'edit', :conditions => {:method => :get} do |time_edit|
41 time_edit.connect 'issues/:issue_id/time_entries/new'
41 time_edit.connect 'issues/:issue_id/time_entries/new'
42 end
42 end
43
43
44 timelog.connect 'time_entries/:id/destroy', :action => 'destroy', :conditions => {:method => :post}
44 timelog.connect 'time_entries/:id/destroy', :action => 'destroy', :conditions => {:method => :post}
45 end
45 end
46
46
47 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
47 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
48 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
48 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
49 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
49 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
50 map.with_options :controller => 'wiki' do |wiki_routes|
50 map.with_options :controller => 'wiki' do |wiki_routes|
51 wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
51 wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
52 wiki_views.connect 'projects/:id/wiki/:page', :action => 'special', :page => /page_index|date_index|export/i
52 wiki_views.connect 'projects/:id/wiki/:page', :action => 'special', :page => /page_index|date_index|export/i
53 wiki_views.connect 'projects/:id/wiki/:page', :action => 'index', :page => nil
53 wiki_views.connect 'projects/:id/wiki/:page', :action => 'index', :page => nil
54 wiki_views.connect 'projects/:id/wiki/:page/edit', :action => 'edit'
54 wiki_views.connect 'projects/:id/wiki/:page/edit', :action => 'edit'
55 wiki_views.connect 'projects/:id/wiki/:page/rename', :action => 'rename'
55 wiki_views.connect 'projects/:id/wiki/:page/rename', :action => 'rename'
56 wiki_views.connect 'projects/:id/wiki/:page/history', :action => 'history'
56 wiki_views.connect 'projects/:id/wiki/:page/history', :action => 'history'
57 wiki_views.connect 'projects/:id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
57 wiki_views.connect 'projects/:id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
58 wiki_views.connect 'projects/:id/wiki/:page/annotate/:version', :action => 'annotate'
58 wiki_views.connect 'projects/:id/wiki/:page/annotate/:version', :action => 'annotate'
59 end
59 end
60
60
61 wiki_routes.connect 'projects/:id/wiki/:page/:action',
61 wiki_routes.connect 'projects/:id/wiki/:page/:action',
62 :action => /edit|rename|destroy|preview|protect/,
62 :action => /edit|rename|destroy|preview|protect/,
63 :conditions => {:method => :post}
63 :conditions => {:method => :post}
64 end
64 end
65
65
66 map.with_options :controller => 'messages' do |messages_routes|
66 map.with_options :controller => 'messages' do |messages_routes|
67 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
67 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
68 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
68 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
69 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
69 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
70 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
70 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
71 end
71 end
72 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
72 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
73 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
73 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
74 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
74 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
75 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
75 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
76 end
76 end
77 end
77 end
78
78
79 map.with_options :controller => 'boards' do |board_routes|
79 map.with_options :controller => 'boards' do |board_routes|
80 board_routes.with_options :conditions => {:method => :get} do |board_views|
80 board_routes.with_options :conditions => {:method => :get} do |board_views|
81 board_views.connect 'projects/:project_id/boards', :action => 'index'
81 board_views.connect 'projects/:project_id/boards', :action => 'index'
82 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
82 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
83 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
83 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
84 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
84 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
85 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
85 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
86 end
86 end
87 board_routes.with_options :conditions => {:method => :post} do |board_actions|
87 board_routes.with_options :conditions => {:method => :post} do |board_actions|
88 board_actions.connect 'projects/:project_id/boards', :action => 'new'
88 board_actions.connect 'projects/:project_id/boards', :action => 'new'
89 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
89 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
90 end
90 end
91 end
91 end
92
92
93 map.with_options :controller => 'documents' do |document_routes|
93 map.with_options :controller => 'documents' do |document_routes|
94 document_routes.with_options :conditions => {:method => :get} do |document_views|
94 document_routes.with_options :conditions => {:method => :get} do |document_views|
95 document_views.connect 'projects/:project_id/documents', :action => 'index'
95 document_views.connect 'projects/:project_id/documents', :action => 'index'
96 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
96 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
97 document_views.connect 'documents/:id', :action => 'show'
97 document_views.connect 'documents/:id', :action => 'show'
98 document_views.connect 'documents/:id/edit', :action => 'edit'
98 document_views.connect 'documents/:id/edit', :action => 'edit'
99 end
99 end
100 document_routes.with_options :conditions => {:method => :post} do |document_actions|
100 document_routes.with_options :conditions => {:method => :post} do |document_actions|
101 document_actions.connect 'projects/:project_id/documents', :action => 'new'
101 document_actions.connect 'projects/:project_id/documents', :action => 'new'
102 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
102 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
103 end
103 end
104 end
104 end
105
105
106 map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move'
106 map.resources :issue_moves, :only => [:new, :create], :path_prefix => '/issues', :as => 'move'
107 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues'
107 map.auto_complete_issues '/issues/auto_complete', :controller => 'auto_completes', :action => 'issues'
108 # TODO: would look nicer as /issues/:id/preview
108 # TODO: would look nicer as /issues/:id/preview
109 map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue'
109 map.preview_issue '/issues/preview/:id', :controller => 'previews', :action => 'issue'
110 map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues'
110 map.issues_context_menu '/issues/context_menu', :controller => 'context_menus', :action => 'issues'
111 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
111 map.issue_changes '/issues/changes', :controller => 'journals', :action => 'index'
112
112
113 map.with_options :controller => 'issues' do |issues_routes|
113 map.with_options :controller => 'issues' do |issues_routes|
114 issues_routes.with_options :conditions => {:method => :get} do |issues_views|
114 issues_routes.with_options :conditions => {:method => :get} do |issues_views|
115 issues_views.connect 'issues', :action => 'index'
115 issues_views.connect 'issues', :action => 'index'
116 issues_views.connect 'issues.:format', :action => 'index'
116 issues_views.connect 'issues.:format', :action => 'index'
117 issues_views.connect 'projects/:project_id/issues', :action => 'index'
117 issues_views.connect 'projects/:project_id/issues', :action => 'index'
118 issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
118 issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
119 issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
119 issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
120 issues_views.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
120 issues_views.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
121 issues_views.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
121 issues_views.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
122 issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
122 issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
123 issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
123 issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
124 issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
124 issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
125 issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/
125 issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/
126 end
126 end
127 issues_routes.with_options :conditions => {:method => :post} do |issues_actions|
127 issues_routes.with_options :conditions => {:method => :post} do |issues_actions|
128 issues_actions.connect 'issues', :action => 'index'
128 issues_actions.connect 'issues', :action => 'index'
129 issues_actions.connect 'projects/:project_id/issues', :action => 'create'
129 issues_actions.connect 'projects/:project_id/issues', :action => 'create'
130 issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
130 issues_actions.connect 'projects/:project_id/issues/gantt', :controller => 'gantts', :action => 'show'
131 issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
131 issues_actions.connect 'projects/:project_id/issues/calendar', :controller => 'calendars', :action => 'show'
132 issues_actions.connect 'issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/
132 issues_actions.connect 'issues/:id/quoted', :controller => 'journals', :action => 'new', :id => /\d+/
133 issues_actions.connect 'issues/:id/:action', :action => /edit|destroy/, :id => /\d+/
133 issues_actions.connect 'issues/:id/:action', :action => /edit|destroy/, :id => /\d+/
134 issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/
134 issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/
135 issues_actions.connect 'issues/bulk_edit', :action => 'bulk_update'
135 end
136 end
136 issues_routes.with_options :conditions => {:method => :put} do |issues_actions|
137 issues_routes.with_options :conditions => {:method => :put} do |issues_actions|
137 issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/
138 issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/
138 issues_actions.connect 'issues/:id.:format', :action => 'update', :id => /\d+/, :format => /xml/
139 issues_actions.connect 'issues/:id.:format', :action => 'update', :id => /\d+/, :format => /xml/
139 end
140 end
140 issues_routes.with_options :conditions => {:method => :delete} do |issues_actions|
141 issues_routes.with_options :conditions => {:method => :delete} do |issues_actions|
141 issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
142 issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
142 end
143 end
143 issues_routes.connect 'issues/gantt', :controller => 'gantts', :action => 'show'
144 issues_routes.connect 'issues/gantt', :controller => 'gantts', :action => 'show'
144 issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show'
145 issues_routes.connect 'issues/calendar', :controller => 'calendars', :action => 'show'
145 issues_routes.connect 'issues/:action'
146 issues_routes.connect 'issues/:action'
146 end
147 end
147
148
148 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
149 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
149 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
150 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
150 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
151 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
151 end
152 end
152
153
153 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
154 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
154 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
155 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
155 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
156 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
156 end
157 end
157
158
158 map.with_options :controller => 'news' do |news_routes|
159 map.with_options :controller => 'news' do |news_routes|
159 news_routes.with_options :conditions => {:method => :get} do |news_views|
160 news_routes.with_options :conditions => {:method => :get} do |news_views|
160 news_views.connect 'news', :action => 'index'
161 news_views.connect 'news', :action => 'index'
161 news_views.connect 'projects/:project_id/news', :action => 'index'
162 news_views.connect 'projects/:project_id/news', :action => 'index'
162 news_views.connect 'projects/:project_id/news.:format', :action => 'index'
163 news_views.connect 'projects/:project_id/news.:format', :action => 'index'
163 news_views.connect 'news.:format', :action => 'index'
164 news_views.connect 'news.:format', :action => 'index'
164 news_views.connect 'projects/:project_id/news/new', :action => 'new'
165 news_views.connect 'projects/:project_id/news/new', :action => 'new'
165 news_views.connect 'news/:id', :action => 'show'
166 news_views.connect 'news/:id', :action => 'show'
166 news_views.connect 'news/:id/edit', :action => 'edit'
167 news_views.connect 'news/:id/edit', :action => 'edit'
167 end
168 end
168 news_routes.with_options do |news_actions|
169 news_routes.with_options do |news_actions|
169 news_actions.connect 'projects/:project_id/news', :action => 'new'
170 news_actions.connect 'projects/:project_id/news', :action => 'new'
170 news_actions.connect 'news/:id/edit', :action => 'edit'
171 news_actions.connect 'news/:id/edit', :action => 'edit'
171 news_actions.connect 'news/:id/destroy', :action => 'destroy'
172 news_actions.connect 'news/:id/destroy', :action => 'destroy'
172 end
173 end
173 end
174 end
174
175
175 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
176 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
176
177
177 map.with_options :controller => 'users' do |users|
178 map.with_options :controller => 'users' do |users|
178 users.with_options :conditions => {:method => :get} do |user_views|
179 users.with_options :conditions => {:method => :get} do |user_views|
179 user_views.connect 'users', :action => 'index'
180 user_views.connect 'users', :action => 'index'
180 user_views.connect 'users/:id', :action => 'show', :id => /\d+/
181 user_views.connect 'users/:id', :action => 'show', :id => /\d+/
181 user_views.connect 'users/new', :action => 'add'
182 user_views.connect 'users/new', :action => 'add'
182 user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil
183 user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil
183 end
184 end
184 users.with_options :conditions => {:method => :post} do |user_actions|
185 users.with_options :conditions => {:method => :post} do |user_actions|
185 user_actions.connect 'users', :action => 'add'
186 user_actions.connect 'users', :action => 'add'
186 user_actions.connect 'users/new', :action => 'add'
187 user_actions.connect 'users/new', :action => 'add'
187 user_actions.connect 'users/:id/edit', :action => 'edit'
188 user_actions.connect 'users/:id/edit', :action => 'edit'
188 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
189 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
189 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
190 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
190 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
191 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
191 end
192 end
192 end
193 end
193
194
194 map.with_options :controller => 'projects' do |projects|
195 map.with_options :controller => 'projects' do |projects|
195 projects.with_options :conditions => {:method => :get} do |project_views|
196 projects.with_options :conditions => {:method => :get} do |project_views|
196 project_views.connect 'projects', :action => 'index'
197 project_views.connect 'projects', :action => 'index'
197 project_views.connect 'projects.:format', :action => 'index'
198 project_views.connect 'projects.:format', :action => 'index'
198 project_views.connect 'projects/new', :action => 'add'
199 project_views.connect 'projects/new', :action => 'add'
199 project_views.connect 'projects/:id', :action => 'show'
200 project_views.connect 'projects/:id', :action => 'show'
200 project_views.connect 'projects/:id.:format', :action => 'show'
201 project_views.connect 'projects/:id.:format', :action => 'show'
201 project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
202 project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
202 project_views.connect 'projects/:id/files', :action => 'list_files'
203 project_views.connect 'projects/:id/files', :action => 'list_files'
203 project_views.connect 'projects/:id/files/new', :action => 'add_file'
204 project_views.connect 'projects/:id/files/new', :action => 'add_file'
204 project_views.connect 'projects/:id/settings/:tab', :action => 'settings'
205 project_views.connect 'projects/:id/settings/:tab', :action => 'settings'
205 end
206 end
206
207
207 projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity|
208 projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity|
208 activity.connect 'projects/:id/activity'
209 activity.connect 'projects/:id/activity'
209 activity.connect 'projects/:id/activity.:format'
210 activity.connect 'projects/:id/activity.:format'
210 activity.connect 'activity', :id => nil
211 activity.connect 'activity', :id => nil
211 activity.connect 'activity.:format', :id => nil
212 activity.connect 'activity.:format', :id => nil
212 end
213 end
213
214
214 projects.with_options :conditions => {:method => :post} do |project_actions|
215 projects.with_options :conditions => {:method => :post} do |project_actions|
215 project_actions.connect 'projects/new', :action => 'add'
216 project_actions.connect 'projects/new', :action => 'add'
216 project_actions.connect 'projects', :action => 'add'
217 project_actions.connect 'projects', :action => 'add'
217 project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
218 project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
218 project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/
219 project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/
219 project_actions.connect 'projects/:id/files/new', :action => 'add_file'
220 project_actions.connect 'projects/:id/files/new', :action => 'add_file'
220 project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
221 project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
221 end
222 end
222
223
223 projects.with_options :conditions => {:method => :put} do |project_actions|
224 projects.with_options :conditions => {:method => :put} do |project_actions|
224 project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
225 project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
225 end
226 end
226
227
227 projects.with_options :conditions => {:method => :delete} do |project_actions|
228 projects.with_options :conditions => {:method => :delete} do |project_actions|
228 project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
229 project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
229 project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
230 project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
230 end
231 end
231 end
232 end
232
233
233 map.with_options :controller => 'versions' do |versions|
234 map.with_options :controller => 'versions' do |versions|
234 versions.connect 'projects/:project_id/versions/new', :action => 'new'
235 versions.connect 'projects/:project_id/versions/new', :action => 'new'
235 versions.with_options :conditions => {:method => :post} do |version_actions|
236 versions.with_options :conditions => {:method => :post} do |version_actions|
236 version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed'
237 version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed'
237 end
238 end
238 end
239 end
239
240
240 map.with_options :controller => 'issue_categories' do |categories|
241 map.with_options :controller => 'issue_categories' do |categories|
241 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
242 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
242 end
243 end
243
244
244 map.with_options :controller => 'repositories' do |repositories|
245 map.with_options :controller => 'repositories' do |repositories|
245 repositories.with_options :conditions => {:method => :get} do |repository_views|
246 repositories.with_options :conditions => {:method => :get} do |repository_views|
246 repository_views.connect 'projects/:id/repository', :action => 'show'
247 repository_views.connect 'projects/:id/repository', :action => 'show'
247 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
248 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
248 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
249 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
249 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
250 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
250 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
251 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
251 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
252 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
252 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
253 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
253 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
254 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
254 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
255 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
255 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
256 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
256 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
257 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
257 # TODO: why the following route is required?
258 # TODO: why the following route is required?
258 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
259 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
259 repository_views.connect 'projects/:id/repository/:action/*path'
260 repository_views.connect 'projects/:id/repository/:action/*path'
260 end
261 end
261
262
262 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
263 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
263 end
264 end
264
265
265 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
266 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
266 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
267 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
267 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
268 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
268
269
269 map.resources :groups
270 map.resources :groups
270
271
271 #left old routes at the bottom for backwards compat
272 #left old routes at the bottom for backwards compat
272 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
273 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
273 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
274 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
274 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
275 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
275 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
276 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
276 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
277 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
277 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
278 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
278 map.connect 'projects/:project_id/news/:action', :controller => 'news'
279 map.connect 'projects/:project_id/news/:action', :controller => 'news'
279 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
280 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
280 map.with_options :controller => 'repositories' do |omap|
281 map.with_options :controller => 'repositories' do |omap|
281 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
282 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
282 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
283 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
283 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
284 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
284 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
285 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
285 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
286 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
286 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
287 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
287 end
288 end
288
289
289 map.with_options :controller => 'sys' do |sys|
290 map.with_options :controller => 'sys' do |sys|
290 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
291 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
291 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
292 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
292 end
293 end
293
294
294 # Install the default route as the lowest priority.
295 # Install the default route as the lowest priority.
295 map.connect ':controller/:action/:id'
296 map.connect ':controller/:action/:id'
296 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
297 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
297 # Used for OpenID
298 # Used for OpenID
298 map.root :controller => 'account', :action => 'login'
299 map.root :controller => 'account', :action => 'login'
299 end
300 end
@@ -1,231 +1,231
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/activity'
3 require 'redmine/activity'
4 require 'redmine/search'
4 require 'redmine/search'
5 require 'redmine/custom_field_format'
5 require 'redmine/custom_field_format'
6 require 'redmine/mime_type'
6 require 'redmine/mime_type'
7 require 'redmine/core_ext'
7 require 'redmine/core_ext'
8 require 'redmine/themes'
8 require 'redmine/themes'
9 require 'redmine/hook'
9 require 'redmine/hook'
10 require 'redmine/plugin'
10 require 'redmine/plugin'
11 require 'redmine/wiki_formatting'
11 require 'redmine/wiki_formatting'
12 require 'redmine/scm/base'
12 require 'redmine/scm/base'
13
13
14 begin
14 begin
15 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
15 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
16 rescue LoadError
16 rescue LoadError
17 # RMagick is not available
17 # RMagick is not available
18 end
18 end
19
19
20 if RUBY_VERSION < '1.9'
20 if RUBY_VERSION < '1.9'
21 require 'faster_csv'
21 require 'faster_csv'
22 else
22 else
23 require 'csv'
23 require 'csv'
24 FCSV = CSV
24 FCSV = CSV
25 end
25 end
26
26
27 Redmine::Scm::Base.add "Subversion"
27 Redmine::Scm::Base.add "Subversion"
28 Redmine::Scm::Base.add "Darcs"
28 Redmine::Scm::Base.add "Darcs"
29 Redmine::Scm::Base.add "Mercurial"
29 Redmine::Scm::Base.add "Mercurial"
30 Redmine::Scm::Base.add "Cvs"
30 Redmine::Scm::Base.add "Cvs"
31 Redmine::Scm::Base.add "Bazaar"
31 Redmine::Scm::Base.add "Bazaar"
32 Redmine::Scm::Base.add "Git"
32 Redmine::Scm::Base.add "Git"
33 Redmine::Scm::Base.add "Filesystem"
33 Redmine::Scm::Base.add "Filesystem"
34
34
35 Redmine::CustomFieldFormat.map do |fields|
35 Redmine::CustomFieldFormat.map do |fields|
36 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
36 fields.register Redmine::CustomFieldFormat.new('string', :label => :label_string, :order => 1)
37 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
37 fields.register Redmine::CustomFieldFormat.new('text', :label => :label_text, :order => 2)
38 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
38 fields.register Redmine::CustomFieldFormat.new('int', :label => :label_integer, :order => 3)
39 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
39 fields.register Redmine::CustomFieldFormat.new('float', :label => :label_float, :order => 4)
40 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
40 fields.register Redmine::CustomFieldFormat.new('list', :label => :label_list, :order => 5)
41 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
41 fields.register Redmine::CustomFieldFormat.new('date', :label => :label_date, :order => 6)
42 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
42 fields.register Redmine::CustomFieldFormat.new('bool', :label => :label_boolean, :order => 7)
43 end
43 end
44
44
45 # Permissions
45 # Permissions
46 Redmine::AccessControl.map do |map|
46 Redmine::AccessControl.map do |map|
47 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
47 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
48 map.permission :search_project, {:search => :index}, :public => true
48 map.permission :search_project, {:search => :index}, :public => true
49 map.permission :add_project, {:projects => :add}, :require => :loggedin
49 map.permission :add_project, {:projects => :add}, :require => :loggedin
50 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
50 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
51 map.permission :select_project_modules, {:projects => :modules}, :require => :member
51 map.permission :select_project_modules, {:projects => :modules}, :require => :member
52 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
52 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy, :autocomplete_for_member]}, :require => :member
53 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :edit, :close_completed, :destroy]}, :require => :member
53 map.permission :manage_versions, {:projects => :settings, :versions => [:new, :edit, :close_completed, :destroy]}, :require => :member
54 map.permission :add_subprojects, {:projects => :add}, :require => :member
54 map.permission :add_subprojects, {:projects => :add}, :require => :member
55
55
56 map.project_module :issue_tracking do |map|
56 map.project_module :issue_tracking do |map|
57 # Issue categories
57 # Issue categories
58 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member
58 map.permission :manage_categories, {:projects => :settings, :issue_categories => [:new, :edit, :destroy]}, :require => :member
59 # Issues
59 # Issues
60 map.permission :view_issues, {:projects => :roadmap,
60 map.permission :view_issues, {:projects => :roadmap,
61 :issues => [:index, :show],
61 :issues => [:index, :show],
62 :auto_complete => [:issues],
62 :auto_complete => [:issues],
63 :context_menus => [:issues],
63 :context_menus => [:issues],
64 :versions => [:show, :status_by],
64 :versions => [:show, :status_by],
65 :journals => :index,
65 :journals => :index,
66 :queries => :index,
66 :queries => :index,
67 :reports => [:issue_report, :issue_report_details]}
67 :reports => [:issue_report, :issue_report_details]}
68 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
68 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
69 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :update_form], :journals => [:new]}
69 map.permission :edit_issues, {:issues => [:edit, :update, :bulk_edit, :bulk_update, :update_form], :journals => [:new]}
70 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
70 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
71 map.permission :manage_subtasks, {}
71 map.permission :manage_subtasks, {}
72 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
72 map.permission :add_issue_notes, {:issues => [:edit, :update], :journals => [:new]}
73 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
73 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
74 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
74 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
75 map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
75 map.permission :move_issues, {:issue_moves => [:new, :create]}, :require => :loggedin
76 map.permission :delete_issues, {:issues => :destroy}, :require => :member
76 map.permission :delete_issues, {:issues => :destroy}, :require => :member
77 # Queries
77 # Queries
78 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
78 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
79 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
79 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
80 # Watchers
80 # Watchers
81 map.permission :view_issue_watchers, {}
81 map.permission :view_issue_watchers, {}
82 map.permission :add_issue_watchers, {:watchers => :new}
82 map.permission :add_issue_watchers, {:watchers => :new}
83 map.permission :delete_issue_watchers, {:watchers => :destroy}
83 map.permission :delete_issue_watchers, {:watchers => :destroy}
84 end
84 end
85
85
86 map.project_module :time_tracking do |map|
86 map.project_module :time_tracking do |map|
87 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
87 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
88 map.permission :view_time_entries, :timelog => [:details, :report]
88 map.permission :view_time_entries, :timelog => [:details, :report]
89 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
89 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
90 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
90 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
91 map.permission :manage_project_activities, {:projects => [:save_activities, :reset_activities]}, :require => :member
91 map.permission :manage_project_activities, {:projects => [:save_activities, :reset_activities]}, :require => :member
92 end
92 end
93
93
94 map.project_module :news do |map|
94 map.project_module :news do |map|
95 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
95 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
96 map.permission :view_news, {:news => [:index, :show]}, :public => true
96 map.permission :view_news, {:news => [:index, :show]}, :public => true
97 map.permission :comment_news, {:news => :add_comment}
97 map.permission :comment_news, {:news => :add_comment}
98 end
98 end
99
99
100 map.project_module :documents do |map|
100 map.project_module :documents do |map|
101 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin
101 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment]}, :require => :loggedin
102 map.permission :view_documents, :documents => [:index, :show, :download]
102 map.permission :view_documents, :documents => [:index, :show, :download]
103 end
103 end
104
104
105 map.project_module :files do |map|
105 map.project_module :files do |map|
106 map.permission :manage_files, {:projects => :add_file}, :require => :loggedin
106 map.permission :manage_files, {:projects => :add_file}, :require => :loggedin
107 map.permission :view_files, :projects => :list_files, :versions => :download
107 map.permission :view_files, :projects => :list_files, :versions => :download
108 end
108 end
109
109
110 map.project_module :wiki do |map|
110 map.project_module :wiki do |map|
111 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
111 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
112 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
112 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
113 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
113 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
114 map.permission :view_wiki_pages, :wiki => [:index, :special]
114 map.permission :view_wiki_pages, :wiki => [:index, :special]
115 map.permission :export_wiki_pages, {}
115 map.permission :export_wiki_pages, {}
116 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
116 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
117 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
117 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
118 map.permission :delete_wiki_pages_attachments, {}
118 map.permission :delete_wiki_pages_attachments, {}
119 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
119 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
120 end
120 end
121
121
122 map.project_module :repository do |map|
122 map.project_module :repository do |map|
123 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
123 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
124 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
124 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
125 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
125 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
126 map.permission :commit_access, {}
126 map.permission :commit_access, {}
127 end
127 end
128
128
129 map.project_module :boards do |map|
129 map.project_module :boards do |map|
130 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
130 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
131 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
131 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
132 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
132 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
133 map.permission :edit_messages, {:messages => :edit}, :require => :member
133 map.permission :edit_messages, {:messages => :edit}, :require => :member
134 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
134 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
135 map.permission :delete_messages, {:messages => :destroy}, :require => :member
135 map.permission :delete_messages, {:messages => :destroy}, :require => :member
136 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
136 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
137 end
137 end
138
138
139 map.project_module :calendar do |map|
139 map.project_module :calendar do |map|
140 map.permission :view_calendar, :calendars => :show
140 map.permission :view_calendar, :calendars => :show
141 end
141 end
142
142
143 map.project_module :gantt do |map|
143 map.project_module :gantt do |map|
144 map.permission :view_gantt, :gantts => :show
144 map.permission :view_gantt, :gantts => :show
145 end
145 end
146 end
146 end
147
147
148 Redmine::MenuManager.map :top_menu do |menu|
148 Redmine::MenuManager.map :top_menu do |menu|
149 menu.push :home, :home_path
149 menu.push :home, :home_path
150 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
150 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
151 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
151 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
152 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
152 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
153 menu.push :help, Redmine::Info.help_url, :last => true
153 menu.push :help, Redmine::Info.help_url, :last => true
154 end
154 end
155
155
156 Redmine::MenuManager.map :account_menu do |menu|
156 Redmine::MenuManager.map :account_menu do |menu|
157 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
157 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
158 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
158 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
159 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
159 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
160 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
160 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
161 end
161 end
162
162
163 Redmine::MenuManager.map :application_menu do |menu|
163 Redmine::MenuManager.map :application_menu do |menu|
164 # Empty
164 # Empty
165 end
165 end
166
166
167 Redmine::MenuManager.map :admin_menu do |menu|
167 Redmine::MenuManager.map :admin_menu do |menu|
168 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
168 menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
169 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
169 menu.push :users, {:controller => 'users'}, :caption => :label_user_plural
170 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
170 menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
171 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
171 menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
172 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
172 menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
173 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
173 menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
174 :html => {:class => 'issue_statuses'}
174 :html => {:class => 'issue_statuses'}
175 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
175 menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
176 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
176 menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
177 :html => {:class => 'custom_fields'}
177 :html => {:class => 'custom_fields'}
178 menu.push :enumerations, {:controller => 'enumerations'}
178 menu.push :enumerations, {:controller => 'enumerations'}
179 menu.push :settings, {:controller => 'settings'}
179 menu.push :settings, {:controller => 'settings'}
180 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
180 menu.push :ldap_authentication, {:controller => 'ldap_auth_sources', :action => 'index'},
181 :html => {:class => 'server_authentication'}
181 :html => {:class => 'server_authentication'}
182 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
182 menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
183 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
183 menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
184 end
184 end
185
185
186 Redmine::MenuManager.map :project_menu do |menu|
186 Redmine::MenuManager.map :project_menu do |menu|
187 menu.push :overview, { :controller => 'projects', :action => 'show' }
187 menu.push :overview, { :controller => 'projects', :action => 'show' }
188 menu.push :activity, { :controller => 'projects', :action => 'activity' }
188 menu.push :activity, { :controller => 'projects', :action => 'activity' }
189 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
189 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
190 :if => Proc.new { |p| p.shared_versions.any? }
190 :if => Proc.new { |p| p.shared_versions.any? }
191 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
191 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
192 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
192 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
193 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
193 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
194 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
194 menu.push :gantt, { :controller => 'gantts', :action => 'show' }, :param => :project_id, :caption => :label_gantt
195 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
195 menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
196 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
196 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
197 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
197 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
198 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
198 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
199 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
199 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
200 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
200 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
201 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
201 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
202 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_file_plural
202 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_file_plural
203 menu.push :repository, { :controller => 'repositories', :action => 'show' },
203 menu.push :repository, { :controller => 'repositories', :action => 'show' },
204 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
204 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
205 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
205 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
206 end
206 end
207
207
208 Redmine::Activity.map do |activity|
208 Redmine::Activity.map do |activity|
209 activity.register :issues, :class_name => %w(Issue Journal)
209 activity.register :issues, :class_name => %w(Issue Journal)
210 activity.register :changesets
210 activity.register :changesets
211 activity.register :news
211 activity.register :news
212 activity.register :documents, :class_name => %w(Document Attachment)
212 activity.register :documents, :class_name => %w(Document Attachment)
213 activity.register :files, :class_name => 'Attachment'
213 activity.register :files, :class_name => 'Attachment'
214 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
214 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
215 activity.register :messages, :default => false
215 activity.register :messages, :default => false
216 activity.register :time_entries, :default => false
216 activity.register :time_entries, :default => false
217 end
217 end
218
218
219 Redmine::Search.map do |search|
219 Redmine::Search.map do |search|
220 search.register :issues
220 search.register :issues
221 search.register :news
221 search.register :news
222 search.register :documents
222 search.register :documents
223 search.register :changesets
223 search.register :changesets
224 search.register :wiki_pages
224 search.register :wiki_pages
225 search.register :messages
225 search.register :messages
226 search.register :projects
226 search.register :projects
227 end
227 end
228
228
229 Redmine::WikiFormatting.map do |format|
229 Redmine::WikiFormatting.map do |format|
230 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
230 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
231 end
231 end
@@ -1,1069 +1,1069
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'issues_controller'
19 require 'issues_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class IssuesController; def rescue_action(e) raise e end; end
22 class IssuesController; def rescue_action(e) raise e end; end
23
23
24 class IssuesControllerTest < ActionController::TestCase
24 class IssuesControllerTest < ActionController::TestCase
25 fixtures :projects,
25 fixtures :projects,
26 :users,
26 :users,
27 :roles,
27 :roles,
28 :members,
28 :members,
29 :member_roles,
29 :member_roles,
30 :issues,
30 :issues,
31 :issue_statuses,
31 :issue_statuses,
32 :versions,
32 :versions,
33 :trackers,
33 :trackers,
34 :projects_trackers,
34 :projects_trackers,
35 :issue_categories,
35 :issue_categories,
36 :enabled_modules,
36 :enabled_modules,
37 :enumerations,
37 :enumerations,
38 :attachments,
38 :attachments,
39 :workflows,
39 :workflows,
40 :custom_fields,
40 :custom_fields,
41 :custom_values,
41 :custom_values,
42 :custom_fields_projects,
42 :custom_fields_projects,
43 :custom_fields_trackers,
43 :custom_fields_trackers,
44 :time_entries,
44 :time_entries,
45 :journals,
45 :journals,
46 :journal_details,
46 :journal_details,
47 :queries
47 :queries
48
48
49 def setup
49 def setup
50 @controller = IssuesController.new
50 @controller = IssuesController.new
51 @request = ActionController::TestRequest.new
51 @request = ActionController::TestRequest.new
52 @response = ActionController::TestResponse.new
52 @response = ActionController::TestResponse.new
53 User.current = nil
53 User.current = nil
54 end
54 end
55
55
56 def test_index
56 def test_index
57 Setting.default_language = 'en'
57 Setting.default_language = 'en'
58
58
59 get :index
59 get :index
60 assert_response :success
60 assert_response :success
61 assert_template 'index.rhtml'
61 assert_template 'index.rhtml'
62 assert_not_nil assigns(:issues)
62 assert_not_nil assigns(:issues)
63 assert_nil assigns(:project)
63 assert_nil assigns(:project)
64 assert_tag :tag => 'a', :content => /Can't print recipes/
64 assert_tag :tag => 'a', :content => /Can't print recipes/
65 assert_tag :tag => 'a', :content => /Subproject issue/
65 assert_tag :tag => 'a', :content => /Subproject issue/
66 # private projects hidden
66 # private projects hidden
67 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
67 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
68 assert_no_tag :tag => 'a', :content => /Issue on project 2/
68 assert_no_tag :tag => 'a', :content => /Issue on project 2/
69 # project column
69 # project column
70 assert_tag :tag => 'th', :content => /Project/
70 assert_tag :tag => 'th', :content => /Project/
71 end
71 end
72
72
73 def test_index_should_not_list_issues_when_module_disabled
73 def test_index_should_not_list_issues_when_module_disabled
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
74 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
75 get :index
75 get :index
76 assert_response :success
76 assert_response :success
77 assert_template 'index.rhtml'
77 assert_template 'index.rhtml'
78 assert_not_nil assigns(:issues)
78 assert_not_nil assigns(:issues)
79 assert_nil assigns(:project)
79 assert_nil assigns(:project)
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
80 assert_no_tag :tag => 'a', :content => /Can't print recipes/
81 assert_tag :tag => 'a', :content => /Subproject issue/
81 assert_tag :tag => 'a', :content => /Subproject issue/
82 end
82 end
83
83
84 def test_index_should_not_list_issues_when_module_disabled
84 def test_index_should_not_list_issues_when_module_disabled
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
85 EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
86 get :index
86 get :index
87 assert_response :success
87 assert_response :success
88 assert_template 'index.rhtml'
88 assert_template 'index.rhtml'
89 assert_not_nil assigns(:issues)
89 assert_not_nil assigns(:issues)
90 assert_nil assigns(:project)
90 assert_nil assigns(:project)
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
91 assert_no_tag :tag => 'a', :content => /Can't print recipes/
92 assert_tag :tag => 'a', :content => /Subproject issue/
92 assert_tag :tag => 'a', :content => /Subproject issue/
93 end
93 end
94
94
95 def test_index_with_project
95 def test_index_with_project
96 Setting.display_subprojects_issues = 0
96 Setting.display_subprojects_issues = 0
97 get :index, :project_id => 1
97 get :index, :project_id => 1
98 assert_response :success
98 assert_response :success
99 assert_template 'index.rhtml'
99 assert_template 'index.rhtml'
100 assert_not_nil assigns(:issues)
100 assert_not_nil assigns(:issues)
101 assert_tag :tag => 'a', :content => /Can't print recipes/
101 assert_tag :tag => 'a', :content => /Can't print recipes/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
102 assert_no_tag :tag => 'a', :content => /Subproject issue/
103 end
103 end
104
104
105 def test_index_with_project_and_subprojects
105 def test_index_with_project_and_subprojects
106 Setting.display_subprojects_issues = 1
106 Setting.display_subprojects_issues = 1
107 get :index, :project_id => 1
107 get :index, :project_id => 1
108 assert_response :success
108 assert_response :success
109 assert_template 'index.rhtml'
109 assert_template 'index.rhtml'
110 assert_not_nil assigns(:issues)
110 assert_not_nil assigns(:issues)
111 assert_tag :tag => 'a', :content => /Can't print recipes/
111 assert_tag :tag => 'a', :content => /Can't print recipes/
112 assert_tag :tag => 'a', :content => /Subproject issue/
112 assert_tag :tag => 'a', :content => /Subproject issue/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
113 assert_no_tag :tag => 'a', :content => /Issue of a private subproject/
114 end
114 end
115
115
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
116 def test_index_with_project_and_subprojects_should_show_private_subprojects
117 @request.session[:user_id] = 2
117 @request.session[:user_id] = 2
118 Setting.display_subprojects_issues = 1
118 Setting.display_subprojects_issues = 1
119 get :index, :project_id => 1
119 get :index, :project_id => 1
120 assert_response :success
120 assert_response :success
121 assert_template 'index.rhtml'
121 assert_template 'index.rhtml'
122 assert_not_nil assigns(:issues)
122 assert_not_nil assigns(:issues)
123 assert_tag :tag => 'a', :content => /Can't print recipes/
123 assert_tag :tag => 'a', :content => /Can't print recipes/
124 assert_tag :tag => 'a', :content => /Subproject issue/
124 assert_tag :tag => 'a', :content => /Subproject issue/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
125 assert_tag :tag => 'a', :content => /Issue of a private subproject/
126 end
126 end
127
127
128 def test_index_with_project_and_filter
128 def test_index_with_project_and_filter
129 get :index, :project_id => 1, :set_filter => 1
129 get :index, :project_id => 1, :set_filter => 1
130 assert_response :success
130 assert_response :success
131 assert_template 'index.rhtml'
131 assert_template 'index.rhtml'
132 assert_not_nil assigns(:issues)
132 assert_not_nil assigns(:issues)
133 end
133 end
134
134
135 def test_index_with_query
135 def test_index_with_query
136 get :index, :project_id => 1, :query_id => 5
136 get :index, :project_id => 1, :query_id => 5
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 assert_nil assigns(:issue_count_by_group)
140 assert_nil assigns(:issue_count_by_group)
141 end
141 end
142
142
143 def test_index_with_query_grouped_by_tracker
143 def test_index_with_query_grouped_by_tracker
144 get :index, :project_id => 1, :query_id => 6
144 get :index, :project_id => 1, :query_id => 6
145 assert_response :success
145 assert_response :success
146 assert_template 'index.rhtml'
146 assert_template 'index.rhtml'
147 assert_not_nil assigns(:issues)
147 assert_not_nil assigns(:issues)
148 assert_not_nil assigns(:issue_count_by_group)
148 assert_not_nil assigns(:issue_count_by_group)
149 end
149 end
150
150
151 def test_index_with_query_grouped_by_list_custom_field
151 def test_index_with_query_grouped_by_list_custom_field
152 get :index, :project_id => 1, :query_id => 9
152 get :index, :project_id => 1, :query_id => 9
153 assert_response :success
153 assert_response :success
154 assert_template 'index.rhtml'
154 assert_template 'index.rhtml'
155 assert_not_nil assigns(:issues)
155 assert_not_nil assigns(:issues)
156 assert_not_nil assigns(:issue_count_by_group)
156 assert_not_nil assigns(:issue_count_by_group)
157 end
157 end
158
158
159 def test_index_sort_by_field_not_included_in_columns
159 def test_index_sort_by_field_not_included_in_columns
160 Setting.issue_list_default_columns = %w(subject author)
160 Setting.issue_list_default_columns = %w(subject author)
161 get :index, :sort => 'tracker'
161 get :index, :sort => 'tracker'
162 end
162 end
163
163
164 def test_index_csv_with_project
164 def test_index_csv_with_project
165 Setting.default_language = 'en'
165 Setting.default_language = 'en'
166
166
167 get :index, :format => 'csv'
167 get :index, :format => 'csv'
168 assert_response :success
168 assert_response :success
169 assert_not_nil assigns(:issues)
169 assert_not_nil assigns(:issues)
170 assert_equal 'text/csv', @response.content_type
170 assert_equal 'text/csv', @response.content_type
171 assert @response.body.starts_with?("#,")
171 assert @response.body.starts_with?("#,")
172
172
173 get :index, :project_id => 1, :format => 'csv'
173 get :index, :project_id => 1, :format => 'csv'
174 assert_response :success
174 assert_response :success
175 assert_not_nil assigns(:issues)
175 assert_not_nil assigns(:issues)
176 assert_equal 'text/csv', @response.content_type
176 assert_equal 'text/csv', @response.content_type
177 end
177 end
178
178
179 def test_index_pdf
179 def test_index_pdf
180 get :index, :format => 'pdf'
180 get :index, :format => 'pdf'
181 assert_response :success
181 assert_response :success
182 assert_not_nil assigns(:issues)
182 assert_not_nil assigns(:issues)
183 assert_equal 'application/pdf', @response.content_type
183 assert_equal 'application/pdf', @response.content_type
184
184
185 get :index, :project_id => 1, :format => 'pdf'
185 get :index, :project_id => 1, :format => 'pdf'
186 assert_response :success
186 assert_response :success
187 assert_not_nil assigns(:issues)
187 assert_not_nil assigns(:issues)
188 assert_equal 'application/pdf', @response.content_type
188 assert_equal 'application/pdf', @response.content_type
189
189
190 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
190 get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
191 assert_response :success
191 assert_response :success
192 assert_not_nil assigns(:issues)
192 assert_not_nil assigns(:issues)
193 assert_equal 'application/pdf', @response.content_type
193 assert_equal 'application/pdf', @response.content_type
194 end
194 end
195
195
196 def test_index_pdf_with_query_grouped_by_list_custom_field
196 def test_index_pdf_with_query_grouped_by_list_custom_field
197 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
197 get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
198 assert_response :success
198 assert_response :success
199 assert_not_nil assigns(:issues)
199 assert_not_nil assigns(:issues)
200 assert_not_nil assigns(:issue_count_by_group)
200 assert_not_nil assigns(:issue_count_by_group)
201 assert_equal 'application/pdf', @response.content_type
201 assert_equal 'application/pdf', @response.content_type
202 end
202 end
203
203
204 def test_index_sort
204 def test_index_sort
205 get :index, :sort => 'tracker,id:desc'
205 get :index, :sort => 'tracker,id:desc'
206 assert_response :success
206 assert_response :success
207
207
208 sort_params = @request.session['issues_index_sort']
208 sort_params = @request.session['issues_index_sort']
209 assert sort_params.is_a?(String)
209 assert sort_params.is_a?(String)
210 assert_equal 'tracker,id:desc', sort_params
210 assert_equal 'tracker,id:desc', sort_params
211
211
212 issues = assigns(:issues)
212 issues = assigns(:issues)
213 assert_not_nil issues
213 assert_not_nil issues
214 assert !issues.empty?
214 assert !issues.empty?
215 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
215 assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
216 end
216 end
217
217
218 def test_index_with_columns
218 def test_index_with_columns
219 columns = ['tracker', 'subject', 'assigned_to']
219 columns = ['tracker', 'subject', 'assigned_to']
220 get :index, :set_filter => 1, :query => { 'column_names' => columns}
220 get :index, :set_filter => 1, :query => { 'column_names' => columns}
221 assert_response :success
221 assert_response :success
222
222
223 # query should use specified columns
223 # query should use specified columns
224 query = assigns(:query)
224 query = assigns(:query)
225 assert_kind_of Query, query
225 assert_kind_of Query, query
226 assert_equal columns, query.column_names.map(&:to_s)
226 assert_equal columns, query.column_names.map(&:to_s)
227
227
228 # columns should be stored in session
228 # columns should be stored in session
229 assert_kind_of Hash, session[:query]
229 assert_kind_of Hash, session[:query]
230 assert_kind_of Array, session[:query][:column_names]
230 assert_kind_of Array, session[:query][:column_names]
231 assert_equal columns, session[:query][:column_names].map(&:to_s)
231 assert_equal columns, session[:query][:column_names].map(&:to_s)
232 end
232 end
233
233
234 def test_show_by_anonymous
234 def test_show_by_anonymous
235 get :show, :id => 1
235 get :show, :id => 1
236 assert_response :success
236 assert_response :success
237 assert_template 'show.rhtml'
237 assert_template 'show.rhtml'
238 assert_not_nil assigns(:issue)
238 assert_not_nil assigns(:issue)
239 assert_equal Issue.find(1), assigns(:issue)
239 assert_equal Issue.find(1), assigns(:issue)
240
240
241 # anonymous role is allowed to add a note
241 # anonymous role is allowed to add a note
242 assert_tag :tag => 'form',
242 assert_tag :tag => 'form',
243 :descendant => { :tag => 'fieldset',
243 :descendant => { :tag => 'fieldset',
244 :child => { :tag => 'legend',
244 :child => { :tag => 'legend',
245 :content => /Notes/ } }
245 :content => /Notes/ } }
246 end
246 end
247
247
248 def test_show_by_manager
248 def test_show_by_manager
249 @request.session[:user_id] = 2
249 @request.session[:user_id] = 2
250 get :show, :id => 1
250 get :show, :id => 1
251 assert_response :success
251 assert_response :success
252
252
253 assert_tag :tag => 'form',
253 assert_tag :tag => 'form',
254 :descendant => { :tag => 'fieldset',
254 :descendant => { :tag => 'fieldset',
255 :child => { :tag => 'legend',
255 :child => { :tag => 'legend',
256 :content => /Change properties/ } },
256 :content => /Change properties/ } },
257 :descendant => { :tag => 'fieldset',
257 :descendant => { :tag => 'fieldset',
258 :child => { :tag => 'legend',
258 :child => { :tag => 'legend',
259 :content => /Log time/ } },
259 :content => /Log time/ } },
260 :descendant => { :tag => 'fieldset',
260 :descendant => { :tag => 'fieldset',
261 :child => { :tag => 'legend',
261 :child => { :tag => 'legend',
262 :content => /Notes/ } }
262 :content => /Notes/ } }
263 end
263 end
264
264
265 def test_show_should_deny_anonymous_access_without_permission
265 def test_show_should_deny_anonymous_access_without_permission
266 Role.anonymous.remove_permission!(:view_issues)
266 Role.anonymous.remove_permission!(:view_issues)
267 get :show, :id => 1
267 get :show, :id => 1
268 assert_response :redirect
268 assert_response :redirect
269 end
269 end
270
270
271 def test_show_should_deny_non_member_access_without_permission
271 def test_show_should_deny_non_member_access_without_permission
272 Role.non_member.remove_permission!(:view_issues)
272 Role.non_member.remove_permission!(:view_issues)
273 @request.session[:user_id] = 9
273 @request.session[:user_id] = 9
274 get :show, :id => 1
274 get :show, :id => 1
275 assert_response 403
275 assert_response 403
276 end
276 end
277
277
278 def test_show_should_deny_member_access_without_permission
278 def test_show_should_deny_member_access_without_permission
279 Role.find(1).remove_permission!(:view_issues)
279 Role.find(1).remove_permission!(:view_issues)
280 @request.session[:user_id] = 2
280 @request.session[:user_id] = 2
281 get :show, :id => 1
281 get :show, :id => 1
282 assert_response 403
282 assert_response 403
283 end
283 end
284
284
285 def test_show_should_not_disclose_relations_to_invisible_issues
285 def test_show_should_not_disclose_relations_to_invisible_issues
286 Setting.cross_project_issue_relations = '1'
286 Setting.cross_project_issue_relations = '1'
287 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
287 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
288 # Relation to a private project issue
288 # Relation to a private project issue
289 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
289 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
290
290
291 get :show, :id => 1
291 get :show, :id => 1
292 assert_response :success
292 assert_response :success
293
293
294 assert_tag :div, :attributes => { :id => 'relations' },
294 assert_tag :div, :attributes => { :id => 'relations' },
295 :descendant => { :tag => 'a', :content => /#2$/ }
295 :descendant => { :tag => 'a', :content => /#2$/ }
296 assert_no_tag :div, :attributes => { :id => 'relations' },
296 assert_no_tag :div, :attributes => { :id => 'relations' },
297 :descendant => { :tag => 'a', :content => /#4$/ }
297 :descendant => { :tag => 'a', :content => /#4$/ }
298 end
298 end
299
299
300 def test_show_atom
300 def test_show_atom
301 get :show, :id => 2, :format => 'atom'
301 get :show, :id => 2, :format => 'atom'
302 assert_response :success
302 assert_response :success
303 assert_template 'journals/index.rxml'
303 assert_template 'journals/index.rxml'
304 # Inline image
304 # Inline image
305 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
305 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
306 end
306 end
307
307
308 def test_show_export_to_pdf
308 def test_show_export_to_pdf
309 get :show, :id => 3, :format => 'pdf'
309 get :show, :id => 3, :format => 'pdf'
310 assert_response :success
310 assert_response :success
311 assert_equal 'application/pdf', @response.content_type
311 assert_equal 'application/pdf', @response.content_type
312 assert @response.body.starts_with?('%PDF')
312 assert @response.body.starts_with?('%PDF')
313 assert_not_nil assigns(:issue)
313 assert_not_nil assigns(:issue)
314 end
314 end
315
315
316 def test_get_new
316 def test_get_new
317 @request.session[:user_id] = 2
317 @request.session[:user_id] = 2
318 get :new, :project_id => 1, :tracker_id => 1
318 get :new, :project_id => 1, :tracker_id => 1
319 assert_response :success
319 assert_response :success
320 assert_template 'new'
320 assert_template 'new'
321
321
322 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
322 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
323 :value => 'Default string' }
323 :value => 'Default string' }
324 end
324 end
325
325
326 def test_get_new_without_tracker_id
326 def test_get_new_without_tracker_id
327 @request.session[:user_id] = 2
327 @request.session[:user_id] = 2
328 get :new, :project_id => 1
328 get :new, :project_id => 1
329 assert_response :success
329 assert_response :success
330 assert_template 'new'
330 assert_template 'new'
331
331
332 issue = assigns(:issue)
332 issue = assigns(:issue)
333 assert_not_nil issue
333 assert_not_nil issue
334 assert_equal Project.find(1).trackers.first, issue.tracker
334 assert_equal Project.find(1).trackers.first, issue.tracker
335 end
335 end
336
336
337 def test_get_new_with_no_default_status_should_display_an_error
337 def test_get_new_with_no_default_status_should_display_an_error
338 @request.session[:user_id] = 2
338 @request.session[:user_id] = 2
339 IssueStatus.delete_all
339 IssueStatus.delete_all
340
340
341 get :new, :project_id => 1
341 get :new, :project_id => 1
342 assert_response 500
342 assert_response 500
343 assert_not_nil flash[:error]
343 assert_not_nil flash[:error]
344 assert_tag :tag => 'div', :attributes => { :class => /error/ },
344 assert_tag :tag => 'div', :attributes => { :class => /error/ },
345 :content => /No default issue/
345 :content => /No default issue/
346 end
346 end
347
347
348 def test_get_new_with_no_tracker_should_display_an_error
348 def test_get_new_with_no_tracker_should_display_an_error
349 @request.session[:user_id] = 2
349 @request.session[:user_id] = 2
350 Tracker.delete_all
350 Tracker.delete_all
351
351
352 get :new, :project_id => 1
352 get :new, :project_id => 1
353 assert_response 500
353 assert_response 500
354 assert_not_nil flash[:error]
354 assert_not_nil flash[:error]
355 assert_tag :tag => 'div', :attributes => { :class => /error/ },
355 assert_tag :tag => 'div', :attributes => { :class => /error/ },
356 :content => /No tracker/
356 :content => /No tracker/
357 end
357 end
358
358
359 def test_update_new_form
359 def test_update_new_form
360 @request.session[:user_id] = 2
360 @request.session[:user_id] = 2
361 xhr :post, :new, :project_id => 1,
361 xhr :post, :new, :project_id => 1,
362 :issue => {:tracker_id => 2,
362 :issue => {:tracker_id => 2,
363 :subject => 'This is the test_new issue',
363 :subject => 'This is the test_new issue',
364 :description => 'This is the description',
364 :description => 'This is the description',
365 :priority_id => 5}
365 :priority_id => 5}
366 assert_response :success
366 assert_response :success
367 assert_template 'attributes'
367 assert_template 'attributes'
368
368
369 issue = assigns(:issue)
369 issue = assigns(:issue)
370 assert_kind_of Issue, issue
370 assert_kind_of Issue, issue
371 assert_equal 1, issue.project_id
371 assert_equal 1, issue.project_id
372 assert_equal 2, issue.tracker_id
372 assert_equal 2, issue.tracker_id
373 assert_equal 'This is the test_new issue', issue.subject
373 assert_equal 'This is the test_new issue', issue.subject
374 end
374 end
375
375
376 def test_post_create
376 def test_post_create
377 @request.session[:user_id] = 2
377 @request.session[:user_id] = 2
378 assert_difference 'Issue.count' do
378 assert_difference 'Issue.count' do
379 post :create, :project_id => 1,
379 post :create, :project_id => 1,
380 :issue => {:tracker_id => 3,
380 :issue => {:tracker_id => 3,
381 :status_id => 2,
381 :status_id => 2,
382 :subject => 'This is the test_new issue',
382 :subject => 'This is the test_new issue',
383 :description => 'This is the description',
383 :description => 'This is the description',
384 :priority_id => 5,
384 :priority_id => 5,
385 :estimated_hours => '',
385 :estimated_hours => '',
386 :custom_field_values => {'2' => 'Value for field 2'}}
386 :custom_field_values => {'2' => 'Value for field 2'}}
387 end
387 end
388 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
388 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
389
389
390 issue = Issue.find_by_subject('This is the test_new issue')
390 issue = Issue.find_by_subject('This is the test_new issue')
391 assert_not_nil issue
391 assert_not_nil issue
392 assert_equal 2, issue.author_id
392 assert_equal 2, issue.author_id
393 assert_equal 3, issue.tracker_id
393 assert_equal 3, issue.tracker_id
394 assert_equal 2, issue.status_id
394 assert_equal 2, issue.status_id
395 assert_nil issue.estimated_hours
395 assert_nil issue.estimated_hours
396 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
396 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
397 assert_not_nil v
397 assert_not_nil v
398 assert_equal 'Value for field 2', v.value
398 assert_equal 'Value for field 2', v.value
399 end
399 end
400
400
401 def test_post_create_and_continue
401 def test_post_create_and_continue
402 @request.session[:user_id] = 2
402 @request.session[:user_id] = 2
403 post :create, :project_id => 1,
403 post :create, :project_id => 1,
404 :issue => {:tracker_id => 3,
404 :issue => {:tracker_id => 3,
405 :subject => 'This is first issue',
405 :subject => 'This is first issue',
406 :priority_id => 5},
406 :priority_id => 5},
407 :continue => ''
407 :continue => ''
408 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
408 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
409 end
409 end
410
410
411 def test_post_create_without_custom_fields_param
411 def test_post_create_without_custom_fields_param
412 @request.session[:user_id] = 2
412 @request.session[:user_id] = 2
413 assert_difference 'Issue.count' do
413 assert_difference 'Issue.count' do
414 post :create, :project_id => 1,
414 post :create, :project_id => 1,
415 :issue => {:tracker_id => 1,
415 :issue => {:tracker_id => 1,
416 :subject => 'This is the test_new issue',
416 :subject => 'This is the test_new issue',
417 :description => 'This is the description',
417 :description => 'This is the description',
418 :priority_id => 5}
418 :priority_id => 5}
419 end
419 end
420 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
420 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
421 end
421 end
422
422
423 def test_post_create_with_required_custom_field_and_without_custom_fields_param
423 def test_post_create_with_required_custom_field_and_without_custom_fields_param
424 field = IssueCustomField.find_by_name('Database')
424 field = IssueCustomField.find_by_name('Database')
425 field.update_attribute(:is_required, true)
425 field.update_attribute(:is_required, true)
426
426
427 @request.session[:user_id] = 2
427 @request.session[:user_id] = 2
428 post :create, :project_id => 1,
428 post :create, :project_id => 1,
429 :issue => {:tracker_id => 1,
429 :issue => {:tracker_id => 1,
430 :subject => 'This is the test_new issue',
430 :subject => 'This is the test_new issue',
431 :description => 'This is the description',
431 :description => 'This is the description',
432 :priority_id => 5}
432 :priority_id => 5}
433 assert_response :success
433 assert_response :success
434 assert_template 'new'
434 assert_template 'new'
435 issue = assigns(:issue)
435 issue = assigns(:issue)
436 assert_not_nil issue
436 assert_not_nil issue
437 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
437 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
438 end
438 end
439
439
440 def test_post_create_with_watchers
440 def test_post_create_with_watchers
441 @request.session[:user_id] = 2
441 @request.session[:user_id] = 2
442 ActionMailer::Base.deliveries.clear
442 ActionMailer::Base.deliveries.clear
443
443
444 assert_difference 'Watcher.count', 2 do
444 assert_difference 'Watcher.count', 2 do
445 post :create, :project_id => 1,
445 post :create, :project_id => 1,
446 :issue => {:tracker_id => 1,
446 :issue => {:tracker_id => 1,
447 :subject => 'This is a new issue with watchers',
447 :subject => 'This is a new issue with watchers',
448 :description => 'This is the description',
448 :description => 'This is the description',
449 :priority_id => 5,
449 :priority_id => 5,
450 :watcher_user_ids => ['2', '3']}
450 :watcher_user_ids => ['2', '3']}
451 end
451 end
452 issue = Issue.find_by_subject('This is a new issue with watchers')
452 issue = Issue.find_by_subject('This is a new issue with watchers')
453 assert_not_nil issue
453 assert_not_nil issue
454 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
454 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
455
455
456 # Watchers added
456 # Watchers added
457 assert_equal [2, 3], issue.watcher_user_ids.sort
457 assert_equal [2, 3], issue.watcher_user_ids.sort
458 assert issue.watched_by?(User.find(3))
458 assert issue.watched_by?(User.find(3))
459 # Watchers notified
459 # Watchers notified
460 mail = ActionMailer::Base.deliveries.last
460 mail = ActionMailer::Base.deliveries.last
461 assert_kind_of TMail::Mail, mail
461 assert_kind_of TMail::Mail, mail
462 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
462 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
463 end
463 end
464
464
465 def test_post_create_subissue
465 def test_post_create_subissue
466 @request.session[:user_id] = 2
466 @request.session[:user_id] = 2
467
467
468 assert_difference 'Issue.count' do
468 assert_difference 'Issue.count' do
469 post :create, :project_id => 1,
469 post :create, :project_id => 1,
470 :issue => {:tracker_id => 1,
470 :issue => {:tracker_id => 1,
471 :subject => 'This is a child issue',
471 :subject => 'This is a child issue',
472 :parent_issue_id => 2}
472 :parent_issue_id => 2}
473 end
473 end
474 issue = Issue.find_by_subject('This is a child issue')
474 issue = Issue.find_by_subject('This is a child issue')
475 assert_not_nil issue
475 assert_not_nil issue
476 assert_equal Issue.find(2), issue.parent
476 assert_equal Issue.find(2), issue.parent
477 end
477 end
478
478
479 def test_post_create_should_send_a_notification
479 def test_post_create_should_send_a_notification
480 ActionMailer::Base.deliveries.clear
480 ActionMailer::Base.deliveries.clear
481 @request.session[:user_id] = 2
481 @request.session[:user_id] = 2
482 assert_difference 'Issue.count' do
482 assert_difference 'Issue.count' do
483 post :create, :project_id => 1,
483 post :create, :project_id => 1,
484 :issue => {:tracker_id => 3,
484 :issue => {:tracker_id => 3,
485 :subject => 'This is the test_new issue',
485 :subject => 'This is the test_new issue',
486 :description => 'This is the description',
486 :description => 'This is the description',
487 :priority_id => 5,
487 :priority_id => 5,
488 :estimated_hours => '',
488 :estimated_hours => '',
489 :custom_field_values => {'2' => 'Value for field 2'}}
489 :custom_field_values => {'2' => 'Value for field 2'}}
490 end
490 end
491 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
491 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
492
492
493 assert_equal 1, ActionMailer::Base.deliveries.size
493 assert_equal 1, ActionMailer::Base.deliveries.size
494 end
494 end
495
495
496 def test_post_create_should_preserve_fields_values_on_validation_failure
496 def test_post_create_should_preserve_fields_values_on_validation_failure
497 @request.session[:user_id] = 2
497 @request.session[:user_id] = 2
498 post :create, :project_id => 1,
498 post :create, :project_id => 1,
499 :issue => {:tracker_id => 1,
499 :issue => {:tracker_id => 1,
500 # empty subject
500 # empty subject
501 :subject => '',
501 :subject => '',
502 :description => 'This is a description',
502 :description => 'This is a description',
503 :priority_id => 6,
503 :priority_id => 6,
504 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
504 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
505 assert_response :success
505 assert_response :success
506 assert_template 'new'
506 assert_template 'new'
507
507
508 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
508 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
509 :content => 'This is a description'
509 :content => 'This is a description'
510 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
510 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
511 :child => { :tag => 'option', :attributes => { :selected => 'selected',
511 :child => { :tag => 'option', :attributes => { :selected => 'selected',
512 :value => '6' },
512 :value => '6' },
513 :content => 'High' }
513 :content => 'High' }
514 # Custom fields
514 # Custom fields
515 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
515 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
516 :child => { :tag => 'option', :attributes => { :selected => 'selected',
516 :child => { :tag => 'option', :attributes => { :selected => 'selected',
517 :value => 'Oracle' },
517 :value => 'Oracle' },
518 :content => 'Oracle' }
518 :content => 'Oracle' }
519 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
519 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
520 :value => 'Value for field 2'}
520 :value => 'Value for field 2'}
521 end
521 end
522
522
523 def test_post_create_should_ignore_non_safe_attributes
523 def test_post_create_should_ignore_non_safe_attributes
524 @request.session[:user_id] = 2
524 @request.session[:user_id] = 2
525 assert_nothing_raised do
525 assert_nothing_raised do
526 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
526 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
527 end
527 end
528 end
528 end
529
529
530 context "without workflow privilege" do
530 context "without workflow privilege" do
531 setup do
531 setup do
532 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
532 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
533 Role.anonymous.add_permission! :add_issues
533 Role.anonymous.add_permission! :add_issues
534 end
534 end
535
535
536 context "#new" do
536 context "#new" do
537 should "propose default status only" do
537 should "propose default status only" do
538 get :new, :project_id => 1
538 get :new, :project_id => 1
539 assert_response :success
539 assert_response :success
540 assert_template 'new'
540 assert_template 'new'
541 assert_tag :tag => 'select',
541 assert_tag :tag => 'select',
542 :attributes => {:name => 'issue[status_id]'},
542 :attributes => {:name => 'issue[status_id]'},
543 :children => {:count => 1},
543 :children => {:count => 1},
544 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
544 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
545 end
545 end
546
546
547 should "accept default status" do
547 should "accept default status" do
548 assert_difference 'Issue.count' do
548 assert_difference 'Issue.count' do
549 post :create, :project_id => 1,
549 post :create, :project_id => 1,
550 :issue => {:tracker_id => 1,
550 :issue => {:tracker_id => 1,
551 :subject => 'This is an issue',
551 :subject => 'This is an issue',
552 :status_id => 1}
552 :status_id => 1}
553 end
553 end
554 issue = Issue.last(:order => 'id')
554 issue = Issue.last(:order => 'id')
555 assert_equal IssueStatus.default, issue.status
555 assert_equal IssueStatus.default, issue.status
556 end
556 end
557
557
558 should "ignore unauthorized status" do
558 should "ignore unauthorized status" do
559 assert_difference 'Issue.count' do
559 assert_difference 'Issue.count' do
560 post :create, :project_id => 1,
560 post :create, :project_id => 1,
561 :issue => {:tracker_id => 1,
561 :issue => {:tracker_id => 1,
562 :subject => 'This is an issue',
562 :subject => 'This is an issue',
563 :status_id => 3}
563 :status_id => 3}
564 end
564 end
565 issue = Issue.last(:order => 'id')
565 issue = Issue.last(:order => 'id')
566 assert_equal IssueStatus.default, issue.status
566 assert_equal IssueStatus.default, issue.status
567 end
567 end
568 end
568 end
569 end
569 end
570
570
571 def test_copy_issue
571 def test_copy_issue
572 @request.session[:user_id] = 2
572 @request.session[:user_id] = 2
573 get :new, :project_id => 1, :copy_from => 1
573 get :new, :project_id => 1, :copy_from => 1
574 assert_template 'new'
574 assert_template 'new'
575 assert_not_nil assigns(:issue)
575 assert_not_nil assigns(:issue)
576 orig = Issue.find(1)
576 orig = Issue.find(1)
577 assert_equal orig.subject, assigns(:issue).subject
577 assert_equal orig.subject, assigns(:issue).subject
578 end
578 end
579
579
580 def test_get_edit
580 def test_get_edit
581 @request.session[:user_id] = 2
581 @request.session[:user_id] = 2
582 get :edit, :id => 1
582 get :edit, :id => 1
583 assert_response :success
583 assert_response :success
584 assert_template 'edit'
584 assert_template 'edit'
585 assert_not_nil assigns(:issue)
585 assert_not_nil assigns(:issue)
586 assert_equal Issue.find(1), assigns(:issue)
586 assert_equal Issue.find(1), assigns(:issue)
587 end
587 end
588
588
589 def test_get_edit_with_params
589 def test_get_edit_with_params
590 @request.session[:user_id] = 2
590 @request.session[:user_id] = 2
591 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
591 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
592 assert_response :success
592 assert_response :success
593 assert_template 'edit'
593 assert_template 'edit'
594
594
595 issue = assigns(:issue)
595 issue = assigns(:issue)
596 assert_not_nil issue
596 assert_not_nil issue
597
597
598 assert_equal 5, issue.status_id
598 assert_equal 5, issue.status_id
599 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
599 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
600 :child => { :tag => 'option',
600 :child => { :tag => 'option',
601 :content => 'Closed',
601 :content => 'Closed',
602 :attributes => { :selected => 'selected' } }
602 :attributes => { :selected => 'selected' } }
603
603
604 assert_equal 7, issue.priority_id
604 assert_equal 7, issue.priority_id
605 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
605 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
606 :child => { :tag => 'option',
606 :child => { :tag => 'option',
607 :content => 'Urgent',
607 :content => 'Urgent',
608 :attributes => { :selected => 'selected' } }
608 :attributes => { :selected => 'selected' } }
609 end
609 end
610
610
611 def test_update_edit_form
611 def test_update_edit_form
612 @request.session[:user_id] = 2
612 @request.session[:user_id] = 2
613 xhr :post, :new, :project_id => 1,
613 xhr :post, :new, :project_id => 1,
614 :id => 1,
614 :id => 1,
615 :issue => {:tracker_id => 2,
615 :issue => {:tracker_id => 2,
616 :subject => 'This is the test_new issue',
616 :subject => 'This is the test_new issue',
617 :description => 'This is the description',
617 :description => 'This is the description',
618 :priority_id => 5}
618 :priority_id => 5}
619 assert_response :success
619 assert_response :success
620 assert_template 'attributes'
620 assert_template 'attributes'
621
621
622 issue = assigns(:issue)
622 issue = assigns(:issue)
623 assert_kind_of Issue, issue
623 assert_kind_of Issue, issue
624 assert_equal 1, issue.id
624 assert_equal 1, issue.id
625 assert_equal 1, issue.project_id
625 assert_equal 1, issue.project_id
626 assert_equal 2, issue.tracker_id
626 assert_equal 2, issue.tracker_id
627 assert_equal 'This is the test_new issue', issue.subject
627 assert_equal 'This is the test_new issue', issue.subject
628 end
628 end
629
629
630 def test_update_using_invalid_http_verbs
630 def test_update_using_invalid_http_verbs
631 @request.session[:user_id] = 2
631 @request.session[:user_id] = 2
632 subject = 'Updated by an invalid http verb'
632 subject = 'Updated by an invalid http verb'
633
633
634 get :update, :id => 1, :issue => {:subject => subject}
634 get :update, :id => 1, :issue => {:subject => subject}
635 assert_not_equal subject, Issue.find(1).subject
635 assert_not_equal subject, Issue.find(1).subject
636
636
637 post :update, :id => 1, :issue => {:subject => subject}
637 post :update, :id => 1, :issue => {:subject => subject}
638 assert_not_equal subject, Issue.find(1).subject
638 assert_not_equal subject, Issue.find(1).subject
639
639
640 delete :update, :id => 1, :issue => {:subject => subject}
640 delete :update, :id => 1, :issue => {:subject => subject}
641 assert_not_equal subject, Issue.find(1).subject
641 assert_not_equal subject, Issue.find(1).subject
642 end
642 end
643
643
644 def test_put_update_without_custom_fields_param
644 def test_put_update_without_custom_fields_param
645 @request.session[:user_id] = 2
645 @request.session[:user_id] = 2
646 ActionMailer::Base.deliveries.clear
646 ActionMailer::Base.deliveries.clear
647
647
648 issue = Issue.find(1)
648 issue = Issue.find(1)
649 assert_equal '125', issue.custom_value_for(2).value
649 assert_equal '125', issue.custom_value_for(2).value
650 old_subject = issue.subject
650 old_subject = issue.subject
651 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
651 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
652
652
653 assert_difference('Journal.count') do
653 assert_difference('Journal.count') do
654 assert_difference('JournalDetail.count', 2) do
654 assert_difference('JournalDetail.count', 2) do
655 put :update, :id => 1, :issue => {:subject => new_subject,
655 put :update, :id => 1, :issue => {:subject => new_subject,
656 :priority_id => '6',
656 :priority_id => '6',
657 :category_id => '1' # no change
657 :category_id => '1' # no change
658 }
658 }
659 end
659 end
660 end
660 end
661 assert_redirected_to :action => 'show', :id => '1'
661 assert_redirected_to :action => 'show', :id => '1'
662 issue.reload
662 issue.reload
663 assert_equal new_subject, issue.subject
663 assert_equal new_subject, issue.subject
664 # Make sure custom fields were not cleared
664 # Make sure custom fields were not cleared
665 assert_equal '125', issue.custom_value_for(2).value
665 assert_equal '125', issue.custom_value_for(2).value
666
666
667 mail = ActionMailer::Base.deliveries.last
667 mail = ActionMailer::Base.deliveries.last
668 assert_kind_of TMail::Mail, mail
668 assert_kind_of TMail::Mail, mail
669 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
669 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
670 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
670 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
671 end
671 end
672
672
673 def test_put_update_with_custom_field_change
673 def test_put_update_with_custom_field_change
674 @request.session[:user_id] = 2
674 @request.session[:user_id] = 2
675 issue = Issue.find(1)
675 issue = Issue.find(1)
676 assert_equal '125', issue.custom_value_for(2).value
676 assert_equal '125', issue.custom_value_for(2).value
677
677
678 assert_difference('Journal.count') do
678 assert_difference('Journal.count') do
679 assert_difference('JournalDetail.count', 3) do
679 assert_difference('JournalDetail.count', 3) do
680 put :update, :id => 1, :issue => {:subject => 'Custom field change',
680 put :update, :id => 1, :issue => {:subject => 'Custom field change',
681 :priority_id => '6',
681 :priority_id => '6',
682 :category_id => '1', # no change
682 :category_id => '1', # no change
683 :custom_field_values => { '2' => 'New custom value' }
683 :custom_field_values => { '2' => 'New custom value' }
684 }
684 }
685 end
685 end
686 end
686 end
687 assert_redirected_to :action => 'show', :id => '1'
687 assert_redirected_to :action => 'show', :id => '1'
688 issue.reload
688 issue.reload
689 assert_equal 'New custom value', issue.custom_value_for(2).value
689 assert_equal 'New custom value', issue.custom_value_for(2).value
690
690
691 mail = ActionMailer::Base.deliveries.last
691 mail = ActionMailer::Base.deliveries.last
692 assert_kind_of TMail::Mail, mail
692 assert_kind_of TMail::Mail, mail
693 assert mail.body.include?("Searchable field changed from 125 to New custom value")
693 assert mail.body.include?("Searchable field changed from 125 to New custom value")
694 end
694 end
695
695
696 def test_put_update_with_status_and_assignee_change
696 def test_put_update_with_status_and_assignee_change
697 issue = Issue.find(1)
697 issue = Issue.find(1)
698 assert_equal 1, issue.status_id
698 assert_equal 1, issue.status_id
699 @request.session[:user_id] = 2
699 @request.session[:user_id] = 2
700 assert_difference('TimeEntry.count', 0) do
700 assert_difference('TimeEntry.count', 0) do
701 put :update,
701 put :update,
702 :id => 1,
702 :id => 1,
703 :issue => { :status_id => 2, :assigned_to_id => 3 },
703 :issue => { :status_id => 2, :assigned_to_id => 3 },
704 :notes => 'Assigned to dlopper',
704 :notes => 'Assigned to dlopper',
705 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
705 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
706 end
706 end
707 assert_redirected_to :action => 'show', :id => '1'
707 assert_redirected_to :action => 'show', :id => '1'
708 issue.reload
708 issue.reload
709 assert_equal 2, issue.status_id
709 assert_equal 2, issue.status_id
710 j = Journal.find(:first, :order => 'id DESC')
710 j = Journal.find(:first, :order => 'id DESC')
711 assert_equal 'Assigned to dlopper', j.notes
711 assert_equal 'Assigned to dlopper', j.notes
712 assert_equal 2, j.details.size
712 assert_equal 2, j.details.size
713
713
714 mail = ActionMailer::Base.deliveries.last
714 mail = ActionMailer::Base.deliveries.last
715 assert mail.body.include?("Status changed from New to Assigned")
715 assert mail.body.include?("Status changed from New to Assigned")
716 # subject should contain the new status
716 # subject should contain the new status
717 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
717 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
718 end
718 end
719
719
720 def test_put_update_with_note_only
720 def test_put_update_with_note_only
721 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
721 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
722 # anonymous user
722 # anonymous user
723 put :update,
723 put :update,
724 :id => 1,
724 :id => 1,
725 :notes => notes
725 :notes => notes
726 assert_redirected_to :action => 'show', :id => '1'
726 assert_redirected_to :action => 'show', :id => '1'
727 j = Journal.find(:first, :order => 'id DESC')
727 j = Journal.find(:first, :order => 'id DESC')
728 assert_equal notes, j.notes
728 assert_equal notes, j.notes
729 assert_equal 0, j.details.size
729 assert_equal 0, j.details.size
730 assert_equal User.anonymous, j.user
730 assert_equal User.anonymous, j.user
731
731
732 mail = ActionMailer::Base.deliveries.last
732 mail = ActionMailer::Base.deliveries.last
733 assert mail.body.include?(notes)
733 assert mail.body.include?(notes)
734 end
734 end
735
735
736 def test_put_update_with_note_and_spent_time
736 def test_put_update_with_note_and_spent_time
737 @request.session[:user_id] = 2
737 @request.session[:user_id] = 2
738 spent_hours_before = Issue.find(1).spent_hours
738 spent_hours_before = Issue.find(1).spent_hours
739 assert_difference('TimeEntry.count') do
739 assert_difference('TimeEntry.count') do
740 put :update,
740 put :update,
741 :id => 1,
741 :id => 1,
742 :notes => '2.5 hours added',
742 :notes => '2.5 hours added',
743 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
743 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
744 end
744 end
745 assert_redirected_to :action => 'show', :id => '1'
745 assert_redirected_to :action => 'show', :id => '1'
746
746
747 issue = Issue.find(1)
747 issue = Issue.find(1)
748
748
749 j = Journal.find(:first, :order => 'id DESC')
749 j = Journal.find(:first, :order => 'id DESC')
750 assert_equal '2.5 hours added', j.notes
750 assert_equal '2.5 hours added', j.notes
751 assert_equal 0, j.details.size
751 assert_equal 0, j.details.size
752
752
753 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
753 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
754 assert_not_nil t
754 assert_not_nil t
755 assert_equal 2.5, t.hours
755 assert_equal 2.5, t.hours
756 assert_equal spent_hours_before + 2.5, issue.spent_hours
756 assert_equal spent_hours_before + 2.5, issue.spent_hours
757 end
757 end
758
758
759 def test_put_update_with_attachment_only
759 def test_put_update_with_attachment_only
760 set_tmp_attachments_directory
760 set_tmp_attachments_directory
761
761
762 # Delete all fixtured journals, a race condition can occur causing the wrong
762 # Delete all fixtured journals, a race condition can occur causing the wrong
763 # journal to get fetched in the next find.
763 # journal to get fetched in the next find.
764 Journal.delete_all
764 Journal.delete_all
765
765
766 # anonymous user
766 # anonymous user
767 put :update,
767 put :update,
768 :id => 1,
768 :id => 1,
769 :notes => '',
769 :notes => '',
770 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
770 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
771 assert_redirected_to :action => 'show', :id => '1'
771 assert_redirected_to :action => 'show', :id => '1'
772 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
772 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
773 assert j.notes.blank?
773 assert j.notes.blank?
774 assert_equal 1, j.details.size
774 assert_equal 1, j.details.size
775 assert_equal 'testfile.txt', j.details.first.value
775 assert_equal 'testfile.txt', j.details.first.value
776 assert_equal User.anonymous, j.user
776 assert_equal User.anonymous, j.user
777
777
778 mail = ActionMailer::Base.deliveries.last
778 mail = ActionMailer::Base.deliveries.last
779 assert mail.body.include?('testfile.txt')
779 assert mail.body.include?('testfile.txt')
780 end
780 end
781
781
782 def test_put_update_with_attachment_that_fails_to_save
782 def test_put_update_with_attachment_that_fails_to_save
783 set_tmp_attachments_directory
783 set_tmp_attachments_directory
784
784
785 # Delete all fixtured journals, a race condition can occur causing the wrong
785 # Delete all fixtured journals, a race condition can occur causing the wrong
786 # journal to get fetched in the next find.
786 # journal to get fetched in the next find.
787 Journal.delete_all
787 Journal.delete_all
788
788
789 # Mock out the unsaved attachment
789 # Mock out the unsaved attachment
790 Attachment.any_instance.stubs(:create).returns(Attachment.new)
790 Attachment.any_instance.stubs(:create).returns(Attachment.new)
791
791
792 # anonymous user
792 # anonymous user
793 put :update,
793 put :update,
794 :id => 1,
794 :id => 1,
795 :notes => '',
795 :notes => '',
796 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
796 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
797 assert_redirected_to :action => 'show', :id => '1'
797 assert_redirected_to :action => 'show', :id => '1'
798 assert_equal '1 file(s) could not be saved.', flash[:warning]
798 assert_equal '1 file(s) could not be saved.', flash[:warning]
799
799
800 end if Object.const_defined?(:Mocha)
800 end if Object.const_defined?(:Mocha)
801
801
802 def test_put_update_with_no_change
802 def test_put_update_with_no_change
803 issue = Issue.find(1)
803 issue = Issue.find(1)
804 issue.journals.clear
804 issue.journals.clear
805 ActionMailer::Base.deliveries.clear
805 ActionMailer::Base.deliveries.clear
806
806
807 put :update,
807 put :update,
808 :id => 1,
808 :id => 1,
809 :notes => ''
809 :notes => ''
810 assert_redirected_to :action => 'show', :id => '1'
810 assert_redirected_to :action => 'show', :id => '1'
811
811
812 issue.reload
812 issue.reload
813 assert issue.journals.empty?
813 assert issue.journals.empty?
814 # No email should be sent
814 # No email should be sent
815 assert ActionMailer::Base.deliveries.empty?
815 assert ActionMailer::Base.deliveries.empty?
816 end
816 end
817
817
818 def test_put_update_should_send_a_notification
818 def test_put_update_should_send_a_notification
819 @request.session[:user_id] = 2
819 @request.session[:user_id] = 2
820 ActionMailer::Base.deliveries.clear
820 ActionMailer::Base.deliveries.clear
821 issue = Issue.find(1)
821 issue = Issue.find(1)
822 old_subject = issue.subject
822 old_subject = issue.subject
823 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
823 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
824
824
825 put :update, :id => 1, :issue => {:subject => new_subject,
825 put :update, :id => 1, :issue => {:subject => new_subject,
826 :priority_id => '6',
826 :priority_id => '6',
827 :category_id => '1' # no change
827 :category_id => '1' # no change
828 }
828 }
829 assert_equal 1, ActionMailer::Base.deliveries.size
829 assert_equal 1, ActionMailer::Base.deliveries.size
830 end
830 end
831
831
832 def test_put_update_with_invalid_spent_time
832 def test_put_update_with_invalid_spent_time
833 @request.session[:user_id] = 2
833 @request.session[:user_id] = 2
834 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
834 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
835
835
836 assert_no_difference('Journal.count') do
836 assert_no_difference('Journal.count') do
837 put :update,
837 put :update,
838 :id => 1,
838 :id => 1,
839 :notes => notes,
839 :notes => notes,
840 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
840 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
841 end
841 end
842 assert_response :success
842 assert_response :success
843 assert_template 'edit'
843 assert_template 'edit'
844
844
845 assert_tag :textarea, :attributes => { :name => 'notes' },
845 assert_tag :textarea, :attributes => { :name => 'notes' },
846 :content => notes
846 :content => notes
847 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
847 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
848 end
848 end
849
849
850 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
850 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
851 issue = Issue.find(2)
851 issue = Issue.find(2)
852 @request.session[:user_id] = 2
852 @request.session[:user_id] = 2
853
853
854 put :update,
854 put :update,
855 :id => issue.id,
855 :id => issue.id,
856 :issue => {
856 :issue => {
857 :fixed_version_id => 4
857 :fixed_version_id => 4
858 }
858 }
859
859
860 assert_response :redirect
860 assert_response :redirect
861 issue.reload
861 issue.reload
862 assert_equal 4, issue.fixed_version_id
862 assert_equal 4, issue.fixed_version_id
863 assert_not_equal issue.project_id, issue.fixed_version.project_id
863 assert_not_equal issue.project_id, issue.fixed_version.project_id
864 end
864 end
865
865
866 def test_put_update_should_redirect_back_using_the_back_url_parameter
866 def test_put_update_should_redirect_back_using_the_back_url_parameter
867 issue = Issue.find(2)
867 issue = Issue.find(2)
868 @request.session[:user_id] = 2
868 @request.session[:user_id] = 2
869
869
870 put :update,
870 put :update,
871 :id => issue.id,
871 :id => issue.id,
872 :issue => {
872 :issue => {
873 :fixed_version_id => 4
873 :fixed_version_id => 4
874 },
874 },
875 :back_url => '/issues'
875 :back_url => '/issues'
876
876
877 assert_response :redirect
877 assert_response :redirect
878 assert_redirected_to '/issues'
878 assert_redirected_to '/issues'
879 end
879 end
880
880
881 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
881 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
882 issue = Issue.find(2)
882 issue = Issue.find(2)
883 @request.session[:user_id] = 2
883 @request.session[:user_id] = 2
884
884
885 put :update,
885 put :update,
886 :id => issue.id,
886 :id => issue.id,
887 :issue => {
887 :issue => {
888 :fixed_version_id => 4
888 :fixed_version_id => 4
889 },
889 },
890 :back_url => 'http://google.com'
890 :back_url => 'http://google.com'
891
891
892 assert_response :redirect
892 assert_response :redirect
893 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
893 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
894 end
894 end
895
895
896 def test_get_bulk_edit
896 def test_get_bulk_edit
897 @request.session[:user_id] = 2
897 @request.session[:user_id] = 2
898 get :bulk_edit, :ids => [1, 2]
898 get :bulk_edit, :ids => [1, 2]
899 assert_response :success
899 assert_response :success
900 assert_template 'bulk_edit'
900 assert_template 'bulk_edit'
901
901
902 # Project specific custom field, date type
902 # Project specific custom field, date type
903 field = CustomField.find(9)
903 field = CustomField.find(9)
904 assert !field.is_for_all?
904 assert !field.is_for_all?
905 assert_equal 'date', field.field_format
905 assert_equal 'date', field.field_format
906 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
906 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
907
907
908 # System wide custom field
908 # System wide custom field
909 assert CustomField.find(1).is_for_all?
909 assert CustomField.find(1).is_for_all?
910 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
910 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
911 end
911 end
912
912
913 def test_bulk_edit
913 def test_bulk_update
914 @request.session[:user_id] = 2
914 @request.session[:user_id] = 2
915 # update issues priority
915 # update issues priority
916 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
916 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
917 :issue => {:priority_id => 7,
917 :issue => {:priority_id => 7,
918 :assigned_to_id => '',
918 :assigned_to_id => '',
919 :custom_field_values => {'2' => ''}}
919 :custom_field_values => {'2' => ''}}
920
920
921 assert_response 302
921 assert_response 302
922 # check that the issues were updated
922 # check that the issues were updated
923 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
923 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
924
924
925 issue = Issue.find(1)
925 issue = Issue.find(1)
926 journal = issue.journals.find(:first, :order => 'created_on DESC')
926 journal = issue.journals.find(:first, :order => 'created_on DESC')
927 assert_equal '125', issue.custom_value_for(2).value
927 assert_equal '125', issue.custom_value_for(2).value
928 assert_equal 'Bulk editing', journal.notes
928 assert_equal 'Bulk editing', journal.notes
929 assert_equal 1, journal.details.size
929 assert_equal 1, journal.details.size
930 end
930 end
931
931
932 def test_bullk_edit_should_send_a_notification
932 def test_bullk_update_should_send_a_notification
933 @request.session[:user_id] = 2
933 @request.session[:user_id] = 2
934 ActionMailer::Base.deliveries.clear
934 ActionMailer::Base.deliveries.clear
935 post(:bulk_edit,
935 post(:bulk_update,
936 {
936 {
937 :ids => [1, 2],
937 :ids => [1, 2],
938 :notes => 'Bulk editing',
938 :notes => 'Bulk editing',
939 :issue => {
939 :issue => {
940 :priority_id => 7,
940 :priority_id => 7,
941 :assigned_to_id => '',
941 :assigned_to_id => '',
942 :custom_field_values => {'2' => ''}
942 :custom_field_values => {'2' => ''}
943 }
943 }
944 })
944 })
945
945
946 assert_response 302
946 assert_response 302
947 assert_equal 2, ActionMailer::Base.deliveries.size
947 assert_equal 2, ActionMailer::Base.deliveries.size
948 end
948 end
949
949
950 def test_bulk_edit_status
950 def test_bulk_update_status
951 @request.session[:user_id] = 2
951 @request.session[:user_id] = 2
952 # update issues priority
952 # update issues priority
953 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
953 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
954 :issue => {:priority_id => '',
954 :issue => {:priority_id => '',
955 :assigned_to_id => '',
955 :assigned_to_id => '',
956 :status_id => '5'}
956 :status_id => '5'}
957
957
958 assert_response 302
958 assert_response 302
959 issue = Issue.find(1)
959 issue = Issue.find(1)
960 assert issue.closed?
960 assert issue.closed?
961 end
961 end
962
962
963 def test_bulk_edit_custom_field
963 def test_bulk_update_custom_field
964 @request.session[:user_id] = 2
964 @request.session[:user_id] = 2
965 # update issues priority
965 # update issues priority
966 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
966 post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
967 :issue => {:priority_id => '',
967 :issue => {:priority_id => '',
968 :assigned_to_id => '',
968 :assigned_to_id => '',
969 :custom_field_values => {'2' => '777'}}
969 :custom_field_values => {'2' => '777'}}
970
970
971 assert_response 302
971 assert_response 302
972
972
973 issue = Issue.find(1)
973 issue = Issue.find(1)
974 journal = issue.journals.find(:first, :order => 'created_on DESC')
974 journal = issue.journals.find(:first, :order => 'created_on DESC')
975 assert_equal '777', issue.custom_value_for(2).value
975 assert_equal '777', issue.custom_value_for(2).value
976 assert_equal 1, journal.details.size
976 assert_equal 1, journal.details.size
977 assert_equal '125', journal.details.first.old_value
977 assert_equal '125', journal.details.first.old_value
978 assert_equal '777', journal.details.first.value
978 assert_equal '777', journal.details.first.value
979 end
979 end
980
980
981 def test_bulk_unassign
981 def test_bulk_update_unassign
982 assert_not_nil Issue.find(2).assigned_to
982 assert_not_nil Issue.find(2).assigned_to
983 @request.session[:user_id] = 2
983 @request.session[:user_id] = 2
984 # unassign issues
984 # unassign issues
985 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
985 post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
986 assert_response 302
986 assert_response 302
987 # check that the issues were updated
987 # check that the issues were updated
988 assert_nil Issue.find(2).assigned_to
988 assert_nil Issue.find(2).assigned_to
989 end
989 end
990
990
991 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
991 def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
992 @request.session[:user_id] = 2
992 @request.session[:user_id] = 2
993
993
994 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
994 post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
995
995
996 assert_response :redirect
996 assert_response :redirect
997 issues = Issue.find([1,2])
997 issues = Issue.find([1,2])
998 issues.each do |issue|
998 issues.each do |issue|
999 assert_equal 4, issue.fixed_version_id
999 assert_equal 4, issue.fixed_version_id
1000 assert_not_equal issue.project_id, issue.fixed_version.project_id
1000 assert_not_equal issue.project_id, issue.fixed_version.project_id
1001 end
1001 end
1002 end
1002 end
1003
1003
1004 def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter
1004 def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
1005 @request.session[:user_id] = 2
1005 @request.session[:user_id] = 2
1006 post :bulk_edit, :ids => [1,2], :back_url => '/issues'
1006 post :bulk_update, :ids => [1,2], :back_url => '/issues'
1007
1007
1008 assert_response :redirect
1008 assert_response :redirect
1009 assert_redirected_to '/issues'
1009 assert_redirected_to '/issues'
1010 end
1010 end
1011
1011
1012 def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1012 def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1013 @request.session[:user_id] = 2
1013 @request.session[:user_id] = 2
1014 post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com'
1014 post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
1015
1015
1016 assert_response :redirect
1016 assert_response :redirect
1017 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1017 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1018 end
1018 end
1019
1019
1020 def test_destroy_issue_with_no_time_entries
1020 def test_destroy_issue_with_no_time_entries
1021 assert_nil TimeEntry.find_by_issue_id(2)
1021 assert_nil TimeEntry.find_by_issue_id(2)
1022 @request.session[:user_id] = 2
1022 @request.session[:user_id] = 2
1023 post :destroy, :id => 2
1023 post :destroy, :id => 2
1024 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1024 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1025 assert_nil Issue.find_by_id(2)
1025 assert_nil Issue.find_by_id(2)
1026 end
1026 end
1027
1027
1028 def test_destroy_issues_with_time_entries
1028 def test_destroy_issues_with_time_entries
1029 @request.session[:user_id] = 2
1029 @request.session[:user_id] = 2
1030 post :destroy, :ids => [1, 3]
1030 post :destroy, :ids => [1, 3]
1031 assert_response :success
1031 assert_response :success
1032 assert_template 'destroy'
1032 assert_template 'destroy'
1033 assert_not_nil assigns(:hours)
1033 assert_not_nil assigns(:hours)
1034 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1034 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1035 end
1035 end
1036
1036
1037 def test_destroy_issues_and_destroy_time_entries
1037 def test_destroy_issues_and_destroy_time_entries
1038 @request.session[:user_id] = 2
1038 @request.session[:user_id] = 2
1039 post :destroy, :ids => [1, 3], :todo => 'destroy'
1039 post :destroy, :ids => [1, 3], :todo => 'destroy'
1040 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1040 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1041 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1041 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1042 assert_nil TimeEntry.find_by_id([1, 2])
1042 assert_nil TimeEntry.find_by_id([1, 2])
1043 end
1043 end
1044
1044
1045 def test_destroy_issues_and_assign_time_entries_to_project
1045 def test_destroy_issues_and_assign_time_entries_to_project
1046 @request.session[:user_id] = 2
1046 @request.session[:user_id] = 2
1047 post :destroy, :ids => [1, 3], :todo => 'nullify'
1047 post :destroy, :ids => [1, 3], :todo => 'nullify'
1048 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1048 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1049 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1049 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1050 assert_nil TimeEntry.find(1).issue_id
1050 assert_nil TimeEntry.find(1).issue_id
1051 assert_nil TimeEntry.find(2).issue_id
1051 assert_nil TimeEntry.find(2).issue_id
1052 end
1052 end
1053
1053
1054 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1054 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1055 @request.session[:user_id] = 2
1055 @request.session[:user_id] = 2
1056 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1056 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1057 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1057 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1058 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1058 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1059 assert_equal 2, TimeEntry.find(1).issue_id
1059 assert_equal 2, TimeEntry.find(1).issue_id
1060 assert_equal 2, TimeEntry.find(2).issue_id
1060 assert_equal 2, TimeEntry.find(2).issue_id
1061 end
1061 end
1062
1062
1063 def test_default_search_scope
1063 def test_default_search_scope
1064 get :index
1064 get :index
1065 assert_tag :div, :attributes => {:id => 'quick-search'},
1065 assert_tag :div, :attributes => {:id => 'quick-search'},
1066 :child => {:tag => 'form',
1066 :child => {:tag => 'form',
1067 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1067 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1068 end
1068 end
1069 end
1069 end
@@ -1,288 +1,291
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require "#{File.dirname(__FILE__)}/../test_helper"
18 require "#{File.dirname(__FILE__)}/../test_helper"
19
19
20 class RoutingTest < ActionController::IntegrationTest
20 class RoutingTest < ActionController::IntegrationTest
21 context "activities" do
21 context "activities" do
22 should_route :get, "/activity", :controller => 'projects', :action => 'activity', :id => nil
22 should_route :get, "/activity", :controller => 'projects', :action => 'activity', :id => nil
23 should_route :get, "/activity.atom", :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom'
23 should_route :get, "/activity.atom", :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom'
24 end
24 end
25
25
26 context "attachments" do
26 context "attachments" do
27 should_route :get, "/attachments/1", :controller => 'attachments', :action => 'show', :id => '1'
27 should_route :get, "/attachments/1", :controller => 'attachments', :action => 'show', :id => '1'
28 should_route :get, "/attachments/1/filename.ext", :controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext'
28 should_route :get, "/attachments/1/filename.ext", :controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext'
29 should_route :get, "/attachments/download/1", :controller => 'attachments', :action => 'download', :id => '1'
29 should_route :get, "/attachments/download/1", :controller => 'attachments', :action => 'download', :id => '1'
30 should_route :get, "/attachments/download/1/filename.ext", :controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext'
30 should_route :get, "/attachments/download/1/filename.ext", :controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext'
31 end
31 end
32
32
33 context "boards" do
33 context "boards" do
34 should_route :get, "/projects/world_domination/boards", :controller => 'boards', :action => 'index', :project_id => 'world_domination'
34 should_route :get, "/projects/world_domination/boards", :controller => 'boards', :action => 'index', :project_id => 'world_domination'
35 should_route :get, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
35 should_route :get, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
36 should_route :get, "/projects/world_domination/boards/44", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44'
36 should_route :get, "/projects/world_domination/boards/44", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44'
37 should_route :get, "/projects/world_domination/boards/44.atom", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44', :format => 'atom'
37 should_route :get, "/projects/world_domination/boards/44.atom", :controller => 'boards', :action => 'show', :project_id => 'world_domination', :id => '44', :format => 'atom'
38 should_route :get, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
38 should_route :get, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
39
39
40 should_route :post, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
40 should_route :post, "/projects/world_domination/boards/new", :controller => 'boards', :action => 'new', :project_id => 'world_domination'
41 should_route :post, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
41 should_route :post, "/projects/world_domination/boards/44/edit", :controller => 'boards', :action => 'edit', :project_id => 'world_domination', :id => '44'
42 should_route :post, "/projects/world_domination/boards/44/destroy", :controller => 'boards', :action => 'destroy', :project_id => 'world_domination', :id => '44'
42 should_route :post, "/projects/world_domination/boards/44/destroy", :controller => 'boards', :action => 'destroy', :project_id => 'world_domination', :id => '44'
43
43
44 end
44 end
45
45
46 context "documents" do
46 context "documents" do
47 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
47 should_route :get, "/projects/567/documents", :controller => 'documents', :action => 'index', :project_id => '567'
48 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
48 should_route :get, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
49 should_route :get, "/documents/22", :controller => 'documents', :action => 'show', :id => '22'
49 should_route :get, "/documents/22", :controller => 'documents', :action => 'show', :id => '22'
50 should_route :get, "/documents/22/edit", :controller => 'documents', :action => 'edit', :id => '22'
50 should_route :get, "/documents/22/edit", :controller => 'documents', :action => 'edit', :id => '22'
51
51
52 should_route :post, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
52 should_route :post, "/projects/567/documents/new", :controller => 'documents', :action => 'new', :project_id => '567'
53 should_route :post, "/documents/567/edit", :controller => 'documents', :action => 'edit', :id => '567'
53 should_route :post, "/documents/567/edit", :controller => 'documents', :action => 'edit', :id => '567'
54 should_route :post, "/documents/567/destroy", :controller => 'documents', :action => 'destroy', :id => '567'
54 should_route :post, "/documents/567/destroy", :controller => 'documents', :action => 'destroy', :id => '567'
55 end
55 end
56
56
57 context "issues" do
57 context "issues" do
58 # REST actions
58 # REST actions
59 should_route :get, "/issues", :controller => 'issues', :action => 'index'
59 should_route :get, "/issues", :controller => 'issues', :action => 'index'
60 should_route :get, "/issues.pdf", :controller => 'issues', :action => 'index', :format => 'pdf'
60 should_route :get, "/issues.pdf", :controller => 'issues', :action => 'index', :format => 'pdf'
61 should_route :get, "/issues.atom", :controller => 'issues', :action => 'index', :format => 'atom'
61 should_route :get, "/issues.atom", :controller => 'issues', :action => 'index', :format => 'atom'
62 should_route :get, "/issues.xml", :controller => 'issues', :action => 'index', :format => 'xml'
62 should_route :get, "/issues.xml", :controller => 'issues', :action => 'index', :format => 'xml'
63 should_route :get, "/projects/23/issues", :controller => 'issues', :action => 'index', :project_id => '23'
63 should_route :get, "/projects/23/issues", :controller => 'issues', :action => 'index', :project_id => '23'
64 should_route :get, "/projects/23/issues.pdf", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'pdf'
64 should_route :get, "/projects/23/issues.pdf", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'pdf'
65 should_route :get, "/projects/23/issues.atom", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'atom'
65 should_route :get, "/projects/23/issues.atom", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'atom'
66 should_route :get, "/projects/23/issues.xml", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'xml'
66 should_route :get, "/projects/23/issues.xml", :controller => 'issues', :action => 'index', :project_id => '23', :format => 'xml'
67 should_route :get, "/issues/64", :controller => 'issues', :action => 'show', :id => '64'
67 should_route :get, "/issues/64", :controller => 'issues', :action => 'show', :id => '64'
68 should_route :get, "/issues/64.pdf", :controller => 'issues', :action => 'show', :id => '64', :format => 'pdf'
68 should_route :get, "/issues/64.pdf", :controller => 'issues', :action => 'show', :id => '64', :format => 'pdf'
69 should_route :get, "/issues/64.atom", :controller => 'issues', :action => 'show', :id => '64', :format => 'atom'
69 should_route :get, "/issues/64.atom", :controller => 'issues', :action => 'show', :id => '64', :format => 'atom'
70 should_route :get, "/issues/64.xml", :controller => 'issues', :action => 'show', :id => '64', :format => 'xml'
70 should_route :get, "/issues/64.xml", :controller => 'issues', :action => 'show', :id => '64', :format => 'xml'
71
71
72 should_route :get, "/projects/23/issues/new", :controller => 'issues', :action => 'new', :project_id => '23'
72 should_route :get, "/projects/23/issues/new", :controller => 'issues', :action => 'new', :project_id => '23'
73 should_route :post, "/projects/23/issues", :controller => 'issues', :action => 'create', :project_id => '23'
73 should_route :post, "/projects/23/issues", :controller => 'issues', :action => 'create', :project_id => '23'
74 should_route :post, "/issues.xml", :controller => 'issues', :action => 'create', :format => 'xml'
74 should_route :post, "/issues.xml", :controller => 'issues', :action => 'create', :format => 'xml'
75
75
76 should_route :get, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
76 should_route :get, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
77 # TODO: Should use PUT
77 # TODO: Should use PUT
78 should_route :post, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
78 should_route :post, "/issues/64/edit", :controller => 'issues', :action => 'edit', :id => '64'
79 should_route :put, "/issues/1.xml", :controller => 'issues', :action => 'update', :id => '1', :format => 'xml'
79 should_route :put, "/issues/1.xml", :controller => 'issues', :action => 'update', :id => '1', :format => 'xml'
80
80
81 # TODO: Should use DELETE
81 # TODO: Should use DELETE
82 should_route :post, "/issues/64/destroy", :controller => 'issues', :action => 'destroy', :id => '64'
82 should_route :post, "/issues/64/destroy", :controller => 'issues', :action => 'destroy', :id => '64'
83 should_route :delete, "/issues/1.xml", :controller => 'issues', :action => 'destroy', :id => '1', :format => 'xml'
83 should_route :delete, "/issues/1.xml", :controller => 'issues', :action => 'destroy', :id => '1', :format => 'xml'
84
84
85 # Extra actions
85 # Extra actions
86 should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64'
86 should_route :get, "/projects/23/issues/64/copy", :controller => 'issues', :action => 'new', :project_id => '23', :copy_from => '64'
87
87
88 should_route :get, "/issues/move/new", :controller => 'issue_moves', :action => 'new'
88 should_route :get, "/issues/move/new", :controller => 'issue_moves', :action => 'new'
89 should_route :post, "/issues/move", :controller => 'issue_moves', :action => 'create'
89 should_route :post, "/issues/move", :controller => 'issue_moves', :action => 'create'
90
90
91 should_route :post, "/issues/1/quoted", :controller => 'journals', :action => 'new', :id => '1'
91 should_route :post, "/issues/1/quoted", :controller => 'journals', :action => 'new', :id => '1'
92
92
93 should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show'
93 should_route :get, "/issues/calendar", :controller => 'calendars', :action => 'show'
94 should_route :post, "/issues/calendar", :controller => 'calendars', :action => 'show'
94 should_route :post, "/issues/calendar", :controller => 'calendars', :action => 'show'
95 should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
95 should_route :get, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
96 should_route :post, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
96 should_route :post, "/projects/project-name/issues/calendar", :controller => 'calendars', :action => 'show', :project_id => 'project-name'
97
97
98 should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show'
98 should_route :get, "/issues/gantt", :controller => 'gantts', :action => 'show'
99 should_route :post, "/issues/gantt", :controller => 'gantts', :action => 'show'
99 should_route :post, "/issues/gantt", :controller => 'gantts', :action => 'show'
100 should_route :get, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
100 should_route :get, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
101 should_route :post, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
101 should_route :post, "/projects/project-name/issues/gantt", :controller => 'gantts', :action => 'show', :project_id => 'project-name'
102
102
103 should_route :get, "/issues/auto_complete", :controller => 'auto_completes', :action => 'issues'
103 should_route :get, "/issues/auto_complete", :controller => 'auto_completes', :action => 'issues'
104
104
105 should_route :get, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
105 should_route :get, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
106 should_route :post, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
106 should_route :post, "/issues/preview/123", :controller => 'previews', :action => 'issue', :id => '123'
107 should_route :get, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
107 should_route :get, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
108 should_route :post, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
108 should_route :post, "/issues/context_menu", :controller => 'context_menus', :action => 'issues'
109
109
110 should_route :get, "/issues/changes", :controller => 'journals', :action => 'index'
110 should_route :get, "/issues/changes", :controller => 'journals', :action => 'index'
111
112 should_route :get, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_edit'
113 should_route :post, "/issues/bulk_edit", :controller => 'issues', :action => 'bulk_update'
111 end
114 end
112
115
113 context "issue categories" do
116 context "issue categories" do
114 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
117 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
115
118
116 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
119 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
117 end
120 end
118
121
119 context "issue relations" do
122 context "issue relations" do
120 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
123 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
121 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
124 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
122 end
125 end
123
126
124 context "issue reports" do
127 context "issue reports" do
125 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
128 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
126 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
129 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
127 end
130 end
128
131
129 context "members" do
132 context "members" do
130 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
133 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
131 end
134 end
132
135
133 context "messages" do
136 context "messages" do
134 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
137 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
135 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
138 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
136 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
139 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
137
140
138 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
141 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
139 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
142 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
140 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
143 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
141 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
144 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
142 end
145 end
143
146
144 context "news" do
147 context "news" do
145 should_route :get, "/news", :controller => 'news', :action => 'index'
148 should_route :get, "/news", :controller => 'news', :action => 'index'
146 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
149 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
147 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
150 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
148 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
151 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
149 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
152 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
150 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
153 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
151 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
154 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
152 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
155 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
153 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
156 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
154 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
157 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
155 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
158 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
156
159
157 should_route :post, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
160 should_route :post, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
158 should_route :post, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
161 should_route :post, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
159 should_route :post, "/news/567/destroy", :controller => 'news', :action => 'destroy', :id => '567'
162 should_route :post, "/news/567/destroy", :controller => 'news', :action => 'destroy', :id => '567'
160 end
163 end
161
164
162 context "projects" do
165 context "projects" do
163 should_route :get, "/projects", :controller => 'projects', :action => 'index'
166 should_route :get, "/projects", :controller => 'projects', :action => 'index'
164 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
167 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
165 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
168 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
166 should_route :get, "/projects/new", :controller => 'projects', :action => 'add'
169 should_route :get, "/projects/new", :controller => 'projects', :action => 'add'
167 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
170 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
168 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
171 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
169 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
172 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
170 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
173 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
171 should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567'
174 should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567'
172 should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33'
175 should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33'
173 should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
176 should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
174 should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33'
177 should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33'
175 should_route :get, "/projects/33/activity", :controller => 'projects', :action => 'activity', :id => '33'
178 should_route :get, "/projects/33/activity", :controller => 'projects', :action => 'activity', :id => '33'
176 should_route :get, "/projects/33/activity.atom", :controller => 'projects', :action => 'activity', :id => '33', :format => 'atom'
179 should_route :get, "/projects/33/activity.atom", :controller => 'projects', :action => 'activity', :id => '33', :format => 'atom'
177
180
178 should_route :post, "/projects/new", :controller => 'projects', :action => 'add'
181 should_route :post, "/projects/new", :controller => 'projects', :action => 'add'
179 should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml'
182 should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml'
180 should_route :post, "/projects/4223/edit", :controller => 'projects', :action => 'edit', :id => '4223'
183 should_route :post, "/projects/4223/edit", :controller => 'projects', :action => 'edit', :id => '4223'
181 should_route :post, "/projects/64/destroy", :controller => 'projects', :action => 'destroy', :id => '64'
184 should_route :post, "/projects/64/destroy", :controller => 'projects', :action => 'destroy', :id => '64'
182 should_route :post, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
185 should_route :post, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
183 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
186 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
184 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
187 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
185 should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64'
188 should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64'
186
189
187 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml'
190 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml'
188
191
189 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
192 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
190 should_route :delete, "/projects/64/reset_activities", :controller => 'projects', :action => 'reset_activities', :id => '64'
193 should_route :delete, "/projects/64/reset_activities", :controller => 'projects', :action => 'reset_activities', :id => '64'
191 end
194 end
192
195
193 context "repositories" do
196 context "repositories" do
194 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
197 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
195 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
198 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
196 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
199 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
197 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
200 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
198 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
201 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
199 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
202 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
200 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
203 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
201 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
204 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
202 should_route :get, "/projects/redmine/repository/revisions/2/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
205 should_route :get, "/projects/redmine/repository/revisions/2/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
203 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
206 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
204 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
207 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
205 should_route :get, "/projects/redmine/repository/revisions/2/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
208 should_route :get, "/projects/redmine/repository/revisions/2/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2'
206 should_route :get, "/projects/redmine/repository/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :format => 'raw'
209 should_route :get, "/projects/redmine/repository/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :format => 'raw'
207 should_route :get, "/projects/redmine/repository/revisions/2/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2', :format => 'raw'
210 should_route :get, "/projects/redmine/repository/revisions/2/raw/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c], :rev => '2', :format => 'raw'
208 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
211 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
209 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
212 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
210 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
213 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
211
214
212
215
213 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
216 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
214 end
217 end
215
218
216 context "timelogs" do
219 context "timelogs" do
217 should_route :get, "/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :issue_id => '567'
220 should_route :get, "/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :issue_id => '567'
218 should_route :get, "/projects/ecookbook/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook'
221 should_route :get, "/projects/ecookbook/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook'
219 should_route :get, "/projects/ecookbook/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook', :issue_id => '567'
222 should_route :get, "/projects/ecookbook/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook', :issue_id => '567'
220 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
223 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
221 should_route :get, "/time_entries/report", :controller => 'timelog', :action => 'report'
224 should_route :get, "/time_entries/report", :controller => 'timelog', :action => 'report'
222 should_route :get, "/projects/567/time_entries/report", :controller => 'timelog', :action => 'report', :project_id => '567'
225 should_route :get, "/projects/567/time_entries/report", :controller => 'timelog', :action => 'report', :project_id => '567'
223 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'timelog', :action => 'report', :project_id => '567', :format => 'csv'
226 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'timelog', :action => 'report', :project_id => '567', :format => 'csv'
224 should_route :get, "/time_entries", :controller => 'timelog', :action => 'details'
227 should_route :get, "/time_entries", :controller => 'timelog', :action => 'details'
225 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'details', :format => 'csv'
228 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'details', :format => 'csv'
226 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'details', :format => 'atom'
229 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'details', :format => 'atom'
227 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'details', :project_id => '567'
230 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'details', :project_id => '567'
228 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'csv'
231 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'csv'
229 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'atom'
232 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'atom'
230 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'details', :issue_id => '234'
233 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'details', :issue_id => '234'
231 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'csv'
234 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'csv'
232 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'atom'
235 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'atom'
233 should_route :get, "/projects/ecookbook/issues/123/time_entries", :controller => 'timelog', :action => 'details', :project_id => 'ecookbook', :issue_id => '123'
236 should_route :get, "/projects/ecookbook/issues/123/time_entries", :controller => 'timelog', :action => 'details', :project_id => 'ecookbook', :issue_id => '123'
234
237
235 should_route :post, "/time_entries/55/destroy", :controller => 'timelog', :action => 'destroy', :id => '55'
238 should_route :post, "/time_entries/55/destroy", :controller => 'timelog', :action => 'destroy', :id => '55'
236 end
239 end
237
240
238 context "users" do
241 context "users" do
239 should_route :get, "/users", :controller => 'users', :action => 'index'
242 should_route :get, "/users", :controller => 'users', :action => 'index'
240 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
243 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
241 should_route :get, "/users/new", :controller => 'users', :action => 'add'
244 should_route :get, "/users/new", :controller => 'users', :action => 'add'
242 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
245 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
243 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
246 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
244
247
245 should_route :post, "/users/new", :controller => 'users', :action => 'add'
248 should_route :post, "/users/new", :controller => 'users', :action => 'add'
246 should_route :post, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
249 should_route :post, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
247 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
250 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
248 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
251 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
249 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
252 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
250 end
253 end
251
254
252 context "versions" do
255 context "versions" do
253 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
256 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
254
257
255 should_route :post, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
258 should_route :post, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
256 end
259 end
257
260
258 context "wiki (singular, project's pages)" do
261 context "wiki (singular, project's pages)" do
259 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :id => '567'
262 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :id => '567'
260 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :id => '567', :page => 'lalala'
263 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :id => '567', :page => 'lalala'
261 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
264 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
262 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :id => '1', :page => 'CookBook_documentation'
265 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :id => '1', :page => 'CookBook_documentation'
263 should_route :get, "/projects/1/wiki/CookBook_documentation/diff/2/vs/1", :controller => 'wiki', :action => 'diff', :id => '1', :page => 'CookBook_documentation', :version => '2', :version_from => '1'
266 should_route :get, "/projects/1/wiki/CookBook_documentation/diff/2/vs/1", :controller => 'wiki', :action => 'diff', :id => '1', :page => 'CookBook_documentation', :version => '2', :version_from => '1'
264 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :id => '1', :page => 'CookBook_documentation', :version => '2'
267 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :id => '1', :page => 'CookBook_documentation', :version => '2'
265 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
268 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
266 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'page_index'
269 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'page_index'
267 should_route :get, "/projects/567/wiki/Page_Index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'Page_Index'
270 should_route :get, "/projects/567/wiki/Page_Index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'Page_Index'
268 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'date_index'
271 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'date_index'
269 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'special', :id => '567', :page => 'export'
272 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'special', :id => '567', :page => 'export'
270
273
271 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
274 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
272 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :id => '567', :page => 'CookBook_documentation'
275 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :id => '567', :page => 'CookBook_documentation'
273 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
276 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
274 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :id => '22', :page => 'ladida'
277 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :id => '22', :page => 'ladida'
275 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :id => '22', :page => 'ladida'
278 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :id => '22', :page => 'ladida'
276 end
279 end
277
280
278 context "wikis (plural, admin setup)" do
281 context "wikis (plural, admin setup)" do
279 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
282 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
280
283
281 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
284 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
282 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
285 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
283 end
286 end
284
287
285 context "administration panel" do
288 context "administration panel" do
286 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
289 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
287 end
290 end
288 end
291 end
General Comments 0
You need to be logged in to leave comments. Login now