##// END OF EJS Templates
Refactor: Split IssuesController#new to #new and #create to match REST pattern....
Eric Davis -
r3574:2c898d8a817e
parent child
Show More
@@ -1,580 +1,601
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
19 menu_item :new_issue, :only => :new
20 default_search_scope :issues
20 default_search_scope :issues
21
21
22 before_filter :find_issue, :only => [:show, :edit, :update, :reply]
22 before_filter :find_issue, :only => [:show, :edit, :update, :reply]
23 before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
23 before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
24 before_filter :find_project, :only => [:new, :update_form, :preview, :auto_complete]
24 before_filter :find_project, :only => [:new, :create, :update_form, :preview, :auto_complete]
25 before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :context_menu]
25 before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :context_menu]
26 before_filter :find_optional_project, :only => [:index, :changes, :gantt, :calendar]
26 before_filter :find_optional_project, :only => [:index, :changes, :gantt, :calendar]
27 accept_key_auth :index, :show, :changes
27 accept_key_auth :index, :show, :changes
28
28
29 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
29 rescue_from Query::StatementInvalid, :with => :query_statement_invalid
30
30
31 helper :journals
31 helper :journals
32 helper :projects
32 helper :projects
33 include ProjectsHelper
33 include ProjectsHelper
34 helper :custom_fields
34 helper :custom_fields
35 include CustomFieldsHelper
35 include CustomFieldsHelper
36 helper :issue_relations
36 helper :issue_relations
37 include IssueRelationsHelper
37 include IssueRelationsHelper
38 helper :watchers
38 helper :watchers
39 include WatchersHelper
39 include WatchersHelper
40 helper :attachments
40 helper :attachments
41 include AttachmentsHelper
41 include AttachmentsHelper
42 helper :queries
42 helper :queries
43 include QueriesHelper
43 include QueriesHelper
44 helper :sort
44 helper :sort
45 include SortHelper
45 include SortHelper
46 include IssuesHelper
46 include IssuesHelper
47 helper :timelog
47 helper :timelog
48 include Redmine::Export::PDF
48 include Redmine::Export::PDF
49
49
50 verify :method => [:post, :delete],
50 verify :method => [:post, :delete],
51 :only => :destroy,
51 :only => :destroy,
52 :render => { :nothing => true, :status => :method_not_allowed }
52 :render => { :nothing => true, :status => :method_not_allowed }
53
53
54 verify :method => :post, :only => :create, :render => {:nothing => true, :status => :method_not_allowed }
54 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
55 verify :method => :put, :only => :update, :render => {:nothing => true, :status => :method_not_allowed }
55
56
56 def index
57 def index
57 retrieve_query
58 retrieve_query
58 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
59 sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria)
59 sort_update(@query.sortable_columns)
60 sort_update(@query.sortable_columns)
60
61
61 if @query.valid?
62 if @query.valid?
62 limit = case params[:format]
63 limit = case params[:format]
63 when 'csv', 'pdf'
64 when 'csv', 'pdf'
64 Setting.issues_export_limit.to_i
65 Setting.issues_export_limit.to_i
65 when 'atom'
66 when 'atom'
66 Setting.feeds_limit.to_i
67 Setting.feeds_limit.to_i
67 else
68 else
68 per_page_option
69 per_page_option
69 end
70 end
70
71
71 @issue_count = @query.issue_count
72 @issue_count = @query.issue_count
72 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
73 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
73 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
74 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
74 :order => sort_clause,
75 :order => sort_clause,
75 :offset => @issue_pages.current.offset,
76 :offset => @issue_pages.current.offset,
76 :limit => limit)
77 :limit => limit)
77 @issue_count_by_group = @query.issue_count_by_group
78 @issue_count_by_group = @query.issue_count_by_group
78
79
79 respond_to do |format|
80 respond_to do |format|
80 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
81 format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
81 format.xml { render :layout => false }
82 format.xml { render :layout => false }
82 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
83 format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
83 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
84 format.csv { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
84 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
85 format.pdf { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
85 end
86 end
86 else
87 else
87 # Send html if the query is not valid
88 # Send html if the query is not valid
88 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
89 render(:template => 'issues/index.rhtml', :layout => !request.xhr?)
89 end
90 end
90 rescue ActiveRecord::RecordNotFound
91 rescue ActiveRecord::RecordNotFound
91 render_404
92 render_404
92 end
93 end
93
94
94 def changes
95 def changes
95 retrieve_query
96 retrieve_query
96 sort_init 'id', 'desc'
97 sort_init 'id', 'desc'
97 sort_update(@query.sortable_columns)
98 sort_update(@query.sortable_columns)
98
99
99 if @query.valid?
100 if @query.valid?
100 @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
101 @journals = @query.journals(:order => "#{Journal.table_name}.created_on DESC",
101 :limit => 25)
102 :limit => 25)
102 end
103 end
103 @title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
104 @title = (@project ? @project.name : Setting.app_title) + ": " + (@query.new_record? ? l(:label_changes_details) : @query.name)
104 render :layout => false, :content_type => 'application/atom+xml'
105 render :layout => false, :content_type => 'application/atom+xml'
105 rescue ActiveRecord::RecordNotFound
106 rescue ActiveRecord::RecordNotFound
106 render_404
107 render_404
107 end
108 end
108
109
109 def show
110 def show
110 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
111 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
111 @journals.each_with_index {|j,i| j.indice = i+1}
112 @journals.each_with_index {|j,i| j.indice = i+1}
112 @journals.reverse! if User.current.wants_comments_in_reverse_order?
113 @journals.reverse! if User.current.wants_comments_in_reverse_order?
113 @changesets = @issue.changesets.visible.all
114 @changesets = @issue.changesets.visible.all
114 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
115 @changesets.reverse! if User.current.wants_comments_in_reverse_order?
115 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
116 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
116 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
117 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
117 @priorities = IssuePriority.all
118 @priorities = IssuePriority.all
118 @time_entry = TimeEntry.new
119 @time_entry = TimeEntry.new
119 respond_to do |format|
120 respond_to do |format|
120 format.html { render :template => 'issues/show.rhtml' }
121 format.html { render :template => 'issues/show.rhtml' }
121 format.xml { render :layout => false }
122 format.xml { render :layout => false }
122 format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
123 format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
123 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
124 format.pdf { send_data(issue_to_pdf(@issue), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
124 end
125 end
125 end
126 end
126
127
127 # Add a new issue
128 # Add a new issue
128 # The new issue will be created from an existing one if copy_from parameter is given
129 # The new issue will be created from an existing one if copy_from parameter is given
129 def new
130 def new
130 @issue = Issue.new
131 @issue = Issue.new
131 @issue.copy_from(params[:copy_from]) if params[:copy_from]
132 @issue.copy_from(params[:copy_from]) if params[:copy_from]
132 @issue.project = @project
133 @issue.project = @project
133 # Tracker must be set before custom field values
134 # Tracker must be set before custom field values
134 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
135 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
135 if @issue.tracker.nil?
136 if @issue.tracker.nil?
136 render_error l(:error_no_tracker_in_project)
137 render_error l(:error_no_tracker_in_project)
137 return
138 return
138 end
139 end
139 if @issue.status.nil?
140 if @issue.status.nil?
140 render_error l(:error_no_default_issue_status)
141 render_error l(:error_no_default_issue_status)
141 return
142 return
142 end
143 end
143 if params[:issue].is_a?(Hash)
144 if params[:issue].is_a?(Hash)
144 @issue.safe_attributes = params[:issue]
145 @issue.safe_attributes = params[:issue]
145 @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
146 @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
146 end
147 end
147 @issue.author = User.current
148 @issue.author = User.current
148
149 @issue.start_date ||= Date.today
149 if request.get? || request.xhr?
150 @priorities = IssuePriority.all
150 @issue.start_date ||= Date.today
151 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
151 else
152 render :action => 'new', :layout => !request.xhr?
152 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
153 end
153 if @issue.save
154
154 attachments = Attachment.attach_files(@issue, params[:attachments])
155 def create
155 render_attachment_warning_if_needed(@issue)
156 @issue = Issue.new
156 flash[:notice] = l(:notice_successful_create)
157 @issue.copy_from(params[:copy_from]) if params[:copy_from]
157 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
158 @issue.project = @project
158 respond_to do |format|
159 # Tracker must be set before custom field values
159 format.html {
160 @issue.tracker ||= @project.trackers.find((params[:issue] && params[:issue][:tracker_id]) || params[:tracker_id] || :first)
160 redirect_to(params[:continue] ? { :action => 'new', :issue => {:tracker_id => @issue.tracker,
161 if @issue.tracker.nil?
161 :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
162 render_error l(:error_no_tracker_in_project)
162 { :action => 'show', :id => @issue })
163 return
163 }
164 end
164 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
165 if @issue.status.nil?
165 end
166 render_error l(:error_no_default_issue_status)
166 return
167 return
167 else
168 end
168 respond_to do |format|
169 if params[:issue].is_a?(Hash)
169 format.html { }
170 @issue.safe_attributes = params[:issue]
170 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
171 @issue.watcher_user_ids = params[:issue]['watcher_user_ids'] if User.current.allowed_to?(:add_issue_watchers, @project)
171 end
172 end
172 end
173 @issue.author = User.current
173 end
174
174 @priorities = IssuePriority.all
175 @priorities = IssuePriority.all
175 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
176 @allowed_statuses = @issue.new_statuses_allowed_to(User.current, true)
176 render :layout => !request.xhr?
177
178 call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
179 if @issue.save
180 attachments = Attachment.attach_files(@issue, params[:attachments])
181 render_attachment_warning_if_needed(@issue)
182 flash[:notice] = l(:notice_successful_create)
183 call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
184 respond_to do |format|
185 format.html {
186 redirect_to(params[:continue] ? { :action => 'new', :issue => {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} } :
187 { :action => 'show', :id => @issue })
188 }
189 format.xml { render :action => 'show', :status => :created, :location => url_for(:controller => 'issues', :action => 'show', :id => @issue) }
190 end
191 return
192 else
193 respond_to do |format|
194 format.html { render :action => 'new' }
195 format.xml { render(:xml => @issue.errors, :status => :unprocessable_entity); return }
196 end
197 end
177 end
198 end
178
199
179 # Attributes that can be updated on workflow transition (without :edit permission)
200 # Attributes that can be updated on workflow transition (without :edit permission)
180 # TODO: make it configurable (at least per role)
201 # TODO: make it configurable (at least per role)
181 UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
202 UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
182
203
183 def edit
204 def edit
184 update_issue_from_params
205 update_issue_from_params
185
206
186 @journal = @issue.current_journal
207 @journal = @issue.current_journal
187
208
188 respond_to do |format|
209 respond_to do |format|
189 format.html { }
210 format.html { }
190 format.xml { }
211 format.xml { }
191 end
212 end
192 end
213 end
193
214
194 def update
215 def update
195 update_issue_from_params
216 update_issue_from_params
196
217
197 if @issue.save_issue_with_child_records(params, @time_entry)
218 if @issue.save_issue_with_child_records(params, @time_entry)
198 render_attachment_warning_if_needed(@issue)
219 render_attachment_warning_if_needed(@issue)
199 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
220 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
200
221
201 respond_to do |format|
222 respond_to do |format|
202 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
223 format.html { redirect_back_or_default({:action => 'show', :id => @issue}) }
203 format.xml { head :ok }
224 format.xml { head :ok }
204 end
225 end
205 else
226 else
206 render_attachment_warning_if_needed(@issue)
227 render_attachment_warning_if_needed(@issue)
207 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
228 flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record?
208 @journal = @issue.current_journal
229 @journal = @issue.current_journal
209
230
210 respond_to do |format|
231 respond_to do |format|
211 format.html { render :action => 'edit' }
232 format.html { render :action => 'edit' }
212 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
233 format.xml { render :xml => @issue.errors, :status => :unprocessable_entity }
213 end
234 end
214 end
235 end
215 end
236 end
216
237
217 def reply
238 def reply
218 journal = Journal.find(params[:journal_id]) if params[:journal_id]
239 journal = Journal.find(params[:journal_id]) if params[:journal_id]
219 if journal
240 if journal
220 user = journal.user
241 user = journal.user
221 text = journal.notes
242 text = journal.notes
222 else
243 else
223 user = @issue.author
244 user = @issue.author
224 text = @issue.description
245 text = @issue.description
225 end
246 end
226 # Replaces pre blocks with [...]
247 # Replaces pre blocks with [...]
227 text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
248 text = text.to_s.strip.gsub(%r{<pre>((.|\s)*?)</pre>}m, '[...]')
228 content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
249 content = "#{ll(Setting.default_language, :text_user_wrote, user)}\n> "
229 content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
250 content << text.gsub(/(\r?\n|\r\n?)/, "\n> ") + "\n\n"
230
251
231 render(:update) { |page|
252 render(:update) { |page|
232 page.<< "$('notes').value = \"#{escape_javascript content}\";"
253 page.<< "$('notes').value = \"#{escape_javascript content}\";"
233 page.show 'update'
254 page.show 'update'
234 page << "Form.Element.focus('notes');"
255 page << "Form.Element.focus('notes');"
235 page << "Element.scrollTo('update');"
256 page << "Element.scrollTo('update');"
236 page << "$('notes').scrollTop = $('notes').scrollHeight - $('notes').clientHeight;"
257 page << "$('notes').scrollTop = $('notes').scrollHeight - $('notes').clientHeight;"
237 }
258 }
238 end
259 end
239
260
240 # Bulk edit a set of issues
261 # Bulk edit a set of issues
241 def bulk_edit
262 def bulk_edit
242 @issues.sort!
263 @issues.sort!
243 if request.post?
264 if request.post?
244 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
265 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
245 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
266 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
246 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
267 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
247
268
248 unsaved_issue_ids = []
269 unsaved_issue_ids = []
249 @issues.each do |issue|
270 @issues.each do |issue|
250 issue.reload
271 issue.reload
251 journal = issue.init_journal(User.current, params[:notes])
272 journal = issue.init_journal(User.current, params[:notes])
252 issue.safe_attributes = attributes
273 issue.safe_attributes = attributes
253 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
274 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
254 unless issue.save
275 unless issue.save
255 # Keep unsaved issue ids to display them in flash error
276 # Keep unsaved issue ids to display them in flash error
256 unsaved_issue_ids << issue.id
277 unsaved_issue_ids << issue.id
257 end
278 end
258 end
279 end
259 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
280 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
260 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
281 redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project})
261 return
282 return
262 end
283 end
263 @available_statuses = Workflow.available_statuses(@project)
284 @available_statuses = Workflow.available_statuses(@project)
264 @custom_fields = @project.all_issue_custom_fields
285 @custom_fields = @project.all_issue_custom_fields
265 end
286 end
266
287
267 def move
288 def move
268 @issues.sort!
289 @issues.sort!
269 @copy = params[:copy_options] && params[:copy_options][:copy]
290 @copy = params[:copy_options] && params[:copy_options][:copy]
270 @allowed_projects = Issue.allowed_target_projects_on_move
291 @allowed_projects = Issue.allowed_target_projects_on_move
271 @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
292 @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:new_project_id]} if params[:new_project_id]
272 @target_project ||= @project
293 @target_project ||= @project
273 @trackers = @target_project.trackers
294 @trackers = @target_project.trackers
274 @available_statuses = Workflow.available_statuses(@project)
295 @available_statuses = Workflow.available_statuses(@project)
275 if request.post?
296 if request.post?
276 new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id])
297 new_tracker = params[:new_tracker_id].blank? ? nil : @target_project.trackers.find_by_id(params[:new_tracker_id])
277 unsaved_issue_ids = []
298 unsaved_issue_ids = []
278 moved_issues = []
299 moved_issues = []
279 @issues.each do |issue|
300 @issues.each do |issue|
280 issue.reload
301 issue.reload
281 changed_attributes = {}
302 changed_attributes = {}
282 [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute|
303 [:assigned_to_id, :status_id, :start_date, :due_date].each do |valid_attribute|
283 unless params[valid_attribute].blank?
304 unless params[valid_attribute].blank?
284 changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute])
305 changed_attributes[valid_attribute] = (params[valid_attribute] == 'none' ? nil : params[valid_attribute])
285 end
306 end
286 end
307 end
287 issue.init_journal(User.current)
308 issue.init_journal(User.current)
288 call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy })
309 call_hook(:controller_issues_move_before_save, { :params => params, :issue => issue, :target_project => @target_project, :copy => !!@copy })
289 if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => changed_attributes})
310 if r = issue.move_to_project(@target_project, new_tracker, {:copy => @copy, :attributes => changed_attributes})
290 moved_issues << r
311 moved_issues << r
291 else
312 else
292 unsaved_issue_ids << issue.id
313 unsaved_issue_ids << issue.id
293 end
314 end
294 end
315 end
295 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
316 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
296
317
297 if params[:follow]
318 if params[:follow]
298 if @issues.size == 1 && moved_issues.size == 1
319 if @issues.size == 1 && moved_issues.size == 1
299 redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first
320 redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first
300 else
321 else
301 redirect_to :controller => 'issues', :action => 'index', :project_id => (@target_project || @project)
322 redirect_to :controller => 'issues', :action => 'index', :project_id => (@target_project || @project)
302 end
323 end
303 else
324 else
304 redirect_to :controller => 'issues', :action => 'index', :project_id => @project
325 redirect_to :controller => 'issues', :action => 'index', :project_id => @project
305 end
326 end
306 return
327 return
307 end
328 end
308 render :layout => false if request.xhr?
329 render :layout => false if request.xhr?
309 end
330 end
310
331
311 def destroy
332 def destroy
312 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
333 @hours = TimeEntry.sum(:hours, :conditions => ['issue_id IN (?)', @issues]).to_f
313 if @hours > 0
334 if @hours > 0
314 case params[:todo]
335 case params[:todo]
315 when 'destroy'
336 when 'destroy'
316 # nothing to do
337 # nothing to do
317 when 'nullify'
338 when 'nullify'
318 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
339 TimeEntry.update_all('issue_id = NULL', ['issue_id IN (?)', @issues])
319 when 'reassign'
340 when 'reassign'
320 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
341 reassign_to = @project.issues.find_by_id(params[:reassign_to_id])
321 if reassign_to.nil?
342 if reassign_to.nil?
322 flash.now[:error] = l(:error_issue_not_found_in_project)
343 flash.now[:error] = l(:error_issue_not_found_in_project)
323 return
344 return
324 else
345 else
325 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
346 TimeEntry.update_all("issue_id = #{reassign_to.id}", ['issue_id IN (?)', @issues])
326 end
347 end
327 else
348 else
328 unless params[:format] == 'xml'
349 unless params[:format] == 'xml'
329 # display the destroy form if it's a user request
350 # display the destroy form if it's a user request
330 return
351 return
331 end
352 end
332 end
353 end
333 end
354 end
334 @issues.each(&:destroy)
355 @issues.each(&:destroy)
335 respond_to do |format|
356 respond_to do |format|
336 format.html { redirect_to :action => 'index', :project_id => @project }
357 format.html { redirect_to :action => 'index', :project_id => @project }
337 format.xml { head :ok }
358 format.xml { head :ok }
338 end
359 end
339 end
360 end
340
361
341 def gantt
362 def gantt
342 @gantt = Redmine::Helpers::Gantt.new(params)
363 @gantt = Redmine::Helpers::Gantt.new(params)
343 retrieve_query
364 retrieve_query
344 @query.group_by = nil
365 @query.group_by = nil
345 if @query.valid?
366 if @query.valid?
346 events = []
367 events = []
347 # Issues that have start and due dates
368 # Issues that have start and due dates
348 events += @query.issues(:include => [:tracker, :assigned_to, :priority],
369 events += @query.issues(:include => [:tracker, :assigned_to, :priority],
349 :order => "start_date, due_date",
370 :order => "start_date, due_date",
350 :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to]
371 :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to]
351 )
372 )
352 # Issues that don't have a due date but that are assigned to a version with a date
373 # Issues that don't have a due date but that are assigned to a version with a date
353 events += @query.issues(:include => [:tracker, :assigned_to, :priority, :fixed_version],
374 events += @query.issues(:include => [:tracker, :assigned_to, :priority, :fixed_version],
354 :order => "start_date, effective_date",
375 :order => "start_date, effective_date",
355 :conditions => ["(((start_date>=? and start_date<=?) or (effective_date>=? and effective_date<=?) or (start_date<? and effective_date>?)) and start_date is not null and due_date is null and effective_date is not null)", @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to]
376 :conditions => ["(((start_date>=? and start_date<=?) or (effective_date>=? and effective_date<=?) or (start_date<? and effective_date>?)) and start_date is not null and due_date is null and effective_date is not null)", @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to, @gantt.date_from, @gantt.date_to]
356 )
377 )
357 # Versions
378 # Versions
358 events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @gantt.date_from, @gantt.date_to])
379 events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @gantt.date_from, @gantt.date_to])
359
380
360 @gantt.events = events
381 @gantt.events = events
361 end
382 end
362
383
363 basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
384 basename = (@project ? "#{@project.identifier}-" : '') + 'gantt'
364
385
365 respond_to do |format|
386 respond_to do |format|
366 format.html { render :template => "issues/gantt.rhtml", :layout => !request.xhr? }
387 format.html { render :template => "issues/gantt.rhtml", :layout => !request.xhr? }
367 format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image')
388 format.png { send_data(@gantt.to_image, :disposition => 'inline', :type => 'image/png', :filename => "#{basename}.png") } if @gantt.respond_to?('to_image')
368 format.pdf { send_data(gantt_to_pdf(@gantt, @project), :type => 'application/pdf', :filename => "#{basename}.pdf") }
389 format.pdf { send_data(gantt_to_pdf(@gantt, @project), :type => 'application/pdf', :filename => "#{basename}.pdf") }
369 end
390 end
370 end
391 end
371
392
372 def calendar
393 def calendar
373 if params[:year] and params[:year].to_i > 1900
394 if params[:year] and params[:year].to_i > 1900
374 @year = params[:year].to_i
395 @year = params[:year].to_i
375 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
396 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
376 @month = params[:month].to_i
397 @month = params[:month].to_i
377 end
398 end
378 end
399 end
379 @year ||= Date.today.year
400 @year ||= Date.today.year
380 @month ||= Date.today.month
401 @month ||= Date.today.month
381
402
382 @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
403 @calendar = Redmine::Helpers::Calendar.new(Date.civil(@year, @month, 1), current_language, :month)
383 retrieve_query
404 retrieve_query
384 @query.group_by = nil
405 @query.group_by = nil
385 if @query.valid?
406 if @query.valid?
386 events = []
407 events = []
387 events += @query.issues(:include => [:tracker, :assigned_to, :priority],
408 events += @query.issues(:include => [:tracker, :assigned_to, :priority],
388 :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
409 :conditions => ["((start_date BETWEEN ? AND ?) OR (due_date BETWEEN ? AND ?))", @calendar.startdt, @calendar.enddt, @calendar.startdt, @calendar.enddt]
389 )
410 )
390 events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
411 events += @query.versions(:conditions => ["effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
391
412
392 @calendar.events = events
413 @calendar.events = events
393 end
414 end
394
415
395 render :layout => false if request.xhr?
416 render :layout => false if request.xhr?
396 end
417 end
397
418
398 def context_menu
419 def context_menu
399 @issues = Issue.find_all_by_id(params[:ids], :include => :project)
420 @issues = Issue.find_all_by_id(params[:ids], :include => :project)
400 if (@issues.size == 1)
421 if (@issues.size == 1)
401 @issue = @issues.first
422 @issue = @issues.first
402 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
423 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
403 end
424 end
404 projects = @issues.collect(&:project).compact.uniq
425 projects = @issues.collect(&:project).compact.uniq
405 @project = projects.first if projects.size == 1
426 @project = projects.first if projects.size == 1
406
427
407 @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)),
428 @can = {:edit => (@project && User.current.allowed_to?(:edit_issues, @project)),
408 :log_time => (@project && User.current.allowed_to?(:log_time, @project)),
429 :log_time => (@project && User.current.allowed_to?(:log_time, @project)),
409 :update => (@project && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && @allowed_statuses && !@allowed_statuses.empty?))),
430 :update => (@project && (User.current.allowed_to?(:edit_issues, @project) || (User.current.allowed_to?(:change_status, @project) && @allowed_statuses && !@allowed_statuses.empty?))),
410 :move => (@project && User.current.allowed_to?(:move_issues, @project)),
431 :move => (@project && User.current.allowed_to?(:move_issues, @project)),
411 :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
432 :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)),
412 :delete => (@project && User.current.allowed_to?(:delete_issues, @project))
433 :delete => (@project && User.current.allowed_to?(:delete_issues, @project))
413 }
434 }
414 if @project
435 if @project
415 @assignables = @project.assignable_users
436 @assignables = @project.assignable_users
416 @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to)
437 @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to)
417 @trackers = @project.trackers
438 @trackers = @project.trackers
418 end
439 end
419
440
420 @priorities = IssuePriority.all.reverse
441 @priorities = IssuePriority.all.reverse
421 @statuses = IssueStatus.find(:all, :order => 'position')
442 @statuses = IssueStatus.find(:all, :order => 'position')
422 @back = params[:back_url] || request.env['HTTP_REFERER']
443 @back = params[:back_url] || request.env['HTTP_REFERER']
423
444
424 render :layout => false
445 render :layout => false
425 end
446 end
426
447
427 def update_form
448 def update_form
428 if params[:id].blank?
449 if params[:id].blank?
429 @issue = Issue.new
450 @issue = Issue.new
430 @issue.project = @project
451 @issue.project = @project
431 else
452 else
432 @issue = @project.issues.visible.find(params[:id])
453 @issue = @project.issues.visible.find(params[:id])
433 end
454 end
434 @issue.attributes = params[:issue]
455 @issue.attributes = params[:issue]
435 @allowed_statuses = ([@issue.status] + @issue.status.find_new_statuses_allowed_to(User.current.roles_for_project(@project), @issue.tracker)).uniq
456 @allowed_statuses = ([@issue.status] + @issue.status.find_new_statuses_allowed_to(User.current.roles_for_project(@project), @issue.tracker)).uniq
436 @priorities = IssuePriority.all
457 @priorities = IssuePriority.all
437
458
438 render :partial => 'attributes'
459 render :partial => 'attributes'
439 end
460 end
440
461
441 def preview
462 def preview
442 @issue = @project.issues.find_by_id(params[:id]) unless params[:id].blank?
463 @issue = @project.issues.find_by_id(params[:id]) unless params[:id].blank?
443 if @issue
464 if @issue
444 @attachements = @issue.attachments
465 @attachements = @issue.attachments
445 @description = params[:issue] && params[:issue][:description]
466 @description = params[:issue] && params[:issue][:description]
446 if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n")
467 if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n")
447 @description = nil
468 @description = nil
448 end
469 end
449 @notes = params[:notes]
470 @notes = params[:notes]
450 else
471 else
451 @description = (params[:issue] ? params[:issue][:description] : nil)
472 @description = (params[:issue] ? params[:issue][:description] : nil)
452 end
473 end
453 render :layout => false
474 render :layout => false
454 end
475 end
455
476
456 def auto_complete
477 def auto_complete
457 @issues = []
478 @issues = []
458 q = params[:q].to_s
479 q = params[:q].to_s
459 if q.match(/^\d+$/)
480 if q.match(/^\d+$/)
460 @issues << @project.issues.visible.find_by_id(q.to_i)
481 @issues << @project.issues.visible.find_by_id(q.to_i)
461 end
482 end
462 unless q.blank?
483 unless q.blank?
463 @issues += @project.issues.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
484 @issues += @project.issues.visible.find(:all, :conditions => ["LOWER(#{Issue.table_name}.subject) LIKE ?", "%#{q.downcase}%"], :limit => 10)
464 end
485 end
465 render :layout => false
486 render :layout => false
466 end
487 end
467
488
468 private
489 private
469 def find_issue
490 def find_issue
470 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
491 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
471 @project = @issue.project
492 @project = @issue.project
472 rescue ActiveRecord::RecordNotFound
493 rescue ActiveRecord::RecordNotFound
473 render_404
494 render_404
474 end
495 end
475
496
476 # Filter for bulk operations
497 # Filter for bulk operations
477 def find_issues
498 def find_issues
478 @issues = Issue.find_all_by_id(params[:id] || params[:ids])
499 @issues = Issue.find_all_by_id(params[:id] || params[:ids])
479 raise ActiveRecord::RecordNotFound if @issues.empty?
500 raise ActiveRecord::RecordNotFound if @issues.empty?
480 projects = @issues.collect(&:project).compact.uniq
501 projects = @issues.collect(&:project).compact.uniq
481 if projects.size == 1
502 if projects.size == 1
482 @project = projects.first
503 @project = projects.first
483 else
504 else
484 # TODO: let users bulk edit/move/destroy issues from different projects
505 # TODO: let users bulk edit/move/destroy issues from different projects
485 render_error 'Can not bulk edit/move/destroy issues from different projects'
506 render_error 'Can not bulk edit/move/destroy issues from different projects'
486 return false
507 return false
487 end
508 end
488 rescue ActiveRecord::RecordNotFound
509 rescue ActiveRecord::RecordNotFound
489 render_404
510 render_404
490 end
511 end
491
512
492 def find_project
513 def find_project
493 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
514 project_id = (params[:issue] && params[:issue][:project_id]) || params[:project_id]
494 @project = Project.find(project_id)
515 @project = Project.find(project_id)
495 rescue ActiveRecord::RecordNotFound
516 rescue ActiveRecord::RecordNotFound
496 render_404
517 render_404
497 end
518 end
498
519
499 def find_optional_project
520 def find_optional_project
500 @project = Project.find(params[:project_id]) unless params[:project_id].blank?
521 @project = Project.find(params[:project_id]) unless params[:project_id].blank?
501 allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)
522 allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)
502 allowed ? true : deny_access
523 allowed ? true : deny_access
503 rescue ActiveRecord::RecordNotFound
524 rescue ActiveRecord::RecordNotFound
504 render_404
525 render_404
505 end
526 end
506
527
507 # Retrieve query from session or build a new query
528 # Retrieve query from session or build a new query
508 def retrieve_query
529 def retrieve_query
509 if !params[:query_id].blank?
530 if !params[:query_id].blank?
510 cond = "project_id IS NULL"
531 cond = "project_id IS NULL"
511 cond << " OR project_id = #{@project.id}" if @project
532 cond << " OR project_id = #{@project.id}" if @project
512 @query = Query.find(params[:query_id], :conditions => cond)
533 @query = Query.find(params[:query_id], :conditions => cond)
513 @query.project = @project
534 @query.project = @project
514 session[:query] = {:id => @query.id, :project_id => @query.project_id}
535 session[:query] = {:id => @query.id, :project_id => @query.project_id}
515 sort_clear
536 sort_clear
516 else
537 else
517 if api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
538 if api_request? || params[:set_filter] || session[:query].nil? || session[:query][:project_id] != (@project ? @project.id : nil)
518 # Give it a name, required to be valid
539 # Give it a name, required to be valid
519 @query = Query.new(:name => "_")
540 @query = Query.new(:name => "_")
520 @query.project = @project
541 @query.project = @project
521 if params[:fields] and params[:fields].is_a? Array
542 if params[:fields] and params[:fields].is_a? Array
522 params[:fields].each do |field|
543 params[:fields].each do |field|
523 @query.add_filter(field, params[:operators][field], params[:values][field])
544 @query.add_filter(field, params[:operators][field], params[:values][field])
524 end
545 end
525 else
546 else
526 @query.available_filters.keys.each do |field|
547 @query.available_filters.keys.each do |field|
527 @query.add_short_filter(field, params[field]) if params[field]
548 @query.add_short_filter(field, params[field]) if params[field]
528 end
549 end
529 end
550 end
530 @query.group_by = params[:group_by]
551 @query.group_by = params[:group_by]
531 @query.column_names = params[:query] && params[:query][:column_names]
552 @query.column_names = params[:query] && params[:query][:column_names]
532 session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
553 session[:query] = {:project_id => @query.project_id, :filters => @query.filters, :group_by => @query.group_by, :column_names => @query.column_names}
533 else
554 else
534 @query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
555 @query = Query.find_by_id(session[:query][:id]) if session[:query][:id]
535 @query ||= Query.new(:name => "_", :project => @project, :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
556 @query ||= Query.new(:name => "_", :project => @project, :filters => session[:query][:filters], :group_by => session[:query][:group_by], :column_names => session[:query][:column_names])
536 @query.project = @project
557 @query.project = @project
537 end
558 end
538 end
559 end
539 end
560 end
540
561
541 # Rescues an invalid query statement. Just in case...
562 # Rescues an invalid query statement. Just in case...
542 def query_statement_invalid(exception)
563 def query_statement_invalid(exception)
543 logger.error "Query::StatementInvalid: #{exception.message}" if logger
564 logger.error "Query::StatementInvalid: #{exception.message}" if logger
544 session.delete(:query)
565 session.delete(:query)
545 sort_clear
566 sort_clear
546 render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
567 render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator."
547 end
568 end
548
569
549 # Used by #edit and #update to set some common instance variables
570 # Used by #edit and #update to set some common instance variables
550 # from the params
571 # from the params
551 # TODO: Refactor, not everything in here is needed by #edit
572 # TODO: Refactor, not everything in here is needed by #edit
552 def update_issue_from_params
573 def update_issue_from_params
553 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
574 @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
554 @priorities = IssuePriority.all
575 @priorities = IssuePriority.all
555 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
576 @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
556 @time_entry = TimeEntry.new
577 @time_entry = TimeEntry.new
557
578
558 @notes = params[:notes]
579 @notes = params[:notes]
559 @issue.init_journal(User.current, @notes)
580 @issue.init_journal(User.current, @notes)
560 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
581 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
561 if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue]
582 if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue]
562 attrs = params[:issue].dup
583 attrs = params[:issue].dup
563 attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed
584 attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed
564 attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s}
585 attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s}
565 @issue.safe_attributes = attrs
586 @issue.safe_attributes = attrs
566 end
587 end
567
588
568 end
589 end
569
590
570 def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids)
591 def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids)
571 if unsaved_issue_ids.empty?
592 if unsaved_issue_ids.empty?
572 flash[:notice] = l(:notice_successful_update) unless issues.empty?
593 flash[:notice] = l(:notice_successful_update) unless issues.empty?
573 else
594 else
574 flash[:error] = l(:notice_failed_to_save_issues,
595 flash[:error] = l(:notice_failed_to_save_issues,
575 :count => unsaved_issue_ids.size,
596 :count => unsaved_issue_ids.size,
576 :total => issues.size,
597 :total => issues.size,
577 :ids => '#' + unsaved_issue_ids.join(', #'))
598 :ids => '#' + unsaved_issue_ids.join(', #'))
578 end
599 end
579 end
600 end
580 end
601 end
@@ -1,26 +1,26
1 <h2><%=l(:label_issue_new)%></h2>
1 <h2><%=l(:label_issue_new)%></h2>
2
2
3 <% labelled_tabular_form_for :issue, @issue,
3 <% labelled_tabular_form_for :issue, @issue, :url => {:controller => 'issues', :action => 'create', :project_id => @project},
4 :html => {:multipart => true, :id => 'issue-form'} do |f| %>
4 :html => {:multipart => true, :id => 'issue-form'} do |f| %>
5 <%= error_messages_for 'issue' %>
5 <%= error_messages_for 'issue' %>
6 <div class="box">
6 <div class="box">
7 <%= render :partial => 'issues/form', :locals => {:f => f} %>
7 <%= render :partial => 'issues/form', :locals => {:f => f} %>
8 </div>
8 </div>
9 <%= submit_tag l(:button_create) %>
9 <%= submit_tag l(:button_create) %>
10 <%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
10 <%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
11 <%= link_to_remote l(:label_preview),
11 <%= link_to_remote l(:label_preview),
12 { :url => { :controller => 'issues', :action => 'preview', :project_id => @project },
12 { :url => { :controller => 'issues', :action => 'preview', :project_id => @project },
13 :method => 'post',
13 :method => 'post',
14 :update => 'preview',
14 :update => 'preview',
15 :with => "Form.serialize('issue-form')",
15 :with => "Form.serialize('issue-form')",
16 :complete => "Element.scrollTo('preview')"
16 :complete => "Element.scrollTo('preview')"
17 }, :accesskey => accesskey(:preview) %>
17 }, :accesskey => accesskey(:preview) %>
18
18
19 <%= javascript_tag "Form.Element.focus('issue_subject');" %>
19 <%= javascript_tag "Form.Element.focus('issue_subject');" %>
20 <% end %>
20 <% end %>
21
21
22 <div id="preview" class="wiki"></div>
22 <div id="preview" class="wiki"></div>
23
23
24 <% content_for :header_tags do %>
24 <% content_for :header_tags do %>
25 <%= stylesheet_link_tag 'scm' %>
25 <%= stylesheet_link_tag 'scm' %>
26 <% end %>
26 <% end %>
@@ -1,289 +1,289
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.with_options :controller => 'issues' do |issues_routes|
106 map.with_options :controller => 'issues' do |issues_routes|
107 issues_routes.with_options :conditions => {:method => :get} do |issues_views|
107 issues_routes.with_options :conditions => {:method => :get} do |issues_views|
108 issues_views.connect 'issues', :action => 'index'
108 issues_views.connect 'issues', :action => 'index'
109 issues_views.connect 'issues.:format', :action => 'index'
109 issues_views.connect 'issues.:format', :action => 'index'
110 issues_views.connect 'projects/:project_id/issues', :action => 'index'
110 issues_views.connect 'projects/:project_id/issues', :action => 'index'
111 issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
111 issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
112 issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
112 issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
113 issues_views.connect 'projects/:project_id/issues/gantt', :action => 'gantt'
113 issues_views.connect 'projects/:project_id/issues/gantt', :action => 'gantt'
114 issues_views.connect 'projects/:project_id/issues/calendar', :action => 'calendar'
114 issues_views.connect 'projects/:project_id/issues/calendar', :action => 'calendar'
115 issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
115 issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
116 issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
116 issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
117 issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
117 issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
118 issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/
118 issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/
119 issues_views.connect 'issues/:id/move', :action => 'move', :id => /\d+/
119 issues_views.connect 'issues/:id/move', :action => 'move', :id => /\d+/
120 end
120 end
121 issues_routes.with_options :conditions => {:method => :post} do |issues_actions|
121 issues_routes.with_options :conditions => {:method => :post} do |issues_actions|
122 issues_actions.connect 'issues', :action => 'index'
122 issues_actions.connect 'issues', :action => 'index'
123 issues_actions.connect 'projects/:project_id/issues', :action => 'new'
123 issues_actions.connect 'projects/:project_id/issues', :action => 'create'
124 issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/
124 issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/
125 issues_actions.connect 'issues/:id/:action', :action => /edit|move|destroy/, :id => /\d+/
125 issues_actions.connect 'issues/:id/:action', :action => /edit|move|destroy/, :id => /\d+/
126 issues_actions.connect 'issues.:format', :action => 'new', :format => /xml/
126 issues_actions.connect 'issues.:format', :action => 'create', :format => /xml/
127 end
127 end
128 issues_routes.with_options :conditions => {:method => :put} do |issues_actions|
128 issues_routes.with_options :conditions => {:method => :put} do |issues_actions|
129 issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/
129 issues_actions.connect 'issues/:id/edit', :action => 'update', :id => /\d+/
130 issues_actions.connect 'issues/:id.:format', :action => 'update', :id => /\d+/, :format => /xml/
130 issues_actions.connect 'issues/:id.:format', :action => 'update', :id => /\d+/, :format => /xml/
131 end
131 end
132 issues_routes.with_options :conditions => {:method => :delete} do |issues_actions|
132 issues_routes.with_options :conditions => {:method => :delete} do |issues_actions|
133 issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
133 issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
134 end
134 end
135 issues_routes.connect 'issues/:action'
135 issues_routes.connect 'issues/:action'
136 end
136 end
137
137
138 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
138 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
139 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
139 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
140 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
140 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
141 end
141 end
142
142
143 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
143 map.with_options :controller => 'reports', :conditions => {:method => :get} do |reports|
144 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
144 reports.connect 'projects/:id/issues/report', :action => 'issue_report'
145 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
145 reports.connect 'projects/:id/issues/report/:detail', :action => 'issue_report_details'
146 end
146 end
147
147
148 map.with_options :controller => 'news' do |news_routes|
148 map.with_options :controller => 'news' do |news_routes|
149 news_routes.with_options :conditions => {:method => :get} do |news_views|
149 news_routes.with_options :conditions => {:method => :get} do |news_views|
150 news_views.connect 'news', :action => 'index'
150 news_views.connect 'news', :action => 'index'
151 news_views.connect 'projects/:project_id/news', :action => 'index'
151 news_views.connect 'projects/:project_id/news', :action => 'index'
152 news_views.connect 'projects/:project_id/news.:format', :action => 'index'
152 news_views.connect 'projects/:project_id/news.:format', :action => 'index'
153 news_views.connect 'news.:format', :action => 'index'
153 news_views.connect 'news.:format', :action => 'index'
154 news_views.connect 'projects/:project_id/news/new', :action => 'new'
154 news_views.connect 'projects/:project_id/news/new', :action => 'new'
155 news_views.connect 'news/:id', :action => 'show'
155 news_views.connect 'news/:id', :action => 'show'
156 news_views.connect 'news/:id/edit', :action => 'edit'
156 news_views.connect 'news/:id/edit', :action => 'edit'
157 end
157 end
158 news_routes.with_options do |news_actions|
158 news_routes.with_options do |news_actions|
159 news_actions.connect 'projects/:project_id/news', :action => 'new'
159 news_actions.connect 'projects/:project_id/news', :action => 'new'
160 news_actions.connect 'news/:id/edit', :action => 'edit'
160 news_actions.connect 'news/:id/edit', :action => 'edit'
161 news_actions.connect 'news/:id/destroy', :action => 'destroy'
161 news_actions.connect 'news/:id/destroy', :action => 'destroy'
162 end
162 end
163 end
163 end
164
164
165 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
165 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
166
166
167 map.with_options :controller => 'users' do |users|
167 map.with_options :controller => 'users' do |users|
168 users.with_options :conditions => {:method => :get} do |user_views|
168 users.with_options :conditions => {:method => :get} do |user_views|
169 user_views.connect 'users', :action => 'index'
169 user_views.connect 'users', :action => 'index'
170 user_views.connect 'users/:id', :action => 'show', :id => /\d+/
170 user_views.connect 'users/:id', :action => 'show', :id => /\d+/
171 user_views.connect 'users/new', :action => 'add'
171 user_views.connect 'users/new', :action => 'add'
172 user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil
172 user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil
173 end
173 end
174 users.with_options :conditions => {:method => :post} do |user_actions|
174 users.with_options :conditions => {:method => :post} do |user_actions|
175 user_actions.connect 'users', :action => 'add'
175 user_actions.connect 'users', :action => 'add'
176 user_actions.connect 'users/new', :action => 'add'
176 user_actions.connect 'users/new', :action => 'add'
177 user_actions.connect 'users/:id/edit', :action => 'edit'
177 user_actions.connect 'users/:id/edit', :action => 'edit'
178 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
178 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
179 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
179 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
180 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
180 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
181 end
181 end
182 end
182 end
183
183
184 map.with_options :controller => 'projects' do |projects|
184 map.with_options :controller => 'projects' do |projects|
185 projects.with_options :conditions => {:method => :get} do |project_views|
185 projects.with_options :conditions => {:method => :get} do |project_views|
186 project_views.connect 'projects', :action => 'index'
186 project_views.connect 'projects', :action => 'index'
187 project_views.connect 'projects.:format', :action => 'index'
187 project_views.connect 'projects.:format', :action => 'index'
188 project_views.connect 'projects/new', :action => 'add'
188 project_views.connect 'projects/new', :action => 'add'
189 project_views.connect 'projects/:id', :action => 'show'
189 project_views.connect 'projects/:id', :action => 'show'
190 project_views.connect 'projects/:id.:format', :action => 'show'
190 project_views.connect 'projects/:id.:format', :action => 'show'
191 project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
191 project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
192 project_views.connect 'projects/:id/files', :action => 'list_files'
192 project_views.connect 'projects/:id/files', :action => 'list_files'
193 project_views.connect 'projects/:id/files/new', :action => 'add_file'
193 project_views.connect 'projects/:id/files/new', :action => 'add_file'
194 project_views.connect 'projects/:id/settings/:tab', :action => 'settings'
194 project_views.connect 'projects/:id/settings/:tab', :action => 'settings'
195 end
195 end
196
196
197 projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity|
197 projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity|
198 activity.connect 'projects/:id/activity'
198 activity.connect 'projects/:id/activity'
199 activity.connect 'projects/:id/activity.:format'
199 activity.connect 'projects/:id/activity.:format'
200 activity.connect 'activity', :id => nil
200 activity.connect 'activity', :id => nil
201 activity.connect 'activity.:format', :id => nil
201 activity.connect 'activity.:format', :id => nil
202 end
202 end
203
203
204 projects.with_options :conditions => {:method => :post} do |project_actions|
204 projects.with_options :conditions => {:method => :post} do |project_actions|
205 project_actions.connect 'projects/new', :action => 'add'
205 project_actions.connect 'projects/new', :action => 'add'
206 project_actions.connect 'projects', :action => 'add'
206 project_actions.connect 'projects', :action => 'add'
207 project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
207 project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
208 project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/
208 project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/
209 project_actions.connect 'projects/:id/files/new', :action => 'add_file'
209 project_actions.connect 'projects/:id/files/new', :action => 'add_file'
210 project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
210 project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
211 end
211 end
212
212
213 projects.with_options :conditions => {:method => :put} do |project_actions|
213 projects.with_options :conditions => {:method => :put} do |project_actions|
214 project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
214 project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
215 end
215 end
216
216
217 projects.with_options :conditions => {:method => :delete} do |project_actions|
217 projects.with_options :conditions => {:method => :delete} do |project_actions|
218 project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
218 project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
219 project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
219 project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
220 end
220 end
221 end
221 end
222
222
223 map.with_options :controller => 'versions' do |versions|
223 map.with_options :controller => 'versions' do |versions|
224 versions.connect 'projects/:project_id/versions/new', :action => 'new'
224 versions.connect 'projects/:project_id/versions/new', :action => 'new'
225 versions.with_options :conditions => {:method => :post} do |version_actions|
225 versions.with_options :conditions => {:method => :post} do |version_actions|
226 version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed'
226 version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed'
227 end
227 end
228 end
228 end
229
229
230 map.with_options :controller => 'issue_categories' do |categories|
230 map.with_options :controller => 'issue_categories' do |categories|
231 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
231 categories.connect 'projects/:project_id/issue_categories/new', :action => 'new'
232 end
232 end
233
233
234 map.with_options :controller => 'repositories' do |repositories|
234 map.with_options :controller => 'repositories' do |repositories|
235 repositories.with_options :conditions => {:method => :get} do |repository_views|
235 repositories.with_options :conditions => {:method => :get} do |repository_views|
236 repository_views.connect 'projects/:id/repository', :action => 'show'
236 repository_views.connect 'projects/:id/repository', :action => 'show'
237 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
237 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
238 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
238 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
239 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
239 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
240 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
240 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
241 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
241 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
242 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
242 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
243 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
243 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
244 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
244 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
245 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
245 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
246 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
246 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
247 # TODO: why the following route is required?
247 # TODO: why the following route is required?
248 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
248 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
249 repository_views.connect 'projects/:id/repository/:action/*path'
249 repository_views.connect 'projects/:id/repository/:action/*path'
250 end
250 end
251
251
252 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
252 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
253 end
253 end
254
254
255 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
255 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
256 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
256 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
257 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
257 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
258
258
259 map.resources :groups
259 map.resources :groups
260
260
261 #left old routes at the bottom for backwards compat
261 #left old routes at the bottom for backwards compat
262 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
262 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
263 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
263 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
264 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
264 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
265 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
265 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
266 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
266 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
267 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
267 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
268 map.connect 'projects/:project_id/news/:action', :controller => 'news'
268 map.connect 'projects/:project_id/news/:action', :controller => 'news'
269 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
269 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
270 map.with_options :controller => 'repositories' do |omap|
270 map.with_options :controller => 'repositories' do |omap|
271 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
271 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
272 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
272 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
273 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
273 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
274 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
274 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
275 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
275 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
276 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
276 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
277 end
277 end
278
278
279 map.with_options :controller => 'sys' do |sys|
279 map.with_options :controller => 'sys' do |sys|
280 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
280 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
281 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
281 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
282 end
282 end
283
283
284 # Install the default route as the lowest priority.
284 # Install the default route as the lowest priority.
285 map.connect ':controller/:action/:id'
285 map.connect ':controller/:action/:id'
286 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
286 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
287 # Used for OpenID
287 # Used for OpenID
288 map.root :controller => 'account', :action => 'login'
288 map.root :controller => 'account', :action => 'login'
289 end
289 end
@@ -1,206 +1,206
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, :changes, :show, :context_menu, :auto_complete],
61 :issues => [:index, :changes, :show, :context_menu, :auto_complete],
62 :versions => [:show, :status_by],
62 :versions => [:show, :status_by],
63 :queries => :index,
63 :queries => :index,
64 :reports => [:issue_report, :issue_report_details]}
64 :reports => [:issue_report, :issue_report_details]}
65 map.permission :add_issues, {:issues => [:new, :update_form]}
65 map.permission :add_issues, {:issues => [:new, :create, :update_form]}
66 map.permission :edit_issues, {:issues => [:edit, :update, :reply, :bulk_edit, :update_form]}
66 map.permission :edit_issues, {:issues => [:edit, :update, :reply, :bulk_edit, :update_form]}
67 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
67 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
68 map.permission :manage_subtasks, {}
68 map.permission :manage_subtasks, {}
69 map.permission :add_issue_notes, {:issues => [:edit, :update, :reply]}
69 map.permission :add_issue_notes, {:issues => [:edit, :update, :reply]}
70 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
70 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
71 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
71 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
72 map.permission :move_issues, {:issues => :move}, :require => :loggedin
72 map.permission :move_issues, {:issues => :move}, :require => :loggedin
73 map.permission :delete_issues, {:issues => :destroy}, :require => :member
73 map.permission :delete_issues, {:issues => :destroy}, :require => :member
74 # Queries
74 # Queries
75 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
75 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
76 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
76 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
77 # Gantt & calendar
77 # Gantt & calendar
78 map.permission :view_gantt, :issues => :gantt
78 map.permission :view_gantt, :issues => :gantt
79 map.permission :view_calendar, :issues => :calendar
79 map.permission :view_calendar, :issues => :calendar
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 end
138 end
139
139
140 Redmine::MenuManager.map :top_menu do |menu|
140 Redmine::MenuManager.map :top_menu do |menu|
141 menu.push :home, :home_path
141 menu.push :home, :home_path
142 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
142 menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
143 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
143 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
144 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
144 menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
145 menu.push :help, Redmine::Info.help_url, :last => true
145 menu.push :help, Redmine::Info.help_url, :last => true
146 end
146 end
147
147
148 Redmine::MenuManager.map :account_menu do |menu|
148 Redmine::MenuManager.map :account_menu do |menu|
149 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
149 menu.push :login, :signin_path, :if => Proc.new { !User.current.logged? }
150 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
150 menu.push :register, { :controller => 'account', :action => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
151 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
151 menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
152 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
152 menu.push :logout, :signout_path, :if => Proc.new { User.current.logged? }
153 end
153 end
154
154
155 Redmine::MenuManager.map :application_menu do |menu|
155 Redmine::MenuManager.map :application_menu do |menu|
156 # Empty
156 # Empty
157 end
157 end
158
158
159 Redmine::MenuManager.map :admin_menu do |menu|
159 Redmine::MenuManager.map :admin_menu do |menu|
160 # Empty
160 # Empty
161 end
161 end
162
162
163 Redmine::MenuManager.map :project_menu do |menu|
163 Redmine::MenuManager.map :project_menu do |menu|
164 menu.push :overview, { :controller => 'projects', :action => 'show' }
164 menu.push :overview, { :controller => 'projects', :action => 'show' }
165 menu.push :activity, { :controller => 'projects', :action => 'activity' }
165 menu.push :activity, { :controller => 'projects', :action => 'activity' }
166 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
166 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
167 :if => Proc.new { |p| p.shared_versions.any? }
167 :if => Proc.new { |p| p.shared_versions.any? }
168 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
168 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
169 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
169 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
170 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
170 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
171 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
171 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
172 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
172 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
173 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
173 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
174 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
174 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
175 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
175 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
176 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
176 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
177 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_file_plural
177 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_file_plural
178 menu.push :repository, { :controller => 'repositories', :action => 'show' },
178 menu.push :repository, { :controller => 'repositories', :action => 'show' },
179 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
179 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
180 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
180 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
181 end
181 end
182
182
183 Redmine::Activity.map do |activity|
183 Redmine::Activity.map do |activity|
184 activity.register :issues, :class_name => %w(Issue Journal)
184 activity.register :issues, :class_name => %w(Issue Journal)
185 activity.register :changesets
185 activity.register :changesets
186 activity.register :news
186 activity.register :news
187 activity.register :documents, :class_name => %w(Document Attachment)
187 activity.register :documents, :class_name => %w(Document Attachment)
188 activity.register :files, :class_name => 'Attachment'
188 activity.register :files, :class_name => 'Attachment'
189 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
189 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
190 activity.register :messages, :default => false
190 activity.register :messages, :default => false
191 activity.register :time_entries, :default => false
191 activity.register :time_entries, :default => false
192 end
192 end
193
193
194 Redmine::Search.map do |search|
194 Redmine::Search.map do |search|
195 search.register :issues
195 search.register :issues
196 search.register :news
196 search.register :news
197 search.register :documents
197 search.register :documents
198 search.register :changesets
198 search.register :changesets
199 search.register :wiki_pages
199 search.register :wiki_pages
200 search.register :messages
200 search.register :messages
201 search.register :projects
201 search.register :projects
202 end
202 end
203
203
204 Redmine::WikiFormatting.map do |format|
204 Redmine::WikiFormatting.map do |format|
205 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
205 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
206 end
206 end
@@ -1,1354 +1,1354
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_gantt
234 def test_gantt
235 get :gantt, :project_id => 1
235 get :gantt, :project_id => 1
236 assert_response :success
236 assert_response :success
237 assert_template 'gantt.rhtml'
237 assert_template 'gantt.rhtml'
238 assert_not_nil assigns(:gantt)
238 assert_not_nil assigns(:gantt)
239 events = assigns(:gantt).events
239 events = assigns(:gantt).events
240 assert_not_nil events
240 assert_not_nil events
241 # Issue with start and due dates
241 # Issue with start and due dates
242 i = Issue.find(1)
242 i = Issue.find(1)
243 assert_not_nil i.due_date
243 assert_not_nil i.due_date
244 assert events.include?(Issue.find(1))
244 assert events.include?(Issue.find(1))
245 # Issue with without due date but targeted to a version with date
245 # Issue with without due date but targeted to a version with date
246 i = Issue.find(2)
246 i = Issue.find(2)
247 assert_nil i.due_date
247 assert_nil i.due_date
248 assert events.include?(i)
248 assert events.include?(i)
249 end
249 end
250
250
251 def test_cross_project_gantt
251 def test_cross_project_gantt
252 get :gantt
252 get :gantt
253 assert_response :success
253 assert_response :success
254 assert_template 'gantt.rhtml'
254 assert_template 'gantt.rhtml'
255 assert_not_nil assigns(:gantt)
255 assert_not_nil assigns(:gantt)
256 events = assigns(:gantt).events
256 events = assigns(:gantt).events
257 assert_not_nil events
257 assert_not_nil events
258 end
258 end
259
259
260 def test_gantt_export_to_pdf
260 def test_gantt_export_to_pdf
261 get :gantt, :project_id => 1, :format => 'pdf'
261 get :gantt, :project_id => 1, :format => 'pdf'
262 assert_response :success
262 assert_response :success
263 assert_equal 'application/pdf', @response.content_type
263 assert_equal 'application/pdf', @response.content_type
264 assert @response.body.starts_with?('%PDF')
264 assert @response.body.starts_with?('%PDF')
265 assert_not_nil assigns(:gantt)
265 assert_not_nil assigns(:gantt)
266 end
266 end
267
267
268 def test_cross_project_gantt_export_to_pdf
268 def test_cross_project_gantt_export_to_pdf
269 get :gantt, :format => 'pdf'
269 get :gantt, :format => 'pdf'
270 assert_response :success
270 assert_response :success
271 assert_equal 'application/pdf', @response.content_type
271 assert_equal 'application/pdf', @response.content_type
272 assert @response.body.starts_with?('%PDF')
272 assert @response.body.starts_with?('%PDF')
273 assert_not_nil assigns(:gantt)
273 assert_not_nil assigns(:gantt)
274 end
274 end
275
275
276 if Object.const_defined?(:Magick)
276 if Object.const_defined?(:Magick)
277 def test_gantt_image
277 def test_gantt_image
278 get :gantt, :project_id => 1, :format => 'png'
278 get :gantt, :project_id => 1, :format => 'png'
279 assert_response :success
279 assert_response :success
280 assert_equal 'image/png', @response.content_type
280 assert_equal 'image/png', @response.content_type
281 end
281 end
282 else
282 else
283 puts "RMagick not installed. Skipping tests !!!"
283 puts "RMagick not installed. Skipping tests !!!"
284 end
284 end
285
285
286 def test_calendar
286 def test_calendar
287 get :calendar, :project_id => 1
287 get :calendar, :project_id => 1
288 assert_response :success
288 assert_response :success
289 assert_template 'calendar'
289 assert_template 'calendar'
290 assert_not_nil assigns(:calendar)
290 assert_not_nil assigns(:calendar)
291 end
291 end
292
292
293 def test_cross_project_calendar
293 def test_cross_project_calendar
294 get :calendar
294 get :calendar
295 assert_response :success
295 assert_response :success
296 assert_template 'calendar'
296 assert_template 'calendar'
297 assert_not_nil assigns(:calendar)
297 assert_not_nil assigns(:calendar)
298 end
298 end
299
299
300 def test_changes
300 def test_changes
301 get :changes, :project_id => 1
301 get :changes, :project_id => 1
302 assert_response :success
302 assert_response :success
303 assert_not_nil assigns(:journals)
303 assert_not_nil assigns(:journals)
304 assert_equal 'application/atom+xml', @response.content_type
304 assert_equal 'application/atom+xml', @response.content_type
305 end
305 end
306
306
307 def test_show_by_anonymous
307 def test_show_by_anonymous
308 get :show, :id => 1
308 get :show, :id => 1
309 assert_response :success
309 assert_response :success
310 assert_template 'show.rhtml'
310 assert_template 'show.rhtml'
311 assert_not_nil assigns(:issue)
311 assert_not_nil assigns(:issue)
312 assert_equal Issue.find(1), assigns(:issue)
312 assert_equal Issue.find(1), assigns(:issue)
313
313
314 # anonymous role is allowed to add a note
314 # anonymous role is allowed to add a note
315 assert_tag :tag => 'form',
315 assert_tag :tag => 'form',
316 :descendant => { :tag => 'fieldset',
316 :descendant => { :tag => 'fieldset',
317 :child => { :tag => 'legend',
317 :child => { :tag => 'legend',
318 :content => /Notes/ } }
318 :content => /Notes/ } }
319 end
319 end
320
320
321 def test_show_by_manager
321 def test_show_by_manager
322 @request.session[:user_id] = 2
322 @request.session[:user_id] = 2
323 get :show, :id => 1
323 get :show, :id => 1
324 assert_response :success
324 assert_response :success
325
325
326 assert_tag :tag => 'form',
326 assert_tag :tag => 'form',
327 :descendant => { :tag => 'fieldset',
327 :descendant => { :tag => 'fieldset',
328 :child => { :tag => 'legend',
328 :child => { :tag => 'legend',
329 :content => /Change properties/ } },
329 :content => /Change properties/ } },
330 :descendant => { :tag => 'fieldset',
330 :descendant => { :tag => 'fieldset',
331 :child => { :tag => 'legend',
331 :child => { :tag => 'legend',
332 :content => /Log time/ } },
332 :content => /Log time/ } },
333 :descendant => { :tag => 'fieldset',
333 :descendant => { :tag => 'fieldset',
334 :child => { :tag => 'legend',
334 :child => { :tag => 'legend',
335 :content => /Notes/ } }
335 :content => /Notes/ } }
336 end
336 end
337
337
338 def test_show_should_deny_anonymous_access_without_permission
338 def test_show_should_deny_anonymous_access_without_permission
339 Role.anonymous.remove_permission!(:view_issues)
339 Role.anonymous.remove_permission!(:view_issues)
340 get :show, :id => 1
340 get :show, :id => 1
341 assert_response :redirect
341 assert_response :redirect
342 end
342 end
343
343
344 def test_show_should_deny_non_member_access_without_permission
344 def test_show_should_deny_non_member_access_without_permission
345 Role.non_member.remove_permission!(:view_issues)
345 Role.non_member.remove_permission!(:view_issues)
346 @request.session[:user_id] = 9
346 @request.session[:user_id] = 9
347 get :show, :id => 1
347 get :show, :id => 1
348 assert_response 403
348 assert_response 403
349 end
349 end
350
350
351 def test_show_should_deny_member_access_without_permission
351 def test_show_should_deny_member_access_without_permission
352 Role.find(1).remove_permission!(:view_issues)
352 Role.find(1).remove_permission!(:view_issues)
353 @request.session[:user_id] = 2
353 @request.session[:user_id] = 2
354 get :show, :id => 1
354 get :show, :id => 1
355 assert_response 403
355 assert_response 403
356 end
356 end
357
357
358 def test_show_should_not_disclose_relations_to_invisible_issues
358 def test_show_should_not_disclose_relations_to_invisible_issues
359 Setting.cross_project_issue_relations = '1'
359 Setting.cross_project_issue_relations = '1'
360 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
360 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
361 # Relation to a private project issue
361 # Relation to a private project issue
362 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
362 IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
363
363
364 get :show, :id => 1
364 get :show, :id => 1
365 assert_response :success
365 assert_response :success
366
366
367 assert_tag :div, :attributes => { :id => 'relations' },
367 assert_tag :div, :attributes => { :id => 'relations' },
368 :descendant => { :tag => 'a', :content => /#2$/ }
368 :descendant => { :tag => 'a', :content => /#2$/ }
369 assert_no_tag :div, :attributes => { :id => 'relations' },
369 assert_no_tag :div, :attributes => { :id => 'relations' },
370 :descendant => { :tag => 'a', :content => /#4$/ }
370 :descendant => { :tag => 'a', :content => /#4$/ }
371 end
371 end
372
372
373 def test_show_atom
373 def test_show_atom
374 get :show, :id => 2, :format => 'atom'
374 get :show, :id => 2, :format => 'atom'
375 assert_response :success
375 assert_response :success
376 assert_template 'changes.rxml'
376 assert_template 'changes.rxml'
377 # Inline image
377 # Inline image
378 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
378 assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
379 end
379 end
380
380
381 def test_show_export_to_pdf
381 def test_show_export_to_pdf
382 get :show, :id => 3, :format => 'pdf'
382 get :show, :id => 3, :format => 'pdf'
383 assert_response :success
383 assert_response :success
384 assert_equal 'application/pdf', @response.content_type
384 assert_equal 'application/pdf', @response.content_type
385 assert @response.body.starts_with?('%PDF')
385 assert @response.body.starts_with?('%PDF')
386 assert_not_nil assigns(:issue)
386 assert_not_nil assigns(:issue)
387 end
387 end
388
388
389 def test_get_new
389 def test_get_new
390 @request.session[:user_id] = 2
390 @request.session[:user_id] = 2
391 get :new, :project_id => 1, :tracker_id => 1
391 get :new, :project_id => 1, :tracker_id => 1
392 assert_response :success
392 assert_response :success
393 assert_template 'new'
393 assert_template 'new'
394
394
395 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
395 assert_tag :tag => 'input', :attributes => { :name => 'issue[custom_field_values][2]',
396 :value => 'Default string' }
396 :value => 'Default string' }
397 end
397 end
398
398
399 def test_get_new_without_tracker_id
399 def test_get_new_without_tracker_id
400 @request.session[:user_id] = 2
400 @request.session[:user_id] = 2
401 get :new, :project_id => 1
401 get :new, :project_id => 1
402 assert_response :success
402 assert_response :success
403 assert_template 'new'
403 assert_template 'new'
404
404
405 issue = assigns(:issue)
405 issue = assigns(:issue)
406 assert_not_nil issue
406 assert_not_nil issue
407 assert_equal Project.find(1).trackers.first, issue.tracker
407 assert_equal Project.find(1).trackers.first, issue.tracker
408 end
408 end
409
409
410 def test_get_new_with_no_default_status_should_display_an_error
410 def test_get_new_with_no_default_status_should_display_an_error
411 @request.session[:user_id] = 2
411 @request.session[:user_id] = 2
412 IssueStatus.delete_all
412 IssueStatus.delete_all
413
413
414 get :new, :project_id => 1
414 get :new, :project_id => 1
415 assert_response 500
415 assert_response 500
416 assert_not_nil flash[:error]
416 assert_not_nil flash[:error]
417 assert_tag :tag => 'div', :attributes => { :class => /error/ },
417 assert_tag :tag => 'div', :attributes => { :class => /error/ },
418 :content => /No default issue/
418 :content => /No default issue/
419 end
419 end
420
420
421 def test_get_new_with_no_tracker_should_display_an_error
421 def test_get_new_with_no_tracker_should_display_an_error
422 @request.session[:user_id] = 2
422 @request.session[:user_id] = 2
423 Tracker.delete_all
423 Tracker.delete_all
424
424
425 get :new, :project_id => 1
425 get :new, :project_id => 1
426 assert_response 500
426 assert_response 500
427 assert_not_nil flash[:error]
427 assert_not_nil flash[:error]
428 assert_tag :tag => 'div', :attributes => { :class => /error/ },
428 assert_tag :tag => 'div', :attributes => { :class => /error/ },
429 :content => /No tracker/
429 :content => /No tracker/
430 end
430 end
431
431
432 def test_update_new_form
432 def test_update_new_form
433 @request.session[:user_id] = 2
433 @request.session[:user_id] = 2
434 xhr :post, :update_form, :project_id => 1,
434 xhr :post, :update_form, :project_id => 1,
435 :issue => {:tracker_id => 2,
435 :issue => {:tracker_id => 2,
436 :subject => 'This is the test_new issue',
436 :subject => 'This is the test_new issue',
437 :description => 'This is the description',
437 :description => 'This is the description',
438 :priority_id => 5}
438 :priority_id => 5}
439 assert_response :success
439 assert_response :success
440 assert_template 'attributes'
440 assert_template 'attributes'
441
441
442 issue = assigns(:issue)
442 issue = assigns(:issue)
443 assert_kind_of Issue, issue
443 assert_kind_of Issue, issue
444 assert_equal 1, issue.project_id
444 assert_equal 1, issue.project_id
445 assert_equal 2, issue.tracker_id
445 assert_equal 2, issue.tracker_id
446 assert_equal 'This is the test_new issue', issue.subject
446 assert_equal 'This is the test_new issue', issue.subject
447 end
447 end
448
448
449 def test_post_new
449 def test_post_create
450 @request.session[:user_id] = 2
450 @request.session[:user_id] = 2
451 assert_difference 'Issue.count' do
451 assert_difference 'Issue.count' do
452 post :new, :project_id => 1,
452 post :create, :project_id => 1,
453 :issue => {:tracker_id => 3,
453 :issue => {:tracker_id => 3,
454 :status_id => 2,
454 :status_id => 2,
455 :subject => 'This is the test_new issue',
455 :subject => 'This is the test_new issue',
456 :description => 'This is the description',
456 :description => 'This is the description',
457 :priority_id => 5,
457 :priority_id => 5,
458 :estimated_hours => '',
458 :estimated_hours => '',
459 :custom_field_values => {'2' => 'Value for field 2'}}
459 :custom_field_values => {'2' => 'Value for field 2'}}
460 end
460 end
461 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
461 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
462
462
463 issue = Issue.find_by_subject('This is the test_new issue')
463 issue = Issue.find_by_subject('This is the test_new issue')
464 assert_not_nil issue
464 assert_not_nil issue
465 assert_equal 2, issue.author_id
465 assert_equal 2, issue.author_id
466 assert_equal 3, issue.tracker_id
466 assert_equal 3, issue.tracker_id
467 assert_equal 2, issue.status_id
467 assert_equal 2, issue.status_id
468 assert_nil issue.estimated_hours
468 assert_nil issue.estimated_hours
469 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
469 v = issue.custom_values.find(:first, :conditions => {:custom_field_id => 2})
470 assert_not_nil v
470 assert_not_nil v
471 assert_equal 'Value for field 2', v.value
471 assert_equal 'Value for field 2', v.value
472 end
472 end
473
473
474 def test_post_new_and_continue
474 def test_post_create_and_continue
475 @request.session[:user_id] = 2
475 @request.session[:user_id] = 2
476 post :new, :project_id => 1,
476 post :create, :project_id => 1,
477 :issue => {:tracker_id => 3,
477 :issue => {:tracker_id => 3,
478 :subject => 'This is first issue',
478 :subject => 'This is first issue',
479 :priority_id => 5},
479 :priority_id => 5},
480 :continue => ''
480 :continue => ''
481 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
481 assert_redirected_to :controller => 'issues', :action => 'new', :issue => {:tracker_id => 3}
482 end
482 end
483
483
484 def test_post_new_without_custom_fields_param
484 def test_post_create_without_custom_fields_param
485 @request.session[:user_id] = 2
485 @request.session[:user_id] = 2
486 assert_difference 'Issue.count' do
486 assert_difference 'Issue.count' do
487 post :new, :project_id => 1,
487 post :create, :project_id => 1,
488 :issue => {:tracker_id => 1,
488 :issue => {:tracker_id => 1,
489 :subject => 'This is the test_new issue',
489 :subject => 'This is the test_new issue',
490 :description => 'This is the description',
490 :description => 'This is the description',
491 :priority_id => 5}
491 :priority_id => 5}
492 end
492 end
493 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
493 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
494 end
494 end
495
495
496 def test_post_new_with_required_custom_field_and_without_custom_fields_param
496 def test_post_create_with_required_custom_field_and_without_custom_fields_param
497 field = IssueCustomField.find_by_name('Database')
497 field = IssueCustomField.find_by_name('Database')
498 field.update_attribute(:is_required, true)
498 field.update_attribute(:is_required, true)
499
499
500 @request.session[:user_id] = 2
500 @request.session[:user_id] = 2
501 post :new, :project_id => 1,
501 post :create, :project_id => 1,
502 :issue => {:tracker_id => 1,
502 :issue => {:tracker_id => 1,
503 :subject => 'This is the test_new issue',
503 :subject => 'This is the test_new issue',
504 :description => 'This is the description',
504 :description => 'This is the description',
505 :priority_id => 5}
505 :priority_id => 5}
506 assert_response :success
506 assert_response :success
507 assert_template 'new'
507 assert_template 'new'
508 issue = assigns(:issue)
508 issue = assigns(:issue)
509 assert_not_nil issue
509 assert_not_nil issue
510 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
510 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
511 end
511 end
512
512
513 def test_post_new_with_watchers
513 def test_post_create_with_watchers
514 @request.session[:user_id] = 2
514 @request.session[:user_id] = 2
515 ActionMailer::Base.deliveries.clear
515 ActionMailer::Base.deliveries.clear
516
516
517 assert_difference 'Watcher.count', 2 do
517 assert_difference 'Watcher.count', 2 do
518 post :new, :project_id => 1,
518 post :create, :project_id => 1,
519 :issue => {:tracker_id => 1,
519 :issue => {:tracker_id => 1,
520 :subject => 'This is a new issue with watchers',
520 :subject => 'This is a new issue with watchers',
521 :description => 'This is the description',
521 :description => 'This is the description',
522 :priority_id => 5,
522 :priority_id => 5,
523 :watcher_user_ids => ['2', '3']}
523 :watcher_user_ids => ['2', '3']}
524 end
524 end
525 issue = Issue.find_by_subject('This is a new issue with watchers')
525 issue = Issue.find_by_subject('This is a new issue with watchers')
526 assert_not_nil issue
526 assert_not_nil issue
527 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
527 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
528
528
529 # Watchers added
529 # Watchers added
530 assert_equal [2, 3], issue.watcher_user_ids.sort
530 assert_equal [2, 3], issue.watcher_user_ids.sort
531 assert issue.watched_by?(User.find(3))
531 assert issue.watched_by?(User.find(3))
532 # Watchers notified
532 # Watchers notified
533 mail = ActionMailer::Base.deliveries.last
533 mail = ActionMailer::Base.deliveries.last
534 assert_kind_of TMail::Mail, mail
534 assert_kind_of TMail::Mail, mail
535 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
535 assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
536 end
536 end
537
537
538 def test_post_new_subissue
538 def test_post_create_subissue
539 @request.session[:user_id] = 2
539 @request.session[:user_id] = 2
540
540
541 assert_difference 'Issue.count' do
541 assert_difference 'Issue.count' do
542 post :new, :project_id => 1,
542 post :create, :project_id => 1,
543 :issue => {:tracker_id => 1,
543 :issue => {:tracker_id => 1,
544 :subject => 'This is a child issue',
544 :subject => 'This is a child issue',
545 :parent_issue_id => 2}
545 :parent_issue_id => 2}
546 end
546 end
547 issue = Issue.find_by_subject('This is a child issue')
547 issue = Issue.find_by_subject('This is a child issue')
548 assert_not_nil issue
548 assert_not_nil issue
549 assert_equal Issue.find(2), issue.parent
549 assert_equal Issue.find(2), issue.parent
550 end
550 end
551
551
552 def test_post_new_should_send_a_notification
552 def test_post_create_should_send_a_notification
553 ActionMailer::Base.deliveries.clear
553 ActionMailer::Base.deliveries.clear
554 @request.session[:user_id] = 2
554 @request.session[:user_id] = 2
555 assert_difference 'Issue.count' do
555 assert_difference 'Issue.count' do
556 post :new, :project_id => 1,
556 post :create, :project_id => 1,
557 :issue => {:tracker_id => 3,
557 :issue => {:tracker_id => 3,
558 :subject => 'This is the test_new issue',
558 :subject => 'This is the test_new issue',
559 :description => 'This is the description',
559 :description => 'This is the description',
560 :priority_id => 5,
560 :priority_id => 5,
561 :estimated_hours => '',
561 :estimated_hours => '',
562 :custom_field_values => {'2' => 'Value for field 2'}}
562 :custom_field_values => {'2' => 'Value for field 2'}}
563 end
563 end
564 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
564 assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
565
565
566 assert_equal 1, ActionMailer::Base.deliveries.size
566 assert_equal 1, ActionMailer::Base.deliveries.size
567 end
567 end
568
568
569 def test_post_should_preserve_fields_values_on_validation_failure
569 def test_post_create_should_preserve_fields_values_on_validation_failure
570 @request.session[:user_id] = 2
570 @request.session[:user_id] = 2
571 post :new, :project_id => 1,
571 post :create, :project_id => 1,
572 :issue => {:tracker_id => 1,
572 :issue => {:tracker_id => 1,
573 # empty subject
573 # empty subject
574 :subject => '',
574 :subject => '',
575 :description => 'This is a description',
575 :description => 'This is a description',
576 :priority_id => 6,
576 :priority_id => 6,
577 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
577 :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
578 assert_response :success
578 assert_response :success
579 assert_template 'new'
579 assert_template 'new'
580
580
581 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
581 assert_tag :textarea, :attributes => { :name => 'issue[description]' },
582 :content => 'This is a description'
582 :content => 'This is a description'
583 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
583 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
584 :child => { :tag => 'option', :attributes => { :selected => 'selected',
584 :child => { :tag => 'option', :attributes => { :selected => 'selected',
585 :value => '6' },
585 :value => '6' },
586 :content => 'High' }
586 :content => 'High' }
587 # Custom fields
587 # Custom fields
588 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
588 assert_tag :select, :attributes => { :name => 'issue[custom_field_values][1]' },
589 :child => { :tag => 'option', :attributes => { :selected => 'selected',
589 :child => { :tag => 'option', :attributes => { :selected => 'selected',
590 :value => 'Oracle' },
590 :value => 'Oracle' },
591 :content => 'Oracle' }
591 :content => 'Oracle' }
592 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
592 assert_tag :input, :attributes => { :name => 'issue[custom_field_values][2]',
593 :value => 'Value for field 2'}
593 :value => 'Value for field 2'}
594 end
594 end
595
595
596 def test_post_new_should_ignore_non_safe_attributes
596 def test_post_create_should_ignore_non_safe_attributes
597 @request.session[:user_id] = 2
597 @request.session[:user_id] = 2
598 assert_nothing_raised do
598 assert_nothing_raised do
599 post :new, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
599 post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
600 end
600 end
601 end
601 end
602
602
603 context "without workflow privilege" do
603 context "without workflow privilege" do
604 setup do
604 setup do
605 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
605 Workflow.delete_all(["role_id = ?", Role.anonymous.id])
606 Role.anonymous.add_permission! :add_issues
606 Role.anonymous.add_permission! :add_issues
607 end
607 end
608
608
609 context "#new" do
609 context "#new" do
610 should "propose default status only" do
610 should "propose default status only" do
611 get :new, :project_id => 1
611 get :new, :project_id => 1
612 assert_response :success
612 assert_response :success
613 assert_template 'new'
613 assert_template 'new'
614 assert_tag :tag => 'select',
614 assert_tag :tag => 'select',
615 :attributes => {:name => 'issue[status_id]'},
615 :attributes => {:name => 'issue[status_id]'},
616 :children => {:count => 1},
616 :children => {:count => 1},
617 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
617 :child => {:tag => 'option', :attributes => {:value => IssueStatus.default.id.to_s}}
618 end
618 end
619
619
620 should "accept default status" do
620 should "accept default status" do
621 assert_difference 'Issue.count' do
621 assert_difference 'Issue.count' do
622 post :new, :project_id => 1,
622 post :create, :project_id => 1,
623 :issue => {:tracker_id => 1,
623 :issue => {:tracker_id => 1,
624 :subject => 'This is an issue',
624 :subject => 'This is an issue',
625 :status_id => 1}
625 :status_id => 1}
626 end
626 end
627 issue = Issue.last(:order => 'id')
627 issue = Issue.last(:order => 'id')
628 assert_equal IssueStatus.default, issue.status
628 assert_equal IssueStatus.default, issue.status
629 end
629 end
630
630
631 should "ignore unauthorized status" do
631 should "ignore unauthorized status" do
632 assert_difference 'Issue.count' do
632 assert_difference 'Issue.count' do
633 post :new, :project_id => 1,
633 post :create, :project_id => 1,
634 :issue => {:tracker_id => 1,
634 :issue => {:tracker_id => 1,
635 :subject => 'This is an issue',
635 :subject => 'This is an issue',
636 :status_id => 3}
636 :status_id => 3}
637 end
637 end
638 issue = Issue.last(:order => 'id')
638 issue = Issue.last(:order => 'id')
639 assert_equal IssueStatus.default, issue.status
639 assert_equal IssueStatus.default, issue.status
640 end
640 end
641 end
641 end
642 end
642 end
643
643
644 def test_copy_issue
644 def test_copy_issue
645 @request.session[:user_id] = 2
645 @request.session[:user_id] = 2
646 get :new, :project_id => 1, :copy_from => 1
646 get :new, :project_id => 1, :copy_from => 1
647 assert_template 'new'
647 assert_template 'new'
648 assert_not_nil assigns(:issue)
648 assert_not_nil assigns(:issue)
649 orig = Issue.find(1)
649 orig = Issue.find(1)
650 assert_equal orig.subject, assigns(:issue).subject
650 assert_equal orig.subject, assigns(:issue).subject
651 end
651 end
652
652
653 def test_get_edit
653 def test_get_edit
654 @request.session[:user_id] = 2
654 @request.session[:user_id] = 2
655 get :edit, :id => 1
655 get :edit, :id => 1
656 assert_response :success
656 assert_response :success
657 assert_template 'edit'
657 assert_template 'edit'
658 assert_not_nil assigns(:issue)
658 assert_not_nil assigns(:issue)
659 assert_equal Issue.find(1), assigns(:issue)
659 assert_equal Issue.find(1), assigns(:issue)
660 end
660 end
661
661
662 def test_get_edit_with_params
662 def test_get_edit_with_params
663 @request.session[:user_id] = 2
663 @request.session[:user_id] = 2
664 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
664 get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 }
665 assert_response :success
665 assert_response :success
666 assert_template 'edit'
666 assert_template 'edit'
667
667
668 issue = assigns(:issue)
668 issue = assigns(:issue)
669 assert_not_nil issue
669 assert_not_nil issue
670
670
671 assert_equal 5, issue.status_id
671 assert_equal 5, issue.status_id
672 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
672 assert_tag :select, :attributes => { :name => 'issue[status_id]' },
673 :child => { :tag => 'option',
673 :child => { :tag => 'option',
674 :content => 'Closed',
674 :content => 'Closed',
675 :attributes => { :selected => 'selected' } }
675 :attributes => { :selected => 'selected' } }
676
676
677 assert_equal 7, issue.priority_id
677 assert_equal 7, issue.priority_id
678 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
678 assert_tag :select, :attributes => { :name => 'issue[priority_id]' },
679 :child => { :tag => 'option',
679 :child => { :tag => 'option',
680 :content => 'Urgent',
680 :content => 'Urgent',
681 :attributes => { :selected => 'selected' } }
681 :attributes => { :selected => 'selected' } }
682 end
682 end
683
683
684 def test_update_edit_form
684 def test_update_edit_form
685 @request.session[:user_id] = 2
685 @request.session[:user_id] = 2
686 xhr :post, :update_form, :project_id => 1,
686 xhr :post, :update_form, :project_id => 1,
687 :id => 1,
687 :id => 1,
688 :issue => {:tracker_id => 2,
688 :issue => {:tracker_id => 2,
689 :subject => 'This is the test_new issue',
689 :subject => 'This is the test_new issue',
690 :description => 'This is the description',
690 :description => 'This is the description',
691 :priority_id => 5}
691 :priority_id => 5}
692 assert_response :success
692 assert_response :success
693 assert_template 'attributes'
693 assert_template 'attributes'
694
694
695 issue = assigns(:issue)
695 issue = assigns(:issue)
696 assert_kind_of Issue, issue
696 assert_kind_of Issue, issue
697 assert_equal 1, issue.id
697 assert_equal 1, issue.id
698 assert_equal 1, issue.project_id
698 assert_equal 1, issue.project_id
699 assert_equal 2, issue.tracker_id
699 assert_equal 2, issue.tracker_id
700 assert_equal 'This is the test_new issue', issue.subject
700 assert_equal 'This is the test_new issue', issue.subject
701 end
701 end
702
702
703 def test_reply_to_issue
703 def test_reply_to_issue
704 @request.session[:user_id] = 2
704 @request.session[:user_id] = 2
705 get :reply, :id => 1
705 get :reply, :id => 1
706 assert_response :success
706 assert_response :success
707 assert_select_rjs :show, "update"
707 assert_select_rjs :show, "update"
708 end
708 end
709
709
710 def test_reply_to_note
710 def test_reply_to_note
711 @request.session[:user_id] = 2
711 @request.session[:user_id] = 2
712 get :reply, :id => 1, :journal_id => 2
712 get :reply, :id => 1, :journal_id => 2
713 assert_response :success
713 assert_response :success
714 assert_select_rjs :show, "update"
714 assert_select_rjs :show, "update"
715 end
715 end
716
716
717 def test_update_using_invalid_http_verbs
717 def test_update_using_invalid_http_verbs
718 @request.session[:user_id] = 2
718 @request.session[:user_id] = 2
719 subject = 'Updated by an invalid http verb'
719 subject = 'Updated by an invalid http verb'
720
720
721 get :update, :id => 1, :issue => {:subject => subject}
721 get :update, :id => 1, :issue => {:subject => subject}
722 assert_not_equal subject, Issue.find(1).subject
722 assert_not_equal subject, Issue.find(1).subject
723
723
724 post :update, :id => 1, :issue => {:subject => subject}
724 post :update, :id => 1, :issue => {:subject => subject}
725 assert_not_equal subject, Issue.find(1).subject
725 assert_not_equal subject, Issue.find(1).subject
726
726
727 delete :update, :id => 1, :issue => {:subject => subject}
727 delete :update, :id => 1, :issue => {:subject => subject}
728 assert_not_equal subject, Issue.find(1).subject
728 assert_not_equal subject, Issue.find(1).subject
729 end
729 end
730
730
731 def test_put_update_without_custom_fields_param
731 def test_put_update_without_custom_fields_param
732 @request.session[:user_id] = 2
732 @request.session[:user_id] = 2
733 ActionMailer::Base.deliveries.clear
733 ActionMailer::Base.deliveries.clear
734
734
735 issue = Issue.find(1)
735 issue = Issue.find(1)
736 assert_equal '125', issue.custom_value_for(2).value
736 assert_equal '125', issue.custom_value_for(2).value
737 old_subject = issue.subject
737 old_subject = issue.subject
738 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
738 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
739
739
740 assert_difference('Journal.count') do
740 assert_difference('Journal.count') do
741 assert_difference('JournalDetail.count', 2) do
741 assert_difference('JournalDetail.count', 2) do
742 put :update, :id => 1, :issue => {:subject => new_subject,
742 put :update, :id => 1, :issue => {:subject => new_subject,
743 :priority_id => '6',
743 :priority_id => '6',
744 :category_id => '1' # no change
744 :category_id => '1' # no change
745 }
745 }
746 end
746 end
747 end
747 end
748 assert_redirected_to :action => 'show', :id => '1'
748 assert_redirected_to :action => 'show', :id => '1'
749 issue.reload
749 issue.reload
750 assert_equal new_subject, issue.subject
750 assert_equal new_subject, issue.subject
751 # Make sure custom fields were not cleared
751 # Make sure custom fields were not cleared
752 assert_equal '125', issue.custom_value_for(2).value
752 assert_equal '125', issue.custom_value_for(2).value
753
753
754 mail = ActionMailer::Base.deliveries.last
754 mail = ActionMailer::Base.deliveries.last
755 assert_kind_of TMail::Mail, mail
755 assert_kind_of TMail::Mail, mail
756 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
756 assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
757 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
757 assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
758 end
758 end
759
759
760 def test_put_update_with_custom_field_change
760 def test_put_update_with_custom_field_change
761 @request.session[:user_id] = 2
761 @request.session[:user_id] = 2
762 issue = Issue.find(1)
762 issue = Issue.find(1)
763 assert_equal '125', issue.custom_value_for(2).value
763 assert_equal '125', issue.custom_value_for(2).value
764
764
765 assert_difference('Journal.count') do
765 assert_difference('Journal.count') do
766 assert_difference('JournalDetail.count', 3) do
766 assert_difference('JournalDetail.count', 3) do
767 put :update, :id => 1, :issue => {:subject => 'Custom field change',
767 put :update, :id => 1, :issue => {:subject => 'Custom field change',
768 :priority_id => '6',
768 :priority_id => '6',
769 :category_id => '1', # no change
769 :category_id => '1', # no change
770 :custom_field_values => { '2' => 'New custom value' }
770 :custom_field_values => { '2' => 'New custom value' }
771 }
771 }
772 end
772 end
773 end
773 end
774 assert_redirected_to :action => 'show', :id => '1'
774 assert_redirected_to :action => 'show', :id => '1'
775 issue.reload
775 issue.reload
776 assert_equal 'New custom value', issue.custom_value_for(2).value
776 assert_equal 'New custom value', issue.custom_value_for(2).value
777
777
778 mail = ActionMailer::Base.deliveries.last
778 mail = ActionMailer::Base.deliveries.last
779 assert_kind_of TMail::Mail, mail
779 assert_kind_of TMail::Mail, mail
780 assert mail.body.include?("Searchable field changed from 125 to New custom value")
780 assert mail.body.include?("Searchable field changed from 125 to New custom value")
781 end
781 end
782
782
783 def test_put_update_with_status_and_assignee_change
783 def test_put_update_with_status_and_assignee_change
784 issue = Issue.find(1)
784 issue = Issue.find(1)
785 assert_equal 1, issue.status_id
785 assert_equal 1, issue.status_id
786 @request.session[:user_id] = 2
786 @request.session[:user_id] = 2
787 assert_difference('TimeEntry.count', 0) do
787 assert_difference('TimeEntry.count', 0) do
788 put :update,
788 put :update,
789 :id => 1,
789 :id => 1,
790 :issue => { :status_id => 2, :assigned_to_id => 3 },
790 :issue => { :status_id => 2, :assigned_to_id => 3 },
791 :notes => 'Assigned to dlopper',
791 :notes => 'Assigned to dlopper',
792 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
792 :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
793 end
793 end
794 assert_redirected_to :action => 'show', :id => '1'
794 assert_redirected_to :action => 'show', :id => '1'
795 issue.reload
795 issue.reload
796 assert_equal 2, issue.status_id
796 assert_equal 2, issue.status_id
797 j = Journal.find(:first, :order => 'id DESC')
797 j = Journal.find(:first, :order => 'id DESC')
798 assert_equal 'Assigned to dlopper', j.notes
798 assert_equal 'Assigned to dlopper', j.notes
799 assert_equal 2, j.details.size
799 assert_equal 2, j.details.size
800
800
801 mail = ActionMailer::Base.deliveries.last
801 mail = ActionMailer::Base.deliveries.last
802 assert mail.body.include?("Status changed from New to Assigned")
802 assert mail.body.include?("Status changed from New to Assigned")
803 # subject should contain the new status
803 # subject should contain the new status
804 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
804 assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
805 end
805 end
806
806
807 def test_put_update_with_note_only
807 def test_put_update_with_note_only
808 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
808 notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
809 # anonymous user
809 # anonymous user
810 put :update,
810 put :update,
811 :id => 1,
811 :id => 1,
812 :notes => notes
812 :notes => notes
813 assert_redirected_to :action => 'show', :id => '1'
813 assert_redirected_to :action => 'show', :id => '1'
814 j = Journal.find(:first, :order => 'id DESC')
814 j = Journal.find(:first, :order => 'id DESC')
815 assert_equal notes, j.notes
815 assert_equal notes, j.notes
816 assert_equal 0, j.details.size
816 assert_equal 0, j.details.size
817 assert_equal User.anonymous, j.user
817 assert_equal User.anonymous, j.user
818
818
819 mail = ActionMailer::Base.deliveries.last
819 mail = ActionMailer::Base.deliveries.last
820 assert mail.body.include?(notes)
820 assert mail.body.include?(notes)
821 end
821 end
822
822
823 def test_put_update_with_note_and_spent_time
823 def test_put_update_with_note_and_spent_time
824 @request.session[:user_id] = 2
824 @request.session[:user_id] = 2
825 spent_hours_before = Issue.find(1).spent_hours
825 spent_hours_before = Issue.find(1).spent_hours
826 assert_difference('TimeEntry.count') do
826 assert_difference('TimeEntry.count') do
827 put :update,
827 put :update,
828 :id => 1,
828 :id => 1,
829 :notes => '2.5 hours added',
829 :notes => '2.5 hours added',
830 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first }
830 :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first }
831 end
831 end
832 assert_redirected_to :action => 'show', :id => '1'
832 assert_redirected_to :action => 'show', :id => '1'
833
833
834 issue = Issue.find(1)
834 issue = Issue.find(1)
835
835
836 j = Journal.find(:first, :order => 'id DESC')
836 j = Journal.find(:first, :order => 'id DESC')
837 assert_equal '2.5 hours added', j.notes
837 assert_equal '2.5 hours added', j.notes
838 assert_equal 0, j.details.size
838 assert_equal 0, j.details.size
839
839
840 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
840 t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
841 assert_not_nil t
841 assert_not_nil t
842 assert_equal 2.5, t.hours
842 assert_equal 2.5, t.hours
843 assert_equal spent_hours_before + 2.5, issue.spent_hours
843 assert_equal spent_hours_before + 2.5, issue.spent_hours
844 end
844 end
845
845
846 def test_put_update_with_attachment_only
846 def test_put_update_with_attachment_only
847 set_tmp_attachments_directory
847 set_tmp_attachments_directory
848
848
849 # Delete all fixtured journals, a race condition can occur causing the wrong
849 # Delete all fixtured journals, a race condition can occur causing the wrong
850 # journal to get fetched in the next find.
850 # journal to get fetched in the next find.
851 Journal.delete_all
851 Journal.delete_all
852
852
853 # anonymous user
853 # anonymous user
854 put :update,
854 put :update,
855 :id => 1,
855 :id => 1,
856 :notes => '',
856 :notes => '',
857 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
857 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
858 assert_redirected_to :action => 'show', :id => '1'
858 assert_redirected_to :action => 'show', :id => '1'
859 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
859 j = Issue.find(1).journals.find(:first, :order => 'id DESC')
860 assert j.notes.blank?
860 assert j.notes.blank?
861 assert_equal 1, j.details.size
861 assert_equal 1, j.details.size
862 assert_equal 'testfile.txt', j.details.first.value
862 assert_equal 'testfile.txt', j.details.first.value
863 assert_equal User.anonymous, j.user
863 assert_equal User.anonymous, j.user
864
864
865 mail = ActionMailer::Base.deliveries.last
865 mail = ActionMailer::Base.deliveries.last
866 assert mail.body.include?('testfile.txt')
866 assert mail.body.include?('testfile.txt')
867 end
867 end
868
868
869 def test_put_update_with_attachment_that_fails_to_save
869 def test_put_update_with_attachment_that_fails_to_save
870 set_tmp_attachments_directory
870 set_tmp_attachments_directory
871
871
872 # Delete all fixtured journals, a race condition can occur causing the wrong
872 # Delete all fixtured journals, a race condition can occur causing the wrong
873 # journal to get fetched in the next find.
873 # journal to get fetched in the next find.
874 Journal.delete_all
874 Journal.delete_all
875
875
876 # Mock out the unsaved attachment
876 # Mock out the unsaved attachment
877 Attachment.any_instance.stubs(:create).returns(Attachment.new)
877 Attachment.any_instance.stubs(:create).returns(Attachment.new)
878
878
879 # anonymous user
879 # anonymous user
880 put :update,
880 put :update,
881 :id => 1,
881 :id => 1,
882 :notes => '',
882 :notes => '',
883 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
883 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
884 assert_redirected_to :action => 'show', :id => '1'
884 assert_redirected_to :action => 'show', :id => '1'
885 assert_equal '1 file(s) could not be saved.', flash[:warning]
885 assert_equal '1 file(s) could not be saved.', flash[:warning]
886
886
887 end if Object.const_defined?(:Mocha)
887 end if Object.const_defined?(:Mocha)
888
888
889 def test_put_update_with_no_change
889 def test_put_update_with_no_change
890 issue = Issue.find(1)
890 issue = Issue.find(1)
891 issue.journals.clear
891 issue.journals.clear
892 ActionMailer::Base.deliveries.clear
892 ActionMailer::Base.deliveries.clear
893
893
894 put :update,
894 put :update,
895 :id => 1,
895 :id => 1,
896 :notes => ''
896 :notes => ''
897 assert_redirected_to :action => 'show', :id => '1'
897 assert_redirected_to :action => 'show', :id => '1'
898
898
899 issue.reload
899 issue.reload
900 assert issue.journals.empty?
900 assert issue.journals.empty?
901 # No email should be sent
901 # No email should be sent
902 assert ActionMailer::Base.deliveries.empty?
902 assert ActionMailer::Base.deliveries.empty?
903 end
903 end
904
904
905 def test_put_update_should_send_a_notification
905 def test_put_update_should_send_a_notification
906 @request.session[:user_id] = 2
906 @request.session[:user_id] = 2
907 ActionMailer::Base.deliveries.clear
907 ActionMailer::Base.deliveries.clear
908 issue = Issue.find(1)
908 issue = Issue.find(1)
909 old_subject = issue.subject
909 old_subject = issue.subject
910 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
910 new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
911
911
912 put :update, :id => 1, :issue => {:subject => new_subject,
912 put :update, :id => 1, :issue => {:subject => new_subject,
913 :priority_id => '6',
913 :priority_id => '6',
914 :category_id => '1' # no change
914 :category_id => '1' # no change
915 }
915 }
916 assert_equal 1, ActionMailer::Base.deliveries.size
916 assert_equal 1, ActionMailer::Base.deliveries.size
917 end
917 end
918
918
919 def test_put_update_with_invalid_spent_time
919 def test_put_update_with_invalid_spent_time
920 @request.session[:user_id] = 2
920 @request.session[:user_id] = 2
921 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
921 notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
922
922
923 assert_no_difference('Journal.count') do
923 assert_no_difference('Journal.count') do
924 put :update,
924 put :update,
925 :id => 1,
925 :id => 1,
926 :notes => notes,
926 :notes => notes,
927 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
927 :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
928 end
928 end
929 assert_response :success
929 assert_response :success
930 assert_template 'edit'
930 assert_template 'edit'
931
931
932 assert_tag :textarea, :attributes => { :name => 'notes' },
932 assert_tag :textarea, :attributes => { :name => 'notes' },
933 :content => notes
933 :content => notes
934 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
934 assert_tag :input, :attributes => { :name => 'time_entry[hours]', :value => "2z" }
935 end
935 end
936
936
937 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
937 def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
938 issue = Issue.find(2)
938 issue = Issue.find(2)
939 @request.session[:user_id] = 2
939 @request.session[:user_id] = 2
940
940
941 put :update,
941 put :update,
942 :id => issue.id,
942 :id => issue.id,
943 :issue => {
943 :issue => {
944 :fixed_version_id => 4
944 :fixed_version_id => 4
945 }
945 }
946
946
947 assert_response :redirect
947 assert_response :redirect
948 issue.reload
948 issue.reload
949 assert_equal 4, issue.fixed_version_id
949 assert_equal 4, issue.fixed_version_id
950 assert_not_equal issue.project_id, issue.fixed_version.project_id
950 assert_not_equal issue.project_id, issue.fixed_version.project_id
951 end
951 end
952
952
953 def test_put_update_should_redirect_back_using_the_back_url_parameter
953 def test_put_update_should_redirect_back_using_the_back_url_parameter
954 issue = Issue.find(2)
954 issue = Issue.find(2)
955 @request.session[:user_id] = 2
955 @request.session[:user_id] = 2
956
956
957 put :update,
957 put :update,
958 :id => issue.id,
958 :id => issue.id,
959 :issue => {
959 :issue => {
960 :fixed_version_id => 4
960 :fixed_version_id => 4
961 },
961 },
962 :back_url => '/issues'
962 :back_url => '/issues'
963
963
964 assert_response :redirect
964 assert_response :redirect
965 assert_redirected_to '/issues'
965 assert_redirected_to '/issues'
966 end
966 end
967
967
968 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
968 def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
969 issue = Issue.find(2)
969 issue = Issue.find(2)
970 @request.session[:user_id] = 2
970 @request.session[:user_id] = 2
971
971
972 put :update,
972 put :update,
973 :id => issue.id,
973 :id => issue.id,
974 :issue => {
974 :issue => {
975 :fixed_version_id => 4
975 :fixed_version_id => 4
976 },
976 },
977 :back_url => 'http://google.com'
977 :back_url => 'http://google.com'
978
978
979 assert_response :redirect
979 assert_response :redirect
980 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
980 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
981 end
981 end
982
982
983 def test_get_bulk_edit
983 def test_get_bulk_edit
984 @request.session[:user_id] = 2
984 @request.session[:user_id] = 2
985 get :bulk_edit, :ids => [1, 2]
985 get :bulk_edit, :ids => [1, 2]
986 assert_response :success
986 assert_response :success
987 assert_template 'bulk_edit'
987 assert_template 'bulk_edit'
988
988
989 # Project specific custom field, date type
989 # Project specific custom field, date type
990 field = CustomField.find(9)
990 field = CustomField.find(9)
991 assert !field.is_for_all?
991 assert !field.is_for_all?
992 assert_equal 'date', field.field_format
992 assert_equal 'date', field.field_format
993 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
993 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
994
994
995 # System wide custom field
995 # System wide custom field
996 assert CustomField.find(1).is_for_all?
996 assert CustomField.find(1).is_for_all?
997 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
997 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
998 end
998 end
999
999
1000 def test_bulk_edit
1000 def test_bulk_edit
1001 @request.session[:user_id] = 2
1001 @request.session[:user_id] = 2
1002 # update issues priority
1002 # update issues priority
1003 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
1003 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
1004 :issue => {:priority_id => 7,
1004 :issue => {:priority_id => 7,
1005 :assigned_to_id => '',
1005 :assigned_to_id => '',
1006 :custom_field_values => {'2' => ''}}
1006 :custom_field_values => {'2' => ''}}
1007
1007
1008 assert_response 302
1008 assert_response 302
1009 # check that the issues were updated
1009 # check that the issues were updated
1010 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
1010 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
1011
1011
1012 issue = Issue.find(1)
1012 issue = Issue.find(1)
1013 journal = issue.journals.find(:first, :order => 'created_on DESC')
1013 journal = issue.journals.find(:first, :order => 'created_on DESC')
1014 assert_equal '125', issue.custom_value_for(2).value
1014 assert_equal '125', issue.custom_value_for(2).value
1015 assert_equal 'Bulk editing', journal.notes
1015 assert_equal 'Bulk editing', journal.notes
1016 assert_equal 1, journal.details.size
1016 assert_equal 1, journal.details.size
1017 end
1017 end
1018
1018
1019 def test_bullk_edit_should_send_a_notification
1019 def test_bullk_edit_should_send_a_notification
1020 @request.session[:user_id] = 2
1020 @request.session[:user_id] = 2
1021 ActionMailer::Base.deliveries.clear
1021 ActionMailer::Base.deliveries.clear
1022 post(:bulk_edit,
1022 post(:bulk_edit,
1023 {
1023 {
1024 :ids => [1, 2],
1024 :ids => [1, 2],
1025 :notes => 'Bulk editing',
1025 :notes => 'Bulk editing',
1026 :issue => {
1026 :issue => {
1027 :priority_id => 7,
1027 :priority_id => 7,
1028 :assigned_to_id => '',
1028 :assigned_to_id => '',
1029 :custom_field_values => {'2' => ''}
1029 :custom_field_values => {'2' => ''}
1030 }
1030 }
1031 })
1031 })
1032
1032
1033 assert_response 302
1033 assert_response 302
1034 assert_equal 2, ActionMailer::Base.deliveries.size
1034 assert_equal 2, ActionMailer::Base.deliveries.size
1035 end
1035 end
1036
1036
1037 def test_bulk_edit_status
1037 def test_bulk_edit_status
1038 @request.session[:user_id] = 2
1038 @request.session[:user_id] = 2
1039 # update issues priority
1039 # update issues priority
1040 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
1040 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
1041 :issue => {:priority_id => '',
1041 :issue => {:priority_id => '',
1042 :assigned_to_id => '',
1042 :assigned_to_id => '',
1043 :status_id => '5'}
1043 :status_id => '5'}
1044
1044
1045 assert_response 302
1045 assert_response 302
1046 issue = Issue.find(1)
1046 issue = Issue.find(1)
1047 assert issue.closed?
1047 assert issue.closed?
1048 end
1048 end
1049
1049
1050 def test_bulk_edit_custom_field
1050 def test_bulk_edit_custom_field
1051 @request.session[:user_id] = 2
1051 @request.session[:user_id] = 2
1052 # update issues priority
1052 # update issues priority
1053 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
1053 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
1054 :issue => {:priority_id => '',
1054 :issue => {:priority_id => '',
1055 :assigned_to_id => '',
1055 :assigned_to_id => '',
1056 :custom_field_values => {'2' => '777'}}
1056 :custom_field_values => {'2' => '777'}}
1057
1057
1058 assert_response 302
1058 assert_response 302
1059
1059
1060 issue = Issue.find(1)
1060 issue = Issue.find(1)
1061 journal = issue.journals.find(:first, :order => 'created_on DESC')
1061 journal = issue.journals.find(:first, :order => 'created_on DESC')
1062 assert_equal '777', issue.custom_value_for(2).value
1062 assert_equal '777', issue.custom_value_for(2).value
1063 assert_equal 1, journal.details.size
1063 assert_equal 1, journal.details.size
1064 assert_equal '125', journal.details.first.old_value
1064 assert_equal '125', journal.details.first.old_value
1065 assert_equal '777', journal.details.first.value
1065 assert_equal '777', journal.details.first.value
1066 end
1066 end
1067
1067
1068 def test_bulk_unassign
1068 def test_bulk_unassign
1069 assert_not_nil Issue.find(2).assigned_to
1069 assert_not_nil Issue.find(2).assigned_to
1070 @request.session[:user_id] = 2
1070 @request.session[:user_id] = 2
1071 # unassign issues
1071 # unassign issues
1072 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1072 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
1073 assert_response 302
1073 assert_response 302
1074 # check that the issues were updated
1074 # check that the issues were updated
1075 assert_nil Issue.find(2).assigned_to
1075 assert_nil Issue.find(2).assigned_to
1076 end
1076 end
1077
1077
1078 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
1078 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
1079 @request.session[:user_id] = 2
1079 @request.session[:user_id] = 2
1080
1080
1081 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
1081 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
1082
1082
1083 assert_response :redirect
1083 assert_response :redirect
1084 issues = Issue.find([1,2])
1084 issues = Issue.find([1,2])
1085 issues.each do |issue|
1085 issues.each do |issue|
1086 assert_equal 4, issue.fixed_version_id
1086 assert_equal 4, issue.fixed_version_id
1087 assert_not_equal issue.project_id, issue.fixed_version.project_id
1087 assert_not_equal issue.project_id, issue.fixed_version.project_id
1088 end
1088 end
1089 end
1089 end
1090
1090
1091 def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter
1091 def test_post_bulk_edit_should_redirect_back_using_the_back_url_parameter
1092 @request.session[:user_id] = 2
1092 @request.session[:user_id] = 2
1093 post :bulk_edit, :ids => [1,2], :back_url => '/issues'
1093 post :bulk_edit, :ids => [1,2], :back_url => '/issues'
1094
1094
1095 assert_response :redirect
1095 assert_response :redirect
1096 assert_redirected_to '/issues'
1096 assert_redirected_to '/issues'
1097 end
1097 end
1098
1098
1099 def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1099 def test_post_bulk_edit_should_not_redirect_back_using_the_back_url_parameter_off_the_host
1100 @request.session[:user_id] = 2
1100 @request.session[:user_id] = 2
1101 post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com'
1101 post :bulk_edit, :ids => [1,2], :back_url => 'http://google.com'
1102
1102
1103 assert_response :redirect
1103 assert_response :redirect
1104 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1104 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
1105 end
1105 end
1106
1106
1107 def test_move_one_issue_to_another_project
1107 def test_move_one_issue_to_another_project
1108 @request.session[:user_id] = 2
1108 @request.session[:user_id] = 2
1109 post :move, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1109 post :move, :id => 1, :new_project_id => 2, :tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1110 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1110 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1111 assert_equal 2, Issue.find(1).project_id
1111 assert_equal 2, Issue.find(1).project_id
1112 end
1112 end
1113
1113
1114 def test_move_one_issue_to_another_project_should_follow_when_needed
1114 def test_move_one_issue_to_another_project_should_follow_when_needed
1115 @request.session[:user_id] = 2
1115 @request.session[:user_id] = 2
1116 post :move, :id => 1, :new_project_id => 2, :follow => '1'
1116 post :move, :id => 1, :new_project_id => 2, :follow => '1'
1117 assert_redirected_to '/issues/1'
1117 assert_redirected_to '/issues/1'
1118 end
1118 end
1119
1119
1120 def test_bulk_move_to_another_project
1120 def test_bulk_move_to_another_project
1121 @request.session[:user_id] = 2
1121 @request.session[:user_id] = 2
1122 post :move, :ids => [1, 2], :new_project_id => 2
1122 post :move, :ids => [1, 2], :new_project_id => 2
1123 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1123 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1124 # Issues moved to project 2
1124 # Issues moved to project 2
1125 assert_equal 2, Issue.find(1).project_id
1125 assert_equal 2, Issue.find(1).project_id
1126 assert_equal 2, Issue.find(2).project_id
1126 assert_equal 2, Issue.find(2).project_id
1127 # No tracker change
1127 # No tracker change
1128 assert_equal 1, Issue.find(1).tracker_id
1128 assert_equal 1, Issue.find(1).tracker_id
1129 assert_equal 2, Issue.find(2).tracker_id
1129 assert_equal 2, Issue.find(2).tracker_id
1130 end
1130 end
1131
1131
1132 def test_bulk_move_to_another_tracker
1132 def test_bulk_move_to_another_tracker
1133 @request.session[:user_id] = 2
1133 @request.session[:user_id] = 2
1134 post :move, :ids => [1, 2], :new_tracker_id => 2
1134 post :move, :ids => [1, 2], :new_tracker_id => 2
1135 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1135 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1136 assert_equal 2, Issue.find(1).tracker_id
1136 assert_equal 2, Issue.find(1).tracker_id
1137 assert_equal 2, Issue.find(2).tracker_id
1137 assert_equal 2, Issue.find(2).tracker_id
1138 end
1138 end
1139
1139
1140 def test_bulk_copy_to_another_project
1140 def test_bulk_copy_to_another_project
1141 @request.session[:user_id] = 2
1141 @request.session[:user_id] = 2
1142 assert_difference 'Issue.count', 2 do
1142 assert_difference 'Issue.count', 2 do
1143 assert_no_difference 'Project.find(1).issues.count' do
1143 assert_no_difference 'Project.find(1).issues.count' do
1144 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
1144 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}
1145 end
1145 end
1146 end
1146 end
1147 assert_redirected_to 'projects/ecookbook/issues'
1147 assert_redirected_to 'projects/ecookbook/issues'
1148 end
1148 end
1149
1149
1150 context "#move via bulk copy" do
1150 context "#move via bulk copy" do
1151 should "allow not changing the issue's attributes" do
1151 should "allow not changing the issue's attributes" do
1152 @request.session[:user_id] = 2
1152 @request.session[:user_id] = 2
1153 issue_before_move = Issue.find(1)
1153 issue_before_move = Issue.find(1)
1154 assert_difference 'Issue.count', 1 do
1154 assert_difference 'Issue.count', 1 do
1155 assert_no_difference 'Project.find(1).issues.count' do
1155 assert_no_difference 'Project.find(1).issues.count' do
1156 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1156 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => '', :status_id => '', :start_date => '', :due_date => ''
1157 end
1157 end
1158 end
1158 end
1159 issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2})
1159 issue_after_move = Issue.first(:order => 'id desc', :conditions => {:project_id => 2})
1160 assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id
1160 assert_equal issue_before_move.tracker_id, issue_after_move.tracker_id
1161 assert_equal issue_before_move.status_id, issue_after_move.status_id
1161 assert_equal issue_before_move.status_id, issue_after_move.status_id
1162 assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id
1162 assert_equal issue_before_move.assigned_to_id, issue_after_move.assigned_to_id
1163 end
1163 end
1164
1164
1165 should "allow changing the issue's attributes" do
1165 should "allow changing the issue's attributes" do
1166 @request.session[:user_id] = 2
1166 @request.session[:user_id] = 2
1167 assert_difference 'Issue.count', 2 do
1167 assert_difference 'Issue.count', 2 do
1168 assert_no_difference 'Project.find(1).issues.count' do
1168 assert_no_difference 'Project.find(1).issues.count' do
1169 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31'
1169 post :move, :ids => [1, 2], :new_project_id => 2, :copy_options => {:copy => '1'}, :new_tracker_id => '', :assigned_to_id => 4, :status_id => 3, :start_date => '2009-12-01', :due_date => '2009-12-31'
1170 end
1170 end
1171 end
1171 end
1172
1172
1173 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
1173 copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
1174 assert_equal 2, copied_issues.size
1174 assert_equal 2, copied_issues.size
1175 copied_issues.each do |issue|
1175 copied_issues.each do |issue|
1176 assert_equal 2, issue.project_id, "Project is incorrect"
1176 assert_equal 2, issue.project_id, "Project is incorrect"
1177 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
1177 assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
1178 assert_equal 3, issue.status_id, "Status is incorrect"
1178 assert_equal 3, issue.status_id, "Status is incorrect"
1179 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
1179 assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
1180 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
1180 assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
1181 end
1181 end
1182 end
1182 end
1183 end
1183 end
1184
1184
1185 def test_copy_to_another_project_should_follow_when_needed
1185 def test_copy_to_another_project_should_follow_when_needed
1186 @request.session[:user_id] = 2
1186 @request.session[:user_id] = 2
1187 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1'
1187 post :move, :ids => [1], :new_project_id => 2, :copy_options => {:copy => '1'}, :follow => '1'
1188 issue = Issue.first(:order => 'id DESC')
1188 issue = Issue.first(:order => 'id DESC')
1189 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1189 assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
1190 end
1190 end
1191
1191
1192 def test_context_menu_one_issue
1192 def test_context_menu_one_issue
1193 @request.session[:user_id] = 2
1193 @request.session[:user_id] = 2
1194 get :context_menu, :ids => [1]
1194 get :context_menu, :ids => [1]
1195 assert_response :success
1195 assert_response :success
1196 assert_template 'context_menu'
1196 assert_template 'context_menu'
1197 assert_tag :tag => 'a', :content => 'Edit',
1197 assert_tag :tag => 'a', :content => 'Edit',
1198 :attributes => { :href => '/issues/1/edit',
1198 :attributes => { :href => '/issues/1/edit',
1199 :class => 'icon-edit' }
1199 :class => 'icon-edit' }
1200 assert_tag :tag => 'a', :content => 'Closed',
1200 assert_tag :tag => 'a', :content => 'Closed',
1201 :attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5',
1201 :attributes => { :href => '/issues/1/edit?issue%5Bstatus_id%5D=5',
1202 :class => '' }
1202 :class => '' }
1203 assert_tag :tag => 'a', :content => 'Immediate',
1203 assert_tag :tag => 'a', :content => 'Immediate',
1204 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
1204 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bpriority_id%5D=8',
1205 :class => '' }
1205 :class => '' }
1206 # Versions
1206 # Versions
1207 assert_tag :tag => 'a', :content => '2.0',
1207 assert_tag :tag => 'a', :content => '2.0',
1208 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
1208 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=3',
1209 :class => '' }
1209 :class => '' }
1210 assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
1210 assert_tag :tag => 'a', :content => 'eCookbook Subproject 1 - 2.0',
1211 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
1211 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bfixed_version_id%5D=4',
1212 :class => '' }
1212 :class => '' }
1213
1213
1214 assert_tag :tag => 'a', :content => 'Dave Lopper',
1214 assert_tag :tag => 'a', :content => 'Dave Lopper',
1215 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
1215 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;issue%5Bassigned_to_id%5D=3',
1216 :class => '' }
1216 :class => '' }
1217 assert_tag :tag => 'a', :content => 'Duplicate',
1217 assert_tag :tag => 'a', :content => 'Duplicate',
1218 :attributes => { :href => '/projects/ecookbook/issues/1/copy',
1218 :attributes => { :href => '/projects/ecookbook/issues/1/copy',
1219 :class => 'icon-duplicate' }
1219 :class => 'icon-duplicate' }
1220 assert_tag :tag => 'a', :content => 'Copy',
1220 assert_tag :tag => 'a', :content => 'Copy',
1221 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1',
1221 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1',
1222 :class => 'icon-copy' }
1222 :class => 'icon-copy' }
1223 assert_tag :tag => 'a', :content => 'Move',
1223 assert_tag :tag => 'a', :content => 'Move',
1224 :attributes => { :href => '/issues/move?ids%5B%5D=1',
1224 :attributes => { :href => '/issues/move?ids%5B%5D=1',
1225 :class => 'icon-move' }
1225 :class => 'icon-move' }
1226 assert_tag :tag => 'a', :content => 'Delete',
1226 assert_tag :tag => 'a', :content => 'Delete',
1227 :attributes => { :href => '/issues/destroy?ids%5B%5D=1',
1227 :attributes => { :href => '/issues/destroy?ids%5B%5D=1',
1228 :class => 'icon-del' }
1228 :class => 'icon-del' }
1229 end
1229 end
1230
1230
1231 def test_context_menu_one_issue_by_anonymous
1231 def test_context_menu_one_issue_by_anonymous
1232 get :context_menu, :ids => [1]
1232 get :context_menu, :ids => [1]
1233 assert_response :success
1233 assert_response :success
1234 assert_template 'context_menu'
1234 assert_template 'context_menu'
1235 assert_tag :tag => 'a', :content => 'Delete',
1235 assert_tag :tag => 'a', :content => 'Delete',
1236 :attributes => { :href => '#',
1236 :attributes => { :href => '#',
1237 :class => 'icon-del disabled' }
1237 :class => 'icon-del disabled' }
1238 end
1238 end
1239
1239
1240 def test_context_menu_multiple_issues_of_same_project
1240 def test_context_menu_multiple_issues_of_same_project
1241 @request.session[:user_id] = 2
1241 @request.session[:user_id] = 2
1242 get :context_menu, :ids => [1, 2]
1242 get :context_menu, :ids => [1, 2]
1243 assert_response :success
1243 assert_response :success
1244 assert_template 'context_menu'
1244 assert_template 'context_menu'
1245 assert_tag :tag => 'a', :content => 'Edit',
1245 assert_tag :tag => 'a', :content => 'Edit',
1246 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2',
1246 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2',
1247 :class => 'icon-edit' }
1247 :class => 'icon-edit' }
1248 assert_tag :tag => 'a', :content => 'Immediate',
1248 assert_tag :tag => 'a', :content => 'Immediate',
1249 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bpriority_id%5D=8',
1249 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bpriority_id%5D=8',
1250 :class => '' }
1250 :class => '' }
1251 assert_tag :tag => 'a', :content => 'Dave Lopper',
1251 assert_tag :tag => 'a', :content => 'Dave Lopper',
1252 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bassigned_to_id%5D=3',
1252 :attributes => { :href => '/issues/bulk_edit?ids%5B%5D=1&amp;ids%5B%5D=2&amp;issue%5Bassigned_to_id%5D=3',
1253 :class => '' }
1253 :class => '' }
1254 assert_tag :tag => 'a', :content => 'Copy',
1254 assert_tag :tag => 'a', :content => 'Copy',
1255 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1&amp;ids%5B%5D=2',
1255 :attributes => { :href => '/issues/move?copy_options%5Bcopy%5D=t&amp;ids%5B%5D=1&amp;ids%5B%5D=2',
1256 :class => 'icon-copy' }
1256 :class => 'icon-copy' }
1257 assert_tag :tag => 'a', :content => 'Move',
1257 assert_tag :tag => 'a', :content => 'Move',
1258 :attributes => { :href => '/issues/move?ids%5B%5D=1&amp;ids%5B%5D=2',
1258 :attributes => { :href => '/issues/move?ids%5B%5D=1&amp;ids%5B%5D=2',
1259 :class => 'icon-move' }
1259 :class => 'icon-move' }
1260 assert_tag :tag => 'a', :content => 'Delete',
1260 assert_tag :tag => 'a', :content => 'Delete',
1261 :attributes => { :href => '/issues/destroy?ids%5B%5D=1&amp;ids%5B%5D=2',
1261 :attributes => { :href => '/issues/destroy?ids%5B%5D=1&amp;ids%5B%5D=2',
1262 :class => 'icon-del' }
1262 :class => 'icon-del' }
1263 end
1263 end
1264
1264
1265 def test_context_menu_multiple_issues_of_different_project
1265 def test_context_menu_multiple_issues_of_different_project
1266 @request.session[:user_id] = 2
1266 @request.session[:user_id] = 2
1267 get :context_menu, :ids => [1, 2, 4]
1267 get :context_menu, :ids => [1, 2, 4]
1268 assert_response :success
1268 assert_response :success
1269 assert_template 'context_menu'
1269 assert_template 'context_menu'
1270 assert_tag :tag => 'a', :content => 'Delete',
1270 assert_tag :tag => 'a', :content => 'Delete',
1271 :attributes => { :href => '#',
1271 :attributes => { :href => '#',
1272 :class => 'icon-del disabled' }
1272 :class => 'icon-del disabled' }
1273 end
1273 end
1274
1274
1275 def test_preview_new_issue
1275 def test_preview_new_issue
1276 @request.session[:user_id] = 2
1276 @request.session[:user_id] = 2
1277 post :preview, :project_id => '1', :issue => {:description => 'Foo'}
1277 post :preview, :project_id => '1', :issue => {:description => 'Foo'}
1278 assert_response :success
1278 assert_response :success
1279 assert_template 'preview'
1279 assert_template 'preview'
1280 assert_not_nil assigns(:description)
1280 assert_not_nil assigns(:description)
1281 end
1281 end
1282
1282
1283 def test_preview_notes
1283 def test_preview_notes
1284 @request.session[:user_id] = 2
1284 @request.session[:user_id] = 2
1285 post :preview, :project_id => '1', :id => 1, :issue => {:description => Issue.find(1).description}, :notes => 'Foo'
1285 post :preview, :project_id => '1', :id => 1, :issue => {:description => Issue.find(1).description}, :notes => 'Foo'
1286 assert_response :success
1286 assert_response :success
1287 assert_template 'preview'
1287 assert_template 'preview'
1288 assert_not_nil assigns(:notes)
1288 assert_not_nil assigns(:notes)
1289 end
1289 end
1290
1290
1291 def test_auto_complete_should_not_be_case_sensitive
1291 def test_auto_complete_should_not_be_case_sensitive
1292 get :auto_complete, :project_id => 'ecookbook', :q => 'ReCiPe'
1292 get :auto_complete, :project_id => 'ecookbook', :q => 'ReCiPe'
1293 assert_response :success
1293 assert_response :success
1294 assert_not_nil assigns(:issues)
1294 assert_not_nil assigns(:issues)
1295 assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
1295 assert assigns(:issues).detect {|issue| issue.subject.match /recipe/}
1296 end
1296 end
1297
1297
1298 def test_auto_complete_should_return_issue_with_given_id
1298 def test_auto_complete_should_return_issue_with_given_id
1299 get :auto_complete, :project_id => 'subproject1', :q => '13'
1299 get :auto_complete, :project_id => 'subproject1', :q => '13'
1300 assert_response :success
1300 assert_response :success
1301 assert_not_nil assigns(:issues)
1301 assert_not_nil assigns(:issues)
1302 assert assigns(:issues).include?(Issue.find(13))
1302 assert assigns(:issues).include?(Issue.find(13))
1303 end
1303 end
1304
1304
1305 def test_destroy_issue_with_no_time_entries
1305 def test_destroy_issue_with_no_time_entries
1306 assert_nil TimeEntry.find_by_issue_id(2)
1306 assert_nil TimeEntry.find_by_issue_id(2)
1307 @request.session[:user_id] = 2
1307 @request.session[:user_id] = 2
1308 post :destroy, :id => 2
1308 post :destroy, :id => 2
1309 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1309 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1310 assert_nil Issue.find_by_id(2)
1310 assert_nil Issue.find_by_id(2)
1311 end
1311 end
1312
1312
1313 def test_destroy_issues_with_time_entries
1313 def test_destroy_issues_with_time_entries
1314 @request.session[:user_id] = 2
1314 @request.session[:user_id] = 2
1315 post :destroy, :ids => [1, 3]
1315 post :destroy, :ids => [1, 3]
1316 assert_response :success
1316 assert_response :success
1317 assert_template 'destroy'
1317 assert_template 'destroy'
1318 assert_not_nil assigns(:hours)
1318 assert_not_nil assigns(:hours)
1319 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1319 assert Issue.find_by_id(1) && Issue.find_by_id(3)
1320 end
1320 end
1321
1321
1322 def test_destroy_issues_and_destroy_time_entries
1322 def test_destroy_issues_and_destroy_time_entries
1323 @request.session[:user_id] = 2
1323 @request.session[:user_id] = 2
1324 post :destroy, :ids => [1, 3], :todo => 'destroy'
1324 post :destroy, :ids => [1, 3], :todo => 'destroy'
1325 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1325 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1326 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1326 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1327 assert_nil TimeEntry.find_by_id([1, 2])
1327 assert_nil TimeEntry.find_by_id([1, 2])
1328 end
1328 end
1329
1329
1330 def test_destroy_issues_and_assign_time_entries_to_project
1330 def test_destroy_issues_and_assign_time_entries_to_project
1331 @request.session[:user_id] = 2
1331 @request.session[:user_id] = 2
1332 post :destroy, :ids => [1, 3], :todo => 'nullify'
1332 post :destroy, :ids => [1, 3], :todo => 'nullify'
1333 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1333 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1334 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1334 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1335 assert_nil TimeEntry.find(1).issue_id
1335 assert_nil TimeEntry.find(1).issue_id
1336 assert_nil TimeEntry.find(2).issue_id
1336 assert_nil TimeEntry.find(2).issue_id
1337 end
1337 end
1338
1338
1339 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1339 def test_destroy_issues_and_reassign_time_entries_to_another_issue
1340 @request.session[:user_id] = 2
1340 @request.session[:user_id] = 2
1341 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1341 post :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
1342 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1342 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
1343 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1343 assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
1344 assert_equal 2, TimeEntry.find(1).issue_id
1344 assert_equal 2, TimeEntry.find(1).issue_id
1345 assert_equal 2, TimeEntry.find(2).issue_id
1345 assert_equal 2, TimeEntry.find(2).issue_id
1346 end
1346 end
1347
1347
1348 def test_default_search_scope
1348 def test_default_search_scope
1349 get :index
1349 get :index
1350 assert_tag :div, :attributes => {:id => 'quick-search'},
1350 assert_tag :div, :attributes => {:id => 'quick-search'},
1351 :child => {:tag => 'form',
1351 :child => {:tag => 'form',
1352 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1352 :child => {:tag => 'input', :attributes => {:name => 'issues', :type => 'hidden', :value => '1'}}}
1353 end
1353 end
1354 end
1354 end
@@ -1,280 +1,281
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, "/issues.xml", :controller => 'issues', :action => 'new', :format => 'xml'
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
75
75 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'
76 # TODO: Should use PUT
77 # TODO: Should use PUT
77 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'
78 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'
79
80
80 # TODO: Should use DELETE
81 # TODO: Should use DELETE
81 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'
82 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'
83
84
84 # Extra actions
85 # Extra actions
85 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'
86
87
87 should_route :get, "/issues/1/move", :controller => 'issues', :action => 'move', :id => '1'
88 should_route :get, "/issues/1/move", :controller => 'issues', :action => 'move', :id => '1'
88 should_route :post, "/issues/1/move", :controller => 'issues', :action => 'move', :id => '1'
89 should_route :post, "/issues/1/move", :controller => 'issues', :action => 'move', :id => '1'
89
90
90 should_route :post, "/issues/1/quoted", :controller => 'issues', :action => 'reply', :id => '1'
91 should_route :post, "/issues/1/quoted", :controller => 'issues', :action => 'reply', :id => '1'
91
92
92 should_route :get, "/issues/calendar", :controller => 'issues', :action => 'calendar'
93 should_route :get, "/issues/calendar", :controller => 'issues', :action => 'calendar'
93 should_route :post, "/issues/calendar", :controller => 'issues', :action => 'calendar'
94 should_route :post, "/issues/calendar", :controller => 'issues', :action => 'calendar'
94 should_route :get, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
95 should_route :get, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
95 should_route :post, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
96 should_route :post, "/projects/project-name/issues/calendar", :controller => 'issues', :action => 'calendar', :project_id => 'project-name'
96
97
97 should_route :get, "/issues/gantt", :controller => 'issues', :action => 'gantt'
98 should_route :get, "/issues/gantt", :controller => 'issues', :action => 'gantt'
98 should_route :post, "/issues/gantt", :controller => 'issues', :action => 'gantt'
99 should_route :post, "/issues/gantt", :controller => 'issues', :action => 'gantt'
99 should_route :get, "/projects/project-name/issues/gantt", :controller => 'issues', :action => 'gantt', :project_id => 'project-name'
100 should_route :get, "/projects/project-name/issues/gantt", :controller => 'issues', :action => 'gantt', :project_id => 'project-name'
100 should_route :post, "/projects/project-name/issues/gantt", :controller => 'issues', :action => 'gantt', :project_id => 'project-name'
101 should_route :post, "/projects/project-name/issues/gantt", :controller => 'issues', :action => 'gantt', :project_id => 'project-name'
101
102
102 should_route :get, "/issues/auto_complete", :controller => 'issues', :action => 'auto_complete'
103 should_route :get, "/issues/auto_complete", :controller => 'issues', :action => 'auto_complete'
103 end
104 end
104
105
105 context "issue categories" do
106 context "issue categories" do
106 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
107 should_route :get, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
107
108
108 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
109 should_route :post, "/projects/test/issue_categories/new", :controller => 'issue_categories', :action => 'new', :project_id => 'test'
109 end
110 end
110
111
111 context "issue relations" do
112 context "issue relations" do
112 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
113 should_route :post, "/issues/1/relations", :controller => 'issue_relations', :action => 'new', :issue_id => '1'
113 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
114 should_route :post, "/issues/1/relations/23/destroy", :controller => 'issue_relations', :action => 'destroy', :issue_id => '1', :id => '23'
114 end
115 end
115
116
116 context "issue reports" do
117 context "issue reports" do
117 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
118 should_route :get, "/projects/567/issues/report", :controller => 'reports', :action => 'issue_report', :id => '567'
118 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
119 should_route :get, "/projects/567/issues/report/assigned_to", :controller => 'reports', :action => 'issue_report_details', :id => '567', :detail => 'assigned_to'
119 end
120 end
120
121
121 context "members" do
122 context "members" do
122 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
123 should_route :post, "/projects/5234/members/new", :controller => 'members', :action => 'new', :id => '5234'
123 end
124 end
124
125
125 context "messages" do
126 context "messages" do
126 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
127 should_route :get, "/boards/22/topics/2", :controller => 'messages', :action => 'show', :id => '2', :board_id => '22'
127 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
128 should_route :get, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
128 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
129 should_route :get, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
129
130
130 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
131 should_route :post, "/boards/lala/topics/new", :controller => 'messages', :action => 'new', :board_id => 'lala'
131 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
132 should_route :post, "/boards/lala/topics/22/edit", :controller => 'messages', :action => 'edit', :id => '22', :board_id => 'lala'
132 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
133 should_route :post, "/boards/22/topics/555/replies", :controller => 'messages', :action => 'reply', :id => '555', :board_id => '22'
133 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
134 should_route :post, "/boards/22/topics/555/destroy", :controller => 'messages', :action => 'destroy', :id => '555', :board_id => '22'
134 end
135 end
135
136
136 context "news" do
137 context "news" do
137 should_route :get, "/news", :controller => 'news', :action => 'index'
138 should_route :get, "/news", :controller => 'news', :action => 'index'
138 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
139 should_route :get, "/news.atom", :controller => 'news', :action => 'index', :format => 'atom'
139 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
140 should_route :get, "/news.xml", :controller => 'news', :action => 'index', :format => 'xml'
140 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
141 should_route :get, "/news.json", :controller => 'news', :action => 'index', :format => 'json'
141 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
142 should_route :get, "/projects/567/news", :controller => 'news', :action => 'index', :project_id => '567'
142 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
143 should_route :get, "/projects/567/news.atom", :controller => 'news', :action => 'index', :format => 'atom', :project_id => '567'
143 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
144 should_route :get, "/projects/567/news.xml", :controller => 'news', :action => 'index', :format => 'xml', :project_id => '567'
144 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
145 should_route :get, "/projects/567/news.json", :controller => 'news', :action => 'index', :format => 'json', :project_id => '567'
145 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
146 should_route :get, "/news/2", :controller => 'news', :action => 'show', :id => '2'
146 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
147 should_route :get, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
147 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
148 should_route :get, "/news/234", :controller => 'news', :action => 'show', :id => '234'
148
149
149 should_route :post, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
150 should_route :post, "/projects/567/news/new", :controller => 'news', :action => 'new', :project_id => '567'
150 should_route :post, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
151 should_route :post, "/news/567/edit", :controller => 'news', :action => 'edit', :id => '567'
151 should_route :post, "/news/567/destroy", :controller => 'news', :action => 'destroy', :id => '567'
152 should_route :post, "/news/567/destroy", :controller => 'news', :action => 'destroy', :id => '567'
152 end
153 end
153
154
154 context "projects" do
155 context "projects" do
155 should_route :get, "/projects", :controller => 'projects', :action => 'index'
156 should_route :get, "/projects", :controller => 'projects', :action => 'index'
156 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
157 should_route :get, "/projects.atom", :controller => 'projects', :action => 'index', :format => 'atom'
157 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
158 should_route :get, "/projects.xml", :controller => 'projects', :action => 'index', :format => 'xml'
158 should_route :get, "/projects/new", :controller => 'projects', :action => 'add'
159 should_route :get, "/projects/new", :controller => 'projects', :action => 'add'
159 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
160 should_route :get, "/projects/test", :controller => 'projects', :action => 'show', :id => 'test'
160 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
161 should_route :get, "/projects/1.xml", :controller => 'projects', :action => 'show', :id => '1', :format => 'xml'
161 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
162 should_route :get, "/projects/4223/settings", :controller => 'projects', :action => 'settings', :id => '4223'
162 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
163 should_route :get, "/projects/4223/settings/members", :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
163 should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567'
164 should_route :get, "/projects/567/destroy", :controller => 'projects', :action => 'destroy', :id => '567'
164 should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33'
165 should_route :get, "/projects/33/files", :controller => 'projects', :action => 'list_files', :id => '33'
165 should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
166 should_route :get, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
166 should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33'
167 should_route :get, "/projects/33/roadmap", :controller => 'projects', :action => 'roadmap', :id => '33'
167 should_route :get, "/projects/33/activity", :controller => 'projects', :action => 'activity', :id => '33'
168 should_route :get, "/projects/33/activity", :controller => 'projects', :action => 'activity', :id => '33'
168 should_route :get, "/projects/33/activity.atom", :controller => 'projects', :action => 'activity', :id => '33', :format => 'atom'
169 should_route :get, "/projects/33/activity.atom", :controller => 'projects', :action => 'activity', :id => '33', :format => 'atom'
169
170
170 should_route :post, "/projects/new", :controller => 'projects', :action => 'add'
171 should_route :post, "/projects/new", :controller => 'projects', :action => 'add'
171 should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml'
172 should_route :post, "/projects.xml", :controller => 'projects', :action => 'add', :format => 'xml'
172 should_route :post, "/projects/4223/edit", :controller => 'projects', :action => 'edit', :id => '4223'
173 should_route :post, "/projects/4223/edit", :controller => 'projects', :action => 'edit', :id => '4223'
173 should_route :post, "/projects/64/destroy", :controller => 'projects', :action => 'destroy', :id => '64'
174 should_route :post, "/projects/64/destroy", :controller => 'projects', :action => 'destroy', :id => '64'
174 should_route :post, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
175 should_route :post, "/projects/33/files/new", :controller => 'projects', :action => 'add_file', :id => '33'
175 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
176 should_route :post, "/projects/64/archive", :controller => 'projects', :action => 'archive', :id => '64'
176 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
177 should_route :post, "/projects/64/unarchive", :controller => 'projects', :action => 'unarchive', :id => '64'
177 should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64'
178 should_route :post, "/projects/64/activities/save", :controller => 'projects', :action => 'save_activities', :id => '64'
178
179
179 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml'
180 should_route :put, "/projects/1.xml", :controller => 'projects', :action => 'edit', :id => '1', :format => 'xml'
180
181
181 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
182 should_route :delete, "/projects/1.xml", :controller => 'projects', :action => 'destroy', :id => '1', :format => 'xml'
182 should_route :delete, "/projects/64/reset_activities", :controller => 'projects', :action => 'reset_activities', :id => '64'
183 should_route :delete, "/projects/64/reset_activities", :controller => 'projects', :action => 'reset_activities', :id => '64'
183 end
184 end
184
185
185 context "repositories" do
186 context "repositories" do
186 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
187 should_route :get, "/projects/redmine/repository", :controller => 'repositories', :action => 'show', :id => 'redmine'
187 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
188 should_route :get, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
188 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
189 should_route :get, "/projects/redmine/repository/revisions", :controller => 'repositories', :action => 'revisions', :id => 'redmine'
189 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
190 should_route :get, "/projects/redmine/repository/revisions.atom", :controller => 'repositories', :action => 'revisions', :id => 'redmine', :format => 'atom'
190 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
191 should_route :get, "/projects/redmine/repository/revisions/2457", :controller => 'repositories', :action => 'revision', :id => 'redmine', :rev => '2457'
191 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
192 should_route :get, "/projects/redmine/repository/revisions/2457/diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457'
192 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
193 should_route :get, "/projects/redmine/repository/revisions/2457/diff.diff", :controller => 'repositories', :action => 'diff', :id => 'redmine', :rev => '2457', :format => 'diff'
193 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
194 should_route :get, "/projects/redmine/repository/diff/path/to/file.c", :controller => 'repositories', :action => 'diff', :id => 'redmine', :path => %w[path to file.c]
194 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'
195 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'
195 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
196 should_route :get, "/projects/redmine/repository/browse/path/to/file.c", :controller => 'repositories', :action => 'browse', :id => 'redmine', :path => %w[path to file.c]
196 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
197 should_route :get, "/projects/redmine/repository/entry/path/to/file.c", :controller => 'repositories', :action => 'entry', :id => 'redmine', :path => %w[path to file.c]
197 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'
198 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'
198 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'
199 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'
199 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'
200 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'
200 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
201 should_route :get, "/projects/redmine/repository/annotate/path/to/file.c", :controller => 'repositories', :action => 'annotate', :id => 'redmine', :path => %w[path to file.c]
201 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
202 should_route :get, "/projects/redmine/repository/changes/path/to/file.c", :controller => 'repositories', :action => 'changes', :id => 'redmine', :path => %w[path to file.c]
202 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
203 should_route :get, "/projects/redmine/repository/statistics", :controller => 'repositories', :action => 'stats', :id => 'redmine'
203
204
204
205
205 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
206 should_route :post, "/projects/redmine/repository/edit", :controller => 'repositories', :action => 'edit', :id => 'redmine'
206 end
207 end
207
208
208 context "timelogs" do
209 context "timelogs" do
209 should_route :get, "/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :issue_id => '567'
210 should_route :get, "/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :issue_id => '567'
210 should_route :get, "/projects/ecookbook/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook'
211 should_route :get, "/projects/ecookbook/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook'
211 should_route :get, "/projects/ecookbook/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook', :issue_id => '567'
212 should_route :get, "/projects/ecookbook/issues/567/time_entries/new", :controller => 'timelog', :action => 'edit', :project_id => 'ecookbook', :issue_id => '567'
212 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
213 should_route :get, "/time_entries/22/edit", :controller => 'timelog', :action => 'edit', :id => '22'
213 should_route :get, "/time_entries/report", :controller => 'timelog', :action => 'report'
214 should_route :get, "/time_entries/report", :controller => 'timelog', :action => 'report'
214 should_route :get, "/projects/567/time_entries/report", :controller => 'timelog', :action => 'report', :project_id => '567'
215 should_route :get, "/projects/567/time_entries/report", :controller => 'timelog', :action => 'report', :project_id => '567'
215 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'timelog', :action => 'report', :project_id => '567', :format => 'csv'
216 should_route :get, "/projects/567/time_entries/report.csv", :controller => 'timelog', :action => 'report', :project_id => '567', :format => 'csv'
216 should_route :get, "/time_entries", :controller => 'timelog', :action => 'details'
217 should_route :get, "/time_entries", :controller => 'timelog', :action => 'details'
217 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'details', :format => 'csv'
218 should_route :get, "/time_entries.csv", :controller => 'timelog', :action => 'details', :format => 'csv'
218 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'details', :format => 'atom'
219 should_route :get, "/time_entries.atom", :controller => 'timelog', :action => 'details', :format => 'atom'
219 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'details', :project_id => '567'
220 should_route :get, "/projects/567/time_entries", :controller => 'timelog', :action => 'details', :project_id => '567'
220 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'csv'
221 should_route :get, "/projects/567/time_entries.csv", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'csv'
221 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'atom'
222 should_route :get, "/projects/567/time_entries.atom", :controller => 'timelog', :action => 'details', :project_id => '567', :format => 'atom'
222 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'details', :issue_id => '234'
223 should_route :get, "/issues/234/time_entries", :controller => 'timelog', :action => 'details', :issue_id => '234'
223 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'csv'
224 should_route :get, "/issues/234/time_entries.csv", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'csv'
224 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'atom'
225 should_route :get, "/issues/234/time_entries.atom", :controller => 'timelog', :action => 'details', :issue_id => '234', :format => 'atom'
225 should_route :get, "/projects/ecookbook/issues/123/time_entries", :controller => 'timelog', :action => 'details', :project_id => 'ecookbook', :issue_id => '123'
226 should_route :get, "/projects/ecookbook/issues/123/time_entries", :controller => 'timelog', :action => 'details', :project_id => 'ecookbook', :issue_id => '123'
226
227
227 should_route :post, "/time_entries/55/destroy", :controller => 'timelog', :action => 'destroy', :id => '55'
228 should_route :post, "/time_entries/55/destroy", :controller => 'timelog', :action => 'destroy', :id => '55'
228 end
229 end
229
230
230 context "users" do
231 context "users" do
231 should_route :get, "/users", :controller => 'users', :action => 'index'
232 should_route :get, "/users", :controller => 'users', :action => 'index'
232 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
233 should_route :get, "/users/44", :controller => 'users', :action => 'show', :id => '44'
233 should_route :get, "/users/new", :controller => 'users', :action => 'add'
234 should_route :get, "/users/new", :controller => 'users', :action => 'add'
234 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
235 should_route :get, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
235 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
236 should_route :get, "/users/222/edit/membership", :controller => 'users', :action => 'edit', :id => '222', :tab => 'membership'
236
237
237 should_route :post, "/users/new", :controller => 'users', :action => 'add'
238 should_route :post, "/users/new", :controller => 'users', :action => 'add'
238 should_route :post, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
239 should_route :post, "/users/444/edit", :controller => 'users', :action => 'edit', :id => '444'
239 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
240 should_route :post, "/users/123/memberships", :controller => 'users', :action => 'edit_membership', :id => '123'
240 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
241 should_route :post, "/users/123/memberships/55", :controller => 'users', :action => 'edit_membership', :id => '123', :membership_id => '55'
241 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
242 should_route :post, "/users/567/memberships/12/destroy", :controller => 'users', :action => 'destroy_membership', :id => '567', :membership_id => '12'
242 end
243 end
243
244
244 context "versions" do
245 context "versions" do
245 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
246 should_route :get, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
246
247
247 should_route :post, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
248 should_route :post, "/projects/foo/versions/new", :controller => 'versions', :action => 'new', :project_id => 'foo'
248 end
249 end
249
250
250 context "wiki (singular, project's pages)" do
251 context "wiki (singular, project's pages)" do
251 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :id => '567'
252 should_route :get, "/projects/567/wiki", :controller => 'wiki', :action => 'index', :id => '567'
252 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :id => '567', :page => 'lalala'
253 should_route :get, "/projects/567/wiki/lalala", :controller => 'wiki', :action => 'index', :id => '567', :page => 'lalala'
253 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
254 should_route :get, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
254 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :id => '1', :page => 'CookBook_documentation'
255 should_route :get, "/projects/1/wiki/CookBook_documentation/history", :controller => 'wiki', :action => 'history', :id => '1', :page => 'CookBook_documentation'
255 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'
256 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'
256 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :id => '1', :page => 'CookBook_documentation', :version => '2'
257 should_route :get, "/projects/1/wiki/CookBook_documentation/annotate/2", :controller => 'wiki', :action => 'annotate', :id => '1', :page => 'CookBook_documentation', :version => '2'
257 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
258 should_route :get, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
258 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'page_index'
259 should_route :get, "/projects/567/wiki/page_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'page_index'
259 should_route :get, "/projects/567/wiki/Page_Index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'Page_Index'
260 should_route :get, "/projects/567/wiki/Page_Index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'Page_Index'
260 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'date_index'
261 should_route :get, "/projects/567/wiki/date_index", :controller => 'wiki', :action => 'special', :id => '567', :page => 'date_index'
261 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'special', :id => '567', :page => 'export'
262 should_route :get, "/projects/567/wiki/export", :controller => 'wiki', :action => 'special', :id => '567', :page => 'export'
262
263
263 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
264 should_route :post, "/projects/567/wiki/my_page/edit", :controller => 'wiki', :action => 'edit', :id => '567', :page => 'my_page'
264 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :id => '567', :page => 'CookBook_documentation'
265 should_route :post, "/projects/567/wiki/CookBook_documentation/preview", :controller => 'wiki', :action => 'preview', :id => '567', :page => 'CookBook_documentation'
265 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
266 should_route :post, "/projects/22/wiki/ladida/rename", :controller => 'wiki', :action => 'rename', :id => '22', :page => 'ladida'
266 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :id => '22', :page => 'ladida'
267 should_route :post, "/projects/22/wiki/ladida/destroy", :controller => 'wiki', :action => 'destroy', :id => '22', :page => 'ladida'
267 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :id => '22', :page => 'ladida'
268 should_route :post, "/projects/22/wiki/ladida/protect", :controller => 'wiki', :action => 'protect', :id => '22', :page => 'ladida'
268 end
269 end
269
270
270 context "wikis (plural, admin setup)" do
271 context "wikis (plural, admin setup)" do
271 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
272 should_route :get, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
272
273
273 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
274 should_route :post, "/projects/ladida/wiki", :controller => 'wikis', :action => 'edit', :id => 'ladida'
274 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
275 should_route :post, "/projects/ladida/wiki/destroy", :controller => 'wikis', :action => 'destroy', :id => 'ladida'
275 end
276 end
276
277
277 context "administration panel" do
278 context "administration panel" do
278 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
279 should_route :get, "/admin/projects", :controller => 'admin', :action => 'projects'
279 end
280 end
280 end
281 end
General Comments 0
You need to be logged in to leave comments. Login now