##// END OF EJS Templates
Merged r14856 (#21155)....
Jean-Philippe Lang -
r14478:40ba35f6c228
parent child
Show More
@@ -1,367 +1,370
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 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 # The WikiController follows the Rails REST controller pattern but with
18 # The WikiController follows the Rails REST controller pattern but with
19 # a few differences
19 # a few differences
20 #
20 #
21 # * index - shows a list of WikiPages grouped by page or date
21 # * index - shows a list of WikiPages grouped by page or date
22 # * new - not used
22 # * new - not used
23 # * create - not used
23 # * create - not used
24 # * show - will also show the form for creating a new wiki page
24 # * show - will also show the form for creating a new wiki page
25 # * edit - used to edit an existing or new page
25 # * edit - used to edit an existing or new page
26 # * update - used to save a wiki page update to the database, including new pages
26 # * update - used to save a wiki page update to the database, including new pages
27 # * destroy - normal
27 # * destroy - normal
28 #
28 #
29 # Other member and collection methods are also used
29 # Other member and collection methods are also used
30 #
30 #
31 # TODO: still being worked on
31 # TODO: still being worked on
32 class WikiController < ApplicationController
32 class WikiController < ApplicationController
33 default_search_scope :wiki_pages
33 default_search_scope :wiki_pages
34 before_filter :find_wiki, :authorize
34 before_filter :find_wiki, :authorize
35 before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
35 before_filter :find_existing_or_new_page, :only => [:show, :edit, :update]
36 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
36 before_filter :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
37 accept_api_auth :index, :show, :update, :destroy
37 accept_api_auth :index, :show, :update, :destroy
38 before_filter :find_attachments, :only => [:preview]
38 before_filter :find_attachments, :only => [:preview]
39
39
40 helper :attachments
40 helper :attachments
41 include AttachmentsHelper
41 include AttachmentsHelper
42 helper :watchers
42 helper :watchers
43 include Redmine::Export::PDF
43 include Redmine::Export::PDF
44
44
45 # List of pages, sorted alphabetically and by parent (hierarchy)
45 # List of pages, sorted alphabetically and by parent (hierarchy)
46 def index
46 def index
47 load_pages_for_index
47 load_pages_for_index
48
48
49 respond_to do |format|
49 respond_to do |format|
50 format.html {
50 format.html {
51 @pages_by_parent_id = @pages.group_by(&:parent_id)
51 @pages_by_parent_id = @pages.group_by(&:parent_id)
52 }
52 }
53 format.api
53 format.api
54 end
54 end
55 end
55 end
56
56
57 # List of page, by last update
57 # List of page, by last update
58 def date_index
58 def date_index
59 load_pages_for_index
59 load_pages_for_index
60 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
60 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
61 end
61 end
62
62
63 # display a page (in editing mode if it doesn't exist)
63 # display a page (in editing mode if it doesn't exist)
64 def show
64 def show
65 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
65 if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
66 deny_access
66 deny_access
67 return
67 return
68 end
68 end
69 @content = @page.content_for_version(params[:version])
69 @content = @page.content_for_version(params[:version])
70 if @content.nil?
70 if @content.nil?
71 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
71 if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
72 edit
72 edit
73 render :action => 'edit'
73 render :action => 'edit'
74 else
74 else
75 render_404
75 render_404
76 end
76 end
77 return
77 return
78 end
78 end
79 if User.current.allowed_to?(:export_wiki_pages, @project)
79 if User.current.allowed_to?(:export_wiki_pages, @project)
80 if params[:format] == 'pdf'
80 if params[:format] == 'pdf'
81 send_file_headers! :type => 'application/pdf', :filename => "#{@page.title}.pdf"
81 send_file_headers! :type => 'application/pdf', :filename => "#{@page.title}.pdf"
82 return
82 return
83 elsif params[:format] == 'html'
83 elsif params[:format] == 'html'
84 export = render_to_string :action => 'export', :layout => false
84 export = render_to_string :action => 'export', :layout => false
85 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
85 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
86 return
86 return
87 elsif params[:format] == 'txt'
87 elsif params[:format] == 'txt'
88 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
88 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
89 return
89 return
90 end
90 end
91 end
91 end
92 @editable = editable?
92 @editable = editable?
93 @sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
93 @sections_editable = @editable && User.current.allowed_to?(:edit_wiki_pages, @page.project) &&
94 @content.current_version? &&
94 @content.current_version? &&
95 Redmine::WikiFormatting.supports_section_edit?
95 Redmine::WikiFormatting.supports_section_edit?
96
96
97 respond_to do |format|
97 respond_to do |format|
98 format.html
98 format.html
99 format.api
99 format.api
100 end
100 end
101 end
101 end
102
102
103 # edit an existing page or a new one
103 # edit an existing page or a new one
104 def edit
104 def edit
105 return render_403 unless editable?
105 return render_403 unless editable?
106 if @page.new_record?
106 if @page.new_record?
107 if params[:parent].present?
107 if params[:parent].present?
108 @page.parent = @page.wiki.find_page(params[:parent].to_s)
108 @page.parent = @page.wiki.find_page(params[:parent].to_s)
109 end
109 end
110 end
110 end
111
111
112 @content = @page.content_for_version(params[:version])
112 @content = @page.content_for_version(params[:version])
113 @content ||= WikiContent.new(:page => @page)
113 @content ||= WikiContent.new(:page => @page)
114 @content.text = initial_page_content(@page) if @content.text.blank?
114 @content.text = initial_page_content(@page) if @content.text.blank?
115 # don't keep previous comment
115 # don't keep previous comment
116 @content.comments = nil
116 @content.comments = nil
117
117
118 # To prevent StaleObjectError exception when reverting to a previous version
118 # To prevent StaleObjectError exception when reverting to a previous version
119 @content.version = @page.content.version if @page.content
119 @content.version = @page.content.version if @page.content
120
120
121 @text = @content.text
121 @text = @content.text
122 if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
122 if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
123 @section = params[:section].to_i
123 @section = params[:section].to_i
124 @text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
124 @text, @section_hash = Redmine::WikiFormatting.formatter.new(@text).get_section(@section)
125 render_404 if @text.blank?
125 render_404 if @text.blank?
126 end
126 end
127 end
127 end
128
128
129 # Creates a new page or updates an existing one
129 # Creates a new page or updates an existing one
130 def update
130 def update
131 return render_403 unless editable?
131 return render_403 unless editable?
132 was_new_page = @page.new_record?
132 was_new_page = @page.new_record?
133 @page.safe_attributes = params[:wiki_page]
133 @page.safe_attributes = params[:wiki_page]
134
134
135 @content = @page.content || WikiContent.new(:page => @page)
135 @content = @page.content || WikiContent.new(:page => @page)
136 content_params = params[:content]
136 content_params = params[:content]
137 if content_params.nil? && params[:wiki_page].is_a?(Hash)
137 if content_params.nil? && params[:wiki_page].is_a?(Hash)
138 content_params = params[:wiki_page].slice(:text, :comments, :version)
138 content_params = params[:wiki_page].slice(:text, :comments, :version)
139 end
139 end
140 content_params ||= {}
140 content_params ||= {}
141
141
142 @content.comments = content_params[:comments]
142 @content.comments = content_params[:comments]
143 @text = content_params[:text]
143 @text = content_params[:text]
144 if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
144 if params[:section].present? && Redmine::WikiFormatting.supports_section_edit?
145 @section = params[:section].to_i
145 @section = params[:section].to_i
146 @section_hash = params[:section_hash]
146 @section_hash = params[:section_hash]
147 @content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(@section, @text, @section_hash)
147 @content.text = Redmine::WikiFormatting.formatter.new(@content.text).update_section(@section, @text, @section_hash)
148 else
148 else
149 @content.version = content_params[:version] if content_params[:version]
149 @content.version = content_params[:version] if content_params[:version]
150 @content.text = @text
150 @content.text = @text
151 end
151 end
152 @content.author = User.current
152 @content.author = User.current
153
153
154 if @page.save_with_content(@content)
154 if @page.save_with_content(@content)
155 attachments = Attachment.attach_files(@page, params[:attachments])
155 attachments = Attachment.attach_files(@page, params[:attachments])
156 render_attachment_warning_if_needed(@page)
156 render_attachment_warning_if_needed(@page)
157 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
157 call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
158
158
159 respond_to do |format|
159 respond_to do |format|
160 format.html {
160 format.html {
161 anchor = @section ? "section-#{@section}" : nil
161 anchor = @section ? "section-#{@section}" : nil
162 redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor)
162 redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor)
163 }
163 }
164 format.api {
164 format.api {
165 if was_new_page
165 if was_new_page
166 render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
166 render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
167 else
167 else
168 render_api_ok
168 render_api_ok
169 end
169 end
170 }
170 }
171 end
171 end
172 else
172 else
173 respond_to do |format|
173 respond_to do |format|
174 format.html { render :action => 'edit' }
174 format.html { render :action => 'edit' }
175 format.api { render_validation_errors(@content) }
175 format.api { render_validation_errors(@content) }
176 end
176 end
177 end
177 end
178
178
179 rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError
179 rescue ActiveRecord::StaleObjectError, Redmine::WikiFormatting::StaleSectionError
180 # Optimistic locking exception
180 # Optimistic locking exception
181 respond_to do |format|
181 respond_to do |format|
182 format.html {
182 format.html {
183 flash.now[:error] = l(:notice_locking_conflict)
183 flash.now[:error] = l(:notice_locking_conflict)
184 render :action => 'edit'
184 render :action => 'edit'
185 }
185 }
186 format.api { render_api_head :conflict }
186 format.api { render_api_head :conflict }
187 end
187 end
188 end
188 end
189
189
190 # rename a page
190 # rename a page
191 def rename
191 def rename
192 return render_403 unless editable?
192 return render_403 unless editable?
193 @page.redirect_existing_links = true
193 @page.redirect_existing_links = true
194 # used to display the *original* title if some AR validation errors occur
194 # used to display the *original* title if some AR validation errors occur
195 @original_title = @page.pretty_title
195 @original_title = @page.pretty_title
196 @page.safe_attributes = params[:wiki_page]
196 @page.safe_attributes = params[:wiki_page]
197 if request.post? && @page.save
197 if request.post? && @page.save
198 flash[:notice] = l(:notice_successful_update)
198 flash[:notice] = l(:notice_successful_update)
199 redirect_to project_wiki_page_path(@page.project, @page.title)
199 redirect_to project_wiki_page_path(@page.project, @page.title)
200 end
200 end
201 end
201 end
202
202
203 def protect
203 def protect
204 @page.update_attribute :protected, params[:protected]
204 @page.update_attribute :protected, params[:protected]
205 redirect_to project_wiki_page_path(@project, @page.title)
205 redirect_to project_wiki_page_path(@project, @page.title)
206 end
206 end
207
207
208 # show page history
208 # show page history
209 def history
209 def history
210 @version_count = @page.content.versions.count
210 @version_count = @page.content.versions.count
211 @version_pages = Paginator.new @version_count, per_page_option, params['page']
211 @version_pages = Paginator.new @version_count, per_page_option, params['page']
212 # don't load text
212 # don't load text
213 @versions = @page.content.versions.
213 @versions = @page.content.versions.
214 select("id, author_id, comments, updated_on, version").
214 select("id, author_id, comments, updated_on, version").
215 reorder('version DESC').
215 reorder('version DESC').
216 limit(@version_pages.per_page + 1).
216 limit(@version_pages.per_page + 1).
217 offset(@version_pages.offset).
217 offset(@version_pages.offset).
218 to_a
218 to_a
219
219
220 render :layout => false if request.xhr?
220 render :layout => false if request.xhr?
221 end
221 end
222
222
223 def diff
223 def diff
224 @diff = @page.diff(params[:version], params[:version_from])
224 @diff = @page.diff(params[:version], params[:version_from])
225 render_404 unless @diff
225 render_404 unless @diff
226 end
226 end
227
227
228 def annotate
228 def annotate
229 @annotate = @page.annotate(params[:version])
229 @annotate = @page.annotate(params[:version])
230 render_404 unless @annotate
230 render_404 unless @annotate
231 end
231 end
232
232
233 # Removes a wiki page and its history
233 # Removes a wiki page and its history
234 # Children can be either set as root pages, removed or reassigned to another parent page
234 # Children can be either set as root pages, removed or reassigned to another parent page
235 def destroy
235 def destroy
236 return render_403 unless editable?
236 return render_403 unless editable?
237
237
238 @descendants_count = @page.descendants.size
238 @descendants_count = @page.descendants.size
239 if @descendants_count > 0
239 if @descendants_count > 0
240 case params[:todo]
240 case params[:todo]
241 when 'nullify'
241 when 'nullify'
242 # Nothing to do
242 # Nothing to do
243 when 'destroy'
243 when 'destroy'
244 # Removes all its descendants
244 # Removes all its descendants
245 @page.descendants.each(&:destroy)
245 @page.descendants.each(&:destroy)
246 when 'reassign'
246 when 'reassign'
247 # Reassign children to another parent page
247 # Reassign children to another parent page
248 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
248 reassign_to = @wiki.pages.find_by_id(params[:reassign_to_id].to_i)
249 return unless reassign_to
249 return unless reassign_to
250 @page.children.each do |child|
250 @page.children.each do |child|
251 child.update_attribute(:parent, reassign_to)
251 child.update_attribute(:parent, reassign_to)
252 end
252 end
253 else
253 else
254 @reassignable_to = @wiki.pages - @page.self_and_descendants
254 @reassignable_to = @wiki.pages - @page.self_and_descendants
255 # display the destroy form if it's a user request
255 # display the destroy form if it's a user request
256 return unless api_request?
256 return unless api_request?
257 end
257 end
258 end
258 end
259 @page.destroy
259 @page.destroy
260 respond_to do |format|
260 respond_to do |format|
261 format.html { redirect_to project_wiki_index_path(@project) }
261 format.html { redirect_to project_wiki_index_path(@project) }
262 format.api { render_api_ok }
262 format.api { render_api_ok }
263 end
263 end
264 end
264 end
265
265
266 def destroy_version
266 def destroy_version
267 return render_403 unless editable?
267 return render_403 unless editable?
268
268
269 @content = @page.content_for_version(params[:version])
269 if content = @page.content.versions.find_by_version(params[:version])
270 @content.destroy
270 content.destroy
271 redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
271 redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
272 else
273 render_404
274 end
272 end
275 end
273
276
274 # Export wiki to a single pdf or html file
277 # Export wiki to a single pdf or html file
275 def export
278 def export
276 @pages = @wiki.pages.
279 @pages = @wiki.pages.
277 order('title').
280 order('title').
278 includes([:content, {:attachments => :author}]).
281 includes([:content, {:attachments => :author}]).
279 to_a
282 to_a
280 respond_to do |format|
283 respond_to do |format|
281 format.html {
284 format.html {
282 export = render_to_string :action => 'export_multiple', :layout => false
285 export = render_to_string :action => 'export_multiple', :layout => false
283 send_data(export, :type => 'text/html', :filename => "wiki.html")
286 send_data(export, :type => 'text/html', :filename => "wiki.html")
284 }
287 }
285 format.pdf {
288 format.pdf {
286 send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}.pdf"
289 send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}.pdf"
287 }
290 }
288 end
291 end
289 end
292 end
290
293
291 def preview
294 def preview
292 page = @wiki.find_page(params[:id])
295 page = @wiki.find_page(params[:id])
293 # page is nil when previewing a new page
296 # page is nil when previewing a new page
294 return render_403 unless page.nil? || editable?(page)
297 return render_403 unless page.nil? || editable?(page)
295 if page
298 if page
296 @attachments += page.attachments
299 @attachments += page.attachments
297 @previewed = page.content
300 @previewed = page.content
298 end
301 end
299 @text = params[:content][:text]
302 @text = params[:content][:text]
300 render :partial => 'common/preview'
303 render :partial => 'common/preview'
301 end
304 end
302
305
303 def add_attachment
306 def add_attachment
304 return render_403 unless editable?
307 return render_403 unless editable?
305 attachments = Attachment.attach_files(@page, params[:attachments])
308 attachments = Attachment.attach_files(@page, params[:attachments])
306 render_attachment_warning_if_needed(@page)
309 render_attachment_warning_if_needed(@page)
307 redirect_to :action => 'show', :id => @page.title, :project_id => @project
310 redirect_to :action => 'show', :id => @page.title, :project_id => @project
308 end
311 end
309
312
310 private
313 private
311
314
312 def find_wiki
315 def find_wiki
313 @project = Project.find(params[:project_id])
316 @project = Project.find(params[:project_id])
314 @wiki = @project.wiki
317 @wiki = @project.wiki
315 render_404 unless @wiki
318 render_404 unless @wiki
316 rescue ActiveRecord::RecordNotFound
319 rescue ActiveRecord::RecordNotFound
317 render_404
320 render_404
318 end
321 end
319
322
320 # Finds the requested page or a new page if it doesn't exist
323 # Finds the requested page or a new page if it doesn't exist
321 def find_existing_or_new_page
324 def find_existing_or_new_page
322 @page = @wiki.find_or_new_page(params[:id])
325 @page = @wiki.find_or_new_page(params[:id])
323 if @wiki.page_found_with_redirect?
326 if @wiki.page_found_with_redirect?
324 redirect_to_page @page
327 redirect_to_page @page
325 end
328 end
326 end
329 end
327
330
328 # Finds the requested page and returns a 404 error if it doesn't exist
331 # Finds the requested page and returns a 404 error if it doesn't exist
329 def find_existing_page
332 def find_existing_page
330 @page = @wiki.find_page(params[:id])
333 @page = @wiki.find_page(params[:id])
331 if @page.nil?
334 if @page.nil?
332 render_404
335 render_404
333 return
336 return
334 end
337 end
335 if @wiki.page_found_with_redirect?
338 if @wiki.page_found_with_redirect?
336 redirect_to_page @page
339 redirect_to_page @page
337 end
340 end
338 end
341 end
339
342
340 def redirect_to_page(page)
343 def redirect_to_page(page)
341 if page.project && page.project.visible?
344 if page.project && page.project.visible?
342 redirect_to :action => action_name, :project_id => page.project, :id => page.title
345 redirect_to :action => action_name, :project_id => page.project, :id => page.title
343 else
346 else
344 render_404
347 render_404
345 end
348 end
346 end
349 end
347
350
348 # Returns true if the current user is allowed to edit the page, otherwise false
351 # Returns true if the current user is allowed to edit the page, otherwise false
349 def editable?(page = @page)
352 def editable?(page = @page)
350 page.editable_by?(User.current)
353 page.editable_by?(User.current)
351 end
354 end
352
355
353 # Returns the default content of a new wiki page
356 # Returns the default content of a new wiki page
354 def initial_page_content(page)
357 def initial_page_content(page)
355 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
358 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
356 extend helper unless self.instance_of?(helper)
359 extend helper unless self.instance_of?(helper)
357 helper.instance_method(:initial_page_content).bind(self).call(page)
360 helper.instance_method(:initial_page_content).bind(self).call(page)
358 end
361 end
359
362
360 def load_pages_for_index
363 def load_pages_for_index
361 @pages = @wiki.pages.with_updated_on.
364 @pages = @wiki.pages.with_updated_on.
362 reorder("#{WikiPage.table_name}.title").
365 reorder("#{WikiPage.table_name}.title").
363 includes(:wiki => :project).
366 includes(:wiki => :project).
364 includes(:parent).
367 includes(:parent).
365 to_a
368 to_a
366 end
369 end
367 end
370 end
@@ -1,961 +1,973
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class WikiControllerTest < ActionController::TestCase
20 class WikiControllerTest < ActionController::TestCase
21 fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
21 fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
22 :enabled_modules, :wikis, :wiki_pages, :wiki_contents,
22 :enabled_modules, :wikis, :wiki_pages, :wiki_contents,
23 :wiki_content_versions, :attachments,
23 :wiki_content_versions, :attachments,
24 :issues, :issue_statuses
24 :issues, :issue_statuses
25
25
26 def setup
26 def setup
27 User.current = nil
27 User.current = nil
28 end
28 end
29
29
30 def test_show_start_page
30 def test_show_start_page
31 get :show, :project_id => 'ecookbook'
31 get :show, :project_id => 'ecookbook'
32 assert_response :success
32 assert_response :success
33 assert_template 'show'
33 assert_template 'show'
34 assert_select 'h1', :text => /CookBook documentation/
34 assert_select 'h1', :text => /CookBook documentation/
35
35
36 # child_pages macro
36 # child_pages macro
37 assert_select 'ul.pages-hierarchy>li>a[href=?]', '/projects/ecookbook/wiki/Page_with_an_inline_image',
37 assert_select 'ul.pages-hierarchy>li>a[href=?]', '/projects/ecookbook/wiki/Page_with_an_inline_image',
38 :text => 'Page with an inline image'
38 :text => 'Page with an inline image'
39 end
39 end
40
40
41 def test_export_link
41 def test_export_link
42 Role.anonymous.add_permission! :export_wiki_pages
42 Role.anonymous.add_permission! :export_wiki_pages
43 get :show, :project_id => 'ecookbook'
43 get :show, :project_id => 'ecookbook'
44 assert_response :success
44 assert_response :success
45 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation.txt'
45 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation.txt'
46 end
46 end
47
47
48 def test_show_page_with_name
48 def test_show_page_with_name
49 get :show, :project_id => 1, :id => 'Another_page'
49 get :show, :project_id => 1, :id => 'Another_page'
50 assert_response :success
50 assert_response :success
51 assert_template 'show'
51 assert_template 'show'
52 assert_select 'h1', :text => /Another page/
52 assert_select 'h1', :text => /Another page/
53 # Included page with an inline image
53 # Included page with an inline image
54 assert_select 'p', :text => /This is an inline image/
54 assert_select 'p', :text => /This is an inline image/
55 assert_select 'img[src=?][alt=?]', '/attachments/download/3/logo.gif', 'This is a logo'
55 assert_select 'img[src=?][alt=?]', '/attachments/download/3/logo.gif', 'This is a logo'
56 end
56 end
57
57
58 def test_show_old_version
58 def test_show_old_version
59 with_settings :default_language => 'en' do
59 with_settings :default_language => 'en' do
60 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
60 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
61 end
61 end
62 assert_response :success
62 assert_response :success
63 assert_template 'show'
63 assert_template 'show'
64
64
65 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/1', :text => /Previous/
65 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/1', :text => /Previous/
66 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/diff', :text => /diff/
66 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/diff', :text => /diff/
67 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/3', :text => /Next/
67 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/3', :text => /Next/
68 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
68 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
69 end
69 end
70
70
71 def test_show_old_version_with_attachments
71 def test_show_old_version_with_attachments
72 page = WikiPage.find(4)
72 page = WikiPage.find(4)
73 assert page.attachments.any?
73 assert page.attachments.any?
74 content = page.content
74 content = page.content
75 content.text = "update"
75 content.text = "update"
76 content.save!
76 content.save!
77
77
78 get :show, :project_id => 'ecookbook', :id => page.title, :version => '1'
78 get :show, :project_id => 'ecookbook', :id => page.title, :version => '1'
79 assert_kind_of WikiContent::Version, assigns(:content)
79 assert_kind_of WikiContent::Version, assigns(:content)
80 assert_response :success
80 assert_response :success
81 assert_template 'show'
81 assert_template 'show'
82 end
82 end
83
83
84 def test_show_old_version_without_permission_should_be_denied
84 def test_show_old_version_without_permission_should_be_denied
85 Role.anonymous.remove_permission! :view_wiki_edits
85 Role.anonymous.remove_permission! :view_wiki_edits
86
86
87 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
87 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '2'
88 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fprojects%2Fecookbook%2Fwiki%2FCookBook_documentation%2F2'
88 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fprojects%2Fecookbook%2Fwiki%2FCookBook_documentation%2F2'
89 end
89 end
90
90
91 def test_show_first_version
91 def test_show_first_version
92 with_settings :default_language => 'en' do
92 with_settings :default_language => 'en' do
93 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
93 get :show, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => '1'
94 end
94 end
95 assert_response :success
95 assert_response :success
96 assert_template 'show'
96 assert_template 'show'
97
97
98 assert_select 'a', :text => /Previous/, :count => 0
98 assert_select 'a', :text => /Previous/, :count => 0
99 assert_select 'a', :text => /diff/, :count => 0
99 assert_select 'a', :text => /diff/, :count => 0
100 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => /Next/
100 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => /Next/
101 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
101 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => /Current version/
102 end
102 end
103
103
104 def test_show_redirected_page
104 def test_show_redirected_page
105 WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
105 WikiRedirect.create!(:wiki_id => 1, :title => 'Old_title', :redirects_to => 'Another_page')
106
106
107 get :show, :project_id => 'ecookbook', :id => 'Old_title'
107 get :show, :project_id => 'ecookbook', :id => 'Old_title'
108 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
108 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
109 end
109 end
110
110
111 def test_show_with_sidebar
111 def test_show_with_sidebar
112 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
112 page = Project.find(1).wiki.pages.new(:title => 'Sidebar')
113 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
113 page.content = WikiContent.new(:text => 'Side bar content for test_show_with_sidebar')
114 page.save!
114 page.save!
115
115
116 get :show, :project_id => 1, :id => 'Another_page'
116 get :show, :project_id => 1, :id => 'Another_page'
117 assert_response :success
117 assert_response :success
118 assert_select 'div#sidebar', :text => /Side bar content for test_show_with_sidebar/
118 assert_select 'div#sidebar', :text => /Side bar content for test_show_with_sidebar/
119 end
119 end
120
120
121 def test_show_should_display_section_edit_links
121 def test_show_should_display_section_edit_links
122 @request.session[:user_id] = 2
122 @request.session[:user_id] = 2
123 get :show, :project_id => 1, :id => 'Page with sections'
123 get :show, :project_id => 1, :id => 'Page with sections'
124
124
125 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=1', 0
125 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=1', 0
126 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
126 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
127 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=3'
127 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=3'
128 end
128 end
129
129
130 def test_show_current_version_should_display_section_edit_links
130 def test_show_current_version_should_display_section_edit_links
131 @request.session[:user_id] = 2
131 @request.session[:user_id] = 2
132 get :show, :project_id => 1, :id => 'Page with sections', :version => 3
132 get :show, :project_id => 1, :id => 'Page with sections', :version => 3
133
133
134 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
134 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2'
135 end
135 end
136
136
137 def test_show_old_version_should_not_display_section_edit_links
137 def test_show_old_version_should_not_display_section_edit_links
138 @request.session[:user_id] = 2
138 @request.session[:user_id] = 2
139 get :show, :project_id => 1, :id => 'Page with sections', :version => 2
139 get :show, :project_id => 1, :id => 'Page with sections', :version => 2
140
140
141 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2', 0
141 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Page_with_sections/edit?section=2', 0
142 end
142 end
143
143
144 def test_show_unexistent_page_without_edit_right
144 def test_show_unexistent_page_without_edit_right
145 get :show, :project_id => 1, :id => 'Unexistent page'
145 get :show, :project_id => 1, :id => 'Unexistent page'
146 assert_response 404
146 assert_response 404
147 end
147 end
148
148
149 def test_show_unexistent_page_with_edit_right
149 def test_show_unexistent_page_with_edit_right
150 @request.session[:user_id] = 2
150 @request.session[:user_id] = 2
151 get :show, :project_id => 1, :id => 'Unexistent page'
151 get :show, :project_id => 1, :id => 'Unexistent page'
152 assert_response :success
152 assert_response :success
153 assert_template 'edit'
153 assert_template 'edit'
154 end
154 end
155
155
156 def test_show_specific_version_of_an_unexistent_page_without_edit_right
156 def test_show_specific_version_of_an_unexistent_page_without_edit_right
157 get :show, :project_id => 1, :id => 'Unexistent page', :version => 1
157 get :show, :project_id => 1, :id => 'Unexistent page', :version => 1
158 assert_response 404
158 assert_response 404
159 end
159 end
160
160
161 def test_show_unexistent_page_with_parent_should_preselect_parent
161 def test_show_unexistent_page_with_parent_should_preselect_parent
162 @request.session[:user_id] = 2
162 @request.session[:user_id] = 2
163 get :show, :project_id => 1, :id => 'Unexistent page', :parent => 'Another_page'
163 get :show, :project_id => 1, :id => 'Unexistent page', :parent => 'Another_page'
164 assert_response :success
164 assert_response :success
165 assert_template 'edit'
165 assert_template 'edit'
166 assert_select 'select[name=?] option[value="2"][selected=selected]', 'wiki_page[parent_id]'
166 assert_select 'select[name=?] option[value="2"][selected=selected]', 'wiki_page[parent_id]'
167 end
167 end
168
168
169 def test_show_should_not_show_history_without_permission
169 def test_show_should_not_show_history_without_permission
170 Role.anonymous.remove_permission! :view_wiki_edits
170 Role.anonymous.remove_permission! :view_wiki_edits
171 get :show, :project_id => 1, :id => 'Page with sections', :version => 2
171 get :show, :project_id => 1, :id => 'Page with sections', :version => 2
172
172
173 assert_response 302
173 assert_response 302
174 end
174 end
175
175
176 def test_show_page_without_content_should_display_the_edit_form
176 def test_show_page_without_content_should_display_the_edit_form
177 @request.session[:user_id] = 2
177 @request.session[:user_id] = 2
178 WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
178 WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
179
179
180 get :show, :project_id => 1, :id => 'NoContent'
180 get :show, :project_id => 1, :id => 'NoContent'
181 assert_response :success
181 assert_response :success
182 assert_template 'edit'
182 assert_template 'edit'
183 assert_select 'textarea[name=?]', 'content[text]'
183 assert_select 'textarea[name=?]', 'content[text]'
184 end
184 end
185
185
186 def test_create_page
186 def test_create_page
187 @request.session[:user_id] = 2
187 @request.session[:user_id] = 2
188 assert_difference 'WikiPage.count' do
188 assert_difference 'WikiPage.count' do
189 assert_difference 'WikiContent.count' do
189 assert_difference 'WikiContent.count' do
190 put :update, :project_id => 1,
190 put :update, :project_id => 1,
191 :id => 'New page',
191 :id => 'New page',
192 :content => {:comments => 'Created the page',
192 :content => {:comments => 'Created the page',
193 :text => "h1. New page\n\nThis is a new page",
193 :text => "h1. New page\n\nThis is a new page",
194 :version => 0}
194 :version => 0}
195 end
195 end
196 end
196 end
197 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
197 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'New_page'
198 page = Project.find(1).wiki.find_page('New page')
198 page = Project.find(1).wiki.find_page('New page')
199 assert !page.new_record?
199 assert !page.new_record?
200 assert_not_nil page.content
200 assert_not_nil page.content
201 assert_nil page.parent
201 assert_nil page.parent
202 assert_equal 'Created the page', page.content.comments
202 assert_equal 'Created the page', page.content.comments
203 end
203 end
204
204
205 def test_create_page_with_attachments
205 def test_create_page_with_attachments
206 @request.session[:user_id] = 2
206 @request.session[:user_id] = 2
207 assert_difference 'WikiPage.count' do
207 assert_difference 'WikiPage.count' do
208 assert_difference 'Attachment.count' do
208 assert_difference 'Attachment.count' do
209 put :update, :project_id => 1,
209 put :update, :project_id => 1,
210 :id => 'New page',
210 :id => 'New page',
211 :content => {:comments => 'Created the page',
211 :content => {:comments => 'Created the page',
212 :text => "h1. New page\n\nThis is a new page",
212 :text => "h1. New page\n\nThis is a new page",
213 :version => 0},
213 :version => 0},
214 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
214 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
215 end
215 end
216 end
216 end
217 page = Project.find(1).wiki.find_page('New page')
217 page = Project.find(1).wiki.find_page('New page')
218 assert_equal 1, page.attachments.count
218 assert_equal 1, page.attachments.count
219 assert_equal 'testfile.txt', page.attachments.first.filename
219 assert_equal 'testfile.txt', page.attachments.first.filename
220 end
220 end
221
221
222 def test_create_page_with_parent
222 def test_create_page_with_parent
223 @request.session[:user_id] = 2
223 @request.session[:user_id] = 2
224 assert_difference 'WikiPage.count' do
224 assert_difference 'WikiPage.count' do
225 put :update, :project_id => 1, :id => 'New page',
225 put :update, :project_id => 1, :id => 'New page',
226 :content => {:text => "h1. New page\n\nThis is a new page", :version => 0},
226 :content => {:text => "h1. New page\n\nThis is a new page", :version => 0},
227 :wiki_page => {:parent_id => 2}
227 :wiki_page => {:parent_id => 2}
228 end
228 end
229 page = Project.find(1).wiki.find_page('New page')
229 page = Project.find(1).wiki.find_page('New page')
230 assert_equal WikiPage.find(2), page.parent
230 assert_equal WikiPage.find(2), page.parent
231 end
231 end
232
232
233 def test_edit_page
233 def test_edit_page
234 @request.session[:user_id] = 2
234 @request.session[:user_id] = 2
235 get :edit, :project_id => 'ecookbook', :id => 'Another_page'
235 get :edit, :project_id => 'ecookbook', :id => 'Another_page'
236
236
237 assert_response :success
237 assert_response :success
238 assert_template 'edit'
238 assert_template 'edit'
239
239
240 assert_select 'textarea[name=?]', 'content[text]',
240 assert_select 'textarea[name=?]', 'content[text]',
241 :text => WikiPage.find_by_title('Another_page').content.text
241 :text => WikiPage.find_by_title('Another_page').content.text
242 end
242 end
243
243
244 def test_edit_section
244 def test_edit_section
245 @request.session[:user_id] = 2
245 @request.session[:user_id] = 2
246 get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 2
246 get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 2
247
247
248 assert_response :success
248 assert_response :success
249 assert_template 'edit'
249 assert_template 'edit'
250
250
251 page = WikiPage.find_by_title('Page_with_sections')
251 page = WikiPage.find_by_title('Page_with_sections')
252 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
252 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
253
253
254 assert_select 'textarea[name=?]', 'content[text]', :text => section
254 assert_select 'textarea[name=?]', 'content[text]', :text => section
255 assert_select 'input[name=section][type=hidden][value="2"]'
255 assert_select 'input[name=section][type=hidden][value="2"]'
256 assert_select 'input[name=section_hash][type=hidden][value=?]', hash
256 assert_select 'input[name=section_hash][type=hidden][value=?]', hash
257 end
257 end
258
258
259 def test_edit_invalid_section_should_respond_with_404
259 def test_edit_invalid_section_should_respond_with_404
260 @request.session[:user_id] = 2
260 @request.session[:user_id] = 2
261 get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10
261 get :edit, :project_id => 'ecookbook', :id => 'Page_with_sections', :section => 10
262
262
263 assert_response 404
263 assert_response 404
264 end
264 end
265
265
266 def test_update_page
266 def test_update_page
267 @request.session[:user_id] = 2
267 @request.session[:user_id] = 2
268 assert_no_difference 'WikiPage.count' do
268 assert_no_difference 'WikiPage.count' do
269 assert_no_difference 'WikiContent.count' do
269 assert_no_difference 'WikiContent.count' do
270 assert_difference 'WikiContent::Version.count' do
270 assert_difference 'WikiContent::Version.count' do
271 put :update, :project_id => 1,
271 put :update, :project_id => 1,
272 :id => 'Another_page',
272 :id => 'Another_page',
273 :content => {
273 :content => {
274 :comments => "my comments",
274 :comments => "my comments",
275 :text => "edited",
275 :text => "edited",
276 :version => 1
276 :version => 1
277 }
277 }
278 end
278 end
279 end
279 end
280 end
280 end
281 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
281 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
282
282
283 page = Wiki.find(1).pages.find_by_title('Another_page')
283 page = Wiki.find(1).pages.find_by_title('Another_page')
284 assert_equal "edited", page.content.text
284 assert_equal "edited", page.content.text
285 assert_equal 2, page.content.version
285 assert_equal 2, page.content.version
286 assert_equal "my comments", page.content.comments
286 assert_equal "my comments", page.content.comments
287 end
287 end
288
288
289 def test_update_page_with_parent
289 def test_update_page_with_parent
290 @request.session[:user_id] = 2
290 @request.session[:user_id] = 2
291 assert_no_difference 'WikiPage.count' do
291 assert_no_difference 'WikiPage.count' do
292 assert_no_difference 'WikiContent.count' do
292 assert_no_difference 'WikiContent.count' do
293 assert_difference 'WikiContent::Version.count' do
293 assert_difference 'WikiContent::Version.count' do
294 put :update, :project_id => 1,
294 put :update, :project_id => 1,
295 :id => 'Another_page',
295 :id => 'Another_page',
296 :content => {
296 :content => {
297 :comments => "my comments",
297 :comments => "my comments",
298 :text => "edited",
298 :text => "edited",
299 :version => 1
299 :version => 1
300 },
300 },
301 :wiki_page => {:parent_id => '1'}
301 :wiki_page => {:parent_id => '1'}
302 end
302 end
303 end
303 end
304 end
304 end
305 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
305 assert_redirected_to '/projects/ecookbook/wiki/Another_page'
306
306
307 page = Wiki.find(1).pages.find_by_title('Another_page')
307 page = Wiki.find(1).pages.find_by_title('Another_page')
308 assert_equal "edited", page.content.text
308 assert_equal "edited", page.content.text
309 assert_equal 2, page.content.version
309 assert_equal 2, page.content.version
310 assert_equal "my comments", page.content.comments
310 assert_equal "my comments", page.content.comments
311 assert_equal WikiPage.find(1), page.parent
311 assert_equal WikiPage.find(1), page.parent
312 end
312 end
313
313
314 def test_update_page_with_failure
314 def test_update_page_with_failure
315 @request.session[:user_id] = 2
315 @request.session[:user_id] = 2
316 assert_no_difference 'WikiPage.count' do
316 assert_no_difference 'WikiPage.count' do
317 assert_no_difference 'WikiContent.count' do
317 assert_no_difference 'WikiContent.count' do
318 assert_no_difference 'WikiContent::Version.count' do
318 assert_no_difference 'WikiContent::Version.count' do
319 put :update, :project_id => 1,
319 put :update, :project_id => 1,
320 :id => 'Another_page',
320 :id => 'Another_page',
321 :content => {
321 :content => {
322 :comments => 'a' * 300, # failure here, comment is too long
322 :comments => 'a' * 300, # failure here, comment is too long
323 :text => 'edited'
323 :text => 'edited'
324 },
324 },
325 :wiki_page => {
325 :wiki_page => {
326 :parent_id => ""
326 :parent_id => ""
327 }
327 }
328 end
328 end
329 end
329 end
330 end
330 end
331 assert_response :success
331 assert_response :success
332 assert_template 'edit'
332 assert_template 'edit'
333
333
334 assert_select_error /Comment is too long/
334 assert_select_error /Comment is too long/
335 assert_select 'textarea#content_text', :text => "edited"
335 assert_select 'textarea#content_text', :text => "edited"
336 assert_select 'input#content_version[value="1"]'
336 assert_select 'input#content_version[value="1"]'
337 end
337 end
338
338
339 def test_update_page_with_parent_change_only_should_not_create_content_version
339 def test_update_page_with_parent_change_only_should_not_create_content_version
340 @request.session[:user_id] = 2
340 @request.session[:user_id] = 2
341 assert_no_difference 'WikiPage.count' do
341 assert_no_difference 'WikiPage.count' do
342 assert_no_difference 'WikiContent.count' do
342 assert_no_difference 'WikiContent.count' do
343 assert_no_difference 'WikiContent::Version.count' do
343 assert_no_difference 'WikiContent::Version.count' do
344 put :update, :project_id => 1,
344 put :update, :project_id => 1,
345 :id => 'Another_page',
345 :id => 'Another_page',
346 :content => {
346 :content => {
347 :comments => '',
347 :comments => '',
348 :text => Wiki.find(1).find_page('Another_page').content.text,
348 :text => Wiki.find(1).find_page('Another_page').content.text,
349 :version => 1
349 :version => 1
350 },
350 },
351 :wiki_page => {:parent_id => '1'}
351 :wiki_page => {:parent_id => '1'}
352 end
352 end
353 end
353 end
354 end
354 end
355 page = Wiki.find(1).pages.find_by_title('Another_page')
355 page = Wiki.find(1).pages.find_by_title('Another_page')
356 assert_equal 1, page.content.version
356 assert_equal 1, page.content.version
357 assert_equal WikiPage.find(1), page.parent
357 assert_equal WikiPage.find(1), page.parent
358 end
358 end
359
359
360 def test_update_page_with_attachments_only_should_not_create_content_version
360 def test_update_page_with_attachments_only_should_not_create_content_version
361 @request.session[:user_id] = 2
361 @request.session[:user_id] = 2
362 assert_no_difference 'WikiPage.count' do
362 assert_no_difference 'WikiPage.count' do
363 assert_no_difference 'WikiContent.count' do
363 assert_no_difference 'WikiContent.count' do
364 assert_no_difference 'WikiContent::Version.count' do
364 assert_no_difference 'WikiContent::Version.count' do
365 assert_difference 'Attachment.count' do
365 assert_difference 'Attachment.count' do
366 put :update, :project_id => 1,
366 put :update, :project_id => 1,
367 :id => 'Another_page',
367 :id => 'Another_page',
368 :content => {
368 :content => {
369 :comments => '',
369 :comments => '',
370 :text => Wiki.find(1).find_page('Another_page').content.text,
370 :text => Wiki.find(1).find_page('Another_page').content.text,
371 :version => 1
371 :version => 1
372 },
372 },
373 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
373 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
374 end
374 end
375 end
375 end
376 end
376 end
377 end
377 end
378 page = Wiki.find(1).pages.find_by_title('Another_page')
378 page = Wiki.find(1).pages.find_by_title('Another_page')
379 assert_equal 1, page.content.version
379 assert_equal 1, page.content.version
380 end
380 end
381
381
382 def test_update_stale_page_should_not_raise_an_error
382 def test_update_stale_page_should_not_raise_an_error
383 @request.session[:user_id] = 2
383 @request.session[:user_id] = 2
384 c = Wiki.find(1).find_page('Another_page').content
384 c = Wiki.find(1).find_page('Another_page').content
385 c.text = 'Previous text'
385 c.text = 'Previous text'
386 c.save!
386 c.save!
387 assert_equal 2, c.version
387 assert_equal 2, c.version
388
388
389 assert_no_difference 'WikiPage.count' do
389 assert_no_difference 'WikiPage.count' do
390 assert_no_difference 'WikiContent.count' do
390 assert_no_difference 'WikiContent.count' do
391 assert_no_difference 'WikiContent::Version.count' do
391 assert_no_difference 'WikiContent::Version.count' do
392 put :update, :project_id => 1,
392 put :update, :project_id => 1,
393 :id => 'Another_page',
393 :id => 'Another_page',
394 :content => {
394 :content => {
395 :comments => 'My comments',
395 :comments => 'My comments',
396 :text => 'Text should not be lost',
396 :text => 'Text should not be lost',
397 :version => 1
397 :version => 1
398 }
398 }
399 end
399 end
400 end
400 end
401 end
401 end
402 assert_response :success
402 assert_response :success
403 assert_template 'edit'
403 assert_template 'edit'
404 assert_select 'div.error', :text => /Data has been updated by another user/
404 assert_select 'div.error', :text => /Data has been updated by another user/
405 assert_select 'textarea[name=?]', 'content[text]', :text => /Text should not be lost/
405 assert_select 'textarea[name=?]', 'content[text]', :text => /Text should not be lost/
406 assert_select 'input[name=?][value=?]', 'content[comments]', 'My comments'
406 assert_select 'input[name=?][value=?]', 'content[comments]', 'My comments'
407
407
408 c.reload
408 c.reload
409 assert_equal 'Previous text', c.text
409 assert_equal 'Previous text', c.text
410 assert_equal 2, c.version
410 assert_equal 2, c.version
411 end
411 end
412
412
413 def test_update_page_without_content_should_create_content
413 def test_update_page_without_content_should_create_content
414 @request.session[:user_id] = 2
414 @request.session[:user_id] = 2
415 page = WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
415 page = WikiPage.create!(:title => 'NoContent', :wiki => Project.find(1).wiki)
416
416
417 assert_no_difference 'WikiPage.count' do
417 assert_no_difference 'WikiPage.count' do
418 assert_difference 'WikiContent.count' do
418 assert_difference 'WikiContent.count' do
419 put :update, :project_id => 1, :id => 'NoContent', :content => {:text => 'Some content'}
419 put :update, :project_id => 1, :id => 'NoContent', :content => {:text => 'Some content'}
420 assert_response 302
420 assert_response 302
421 end
421 end
422 end
422 end
423 assert_equal 'Some content', page.reload.content.text
423 assert_equal 'Some content', page.reload.content.text
424 end
424 end
425
425
426 def test_update_section
426 def test_update_section
427 @request.session[:user_id] = 2
427 @request.session[:user_id] = 2
428 page = WikiPage.find_by_title('Page_with_sections')
428 page = WikiPage.find_by_title('Page_with_sections')
429 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
429 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
430 text = page.content.text
430 text = page.content.text
431
431
432 assert_no_difference 'WikiPage.count' do
432 assert_no_difference 'WikiPage.count' do
433 assert_no_difference 'WikiContent.count' do
433 assert_no_difference 'WikiContent.count' do
434 assert_difference 'WikiContent::Version.count' do
434 assert_difference 'WikiContent::Version.count' do
435 put :update, :project_id => 1, :id => 'Page_with_sections',
435 put :update, :project_id => 1, :id => 'Page_with_sections',
436 :content => {
436 :content => {
437 :text => "New section content",
437 :text => "New section content",
438 :version => 3
438 :version => 3
439 },
439 },
440 :section => 2,
440 :section => 2,
441 :section_hash => hash
441 :section_hash => hash
442 end
442 end
443 end
443 end
444 end
444 end
445 assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
445 assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
446 assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.reload.content.text
446 assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.reload.content.text
447 end
447 end
448
448
449 def test_update_section_should_allow_stale_page_update
449 def test_update_section_should_allow_stale_page_update
450 @request.session[:user_id] = 2
450 @request.session[:user_id] = 2
451 page = WikiPage.find_by_title('Page_with_sections')
451 page = WikiPage.find_by_title('Page_with_sections')
452 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
452 section, hash = Redmine::WikiFormatting::Textile::Formatter.new(page.content.text).get_section(2)
453 text = page.content.text
453 text = page.content.text
454
454
455 assert_no_difference 'WikiPage.count' do
455 assert_no_difference 'WikiPage.count' do
456 assert_no_difference 'WikiContent.count' do
456 assert_no_difference 'WikiContent.count' do
457 assert_difference 'WikiContent::Version.count' do
457 assert_difference 'WikiContent::Version.count' do
458 put :update, :project_id => 1, :id => 'Page_with_sections',
458 put :update, :project_id => 1, :id => 'Page_with_sections',
459 :content => {
459 :content => {
460 :text => "New section content",
460 :text => "New section content",
461 :version => 2 # Current version is 3
461 :version => 2 # Current version is 3
462 },
462 },
463 :section => 2,
463 :section => 2,
464 :section_hash => hash
464 :section_hash => hash
465 end
465 end
466 end
466 end
467 end
467 end
468 assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
468 assert_redirected_to '/projects/ecookbook/wiki/Page_with_sections#section-2'
469 page.reload
469 page.reload
470 assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.content.text
470 assert_equal Redmine::WikiFormatting::Textile::Formatter.new(text).update_section(2, "New section content"), page.content.text
471 assert_equal 4, page.content.version
471 assert_equal 4, page.content.version
472 end
472 end
473
473
474 def test_update_section_should_not_allow_stale_section_update
474 def test_update_section_should_not_allow_stale_section_update
475 @request.session[:user_id] = 2
475 @request.session[:user_id] = 2
476
476
477 assert_no_difference 'WikiPage.count' do
477 assert_no_difference 'WikiPage.count' do
478 assert_no_difference 'WikiContent.count' do
478 assert_no_difference 'WikiContent.count' do
479 assert_no_difference 'WikiContent::Version.count' do
479 assert_no_difference 'WikiContent::Version.count' do
480 put :update, :project_id => 1, :id => 'Page_with_sections',
480 put :update, :project_id => 1, :id => 'Page_with_sections',
481 :content => {
481 :content => {
482 :comments => 'My comments',
482 :comments => 'My comments',
483 :text => "Text should not be lost",
483 :text => "Text should not be lost",
484 :version => 3
484 :version => 3
485 },
485 },
486 :section => 2,
486 :section => 2,
487 :section_hash => Digest::MD5.hexdigest("wrong hash")
487 :section_hash => Digest::MD5.hexdigest("wrong hash")
488 end
488 end
489 end
489 end
490 end
490 end
491 assert_response :success
491 assert_response :success
492 assert_template 'edit'
492 assert_template 'edit'
493 assert_select 'div.error', :text => /Data has been updated by another user/
493 assert_select 'div.error', :text => /Data has been updated by another user/
494 assert_select 'textarea[name=?]', 'content[text]', :text => /Text should not be lost/
494 assert_select 'textarea[name=?]', 'content[text]', :text => /Text should not be lost/
495 assert_select 'input[name=?][value=?]', 'content[comments]', 'My comments'
495 assert_select 'input[name=?][value=?]', 'content[comments]', 'My comments'
496 end
496 end
497
497
498 def test_preview
498 def test_preview
499 @request.session[:user_id] = 2
499 @request.session[:user_id] = 2
500 xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
500 xhr :post, :preview, :project_id => 1, :id => 'CookBook_documentation',
501 :content => { :comments => '',
501 :content => { :comments => '',
502 :text => 'this is a *previewed text*',
502 :text => 'this is a *previewed text*',
503 :version => 3 }
503 :version => 3 }
504 assert_response :success
504 assert_response :success
505 assert_template 'common/_preview'
505 assert_template 'common/_preview'
506 assert_select 'strong', :text => /previewed text/
506 assert_select 'strong', :text => /previewed text/
507 end
507 end
508
508
509 def test_preview_new_page
509 def test_preview_new_page
510 @request.session[:user_id] = 2
510 @request.session[:user_id] = 2
511 xhr :post, :preview, :project_id => 1, :id => 'New page',
511 xhr :post, :preview, :project_id => 1, :id => 'New page',
512 :content => { :text => 'h1. New page',
512 :content => { :text => 'h1. New page',
513 :comments => '',
513 :comments => '',
514 :version => 0 }
514 :version => 0 }
515 assert_response :success
515 assert_response :success
516 assert_template 'common/_preview'
516 assert_template 'common/_preview'
517 assert_select 'h1', :text => /New page/
517 assert_select 'h1', :text => /New page/
518 end
518 end
519
519
520 def test_history
520 def test_history
521 @request.session[:user_id] = 2
521 @request.session[:user_id] = 2
522 get :history, :project_id => 'ecookbook', :id => 'CookBook_documentation'
522 get :history, :project_id => 'ecookbook', :id => 'CookBook_documentation'
523 assert_response :success
523 assert_response :success
524 assert_template 'history'
524 assert_template 'history'
525 assert_not_nil assigns(:versions)
525 assert_not_nil assigns(:versions)
526 assert_equal 3, assigns(:versions).size
526 assert_equal 3, assigns(:versions).size
527
527
528 assert_select "input[type=submit][name=commit]"
528 assert_select "input[type=submit][name=commit]"
529 assert_select 'td' do
529 assert_select 'td' do
530 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => '2'
530 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => '2'
531 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate', :text => 'Annotate'
531 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2/annotate', :text => 'Annotate'
532 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => 'Delete'
532 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation/2', :text => 'Delete'
533 end
533 end
534 end
534 end
535
535
536 def test_history_with_one_version
536 def test_history_with_one_version
537 @request.session[:user_id] = 2
537 @request.session[:user_id] = 2
538 get :history, :project_id => 'ecookbook', :id => 'Another_page'
538 get :history, :project_id => 'ecookbook', :id => 'Another_page'
539 assert_response :success
539 assert_response :success
540 assert_template 'history'
540 assert_template 'history'
541 assert_not_nil assigns(:versions)
541 assert_not_nil assigns(:versions)
542 assert_equal 1, assigns(:versions).size
542 assert_equal 1, assigns(:versions).size
543 assert_select "input[type=submit][name=commit]", false
543 assert_select "input[type=submit][name=commit]", false
544 assert_select 'td' do
544 assert_select 'td' do
545 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => '1'
545 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => '1'
546 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1/annotate', :text => 'Annotate'
546 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1/annotate', :text => 'Annotate'
547 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => 'Delete', :count => 0
547 assert_select 'a[href=?]', '/projects/ecookbook/wiki/Another_page/1', :text => 'Delete', :count => 0
548 end
548 end
549 end
549 end
550
550
551 def test_diff
551 def test_diff
552 content = WikiPage.find(1).content
552 content = WikiPage.find(1).content
553 assert_difference 'WikiContent::Version.count', 2 do
553 assert_difference 'WikiContent::Version.count', 2 do
554 content.text = "Line removed\nThis is a sample text for testing diffs"
554 content.text = "Line removed\nThis is a sample text for testing diffs"
555 content.save!
555 content.save!
556 content.text = "This is a sample text for testing diffs\nLine added"
556 content.text = "This is a sample text for testing diffs\nLine added"
557 content.save!
557 content.save!
558 end
558 end
559
559
560 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => content.version, :version_from => (content.version - 1)
560 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => content.version, :version_from => (content.version - 1)
561 assert_response :success
561 assert_response :success
562 assert_template 'diff'
562 assert_template 'diff'
563 assert_select 'span.diff_out', :text => 'Line removed'
563 assert_select 'span.diff_out', :text => 'Line removed'
564 assert_select 'span.diff_in', :text => 'Line added'
564 assert_select 'span.diff_in', :text => 'Line added'
565 end
565 end
566
566
567 def test_diff_with_invalid_version_should_respond_with_404
567 def test_diff_with_invalid_version_should_respond_with_404
568 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
568 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
569 assert_response 404
569 assert_response 404
570 end
570 end
571
571
572 def test_diff_with_invalid_version_from_should_respond_with_404
572 def test_diff_with_invalid_version_from_should_respond_with_404
573 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99', :version_from => '98'
573 get :diff, :project_id => 1, :id => 'CookBook_documentation', :version => '99', :version_from => '98'
574 assert_response 404
574 assert_response 404
575 end
575 end
576
576
577 def test_annotate
577 def test_annotate
578 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
578 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => 2
579 assert_response :success
579 assert_response :success
580 assert_template 'annotate'
580 assert_template 'annotate'
581
581
582 # Line 1
582 # Line 1
583 assert_select 'table.annotate tr:nth-child(1)' do
583 assert_select 'table.annotate tr:nth-child(1)' do
584 assert_select 'th.line-num', :text => '1'
584 assert_select 'th.line-num', :text => '1'
585 assert_select 'td.author', :text => /John Smith/
585 assert_select 'td.author', :text => /John Smith/
586 assert_select 'td', :text => /h1\. CookBook documentation/
586 assert_select 'td', :text => /h1\. CookBook documentation/
587 end
587 end
588
588
589 # Line 5
589 # Line 5
590 assert_select 'table.annotate tr:nth-child(5)' do
590 assert_select 'table.annotate tr:nth-child(5)' do
591 assert_select 'th.line-num', :text => '5'
591 assert_select 'th.line-num', :text => '5'
592 assert_select 'td.author', :text => /Redmine Admin/
592 assert_select 'td.author', :text => /Redmine Admin/
593 assert_select 'td', :text => /Some updated \[\[documentation\]\] here/
593 assert_select 'td', :text => /Some updated \[\[documentation\]\] here/
594 end
594 end
595 end
595 end
596
596
597 def test_annotate_with_invalid_version_should_respond_with_404
597 def test_annotate_with_invalid_version_should_respond_with_404
598 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
598 get :annotate, :project_id => 1, :id => 'CookBook_documentation', :version => '99'
599 assert_response 404
599 assert_response 404
600 end
600 end
601
601
602 def test_get_rename
602 def test_get_rename
603 @request.session[:user_id] = 2
603 @request.session[:user_id] = 2
604 get :rename, :project_id => 1, :id => 'Another_page'
604 get :rename, :project_id => 1, :id => 'Another_page'
605 assert_response :success
605 assert_response :success
606 assert_template 'rename'
606 assert_template 'rename'
607
607
608 assert_select 'select[name=?]', 'wiki_page[parent_id]' do
608 assert_select 'select[name=?]', 'wiki_page[parent_id]' do
609 assert_select 'option[value=""]', :text => ''
609 assert_select 'option[value=""]', :text => ''
610 assert_select 'option[selected=selected]', 0
610 assert_select 'option[selected=selected]', 0
611 end
611 end
612 end
612 end
613
613
614 def test_get_rename_child_page
614 def test_get_rename_child_page
615 @request.session[:user_id] = 2
615 @request.session[:user_id] = 2
616 get :rename, :project_id => 1, :id => 'Child_1'
616 get :rename, :project_id => 1, :id => 'Child_1'
617 assert_response :success
617 assert_response :success
618 assert_template 'rename'
618 assert_template 'rename'
619
619
620 assert_select 'select[name=?]', 'wiki_page[parent_id]' do
620 assert_select 'select[name=?]', 'wiki_page[parent_id]' do
621 assert_select 'option[value=""]', :text => ''
621 assert_select 'option[value=""]', :text => ''
622 assert_select 'option[value="2"][selected=selected]', :text => /Another page/
622 assert_select 'option[value="2"][selected=selected]', :text => /Another page/
623 end
623 end
624 end
624 end
625
625
626 def test_rename_with_redirect
626 def test_rename_with_redirect
627 @request.session[:user_id] = 2
627 @request.session[:user_id] = 2
628 post :rename, :project_id => 1, :id => 'Another_page',
628 post :rename, :project_id => 1, :id => 'Another_page',
629 :wiki_page => { :title => 'Another renamed page',
629 :wiki_page => { :title => 'Another renamed page',
630 :redirect_existing_links => 1 }
630 :redirect_existing_links => 1 }
631 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
631 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
632 wiki = Project.find(1).wiki
632 wiki = Project.find(1).wiki
633 # Check redirects
633 # Check redirects
634 assert_not_nil wiki.find_page('Another page')
634 assert_not_nil wiki.find_page('Another page')
635 assert_nil wiki.find_page('Another page', :with_redirect => false)
635 assert_nil wiki.find_page('Another page', :with_redirect => false)
636 end
636 end
637
637
638 def test_rename_without_redirect
638 def test_rename_without_redirect
639 @request.session[:user_id] = 2
639 @request.session[:user_id] = 2
640 post :rename, :project_id => 1, :id => 'Another_page',
640 post :rename, :project_id => 1, :id => 'Another_page',
641 :wiki_page => { :title => 'Another renamed page',
641 :wiki_page => { :title => 'Another renamed page',
642 :redirect_existing_links => "0" }
642 :redirect_existing_links => "0" }
643 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
643 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_renamed_page'
644 wiki = Project.find(1).wiki
644 wiki = Project.find(1).wiki
645 # Check that there's no redirects
645 # Check that there's no redirects
646 assert_nil wiki.find_page('Another page')
646 assert_nil wiki.find_page('Another page')
647 end
647 end
648
648
649 def test_rename_with_parent_assignment
649 def test_rename_with_parent_assignment
650 @request.session[:user_id] = 2
650 @request.session[:user_id] = 2
651 post :rename, :project_id => 1, :id => 'Another_page',
651 post :rename, :project_id => 1, :id => 'Another_page',
652 :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
652 :wiki_page => { :title => 'Another page', :redirect_existing_links => "0", :parent_id => '4' }
653 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
653 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
654 assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
654 assert_equal WikiPage.find(4), WikiPage.find_by_title('Another_page').parent
655 end
655 end
656
656
657 def test_rename_with_parent_unassignment
657 def test_rename_with_parent_unassignment
658 @request.session[:user_id] = 2
658 @request.session[:user_id] = 2
659 post :rename, :project_id => 1, :id => 'Child_1',
659 post :rename, :project_id => 1, :id => 'Child_1',
660 :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
660 :wiki_page => { :title => 'Child 1', :redirect_existing_links => "0", :parent_id => '' }
661 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
661 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Child_1'
662 assert_nil WikiPage.find_by_title('Child_1').parent
662 assert_nil WikiPage.find_by_title('Child_1').parent
663 end
663 end
664
664
665 def test_get_rename_should_show_target_projects_list
665 def test_get_rename_should_show_target_projects_list
666 @request.session[:user_id] = 2
666 @request.session[:user_id] = 2
667 project = Project.find(5)
667 project = Project.find(5)
668 project.enable_module! :wiki
668 project.enable_module! :wiki
669
669
670 get :rename, :project_id => 1, :id => 'Another_page'
670 get :rename, :project_id => 1, :id => 'Another_page'
671 assert_response :success
671 assert_response :success
672 assert_template 'rename'
672 assert_template 'rename'
673
673
674 assert_select 'select[name=?]', 'wiki_page[wiki_id]' do
674 assert_select 'select[name=?]', 'wiki_page[wiki_id]' do
675 assert_select 'option', 2
675 assert_select 'option', 2
676 assert_select 'option[value=?][selected=selected]', '1', :text => /eCookbook/
676 assert_select 'option[value=?][selected=selected]', '1', :text => /eCookbook/
677 assert_select 'option[value=?]', project.wiki.id.to_s, :text => /#{project.name}/
677 assert_select 'option[value=?]', project.wiki.id.to_s, :text => /#{project.name}/
678 end
678 end
679 end
679 end
680
680
681 def test_rename_with_move
681 def test_rename_with_move
682 @request.session[:user_id] = 2
682 @request.session[:user_id] = 2
683 project = Project.find(5)
683 project = Project.find(5)
684 project.enable_module! :wiki
684 project.enable_module! :wiki
685
685
686 post :rename, :project_id => 1, :id => 'Another_page',
686 post :rename, :project_id => 1, :id => 'Another_page',
687 :wiki_page => {
687 :wiki_page => {
688 :wiki_id => project.wiki.id.to_s,
688 :wiki_id => project.wiki.id.to_s,
689 :title => 'Another renamed page',
689 :title => 'Another renamed page',
690 :redirect_existing_links => 1
690 :redirect_existing_links => 1
691 }
691 }
692 assert_redirected_to '/projects/private-child/wiki/Another_renamed_page'
692 assert_redirected_to '/projects/private-child/wiki/Another_renamed_page'
693
693
694 page = WikiPage.find(2)
694 page = WikiPage.find(2)
695 assert_equal project.wiki.id, page.wiki_id
695 assert_equal project.wiki.id, page.wiki_id
696 end
696 end
697
697
698 def test_destroy_a_page_without_children_should_not_ask_confirmation
698 def test_destroy_a_page_without_children_should_not_ask_confirmation
699 @request.session[:user_id] = 2
699 @request.session[:user_id] = 2
700 delete :destroy, :project_id => 1, :id => 'Child_2'
700 delete :destroy, :project_id => 1, :id => 'Child_2'
701 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
701 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
702 end
702 end
703
703
704 def test_destroy_parent_should_ask_confirmation
704 def test_destroy_parent_should_ask_confirmation
705 @request.session[:user_id] = 2
705 @request.session[:user_id] = 2
706 assert_no_difference('WikiPage.count') do
706 assert_no_difference('WikiPage.count') do
707 delete :destroy, :project_id => 1, :id => 'Another_page'
707 delete :destroy, :project_id => 1, :id => 'Another_page'
708 end
708 end
709 assert_response :success
709 assert_response :success
710 assert_template 'destroy'
710 assert_template 'destroy'
711 assert_select 'form' do
711 assert_select 'form' do
712 assert_select 'input[name=todo][value=nullify]'
712 assert_select 'input[name=todo][value=nullify]'
713 assert_select 'input[name=todo][value=destroy]'
713 assert_select 'input[name=todo][value=destroy]'
714 assert_select 'input[name=todo][value=reassign]'
714 assert_select 'input[name=todo][value=reassign]'
715 end
715 end
716 end
716 end
717
717
718 def test_destroy_parent_with_nullify_should_delete_parent_only
718 def test_destroy_parent_with_nullify_should_delete_parent_only
719 @request.session[:user_id] = 2
719 @request.session[:user_id] = 2
720 assert_difference('WikiPage.count', -1) do
720 assert_difference('WikiPage.count', -1) do
721 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
721 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'nullify'
722 end
722 end
723 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
723 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
724 assert_nil WikiPage.find_by_id(2)
724 assert_nil WikiPage.find_by_id(2)
725 end
725 end
726
726
727 def test_destroy_parent_with_cascade_should_delete_descendants
727 def test_destroy_parent_with_cascade_should_delete_descendants
728 @request.session[:user_id] = 2
728 @request.session[:user_id] = 2
729 assert_difference('WikiPage.count', -4) do
729 assert_difference('WikiPage.count', -4) do
730 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
730 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'destroy'
731 end
731 end
732 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
732 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
733 assert_nil WikiPage.find_by_id(2)
733 assert_nil WikiPage.find_by_id(2)
734 assert_nil WikiPage.find_by_id(5)
734 assert_nil WikiPage.find_by_id(5)
735 end
735 end
736
736
737 def test_destroy_parent_with_reassign
737 def test_destroy_parent_with_reassign
738 @request.session[:user_id] = 2
738 @request.session[:user_id] = 2
739 assert_difference('WikiPage.count', -1) do
739 assert_difference('WikiPage.count', -1) do
740 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
740 delete :destroy, :project_id => 1, :id => 'Another_page', :todo => 'reassign', :reassign_to_id => 1
741 end
741 end
742 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
742 assert_redirected_to :action => 'index', :project_id => 'ecookbook'
743 assert_nil WikiPage.find_by_id(2)
743 assert_nil WikiPage.find_by_id(2)
744 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
744 assert_equal WikiPage.find(1), WikiPage.find_by_id(5).parent
745 end
745 end
746
746
747 def test_destroy_version
747 def test_destroy_version
748 @request.session[:user_id] = 2
748 @request.session[:user_id] = 2
749 assert_difference 'WikiContent::Version.count', -1 do
749 assert_difference 'WikiContent::Version.count', -1 do
750 assert_no_difference 'WikiContent.count' do
750 assert_no_difference 'WikiContent.count' do
751 assert_no_difference 'WikiPage.count' do
751 assert_no_difference 'WikiPage.count' do
752 delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 2
752 delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 2
753 assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation/history'
753 assert_redirected_to '/projects/ecookbook/wiki/CookBook_documentation/history'
754 end
754 end
755 end
755 end
756 end
756 end
757 end
757 end
758
758
759 def test_destroy_invalid_version_should_respond_with_404
760 @request.session[:user_id] = 2
761 assert_no_difference 'WikiContent::Version.count' do
762 assert_no_difference 'WikiContent.count' do
763 assert_no_difference 'WikiPage.count' do
764 delete :destroy_version, :project_id => 'ecookbook', :id => 'CookBook_documentation', :version => 99
765 end
766 end
767 end
768 assert_response 404
769 end
770
759 def test_index
771 def test_index
760 get :index, :project_id => 'ecookbook'
772 get :index, :project_id => 'ecookbook'
761 assert_response :success
773 assert_response :success
762 assert_template 'index'
774 assert_template 'index'
763 pages = assigns(:pages)
775 pages = assigns(:pages)
764 assert_not_nil pages
776 assert_not_nil pages
765 assert_equal Project.find(1).wiki.pages.size, pages.size
777 assert_equal Project.find(1).wiki.pages.size, pages.size
766 assert_equal pages.first.content.updated_on, pages.first.updated_on
778 assert_equal pages.first.content.updated_on, pages.first.updated_on
767
779
768 assert_select 'ul.pages-hierarchy' do
780 assert_select 'ul.pages-hierarchy' do
769 assert_select 'li' do
781 assert_select 'li' do
770 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => 'CookBook documentation'
782 assert_select 'a[href=?]', '/projects/ecookbook/wiki/CookBook_documentation', :text => 'CookBook documentation'
771 assert_select 'ul li a[href=?]', '/projects/ecookbook/wiki/Page_with_an_inline_image', :text => 'Page with an inline image'
783 assert_select 'ul li a[href=?]', '/projects/ecookbook/wiki/Page_with_an_inline_image', :text => 'Page with an inline image'
772 end
784 end
773 assert_select 'li a[href=?]', '/projects/ecookbook/wiki/Another_page', :text => 'Another page'
785 assert_select 'li a[href=?]', '/projects/ecookbook/wiki/Another_page', :text => 'Another page'
774 end
786 end
775 end
787 end
776
788
777 def test_index_should_include_atom_link
789 def test_index_should_include_atom_link
778 get :index, :project_id => 'ecookbook'
790 get :index, :project_id => 'ecookbook'
779 assert_select 'a[href=?]', '/projects/ecookbook/activity.atom?show_wiki_edits=1'
791 assert_select 'a[href=?]', '/projects/ecookbook/activity.atom?show_wiki_edits=1'
780 end
792 end
781
793
782 def test_export_to_html
794 def test_export_to_html
783 @request.session[:user_id] = 2
795 @request.session[:user_id] = 2
784 get :export, :project_id => 'ecookbook'
796 get :export, :project_id => 'ecookbook'
785
797
786 assert_response :success
798 assert_response :success
787 assert_not_nil assigns(:pages)
799 assert_not_nil assigns(:pages)
788 assert assigns(:pages).any?
800 assert assigns(:pages).any?
789 assert_equal "text/html", @response.content_type
801 assert_equal "text/html", @response.content_type
790
802
791 assert_select "a[name=?]", "CookBook_documentation"
803 assert_select "a[name=?]", "CookBook_documentation"
792 assert_select "a[name=?]", "Another_page"
804 assert_select "a[name=?]", "Another_page"
793 assert_select "a[name=?]", "Page_with_an_inline_image"
805 assert_select "a[name=?]", "Page_with_an_inline_image"
794 end
806 end
795
807
796 def test_export_to_pdf
808 def test_export_to_pdf
797 @request.session[:user_id] = 2
809 @request.session[:user_id] = 2
798 get :export, :project_id => 'ecookbook', :format => 'pdf'
810 get :export, :project_id => 'ecookbook', :format => 'pdf'
799
811
800 assert_response :success
812 assert_response :success
801 assert_not_nil assigns(:pages)
813 assert_not_nil assigns(:pages)
802 assert assigns(:pages).any?
814 assert assigns(:pages).any?
803 assert_equal 'application/pdf', @response.content_type
815 assert_equal 'application/pdf', @response.content_type
804 assert_equal 'attachment; filename="ecookbook.pdf"', @response.headers['Content-Disposition']
816 assert_equal 'attachment; filename="ecookbook.pdf"', @response.headers['Content-Disposition']
805 assert @response.body.starts_with?('%PDF')
817 assert @response.body.starts_with?('%PDF')
806 end
818 end
807
819
808 def test_export_without_permission_should_be_denied
820 def test_export_without_permission_should_be_denied
809 @request.session[:user_id] = 2
821 @request.session[:user_id] = 2
810 Role.find_by_name('Manager').remove_permission! :export_wiki_pages
822 Role.find_by_name('Manager').remove_permission! :export_wiki_pages
811 get :export, :project_id => 'ecookbook'
823 get :export, :project_id => 'ecookbook'
812
824
813 assert_response 403
825 assert_response 403
814 end
826 end
815
827
816 def test_date_index
828 def test_date_index
817 get :date_index, :project_id => 'ecookbook'
829 get :date_index, :project_id => 'ecookbook'
818
830
819 assert_response :success
831 assert_response :success
820 assert_template 'date_index'
832 assert_template 'date_index'
821 assert_not_nil assigns(:pages)
833 assert_not_nil assigns(:pages)
822 assert_not_nil assigns(:pages_by_date)
834 assert_not_nil assigns(:pages_by_date)
823
835
824 assert_select 'a[href=?]', '/projects/ecookbook/activity.atom?show_wiki_edits=1'
836 assert_select 'a[href=?]', '/projects/ecookbook/activity.atom?show_wiki_edits=1'
825 end
837 end
826
838
827 def test_not_found
839 def test_not_found
828 get :show, :project_id => 999
840 get :show, :project_id => 999
829 assert_response 404
841 assert_response 404
830 end
842 end
831
843
832 def test_protect_page
844 def test_protect_page
833 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
845 page = WikiPage.find_by_wiki_id_and_title(1, 'Another_page')
834 assert !page.protected?
846 assert !page.protected?
835 @request.session[:user_id] = 2
847 @request.session[:user_id] = 2
836 post :protect, :project_id => 1, :id => page.title, :protected => '1'
848 post :protect, :project_id => 1, :id => page.title, :protected => '1'
837 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
849 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'Another_page'
838 assert page.reload.protected?
850 assert page.reload.protected?
839 end
851 end
840
852
841 def test_unprotect_page
853 def test_unprotect_page
842 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
854 page = WikiPage.find_by_wiki_id_and_title(1, 'CookBook_documentation')
843 assert page.protected?
855 assert page.protected?
844 @request.session[:user_id] = 2
856 @request.session[:user_id] = 2
845 post :protect, :project_id => 1, :id => page.title, :protected => '0'
857 post :protect, :project_id => 1, :id => page.title, :protected => '0'
846 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
858 assert_redirected_to :action => 'show', :project_id => 'ecookbook', :id => 'CookBook_documentation'
847 assert !page.reload.protected?
859 assert !page.reload.protected?
848 end
860 end
849
861
850 def test_show_page_with_edit_link
862 def test_show_page_with_edit_link
851 @request.session[:user_id] = 2
863 @request.session[:user_id] = 2
852 get :show, :project_id => 1
864 get :show, :project_id => 1
853 assert_response :success
865 assert_response :success
854 assert_template 'show'
866 assert_template 'show'
855 assert_select 'a[href=?]', '/projects/1/wiki/CookBook_documentation/edit'
867 assert_select 'a[href=?]', '/projects/1/wiki/CookBook_documentation/edit'
856 end
868 end
857
869
858 def test_show_page_without_edit_link
870 def test_show_page_without_edit_link
859 @request.session[:user_id] = 4
871 @request.session[:user_id] = 4
860 get :show, :project_id => 1
872 get :show, :project_id => 1
861 assert_response :success
873 assert_response :success
862 assert_template 'show'
874 assert_template 'show'
863 assert_select 'a[href=?]', '/projects/1/wiki/CookBook_documentation/edit', 0
875 assert_select 'a[href=?]', '/projects/1/wiki/CookBook_documentation/edit', 0
864 end
876 end
865
877
866 def test_show_pdf
878 def test_show_pdf
867 @request.session[:user_id] = 2
879 @request.session[:user_id] = 2
868 get :show, :project_id => 1, :format => 'pdf'
880 get :show, :project_id => 1, :format => 'pdf'
869 assert_response :success
881 assert_response :success
870 assert_not_nil assigns(:page)
882 assert_not_nil assigns(:page)
871 assert_equal 'application/pdf', @response.content_type
883 assert_equal 'application/pdf', @response.content_type
872 assert_equal 'attachment; filename="CookBook_documentation.pdf"',
884 assert_equal 'attachment; filename="CookBook_documentation.pdf"',
873 @response.headers['Content-Disposition']
885 @response.headers['Content-Disposition']
874 end
886 end
875
887
876 def test_show_html
888 def test_show_html
877 @request.session[:user_id] = 2
889 @request.session[:user_id] = 2
878 get :show, :project_id => 1, :format => 'html'
890 get :show, :project_id => 1, :format => 'html'
879 assert_response :success
891 assert_response :success
880 assert_not_nil assigns(:page)
892 assert_not_nil assigns(:page)
881 assert_equal 'text/html', @response.content_type
893 assert_equal 'text/html', @response.content_type
882 assert_equal 'attachment; filename="CookBook_documentation.html"',
894 assert_equal 'attachment; filename="CookBook_documentation.html"',
883 @response.headers['Content-Disposition']
895 @response.headers['Content-Disposition']
884 assert_select 'h1', :text => /CookBook documentation/
896 assert_select 'h1', :text => /CookBook documentation/
885 end
897 end
886
898
887 def test_show_versioned_html
899 def test_show_versioned_html
888 @request.session[:user_id] = 2
900 @request.session[:user_id] = 2
889 get :show, :project_id => 1, :format => 'html', :version => 2
901 get :show, :project_id => 1, :format => 'html', :version => 2
890 assert_response :success
902 assert_response :success
891 assert_not_nil assigns(:content)
903 assert_not_nil assigns(:content)
892 assert_equal 2, assigns(:content).version
904 assert_equal 2, assigns(:content).version
893 assert_equal 'text/html', @response.content_type
905 assert_equal 'text/html', @response.content_type
894 assert_equal 'attachment; filename="CookBook_documentation.html"',
906 assert_equal 'attachment; filename="CookBook_documentation.html"',
895 @response.headers['Content-Disposition']
907 @response.headers['Content-Disposition']
896 assert_select 'h1', :text => /CookBook documentation/
908 assert_select 'h1', :text => /CookBook documentation/
897 end
909 end
898
910
899 def test_show_txt
911 def test_show_txt
900 @request.session[:user_id] = 2
912 @request.session[:user_id] = 2
901 get :show, :project_id => 1, :format => 'txt'
913 get :show, :project_id => 1, :format => 'txt'
902 assert_response :success
914 assert_response :success
903 assert_not_nil assigns(:page)
915 assert_not_nil assigns(:page)
904 assert_equal 'text/plain', @response.content_type
916 assert_equal 'text/plain', @response.content_type
905 assert_equal 'attachment; filename="CookBook_documentation.txt"',
917 assert_equal 'attachment; filename="CookBook_documentation.txt"',
906 @response.headers['Content-Disposition']
918 @response.headers['Content-Disposition']
907 assert_include 'h1. CookBook documentation', @response.body
919 assert_include 'h1. CookBook documentation', @response.body
908 end
920 end
909
921
910 def test_show_versioned_txt
922 def test_show_versioned_txt
911 @request.session[:user_id] = 2
923 @request.session[:user_id] = 2
912 get :show, :project_id => 1, :format => 'txt', :version => 2
924 get :show, :project_id => 1, :format => 'txt', :version => 2
913 assert_response :success
925 assert_response :success
914 assert_not_nil assigns(:content)
926 assert_not_nil assigns(:content)
915 assert_equal 2, assigns(:content).version
927 assert_equal 2, assigns(:content).version
916 assert_equal 'text/plain', @response.content_type
928 assert_equal 'text/plain', @response.content_type
917 assert_equal 'attachment; filename="CookBook_documentation.txt"',
929 assert_equal 'attachment; filename="CookBook_documentation.txt"',
918 @response.headers['Content-Disposition']
930 @response.headers['Content-Disposition']
919 assert_include 'h1. CookBook documentation', @response.body
931 assert_include 'h1. CookBook documentation', @response.body
920 end
932 end
921
933
922 def test_edit_unprotected_page
934 def test_edit_unprotected_page
923 # Non members can edit unprotected wiki pages
935 # Non members can edit unprotected wiki pages
924 @request.session[:user_id] = 4
936 @request.session[:user_id] = 4
925 get :edit, :project_id => 1, :id => 'Another_page'
937 get :edit, :project_id => 1, :id => 'Another_page'
926 assert_response :success
938 assert_response :success
927 assert_template 'edit'
939 assert_template 'edit'
928 end
940 end
929
941
930 def test_edit_protected_page_by_nonmember
942 def test_edit_protected_page_by_nonmember
931 # Non members cannot edit protected wiki pages
943 # Non members cannot edit protected wiki pages
932 @request.session[:user_id] = 4
944 @request.session[:user_id] = 4
933 get :edit, :project_id => 1, :id => 'CookBook_documentation'
945 get :edit, :project_id => 1, :id => 'CookBook_documentation'
934 assert_response 403
946 assert_response 403
935 end
947 end
936
948
937 def test_edit_protected_page_by_member
949 def test_edit_protected_page_by_member
938 @request.session[:user_id] = 2
950 @request.session[:user_id] = 2
939 get :edit, :project_id => 1, :id => 'CookBook_documentation'
951 get :edit, :project_id => 1, :id => 'CookBook_documentation'
940 assert_response :success
952 assert_response :success
941 assert_template 'edit'
953 assert_template 'edit'
942 end
954 end
943
955
944 def test_history_of_non_existing_page_should_return_404
956 def test_history_of_non_existing_page_should_return_404
945 get :history, :project_id => 1, :id => 'Unknown_page'
957 get :history, :project_id => 1, :id => 'Unknown_page'
946 assert_response 404
958 assert_response 404
947 end
959 end
948
960
949 def test_add_attachment
961 def test_add_attachment
950 @request.session[:user_id] = 2
962 @request.session[:user_id] = 2
951 assert_difference 'Attachment.count' do
963 assert_difference 'Attachment.count' do
952 post :add_attachment, :project_id => 1, :id => 'CookBook_documentation',
964 post :add_attachment, :project_id => 1, :id => 'CookBook_documentation',
953 :attachments => {
965 :attachments => {
954 '1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
966 '1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'),
955 'description' => 'test file'}
967 'description' => 'test file'}
956 }
968 }
957 end
969 end
958 attachment = Attachment.order('id DESC').first
970 attachment = Attachment.order('id DESC').first
959 assert_equal Wiki.find(1).find_page('CookBook_documentation'), attachment.container
971 assert_equal Wiki.find(1).find_page('CookBook_documentation'), attachment.container
960 end
972 end
961 end
973 end
General Comments 0
You need to be logged in to leave comments. Login now