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