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